comparison src/fileio.c @ 5118:e0db3c197671 ben-lisp-object

merge up to latest default branch, doesn't compile yet
author Ben Wing <ben@xemacs.org>
date Sat, 26 Dec 2009 21:18:49 -0600
parents aa5ed11f473b
children c12b646d84ee
comparison
equal deleted inserted replaced
5117:3742ea8250b5 5118:e0db3c197671
51 #include "systime.h" 51 #include "systime.h"
52 #include "sysdir.h" 52 #include "sysdir.h"
53 53
54 #ifdef HPUX 54 #ifdef HPUX
55 #include <netio.h> 55 #include <netio.h>
56 #ifdef HPUX_PRE_8_0
57 #include <errnet.h>
58 #endif /* HPUX_PRE_8_0 */
59 #endif /* HPUX */ 56 #endif /* HPUX */
60 57
61 #ifdef WIN32_ANY 58 #ifdef WIN32_ANY
62 #define WIN32_FILENAMES 59 #define WIN32_FILENAMES
63 #include "syswindows.h" 60 #include "syswindows.h"
109 106
110 int disable_auto_save_when_buffer_shrinks; 107 int disable_auto_save_when_buffer_shrinks;
111 108
112 Lisp_Object Vdirectory_sep_char; 109 Lisp_Object Vdirectory_sep_char;
113 110
111 #ifdef HAVE_FSYNC
112 /* Nonzero means skip the call to fsync in Fwrite-region. */
113 int write_region_inhibit_fsync;
114 #endif
115
114 /* These variables describe handlers that have "already" had a chance 116 /* These variables describe handlers that have "already" had a chance
115 to handle the current operation. 117 to handle the current operation.
116 118
117 Vinhibit_file_name_handlers is a list of file name handlers. 119 Vinhibit_file_name_handlers is a list of file name handlers.
118 Vinhibit_file_name_operation is the operation being handled. 120 Vinhibit_file_name_operation is the operation being handled.
120 122
121 static Lisp_Object Vinhibit_file_name_handlers; 123 static Lisp_Object Vinhibit_file_name_handlers;
122 static Lisp_Object Vinhibit_file_name_operation; 124 static Lisp_Object Vinhibit_file_name_operation;
123 125
124 Lisp_Object Qfile_already_exists; 126 Lisp_Object Qfile_already_exists;
127 Lisp_Object Qexcl;
125 128
126 Lisp_Object Qauto_save_hook; 129 Lisp_Object Qauto_save_hook;
127 Lisp_Object Qauto_save_error; 130 Lisp_Object Qauto_save_error;
128 Lisp_Object Qauto_saving; 131 Lisp_Object Qauto_saving;
129 132
395 res[2] = '\0'; 398 res[2] = '\0';
396 } 399 }
397 400
398 if (wd) 401 if (wd)
399 { 402 {
403 int size;
400 qxestrcat (res, wd); 404 qxestrcat (res, wd);
401 if (!IS_DIRECTORY_SEP (res[qxestrlen (res) - 1])) 405 size = qxestrlen (res);
402 qxestrcat (res, (Ibyte *) "/"); 406 if (!IS_DIRECTORY_SEP (res[size - 1]))
407 {
408 res[size] = DIRECTORY_SEP;
409 res[size + 1] = '\0';
410 }
403 beg = res; 411 beg = res;
404 p = beg + qxestrlen (beg); 412 p = beg + qxestrlen (beg);
413 }
414 else
415 {
416 return Qnil;
405 } 417 }
406 if (wd) 418 if (wd)
407 xfree (wd, Ibyte *); 419 xfree (wd, Ibyte *);
408 } 420 }
409 421
612 The Emacs process number forms part of the result, so there is no 624 The Emacs process number forms part of the result, so there is no
613 danger of generating a name being used by another process. 625 danger of generating a name being used by another process.
614 626
615 In addition, this function makes an attempt to choose a name that 627 In addition, this function makes an attempt to choose a name that
616 does not specify an existing file. To make this work, PREFIX should 628 does not specify an existing file. To make this work, PREFIX should
617 be an absolute file name. A reasonable idiom is 629 be an absolute file name.
618 630
619 \(make-temp-name (expand-file-name "myprefix" (temp-directory))) 631 This function is analagous to mktemp(3) under POSIX, and as with it, there
620 632 exists a race condition between the test for the existence of the new file
621 which puts the file in the OS-specified temporary directory. 633 and its creation. See `make-temp-file' for a function which avoids this
634 race condition by specifying the appropriate flags to `write-region'.
622 */ 635 */
623 (prefix)) 636 (prefix))
624 { 637 {
625 static const char tbl[64] = 638 static const char tbl[64] =
626 { 639 {
772 785
773 /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */ 786 /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */
774 if (NILP (default_directory)) 787 if (NILP (default_directory))
775 default_directory = current_buffer->directory; 788 default_directory = current_buffer->directory;
776 if (! STRINGP (default_directory)) 789 if (! STRINGP (default_directory))
777 #ifdef WIN32_NATIVE 790 default_directory = build_string (DEFAULT_DIRECTORY_FALLBACK);
778 default_directory = build_string ("C:\\");
779 #else
780 default_directory = build_string ("/");
781 #endif
782 791
783 if (!NILP (default_directory)) 792 if (!NILP (default_directory))
784 { 793 {
785 handler = Ffind_file_name_handler (default_directory, Qexpand_file_name); 794 handler = Ffind_file_name_handler (default_directory, Qexpand_file_name);
786 if (!NILP (handler)) 795 if (!NILP (handler))
1505 (filename)) 1514 (filename))
1506 { 1515 {
1507 /* This function can GC. GC checked 2000-07-28 ben. */ 1516 /* This function can GC. GC checked 2000-07-28 ben. */
1508 Ibyte *nm; 1517 Ibyte *nm;
1509 1518
1510 Ibyte *s, *p, *o, *x, *endp; 1519 Ibyte *s, *p, *o, *x, *endp, *got;
1511 Ibyte *target = 0; 1520 Ibyte *target = 0;
1512 int total = 0; 1521 int total = 0;
1513 int substituted = 0; 1522 int substituted = 0, seen_braces;
1514 Ibyte *xnm; 1523 Ibyte *xnm;
1515 Lisp_Object handler; 1524 Lisp_Object handler;
1516 1525
1517 CHECK_STRING (filename); 1526 CHECK_STRING (filename);
1518 1527
1563 p++; 1572 p++;
1564 else 1573 else
1565 { 1574 {
1566 p++; 1575 p++;
1567 if (p == endp) 1576 if (p == endp)
1568 goto badsubst; 1577 {
1578 /* No substitution, no error. */
1579 break;
1580 }
1569 else if (*p == '$') 1581 else if (*p == '$')
1570 { 1582 {
1571 /* "$$" means a single "$" */ 1583 /* "$$" means a single "$" */
1572 p++; 1584 p++;
1573 total -= 1; 1585 total -= 1;
1576 } 1588 }
1577 else if (*p == '{') 1589 else if (*p == '{')
1578 { 1590 {
1579 o = ++p; 1591 o = ++p;
1580 while (p != endp && *p != '}') p++; 1592 while (p != endp && *p != '}') p++;
1581 if (*p != '}') goto missingclose; 1593 if (*p != '}')
1594 {
1595 /* No substitution, no error. Keep looking. */
1596 p = o;
1597 continue;
1598 }
1582 s = p; 1599 s = p;
1583 } 1600 }
1584 else 1601 else
1585 { 1602 {
1586 o = p; 1603 o = p;
1595 #ifdef WIN32_NATIVE 1612 #ifdef WIN32_NATIVE
1596 qxestrupr (target); /* $home == $HOME etc. */ 1613 qxestrupr (target); /* $home == $HOME etc. */
1597 #endif /* WIN32_NATIVE */ 1614 #endif /* WIN32_NATIVE */
1598 1615
1599 /* Get variable value */ 1616 /* Get variable value */
1600 o = egetenv ((CIbyte *) target); 1617 got = egetenv ((CIbyte *) target);
1601 if (!o) goto badvar; 1618 if (got)
1602 total += qxestrlen (o); 1619 {
1603 substituted = 1; 1620 total += qxestrlen (got);
1621 substituted = 1;
1622 }
1604 } 1623 }
1605 1624
1606 if (!substituted) 1625 if (!substituted)
1607 return filename; 1626 return filename;
1608 1627
1616 if (*p != '$') 1635 if (*p != '$')
1617 *x++ = *p++; 1636 *x++ = *p++;
1618 else 1637 else
1619 { 1638 {
1620 p++; 1639 p++;
1640 seen_braces = 0;
1621 if (p == endp) 1641 if (p == endp)
1622 goto badsubst; 1642 {
1643 *x++ = '$';
1644 break;
1645 }
1623 else if (*p == '$') 1646 else if (*p == '$')
1624 { 1647 {
1625 *x++ = *p++; 1648 *x++ = *p++;
1626 continue; 1649 continue;
1627 } 1650 }
1628 else if (*p == '{') 1651 else if (*p == '{')
1629 { 1652 {
1653 seen_braces = 1;
1630 o = ++p; 1654 o = ++p;
1631 while (p != endp && *p != '}') p++; 1655 while (p != endp && *p != '}') p++;
1632 if (*p != '}') goto missingclose; 1656 if (*p != '}')
1657 {
1658 /* Don't syntax error, don't substitute */
1659 *x++ = '{';
1660 p = o;
1661 continue;
1662 }
1633 s = p++; 1663 s = p++;
1634 } 1664 }
1635 else 1665 else
1636 { 1666 {
1637 o = p; 1667 o = p;
1646 #ifdef WIN32_NATIVE 1676 #ifdef WIN32_NATIVE
1647 qxestrupr (target); /* $home == $HOME etc. */ 1677 qxestrupr (target); /* $home == $HOME etc. */
1648 #endif /* WIN32_NATIVE */ 1678 #endif /* WIN32_NATIVE */
1649 1679
1650 /* Get variable value */ 1680 /* Get variable value */
1651 o = egetenv ((CIbyte *) target); 1681 got = egetenv ((CIbyte *) target);
1652 if (!o) 1682 if (got)
1653 goto badvar; 1683 {
1654 1684 qxestrcpy (x, got);
1655 qxestrcpy (x, o); 1685 x += qxestrlen (got);
1656 x += qxestrlen (o); 1686 }
1687 else
1688 {
1689 *x++ = '$';
1690 if (seen_braces)
1691 {
1692 *x++ = '{';
1693 /* Preserve the original case. */
1694 qxestrncpy (x, o, s - o);
1695 x += s - o;
1696 *x++ = '}';
1697 }
1698 else
1699 {
1700 /* Preserve the original case. */
1701 qxestrncpy (x, o, s - o);
1702 x += s - o;
1703 }
1704 }
1657 } 1705 }
1658 1706
1659 *x = 0; 1707 *x = 0;
1660 1708
1661 /* If /~ or // appears, discard everything through first slash. */ 1709 /* If /~ or // appears, discard everything through first slash. */
1676 && p > nm && IS_DIRECTORY_SEP (p[-1])) 1724 && p > nm && IS_DIRECTORY_SEP (p[-1]))
1677 xnm = p; 1725 xnm = p;
1678 #endif 1726 #endif
1679 1727
1680 return make_string (xnm, x - xnm); 1728 return make_string (xnm, x - xnm);
1681
1682 badsubst:
1683 syntax_error ("Bad format environment-variable substitution", filename);
1684 missingclose:
1685 syntax_error ("Missing \"}\" in environment-variable substitution",
1686 filename);
1687 badvar:
1688 syntax_error_2 ("Substituting nonexistent environment variable",
1689 filename, build_intstring (target));
1690
1691 RETURN_NOT_REACHED (Qnil);
1692 } 1729 }
1693 1730
1694 /* A slightly faster and more convenient way to get 1731 /* A slightly faster and more convenient way to get
1695 (directory-file-name (expand-file-name FOO)). */ 1732 (directory-file-name (expand-file-name FOO)). */
1696 1733
2158 Make a symbolic link to FILENAME, named LINKNAME. Both args strings. 2195 Make a symbolic link to FILENAME, named LINKNAME. Both args strings.
2159 Signals a `file-already-exists' error if a file LINKNAME already exists 2196 Signals a `file-already-exists' error if a file LINKNAME already exists
2160 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil. 2197 unless optional third argument OK-IF-ALREADY-EXISTS is non-nil.
2161 A number as third arg means request confirmation if LINKNAME already exists. 2198 A number as third arg means request confirmation if LINKNAME already exists.
2162 This happens for interactive use with M-x. 2199 This happens for interactive use with M-x.
2200
2201 On platforms where symbolic links are not available, any file handlers will
2202 be run, but the check for the existence of LINKNAME will not be done, and
2203 the symbolic link will not be created.
2163 */ 2204 */
2164 (filename, linkname, ok_if_already_exists)) 2205 (filename, linkname, ok_if_already_exists))
2165 { 2206 {
2166 /* This function can GC. GC checked 1997.06.04. */ 2207 /* This function can GC. GC checked 1997.06.04. */
2167 /* XEmacs change: run handlers even if local machine doesn't have symlinks */ 2208 /* XEmacs change: run handlers even if local machine doesn't have symlinks */
2280 /* Return nonzero if file FILENAME exists and can be written. */ 2321 /* Return nonzero if file FILENAME exists and can be written. */
2281 2322
2282 static int 2323 static int
2283 check_writable (const Ibyte *filename) 2324 check_writable (const Ibyte *filename)
2284 { 2325 {
2326 #if defined(WIN32_NATIVE) || defined(CYGWIN)
2327 #ifdef CYGWIN
2328 char filename_buffer[PATH_MAX];
2329 #endif
2330 // Since this has to work for a directory, we can't just call 'CreateFile'
2331 PSECURITY_DESCRIPTOR pDesc; /* Must be freed with LocalFree */
2332 /* these need not be freed, they point into pDesc */
2333 PSID psidOwner;
2334 PSID psidGroup;
2335 PACL pDacl;
2336 PACL pSacl;
2337 /* end of insides of descriptor */
2338 DWORD error;
2339 DWORD attributes;
2340 HANDLE tokenHandle;
2341 GENERIC_MAPPING genericMapping;
2342 DWORD accessMask;
2343 PRIVILEGE_SET PrivilegeSet;
2344 DWORD dwPrivSetSize = sizeof( PRIVILEGE_SET );
2345 BOOL fAccessGranted = FALSE;
2346 DWORD dwAccessAllowed;
2347 Extbyte *fnameext;
2348
2349 #ifdef CYGWIN
2350 cygwin_conv_to_full_win32_path(filename, filename_buffer);
2351 filename = (Ibyte*)filename_buffer;
2352 #endif
2353
2354 C_STRING_TO_TSTR(filename, fnameext);
2355
2356 // First check for a normal file with the old-style readonly bit
2357 attributes = qxeGetFileAttributes(fnameext);
2358 if (FILE_ATTRIBUTE_READONLY == (attributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_READONLY)))
2359 return 0;
2360
2361 /* Win32 prototype lacks const. */
2362 error = qxeGetNamedSecurityInfo(fnameext, SE_FILE_OBJECT,
2363 DACL_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION,
2364 &psidOwner, &psidGroup, &pDacl, &pSacl, &pDesc);
2365 if(error != ERROR_SUCCESS) { // FAT?
2366 attributes = qxeGetFileAttributes(fnameext);
2367 return (attributes & FILE_ATTRIBUTE_DIRECTORY) || (0 == (attributes & FILE_ATTRIBUTE_READONLY));
2368 }
2369
2370 genericMapping.GenericRead = FILE_GENERIC_READ;
2371 genericMapping.GenericWrite = FILE_GENERIC_WRITE;
2372 genericMapping.GenericExecute = FILE_GENERIC_EXECUTE;
2373 genericMapping.GenericAll = FILE_ALL_ACCESS;
2374
2375 if(!ImpersonateSelf(SecurityDelegation)) {
2376 return 0;
2377 }
2378 if(!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &tokenHandle)) {
2379 return 0;
2380 }
2381
2382 accessMask = GENERIC_WRITE;
2383 MapGenericMask(&accessMask, &genericMapping);
2384
2385 if(!AccessCheck(pDesc, tokenHandle, accessMask, &genericMapping,
2386 &PrivilegeSet, // receives privileges used in check
2387 &dwPrivSetSize, // size of PrivilegeSet buffer
2388 &dwAccessAllowed, // receives mask of allowed access rights
2389 &fAccessGranted))
2390 {
2391 CloseHandle(tokenHandle);
2392 RevertToSelf();
2393 LocalFree(pDesc);
2394 return 0;
2395 }
2396 CloseHandle(tokenHandle);
2397 RevertToSelf();
2398 LocalFree(pDesc);
2399 return fAccessGranted == TRUE;
2400 #else
2285 #ifdef HAVE_EACCESS 2401 #ifdef HAVE_EACCESS
2286 return (qxe_eaccess (filename, W_OK) >= 0); 2402 return (qxe_eaccess (filename, W_OK) >= 0);
2287 #else 2403 #else
2288 /* Access isn't quite right because it uses the real uid 2404 /* Access isn't quite right because it uses the real uid
2289 and we really want to test with the effective uid. 2405 and we really want to test with the effective uid.
2290 But Unix doesn't give us a right way to do it. 2406 But Unix doesn't give us a right way to do it.
2291 Opening with O_WRONLY could work for an ordinary file, 2407 Opening with O_WRONLY could work for an ordinary file,
2292 but would lose for directories. */ 2408 but would lose for directories. */
2293 return (qxe_access (filename, W_OK) >= 0); 2409 return (qxe_access (filename, W_OK) >= 0);
2410 #endif
2294 #endif 2411 #endif
2295 } 2412 }
2296 2413
2297 DEFUN ("file-exists-p", Ffile_exists_p, 1, 1, 0, /* 2414 DEFUN ("file-exists-p", Ffile_exists_p, 1, 1, 0, /*
2298 Return t if file FILENAME exists. (This does not mean you can read it.) 2415 Return t if file FILENAME exists. (This does not mean you can read it.)
2798 struct stat st; 2915 struct stat st;
2799 int fd; 2916 int fd;
2800 int saverrno = 0; 2917 int saverrno = 0;
2801 Charcount inserted = 0; 2918 Charcount inserted = 0;
2802 int speccount; 2919 int speccount;
2803 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; 2920 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2804 Lisp_Object handler = Qnil, val; 2921 Lisp_Object val;
2805 int total; 2922 int total;
2806 Ibyte read_buf[READ_BUF_SIZE]; 2923 Ibyte read_buf[READ_BUF_SIZE];
2807 int mc_count; 2924 int mc_count;
2808 struct buffer *buf = current_buffer; 2925 struct buffer *buf = current_buffer;
2809 Lisp_Object curbuf; 2926 Lisp_Object curbuf;
2822 /* #### dmoore - should probably check in various places to see if 2939 /* #### dmoore - should probably check in various places to see if
2823 curbuf was killed and if so signal an error? */ 2940 curbuf was killed and if so signal an error? */
2824 2941
2825 curbuf = wrap_buffer (buf); 2942 curbuf = wrap_buffer (buf);
2826 2943
2827 GCPRO5 (filename, val, visit, handler, curbuf); 2944 GCPRO4 (filename, val, visit, curbuf);
2828 2945
2829 mc_count = (NILP (replace)) ? 2946 mc_count = (NILP (replace)) ?
2830 begin_multiple_change (buf, BUF_PT (buf), BUF_PT (buf)) : 2947 begin_multiple_change (buf, BUF_PT (buf), BUF_PT (buf)) :
2831 begin_multiple_change (buf, BUF_BEG (buf), BUF_Z (buf)); 2948 begin_multiple_change (buf, BUF_BEG (buf), BUF_Z (buf));
2832 2949
2833 speccount = specpdl_depth (); /* begin_multiple_change also adds 2950 speccount = specpdl_depth (); /* begin_multiple_change also adds
2834 an unwind_protect */ 2951 an unwind_protect */
2835 2952
2836 filename = Fexpand_file_name (filename, Qnil); 2953 filename = Fexpand_file_name (filename, Qnil);
2837 2954
2838 /* If the file name has special constructs in it,
2839 call the corresponding file handler. */
2840 handler = Ffind_file_name_handler (filename, Qinsert_file_contents);
2841 if (!NILP (handler))
2842 {
2843 val = call6 (handler, Qinsert_file_contents, filename,
2844 visit, start, end, replace);
2845 goto handled;
2846 }
2847
2848 if (!NILP (used_codesys)) 2955 if (!NILP (used_codesys))
2849 CHECK_SYMBOL (used_codesys); 2956 CHECK_SYMBOL (used_codesys);
2850 2957
2851 if ( (!NILP (start) || !NILP (end)) && !NILP (visit) ) 2958 if ( (!NILP (start) || !NILP (end)) && !NILP (visit) )
2852 invalid_operation ("Attempt to visit less than an entire file", Qunbound); 2959 invalid_operation ("Attempt to visit less than an entire file", Qunbound);
2853 2960
2854 fd = -1; 2961 fd = -1;
2855 2962
2856 if (qxe_stat (XSTRING_DATA (filename), &st) < 0) 2963 if (qxe_stat (XSTRING_DATA (filename), &st) < 0)
2857 { 2964 {
2858 if (fd >= 0) retry_close (fd);
2859 badopen: 2965 badopen:
2860 if (NILP (visit)) 2966 if (NILP (visit))
2861 report_file_error ("Opening input file", filename); 2967 report_file_error ("Opening input file", filename);
2862 st.st_mtime = -1; 2968 st.st_mtime = -1;
2863 goto notfound; 2969 goto notfound;
2947 beginning to that point, but I really don't think it's worth it. If 3053 beginning to that point, but I really don't think it's worth it. If
2948 we implemented the FSF "brute-force" method, we would have to put a 3054 we implemented the FSF "brute-force" method, we would have to put a
2949 reasonable maximum file size on the files. Is any of this worth it? 3055 reasonable maximum file size on the files. Is any of this worth it?
2950 --ben 3056 --ben
2951 3057
3058
3059 It's probably not worth it, and despite what you might take from the
3060 above, we don't do it currently; that is, for non-"binary" coding
3061 systems, we don't try to implement replace-mode at all. See the
3062 do_speedy_insert variable above. The upside of this is that our API
3063 is consistent and not buggy. -- Aidan Kehoe, Fri Oct 27 21:02:30 CEST
3064 2006
2952 */ 3065 */
2953 3066
2954 if (!NILP (replace)) 3067 if (!NILP (replace))
2955 { 3068 {
2956 if (!do_speedy_insert) 3069 if (!do_speedy_insert)
3147 3260
3148 if (!NILP (visit)) 3261 if (!NILP (visit))
3149 { 3262 {
3150 if (!EQ (buf->undo_list, Qt)) 3263 if (!EQ (buf->undo_list, Qt))
3151 buf->undo_list = Qnil; 3264 buf->undo_list = Qnil;
3152 if (NILP (handler)) 3265 buf->modtime = st.st_mtime;
3153 { 3266 buf->filename = filename;
3154 buf->modtime = st.st_mtime; 3267 /* XEmacs addition: */
3155 buf->filename = filename; 3268 /* This function used to be in C, ostensibly so that
3156 /* XEmacs addition: */ 3269 it could be called here. But that's just silly.
3157 /* This function used to be in C, ostensibly so that 3270 There's no reason C code can't call out to Lisp
3158 it could be called here. But that's just silly. 3271 code, and it's a lot cleaner this way. */
3159 There's no reason C code can't call out to Lisp 3272 /* Note: compute-buffer-file-truename is called for
3160 code, and it's a lot cleaner this way. */ 3273 side-effect! Its return value is intentionally
3161 /* Note: compute-buffer-file-truename is called for 3274 ignored. */
3162 side-effect! Its return value is intentionally 3275 if (!NILP (Ffboundp (Qcompute_buffer_file_truename)))
3163 ignored. */ 3276 call1 (Qcompute_buffer_file_truename, wrap_buffer (buf));
3164 if (!NILP (Ffboundp (Qcompute_buffer_file_truename)))
3165 call1 (Qcompute_buffer_file_truename, wrap_buffer (buf));
3166 }
3167 BUF_SAVE_MODIFF (buf) = BUF_MODIFF (buf); 3277 BUF_SAVE_MODIFF (buf) = BUF_MODIFF (buf);
3168 buf->auto_save_modified = BUF_MODIFF (buf); 3278 buf->auto_save_modified = BUF_MODIFF (buf);
3169 buf->saved_size = make_int (BUF_SIZE (buf)); 3279 buf->saved_size = make_int (BUF_SIZE (buf));
3170 #ifdef CLASH_DETECTION 3280 #ifdef CLASH_DETECTION
3171 if (NILP (handler)) 3281 if (!NILP (buf->file_truename))
3172 { 3282 unlock_file (buf->file_truename);
3173 if (!NILP (buf->file_truename)) 3283 unlock_file (filename);
3174 unlock_file (buf->file_truename);
3175 unlock_file (filename);
3176 }
3177 #endif /* CLASH_DETECTION */ 3284 #endif /* CLASH_DETECTION */
3178 if (not_regular) 3285 if (not_regular)
3179 RETURN_UNGCPRO (Fsignal (Qfile_error, 3286 RETURN_UNGCPRO (Fsignal (Qfile_error,
3180 list2 (build_msg_string ("not a regular file"), 3287 list2 (build_msg_string ("not a regular file"),
3181 filename))); 3288 filename)));
3236 Fset_buffer (buf); 3343 Fset_buffer (buf);
3237 Fkill_buffer (tembuf); 3344 Fkill_buffer (tembuf);
3238 return Qnil; 3345 return Qnil;
3239 } 3346 }
3240 3347
3241 DEFUN ("write-region-internal", Fwrite_region_internal, 3, 7, 3348 DEFUN ("write-region-internal", Fwrite_region_internal, 3, 8,
3242 "r\nFWrite region to file: ", /* 3349 "r\nFWrite region to file: ", /*
3243 Write current region into specified file; no coding-system frobbing. 3350 Write current region into specified file; no coding-system frobbing.
3244 This function is identical to `write-region' except for the handling 3351
3245 of the CODESYS argument under XEmacs/Mule. (When Mule support is not 3352 This function is almost identical to `write-region'; see that function for
3246 present, both functions are identical and ignore the CODESYS argument.) 3353 documentation of the START, END, FILENAME, APPEND, VISIT, and LOCKNAME
3247 If support for Mule exists in this Emacs, the file is encoded according 3354 arguments. CODESYS specifies the encoding to be used for the file; if it is
3248 to the value of CODESYS. If this is nil, no code conversion occurs. 3355 nil, no code conversion occurs. (With `write-region' the coding system is
3356 determined automatically if not specified.)
3357
3358 MUSTBENEW specifies that a check for an existing file of the same name
3359 should be made. If it is 'excl, XEmacs will error on detecting such a file
3360 and never write it. If it is some other non-nil value, the user will be
3361 prompted to confirm the overwriting of an existing file. If it is nil,
3362 existing files are silently overwritten when file system permissions allow
3363 this.
3249 3364
3250 As a special kludge to support auto-saving, when START is nil START and 3365 As a special kludge to support auto-saving, when START is nil START and
3251 END are set to the beginning and end, respectively, of the buffer, 3366 END are set to the beginning and end, respectively, of the buffer,
3252 regardless of any restrictions. Don't use this feature. It is documented 3367 regardless of any restrictions. Don't use this feature. It is documented
3253 here because write-region handler writers need to be aware of it. 3368 here because write-region handler writers need to be aware of it.
3254 */ 3369
3255 (start, end, filename, append, visit, lockname, codesys)) 3370 */
3371 (start, end, filename, append, visit, lockname, codesys,
3372 mustbenew))
3256 { 3373 {
3257 /* This function can call lisp. GC checked 2000-07-28 ben */ 3374 /* This function can call lisp. GC checked 2000-07-28 ben */
3258 int desc; 3375 int desc;
3259 int failure; 3376 int failure;
3260 int save_errno = 0; 3377 int save_errno = 0;
3295 get_buffer_range_char (current_buffer, start, end, &start1, &end1, 0); 3412 get_buffer_range_char (current_buffer, start, end, &start1, &end1, 0);
3296 3413
3297 { 3414 {
3298 Lisp_Object handler; 3415 Lisp_Object handler;
3299 3416
3417 if (!NILP (mustbenew) && !EQ (mustbenew, Qexcl))
3418 barf_or_query_if_file_exists (filename, "overwrite", 1, NULL);
3419
3300 if (visiting_other) 3420 if (visiting_other)
3301 visit_file = Fexpand_file_name (visit, Qnil); 3421 visit_file = Fexpand_file_name (visit, Qnil);
3302 else 3422 else
3303 visit_file = filename; 3423 visit_file = filename;
3304 filename = Fexpand_file_name (filename, Qnil); 3424 filename = Fexpand_file_name (filename, Qnil);
3356 3476
3357 fn = filename; 3477 fn = filename;
3358 desc = -1; 3478 desc = -1;
3359 if (!NILP (append)) 3479 if (!NILP (append))
3360 { 3480 {
3361 desc = qxe_open (XSTRING_DATA (fn), O_WRONLY | OPEN_BINARY, 0); 3481 desc = qxe_open (XSTRING_DATA (fn), O_WRONLY | OPEN_BINARY
3482 | (EQ (mustbenew, Qexcl) ? O_EXCL : 0), 0);
3362 } 3483 }
3363 if (desc < 0) 3484 if (desc < 0)
3364 { 3485 {
3365 desc = qxe_open (XSTRING_DATA (fn), 3486 desc = qxe_open (XSTRING_DATA (fn),
3366 O_WRONLY | O_TRUNC | O_CREAT | OPEN_BINARY, 3487 O_WRONLY | (EQ (mustbenew, Qexcl) ? O_EXCL : O_TRUNC)
3488 | O_CREAT | OPEN_BINARY,
3367 auto_saving ? auto_save_mode_bits : CREAT_MODE); 3489 auto_saving ? auto_save_mode_bits : CREAT_MODE);
3368 } 3490 }
3369 3491
3370 if (desc < 0) 3492 if (desc < 0)
3371 { 3493 {
3442 #ifdef HAVE_FSYNC 3564 #ifdef HAVE_FSYNC
3443 /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun). 3565 /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).
3444 Disk full in NFS may be reported here. */ 3566 Disk full in NFS may be reported here. */
3445 /* mib says that closing the file will try to write as fast as NFS can do 3567 /* mib says that closing the file will try to write as fast as NFS can do
3446 it, and that means the fsync here is not crucial for autosave files. */ 3568 it, and that means the fsync here is not crucial for autosave files. */
3447 if (!auto_saving && fsync (desc) < 0 3569 if (!auto_saving && !write_region_inhibit_fsync && fsync (desc) < 0
3448 /* If fsync fails with EINTR, don't treat that as serious. */ 3570 /* If fsync fails with EINTR, don't treat that as serious. */
3449 && errno != EINTR) 3571 && errno != EINTR)
3450 { 3572 {
3451 failure = 1; 3573 failure = 1;
3452 save_errno = errno; 3574 save_errno = errno;
3930 4052
3931 return 4053 return
3932 Fwrite_region_internal (Qnil, Qnil, a, Qnil, Qlambda, Qnil, 4054 Fwrite_region_internal (Qnil, Qnil, a, Qnil, Qlambda, Qnil,
3933 #if 1 /* #### Kyle wants it changed to not use escape-quoted. Think 4055 #if 1 /* #### Kyle wants it changed to not use escape-quoted. Think
3934 carefully about how this works. */ 4056 carefully about how this works. */
3935 Qescape_quoted 4057 Qescape_quoted,
3936 #else 4058 #else
3937 current_buffer->buffer_file_coding_system 4059 current_buffer->buffer_file_coding_system,
3938 #endif 4060 #endif
3939 ); 4061 Qnil);
3940 } 4062 }
3941 4063
3942 static Lisp_Object 4064 static Lisp_Object
3943 auto_save_expand_name_error (Lisp_Object condition_object, 4065 auto_save_expand_name_error (Lisp_Object condition_object,
3944 Lisp_Object UNUSED (ignored)) 4066 Lisp_Object UNUSED (ignored))
4290 DEFSYMBOL (Qinsert_file_contents); 4412 DEFSYMBOL (Qinsert_file_contents);
4291 DEFSYMBOL (Qwrite_region); 4413 DEFSYMBOL (Qwrite_region);
4292 DEFSYMBOL (Qverify_visited_file_modtime); 4414 DEFSYMBOL (Qverify_visited_file_modtime);
4293 DEFSYMBOL (Qset_visited_file_modtime); 4415 DEFSYMBOL (Qset_visited_file_modtime);
4294 DEFSYMBOL (Qcar_less_than_car); /* Vomitous! */ 4416 DEFSYMBOL (Qcar_less_than_car); /* Vomitous! */
4417 DEFSYMBOL (Qexcl);
4295 4418
4296 DEFSYMBOL (Qauto_save_hook); 4419 DEFSYMBOL (Qauto_save_hook);
4297 DEFSYMBOL (Qauto_save_error); 4420 DEFSYMBOL (Qauto_save_error);
4298 DEFSYMBOL (Qauto_saving); 4421 DEFSYMBOL (Qauto_saving);
4299 4422
4433 DEFVAR_LISP ("auto-save-list-file-name", &Vauto_save_list_file_name /* 4556 DEFVAR_LISP ("auto-save-list-file-name", &Vauto_save_list_file_name /*
4434 File name in which we write a list of all auto save file names. 4557 File name in which we write a list of all auto save file names.
4435 */ ); 4558 */ );
4436 Vauto_save_list_file_name = Qnil; 4559 Vauto_save_list_file_name = Qnil;
4437 4560
4561 #ifdef HAVE_FSYNC
4562 DEFVAR_BOOL ("write-region-inhibit-fsync", &write_region_inhibit_fsync /*
4563 *Non-nil means don't call fsync in `write-region'.
4564 This variable affects calls to `write-region' as well as save commands.
4565 A non-nil value may result in data loss!
4566 */ );
4567 write_region_inhibit_fsync = 0;
4568 #endif
4569
4438 DEFVAR_LISP ("auto-save-list-file-prefix", &Vauto_save_list_file_prefix /* 4570 DEFVAR_LISP ("auto-save-list-file-prefix", &Vauto_save_list_file_prefix /*
4439 Prefix for generating auto-save-list-file-name. 4571 Prefix for generating auto-save-list-file-name.
4440 Emacs's pid and the system name will be appended to 4572 Emacs's pid and the system name will be appended to
4441 this prefix to create a unique file name. 4573 this prefix to create a unique file name.
4442 */ ); 4574 */ );