Mercurial > hg > xemacs-beta
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 */ ); |