diff options
Diffstat (limited to 'src/fileio.c')
| -rw-r--r-- | src/fileio.c | 359 |
1 files changed, 251 insertions, 108 deletions
diff --git a/src/fileio.c b/src/fileio.c index c6f8dfe4683..7efe919a9f0 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* File IO for GNU Emacs. | 1 | /* File IO for GNU Emacs. |
| 2 | 2 | ||
| 3 | Copyright (C) 1985-1988, 1993-2011 Free Software Foundation, Inc. | 3 | Copyright (C) 1985-1988, 1993-2012 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | This file is part of GNU Emacs. | 5 | This file is part of GNU Emacs. |
| 6 | 6 | ||
| @@ -62,7 +62,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 62 | 62 | ||
| 63 | #ifdef DOS_NT | 63 | #ifdef DOS_NT |
| 64 | /* On Windows, drive letters must be alphabetic - on DOS, the Netware | 64 | /* On Windows, drive letters must be alphabetic - on DOS, the Netware |
| 65 | redirector allows the six letters between 'Z' and 'a' as well. */ | 65 | redirector allows the six letters between 'Z' and 'a' as well. */ |
| 66 | #ifdef MSDOS | 66 | #ifdef MSDOS |
| 67 | #define IS_DRIVE(x) ((x) >= 'A' && (x) <= 'z') | 67 | #define IS_DRIVE(x) ((x) >= 'A' && (x) <= 'z') |
| 68 | #endif | 68 | #endif |
| @@ -70,7 +70,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 70 | #define IS_DRIVE(x) isalpha ((unsigned char) (x)) | 70 | #define IS_DRIVE(x) isalpha ((unsigned char) (x)) |
| 71 | #endif | 71 | #endif |
| 72 | /* Need to lower-case the drive letter, or else expanded | 72 | /* Need to lower-case the drive letter, or else expanded |
| 73 | filenames will sometimes compare inequal, because | 73 | filenames will sometimes compare unequal, because |
| 74 | `expand-file-name' doesn't always down-case the drive letter. */ | 74 | `expand-file-name' doesn't always down-case the drive letter. */ |
| 75 | #define DRIVE_LETTER(x) (tolower ((unsigned char) (x))) | 75 | #define DRIVE_LETTER(x) (tolower ((unsigned char) (x))) |
| 76 | #endif | 76 | #endif |
| @@ -90,6 +90,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 90 | /* Nonzero during writing of auto-save files */ | 90 | /* Nonzero during writing of auto-save files */ |
| 91 | static int auto_saving; | 91 | static int auto_saving; |
| 92 | 92 | ||
| 93 | /* Nonzero umask during creation of auto-save directories */ | ||
| 94 | static int auto_saving_dir_umask; | ||
| 95 | |||
| 93 | /* Set by auto_save_1 to mode of original file so Fwrite_region will create | 96 | /* Set by auto_save_1 to mode of original file so Fwrite_region will create |
| 94 | a new file with the same mode as the original */ | 97 | a new file with the same mode as the original */ |
| 95 | static int auto_save_mode_bits; | 98 | static int auto_save_mode_bits; |
| @@ -325,7 +328,11 @@ Given a Unix syntax file name, returns a string ending in slash. */) | |||
| 325 | call the corresponding file handler. */ | 328 | call the corresponding file handler. */ |
| 326 | handler = Ffind_file_name_handler (filename, Qfile_name_directory); | 329 | handler = Ffind_file_name_handler (filename, Qfile_name_directory); |
| 327 | if (!NILP (handler)) | 330 | if (!NILP (handler)) |
| 328 | return call2 (handler, Qfile_name_directory, filename); | 331 | { |
| 332 | Lisp_Object handled_name = call2 (handler, Qfile_name_directory, | ||
| 333 | filename); | ||
| 334 | return STRINGP (handled_name) ? handled_name : Qnil; | ||
| 335 | } | ||
| 329 | 336 | ||
| 330 | filename = FILE_SYSTEM_CASE (filename); | 337 | filename = FILE_SYSTEM_CASE (filename); |
| 331 | #ifdef DOS_NT | 338 | #ifdef DOS_NT |
| @@ -338,7 +345,7 @@ Given a Unix syntax file name, returns a string ending in slash. */) | |||
| 338 | 345 | ||
| 339 | while (p != beg && !IS_DIRECTORY_SEP (p[-1]) | 346 | while (p != beg && !IS_DIRECTORY_SEP (p[-1]) |
| 340 | #ifdef DOS_NT | 347 | #ifdef DOS_NT |
| 341 | /* only recognise drive specifier at the beginning */ | 348 | /* only recognize drive specifier at the beginning */ |
| 342 | && !(p[-1] == ':' | 349 | && !(p[-1] == ':' |
| 343 | /* handle the "/:d:foo" and "/:foo" cases correctly */ | 350 | /* handle the "/:d:foo" and "/:foo" cases correctly */ |
| 344 | && ((p == beg + 2 && !IS_DIRECTORY_SEP (*beg)) | 351 | && ((p == beg + 2 && !IS_DIRECTORY_SEP (*beg)) |
| @@ -394,14 +401,20 @@ or the entire name if it contains no slash. */) | |||
| 394 | call the corresponding file handler. */ | 401 | call the corresponding file handler. */ |
| 395 | handler = Ffind_file_name_handler (filename, Qfile_name_nondirectory); | 402 | handler = Ffind_file_name_handler (filename, Qfile_name_nondirectory); |
| 396 | if (!NILP (handler)) | 403 | if (!NILP (handler)) |
| 397 | return call2 (handler, Qfile_name_nondirectory, filename); | 404 | { |
| 405 | Lisp_Object handled_name = call2 (handler, Qfile_name_nondirectory, | ||
| 406 | filename); | ||
| 407 | if (STRINGP (handled_name)) | ||
| 408 | return handled_name; | ||
| 409 | error ("Invalid handler in `file-name-handler-alist'"); | ||
| 410 | } | ||
| 398 | 411 | ||
| 399 | beg = SSDATA (filename); | 412 | beg = SSDATA (filename); |
| 400 | end = p = beg + SBYTES (filename); | 413 | end = p = beg + SBYTES (filename); |
| 401 | 414 | ||
| 402 | while (p != beg && !IS_DIRECTORY_SEP (p[-1]) | 415 | while (p != beg && !IS_DIRECTORY_SEP (p[-1]) |
| 403 | #ifdef DOS_NT | 416 | #ifdef DOS_NT |
| 404 | /* only recognise drive specifier at beginning */ | 417 | /* only recognize drive specifier at beginning */ |
| 405 | && !(p[-1] == ':' | 418 | && !(p[-1] == ':' |
| 406 | /* handle the "/:d:foo" case correctly */ | 419 | /* handle the "/:d:foo" case correctly */ |
| 407 | && (p == beg + 2 || (p == beg + 4 && IS_DIRECTORY_SEP (*beg)))) | 420 | && (p == beg + 2 || (p == beg + 4 && IS_DIRECTORY_SEP (*beg)))) |
| @@ -431,7 +444,11 @@ get a current directory to run processes in. */) | |||
| 431 | call the corresponding file handler. */ | 444 | call the corresponding file handler. */ |
| 432 | handler = Ffind_file_name_handler (filename, Qunhandled_file_name_directory); | 445 | handler = Ffind_file_name_handler (filename, Qunhandled_file_name_directory); |
| 433 | if (!NILP (handler)) | 446 | if (!NILP (handler)) |
| 434 | return call2 (handler, Qunhandled_file_name_directory, filename); | 447 | { |
| 448 | Lisp_Object handled_name = call2 (handler, Qunhandled_file_name_directory, | ||
| 449 | filename); | ||
| 450 | return STRINGP (handled_name) ? handled_name : Qnil; | ||
| 451 | } | ||
| 435 | 452 | ||
| 436 | return Ffile_name_directory (filename); | 453 | return Ffile_name_directory (filename); |
| 437 | } | 454 | } |
| @@ -485,7 +502,13 @@ For a Unix-syntax file name, just appends a slash. */) | |||
| 485 | call the corresponding file handler. */ | 502 | call the corresponding file handler. */ |
| 486 | handler = Ffind_file_name_handler (file, Qfile_name_as_directory); | 503 | handler = Ffind_file_name_handler (file, Qfile_name_as_directory); |
| 487 | if (!NILP (handler)) | 504 | if (!NILP (handler)) |
| 488 | return call2 (handler, Qfile_name_as_directory, file); | 505 | { |
| 506 | Lisp_Object handled_name = call2 (handler, Qfile_name_as_directory, | ||
| 507 | file); | ||
| 508 | if (STRINGP (handled_name)) | ||
| 509 | return handled_name; | ||
| 510 | error ("Invalid handler in `file-name-handler-alist'"); | ||
| 511 | } | ||
| 489 | 512 | ||
| 490 | buf = (char *) alloca (SBYTES (file) + 10); | 513 | buf = (char *) alloca (SBYTES (file) + 10); |
| 491 | file_name_as_directory (buf, SSDATA (file)); | 514 | file_name_as_directory (buf, SSDATA (file)); |
| @@ -544,7 +567,13 @@ In Unix-syntax, this function just removes the final slash. */) | |||
| 544 | call the corresponding file handler. */ | 567 | call the corresponding file handler. */ |
| 545 | handler = Ffind_file_name_handler (directory, Qdirectory_file_name); | 568 | handler = Ffind_file_name_handler (directory, Qdirectory_file_name); |
| 546 | if (!NILP (handler)) | 569 | if (!NILP (handler)) |
| 547 | return call2 (handler, Qdirectory_file_name, directory); | 570 | { |
| 571 | Lisp_Object handled_name = call2 (handler, Qdirectory_file_name, | ||
| 572 | directory); | ||
| 573 | if (STRINGP (handled_name)) | ||
| 574 | return handled_name; | ||
| 575 | error ("Invalid handler in `file-name-handler-alist'"); | ||
| 576 | } | ||
| 548 | 577 | ||
| 549 | buf = (char *) alloca (SBYTES (directory) + 20); | 578 | buf = (char *) alloca (SBYTES (directory) + 20); |
| 550 | directory_file_name (SSDATA (directory), buf); | 579 | directory_file_name (SSDATA (directory), buf); |
| @@ -587,9 +616,9 @@ make_temp_name (Lisp_Object prefix, int base64_p) | |||
| 587 | { | 616 | { |
| 588 | Lisp_Object val; | 617 | Lisp_Object val; |
| 589 | int len, clen; | 618 | int len, clen; |
| 590 | intmax_t pid; | 619 | printmax_t pid; |
| 591 | char *p, *data; | 620 | char *p, *data; |
| 592 | char pidbuf[INT_BUFSIZE_BOUND (pid_t)]; | 621 | char pidbuf[INT_BUFSIZE_BOUND (printmax_t)]; |
| 593 | int pidlen; | 622 | int pidlen; |
| 594 | 623 | ||
| 595 | CHECK_STRING (prefix); | 624 | CHECK_STRING (prefix); |
| @@ -611,7 +640,7 @@ make_temp_name (Lisp_Object prefix, int base64_p) | |||
| 611 | else | 640 | else |
| 612 | { | 641 | { |
| 613 | #ifdef HAVE_LONG_FILE_NAMES | 642 | #ifdef HAVE_LONG_FILE_NAMES |
| 614 | pidlen = sprintf (pidbuf, "%"PRIdMAX, pid); | 643 | pidlen = sprintf (pidbuf, "%"pMd, pid); |
| 615 | #else | 644 | #else |
| 616 | pidbuf[0] = make_temp_name_tbl[pid & 63], pid >>= 6; | 645 | pidbuf[0] = make_temp_name_tbl[pid & 63], pid >>= 6; |
| 617 | pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6; | 646 | pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6; |
| @@ -744,7 +773,7 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 744 | int is_escaped = 0; | 773 | int is_escaped = 0; |
| 745 | #endif /* DOS_NT */ | 774 | #endif /* DOS_NT */ |
| 746 | ptrdiff_t length; | 775 | ptrdiff_t length; |
| 747 | Lisp_Object handler, result; | 776 | Lisp_Object handler, result, handled_name; |
| 748 | int multibyte; | 777 | int multibyte; |
| 749 | Lisp_Object hdir; | 778 | Lisp_Object hdir; |
| 750 | 779 | ||
| @@ -754,7 +783,14 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 754 | call the corresponding file handler. */ | 783 | call the corresponding file handler. */ |
| 755 | handler = Ffind_file_name_handler (name, Qexpand_file_name); | 784 | handler = Ffind_file_name_handler (name, Qexpand_file_name); |
| 756 | if (!NILP (handler)) | 785 | if (!NILP (handler)) |
| 757 | return call3 (handler, Qexpand_file_name, name, default_directory); | 786 | { |
| 787 | handled_name = call3 (handler, Qexpand_file_name, | ||
| 788 | name, default_directory); | ||
| 789 | if (STRINGP (handled_name)) | ||
| 790 | return handled_name; | ||
| 791 | error ("Invalid handler in `file-name-handler-alist'"); | ||
| 792 | } | ||
| 793 | |||
| 758 | 794 | ||
| 759 | /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */ | 795 | /* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */ |
| 760 | if (NILP (default_directory)) | 796 | if (NILP (default_directory)) |
| @@ -780,7 +816,13 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 780 | { | 816 | { |
| 781 | handler = Ffind_file_name_handler (default_directory, Qexpand_file_name); | 817 | handler = Ffind_file_name_handler (default_directory, Qexpand_file_name); |
| 782 | if (!NILP (handler)) | 818 | if (!NILP (handler)) |
| 783 | return call3 (handler, Qexpand_file_name, name, default_directory); | 819 | { |
| 820 | handled_name = call3 (handler, Qexpand_file_name, | ||
| 821 | name, default_directory); | ||
| 822 | if (STRINGP (handled_name)) | ||
| 823 | return handled_name; | ||
| 824 | error ("Invalid handler in `file-name-handler-alist'"); | ||
| 825 | } | ||
| 784 | } | 826 | } |
| 785 | 827 | ||
| 786 | { | 828 | { |
| @@ -1281,7 +1323,13 @@ filesystem tree, not (expand-file-name ".." dirname). */) | |||
| 1281 | to be expanded again. */ | 1323 | to be expanded again. */ |
| 1282 | handler = Ffind_file_name_handler (result, Qexpand_file_name); | 1324 | handler = Ffind_file_name_handler (result, Qexpand_file_name); |
| 1283 | if (!NILP (handler)) | 1325 | if (!NILP (handler)) |
| 1284 | return call3 (handler, Qexpand_file_name, result, default_directory); | 1326 | { |
| 1327 | handled_name = call3 (handler, Qexpand_file_name, | ||
| 1328 | result, default_directory); | ||
| 1329 | if (STRINGP (handled_name)) | ||
| 1330 | return handled_name; | ||
| 1331 | error ("Invalid handler in `file-name-handler-alist'"); | ||
| 1332 | } | ||
| 1285 | 1333 | ||
| 1286 | return result; | 1334 | return result; |
| 1287 | } | 1335 | } |
| @@ -1472,7 +1520,7 @@ search_embedded_absfilename (char *nm, char *endp) | |||
| 1472 | if ((0 | 1520 | if ((0 |
| 1473 | || IS_DIRECTORY_SEP (p[-1])) | 1521 | || IS_DIRECTORY_SEP (p[-1])) |
| 1474 | && file_name_absolute_p (p) | 1522 | && file_name_absolute_p (p) |
| 1475 | #if defined (WINDOWSNT) || defined(CYGWIN) | 1523 | #if defined (WINDOWSNT) || defined (CYGWIN) |
| 1476 | /* // at start of file name is meaningful in Apollo, | 1524 | /* // at start of file name is meaningful in Apollo, |
| 1477 | WindowsNT and Cygwin systems. */ | 1525 | WindowsNT and Cygwin systems. */ |
| 1478 | && !(IS_DIRECTORY_SEP (p[0]) && p - 1 == nm) | 1526 | && !(IS_DIRECTORY_SEP (p[0]) && p - 1 == nm) |
| @@ -1534,7 +1582,13 @@ those `/' is discarded. */) | |||
| 1534 | call the corresponding file handler. */ | 1582 | call the corresponding file handler. */ |
| 1535 | handler = Ffind_file_name_handler (filename, Qsubstitute_in_file_name); | 1583 | handler = Ffind_file_name_handler (filename, Qsubstitute_in_file_name); |
| 1536 | if (!NILP (handler)) | 1584 | if (!NILP (handler)) |
| 1537 | return call2 (handler, Qsubstitute_in_file_name, filename); | 1585 | { |
| 1586 | Lisp_Object handled_name = call2 (handler, Qsubstitute_in_file_name, | ||
| 1587 | filename); | ||
| 1588 | if (STRINGP (handled_name)) | ||
| 1589 | return handled_name; | ||
| 1590 | error ("Invalid handler in `file-name-handler-alist'"); | ||
| 1591 | } | ||
| 1538 | 1592 | ||
| 1539 | /* Always work on a copy of the string, in case GC happens during | 1593 | /* Always work on a copy of the string, in case GC happens during |
| 1540 | decode of environment variables, causing the original Lisp_String | 1594 | decode of environment variables, causing the original Lisp_String |
| @@ -1553,7 +1607,7 @@ those `/' is discarded. */) | |||
| 1553 | if (p) | 1607 | if (p) |
| 1554 | /* Start over with the new string, so we check the file-name-handler | 1608 | /* Start over with the new string, so we check the file-name-handler |
| 1555 | again. Important with filenames like "/home/foo//:/hello///there" | 1609 | again. Important with filenames like "/home/foo//:/hello///there" |
| 1556 | which whould substitute to "/:/hello///there" rather than "/there". */ | 1610 | which would substitute to "/:/hello///there" rather than "/there". */ |
| 1557 | return Fsubstitute_in_file_name | 1611 | return Fsubstitute_in_file_name |
| 1558 | (make_specified_string (p, -1, endp - p, multibyte)); | 1612 | (make_specified_string (p, -1, endp - p, multibyte)); |
| 1559 | 1613 | ||
| @@ -1937,10 +1991,19 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */) | |||
| 1937 | | (NILP (ok_if_already_exists) ? O_EXCL : 0), | 1991 | | (NILP (ok_if_already_exists) ? O_EXCL : 0), |
| 1938 | S_IREAD | S_IWRITE); | 1992 | S_IREAD | S_IWRITE); |
| 1939 | #else /* not MSDOS */ | 1993 | #else /* not MSDOS */ |
| 1940 | ofd = emacs_open (SSDATA (encoded_newname), | 1994 | { |
| 1941 | O_WRONLY | O_TRUNC | O_CREAT | 1995 | int new_mask = 0666; |
| 1942 | | (NILP (ok_if_already_exists) ? O_EXCL : 0), | 1996 | if (input_file_statable_p) |
| 1943 | 0666); | 1997 | { |
| 1998 | if (!NILP (preserve_uid_gid)) | ||
| 1999 | new_mask = 0600; | ||
| 2000 | new_mask &= st.st_mode; | ||
| 2001 | } | ||
| 2002 | ofd = emacs_open (SSDATA (encoded_newname), | ||
| 2003 | (O_WRONLY | O_TRUNC | O_CREAT | ||
| 2004 | | (NILP (ok_if_already_exists) ? O_EXCL : 0)), | ||
| 2005 | new_mask); | ||
| 2006 | } | ||
| 1944 | #endif /* not MSDOS */ | 2007 | #endif /* not MSDOS */ |
| 1945 | if (ofd < 0) | 2008 | if (ofd < 0) |
| 1946 | report_file_error ("Opening output file", Fcons (newname, Qnil)); | 2009 | report_file_error ("Opening output file", Fcons (newname, Qnil)); |
| @@ -1959,9 +2022,21 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */) | |||
| 1959 | owner and group. */ | 2022 | owner and group. */ |
| 1960 | if (input_file_statable_p) | 2023 | if (input_file_statable_p) |
| 1961 | { | 2024 | { |
| 1962 | if (!NILP (preserve_uid_gid) && fchown (ofd, st.st_uid, st.st_gid) != 0) | 2025 | int mode_mask = 07777; |
| 1963 | report_file_error ("Doing chown", Fcons (newname, Qnil)); | 2026 | if (!NILP (preserve_uid_gid)) |
| 1964 | if (fchmod (ofd, st.st_mode & 07777) != 0) | 2027 | { |
| 2028 | /* Attempt to change owner and group. If that doesn't work | ||
| 2029 | attempt to change just the group, as that is sometimes allowed. | ||
| 2030 | Adjust the mode mask to eliminate setuid or setgid bits | ||
| 2031 | that are inappropriate if the owner and group are wrong. */ | ||
| 2032 | if (fchown (ofd, st.st_uid, st.st_gid) != 0) | ||
| 2033 | { | ||
| 2034 | mode_mask &= ~06000; | ||
| 2035 | if (fchown (ofd, -1, st.st_gid) == 0) | ||
| 2036 | mode_mask |= 02000; | ||
| 2037 | } | ||
| 2038 | } | ||
| 2039 | if (fchmod (ofd, st.st_mode & mode_mask) != 0) | ||
| 1965 | report_file_error ("Doing chmod", Fcons (newname, Qnil)); | 2040 | report_file_error ("Doing chmod", Fcons (newname, Qnil)); |
| 1966 | } | 2041 | } |
| 1967 | #endif /* not MSDOS */ | 2042 | #endif /* not MSDOS */ |
| @@ -2041,7 +2116,7 @@ DEFUN ("make-directory-internal", Fmake_directory_internal, | |||
| 2041 | #ifdef WINDOWSNT | 2116 | #ifdef WINDOWSNT |
| 2042 | if (mkdir (dir) != 0) | 2117 | if (mkdir (dir) != 0) |
| 2043 | #else | 2118 | #else |
| 2044 | if (mkdir (dir, 0777) != 0) | 2119 | if (mkdir (dir, 0777 & ~auto_saving_dir_umask) != 0) |
| 2045 | #endif | 2120 | #endif |
| 2046 | report_file_error ("Creating directory", list1 (directory)); | 2121 | report_file_error ("Creating directory", list1 (directory)); |
| 2047 | 2122 | ||
| @@ -2395,15 +2470,27 @@ check_writable (const char *filename) | |||
| 2395 | return (st.st_mode & S_IWRITE || S_ISDIR (st.st_mode)); | 2470 | return (st.st_mode & S_IWRITE || S_ISDIR (st.st_mode)); |
| 2396 | #else /* not MSDOS */ | 2471 | #else /* not MSDOS */ |
| 2397 | #ifdef HAVE_EUIDACCESS | 2472 | #ifdef HAVE_EUIDACCESS |
| 2398 | return (euidaccess (filename, 2) >= 0); | 2473 | int res = (euidaccess (filename, 2) >= 0); |
| 2399 | #else | 2474 | #ifdef CYGWIN |
| 2475 | /* euidaccess may have returned failure because Cygwin couldn't | ||
| 2476 | determine the file's UID or GID; if so, we return success. */ | ||
| 2477 | if (!res) | ||
| 2478 | { | ||
| 2479 | struct stat st; | ||
| 2480 | if (stat (filename, &st) < 0) | ||
| 2481 | return 0; | ||
| 2482 | res = (st.st_uid == -1 || st.st_gid == -1); | ||
| 2483 | } | ||
| 2484 | #endif /* CYGWIN */ | ||
| 2485 | return res; | ||
| 2486 | #else /* not HAVE_EUIDACCESS */ | ||
| 2400 | /* Access isn't quite right because it uses the real uid | 2487 | /* Access isn't quite right because it uses the real uid |
| 2401 | and we really want to test with the effective uid. | 2488 | and we really want to test with the effective uid. |
| 2402 | But Unix doesn't give us a right way to do it. | 2489 | But Unix doesn't give us a right way to do it. |
| 2403 | Opening with O_WRONLY could work for an ordinary file, | 2490 | Opening with O_WRONLY could work for an ordinary file, |
| 2404 | but would lose for directories. */ | 2491 | but would lose for directories. */ |
| 2405 | return (access (filename, 2) >= 0); | 2492 | return (access (filename, 2) >= 0); |
| 2406 | #endif | 2493 | #endif /* not HAVE_EUIDACCESS */ |
| 2407 | #endif /* not MSDOS */ | 2494 | #endif /* not MSDOS */ |
| 2408 | } | 2495 | } |
| 2409 | 2496 | ||
| @@ -2476,7 +2563,7 @@ See also `file-exists-p' and `file-attributes'. */) | |||
| 2476 | 2563 | ||
| 2477 | absname = ENCODE_FILE (absname); | 2564 | absname = ENCODE_FILE (absname); |
| 2478 | 2565 | ||
| 2479 | #if defined(DOS_NT) || defined(macintosh) | 2566 | #if defined (DOS_NT) || defined (macintosh) |
| 2480 | /* Under MS-DOS, Windows, and Macintosh, open does not work for | 2567 | /* Under MS-DOS, Windows, and Macintosh, open does not work for |
| 2481 | directories. */ | 2568 | directories. */ |
| 2482 | if (access (SDATA (absname), 0) == 0) | 2569 | if (access (SDATA (absname), 0) == 0) |
| @@ -2711,9 +2798,13 @@ See `file-symlink-p' to distinguish symlinks. */) | |||
| 2711 | 2798 | ||
| 2712 | DEFUN ("file-selinux-context", Ffile_selinux_context, | 2799 | DEFUN ("file-selinux-context", Ffile_selinux_context, |
| 2713 | Sfile_selinux_context, 1, 1, 0, | 2800 | Sfile_selinux_context, 1, 1, 0, |
| 2714 | doc: /* Return SELinux context of file named FILENAME, | 2801 | doc: /* Return SELinux context of file named FILENAME. |
| 2715 | as a list ("user", "role", "type", "range"). Return (nil, nil, nil, nil) | 2802 | The return value is a list (USER ROLE TYPE RANGE), where the list |
| 2716 | if file does not exist, is not accessible, or SELinux is disabled */) | 2803 | elements are strings naming the user, role, type, and range of the |
| 2804 | file's SELinux security context. | ||
| 2805 | |||
| 2806 | Return (nil nil nil nil) if the file is nonexistent or inaccessible, | ||
| 2807 | or if SELinux is disabled, or if Emacs lacks SELinux support. */) | ||
| 2717 | (Lisp_Object filename) | 2808 | (Lisp_Object filename) |
| 2718 | { | 2809 | { |
| 2719 | Lisp_Object absname; | 2810 | Lisp_Object absname; |
| @@ -2761,14 +2852,17 @@ if file does not exist, is not accessible, or SELinux is disabled */) | |||
| 2761 | } | 2852 | } |
| 2762 | #endif | 2853 | #endif |
| 2763 | 2854 | ||
| 2764 | return Flist (sizeof(values) / sizeof(values[0]), values); | 2855 | return Flist (sizeof (values) / sizeof (values[0]), values); |
| 2765 | } | 2856 | } |
| 2766 | 2857 | ||
| 2767 | DEFUN ("set-file-selinux-context", Fset_file_selinux_context, | 2858 | DEFUN ("set-file-selinux-context", Fset_file_selinux_context, |
| 2768 | Sset_file_selinux_context, 2, 2, 0, | 2859 | Sset_file_selinux_context, 2, 2, 0, |
| 2769 | doc: /* Set SELinux context of file named FILENAME to CONTEXT | 2860 | doc: /* Set SELinux context of file named FILENAME to CONTEXT. |
| 2770 | as a list ("user", "role", "type", "range"). Has no effect if SELinux | 2861 | CONTEXT should be a list (USER ROLE TYPE RANGE), where the list |
| 2771 | is disabled. */) | 2862 | elements are strings naming the components of a SELinux context. |
| 2863 | |||
| 2864 | This function does nothing if SELinux is disabled, or if Emacs was not | ||
| 2865 | compiled with SELinux support. */) | ||
| 2772 | (Lisp_Object filename, Lisp_Object context) | 2866 | (Lisp_Object filename, Lisp_Object context) |
| 2773 | { | 2867 | { |
| 2774 | Lisp_Object absname; | 2868 | Lisp_Object absname; |
| @@ -2832,7 +2926,7 @@ is disabled. */) | |||
| 2832 | context_free (parsed_con); | 2926 | context_free (parsed_con); |
| 2833 | } | 2927 | } |
| 2834 | else | 2928 | else |
| 2835 | report_file_error("Doing lgetfilecon", Fcons (absname, Qnil)); | 2929 | report_file_error ("Doing lgetfilecon", Fcons (absname, Qnil)); |
| 2836 | 2930 | ||
| 2837 | if (con) | 2931 | if (con) |
| 2838 | freecon (con); | 2932 | freecon (con); |
| @@ -2891,7 +2985,7 @@ symbolic notation, like the `chmod' command from GNU Coreutils. */) | |||
| 2891 | 2985 | ||
| 2892 | encoded_absname = ENCODE_FILE (absname); | 2986 | encoded_absname = ENCODE_FILE (absname); |
| 2893 | 2987 | ||
| 2894 | if (chmod (SSDATA (encoded_absname), XINT (mode)) < 0) | 2988 | if (chmod (SSDATA (encoded_absname), XINT (mode) & 07777) < 0) |
| 2895 | report_file_error ("Doing chmod", Fcons (absname, Qnil)); | 2989 | report_file_error ("Doing chmod", Fcons (absname, Qnil)); |
| 2896 | 2990 | ||
| 2897 | return Qnil; | 2991 | return Qnil; |
| @@ -3158,6 +3252,7 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 3158 | EMACS_INT inserted = 0; | 3252 | EMACS_INT inserted = 0; |
| 3159 | int nochange = 0; | 3253 | int nochange = 0; |
| 3160 | register EMACS_INT how_much; | 3254 | register EMACS_INT how_much; |
| 3255 | off_t beg_offset, end_offset; | ||
| 3161 | register EMACS_INT unprocessed; | 3256 | register EMACS_INT unprocessed; |
| 3162 | int count = SPECPDL_INDEX (); | 3257 | int count = SPECPDL_INDEX (); |
| 3163 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; | 3258 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; |
| @@ -3165,6 +3260,7 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 3165 | Lisp_Object p; | 3260 | Lisp_Object p; |
| 3166 | EMACS_INT total = 0; | 3261 | EMACS_INT total = 0; |
| 3167 | int not_regular = 0; | 3262 | int not_regular = 0; |
| 3263 | int save_errno = 0; | ||
| 3168 | char read_buf[READ_BUF_SIZE]; | 3264 | char read_buf[READ_BUF_SIZE]; |
| 3169 | struct coding_system coding; | 3265 | struct coding_system coding; |
| 3170 | char buffer[1 << 14]; | 3266 | char buffer[1 << 14]; |
| @@ -3228,9 +3324,11 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 3228 | #endif /* WINDOWSNT */ | 3324 | #endif /* WINDOWSNT */ |
| 3229 | { | 3325 | { |
| 3230 | badopen: | 3326 | badopen: |
| 3327 | save_errno = errno; | ||
| 3231 | if (NILP (visit)) | 3328 | if (NILP (visit)) |
| 3232 | report_file_error ("Opening input file", Fcons (orig_filename, Qnil)); | 3329 | report_file_error ("Opening input file", Fcons (orig_filename, Qnil)); |
| 3233 | st.st_mtime = -1; | 3330 | st.st_mtime = -1; |
| 3331 | st.st_size = -1; | ||
| 3234 | how_much = 0; | 3332 | how_much = 0; |
| 3235 | if (!NILP (Vcoding_system_for_read)) | 3333 | if (!NILP (Vcoding_system_for_read)) |
| 3236 | Fset (Qbuffer_file_coding_system, Vcoding_system_for_read); | 3334 | Fset (Qbuffer_file_coding_system, Vcoding_system_for_read); |
| @@ -3263,15 +3361,6 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 3263 | record_unwind_protect (close_file_unwind, make_number (fd)); | 3361 | record_unwind_protect (close_file_unwind, make_number (fd)); |
| 3264 | 3362 | ||
| 3265 | 3363 | ||
| 3266 | /* Check whether the size is too large or negative, which can happen on a | ||
| 3267 | platform that allows file sizes greater than the maximum off_t value. */ | ||
| 3268 | if (! not_regular | ||
| 3269 | && ! (0 <= st.st_size && st.st_size <= BUF_BYTES_MAX)) | ||
| 3270 | buffer_overflow (); | ||
| 3271 | |||
| 3272 | /* Prevent redisplay optimizations. */ | ||
| 3273 | current_buffer->clip_changed = 1; | ||
| 3274 | |||
| 3275 | if (!NILP (visit)) | 3364 | if (!NILP (visit)) |
| 3276 | { | 3365 | { |
| 3277 | if (!NILP (beg) || !NILP (end)) | 3366 | if (!NILP (beg) || !NILP (end)) |
| @@ -3281,26 +3370,64 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 3281 | } | 3370 | } |
| 3282 | 3371 | ||
| 3283 | if (!NILP (beg)) | 3372 | if (!NILP (beg)) |
| 3284 | CHECK_NUMBER (beg); | 3373 | { |
| 3374 | if (! (RANGED_INTEGERP (0, beg, TYPE_MAXIMUM (off_t)))) | ||
| 3375 | wrong_type_argument (intern ("file-offset"), beg); | ||
| 3376 | beg_offset = XFASTINT (beg); | ||
| 3377 | } | ||
| 3285 | else | 3378 | else |
| 3286 | XSETFASTINT (beg, 0); | 3379 | beg_offset = 0; |
| 3287 | 3380 | ||
| 3288 | if (!NILP (end)) | 3381 | if (!NILP (end)) |
| 3289 | CHECK_NUMBER (end); | 3382 | { |
| 3383 | if (! (RANGED_INTEGERP (0, end, TYPE_MAXIMUM (off_t)))) | ||
| 3384 | wrong_type_argument (intern ("file-offset"), end); | ||
| 3385 | end_offset = XFASTINT (end); | ||
| 3386 | } | ||
| 3290 | else | 3387 | else |
| 3291 | { | 3388 | { |
| 3292 | if (! not_regular) | 3389 | if (not_regular) |
| 3390 | end_offset = TYPE_MAXIMUM (off_t); | ||
| 3391 | else | ||
| 3293 | { | 3392 | { |
| 3294 | XSETINT (end, st.st_size); | 3393 | end_offset = st.st_size; |
| 3394 | |||
| 3395 | /* A negative size can happen on a platform that allows file | ||
| 3396 | sizes greater than the maximum off_t value. */ | ||
| 3397 | if (end_offset < 0) | ||
| 3398 | buffer_overflow (); | ||
| 3295 | 3399 | ||
| 3296 | /* The file size returned from stat may be zero, but data | 3400 | /* The file size returned from stat may be zero, but data |
| 3297 | may be readable nonetheless, for example when this is a | 3401 | may be readable nonetheless, for example when this is a |
| 3298 | file in the /proc filesystem. */ | 3402 | file in the /proc filesystem. */ |
| 3299 | if (st.st_size == 0) | 3403 | if (end_offset == 0) |
| 3300 | XSETINT (end, READ_BUF_SIZE); | 3404 | end_offset = READ_BUF_SIZE; |
| 3301 | } | 3405 | } |
| 3302 | } | 3406 | } |
| 3303 | 3407 | ||
| 3408 | /* Check now whether the buffer will become too large, | ||
| 3409 | in the likely case where the file's length is not changing. | ||
| 3410 | This saves a lot of needless work before a buffer overflow. */ | ||
| 3411 | if (! not_regular) | ||
| 3412 | { | ||
| 3413 | /* The likely offset where we will stop reading. We could read | ||
| 3414 | more (or less), if the file grows (or shrinks) as we read it. */ | ||
| 3415 | off_t likely_end = min (end_offset, st.st_size); | ||
| 3416 | |||
| 3417 | if (beg_offset < likely_end) | ||
| 3418 | { | ||
| 3419 | ptrdiff_t buf_bytes = | ||
| 3420 | Z_BYTE - (!NILP (replace) ? ZV_BYTE - BEGV_BYTE : 0); | ||
| 3421 | ptrdiff_t buf_growth_max = BUF_BYTES_MAX - buf_bytes; | ||
| 3422 | off_t likely_growth = likely_end - beg_offset; | ||
| 3423 | if (buf_growth_max < likely_growth) | ||
| 3424 | buffer_overflow (); | ||
| 3425 | } | ||
| 3426 | } | ||
| 3427 | |||
| 3428 | /* Prevent redisplay optimizations. */ | ||
| 3429 | current_buffer->clip_changed = 1; | ||
| 3430 | |||
| 3304 | if (EQ (Vcoding_system_for_read, Qauto_save_coding)) | 3431 | if (EQ (Vcoding_system_for_read, Qauto_save_coding)) |
| 3305 | { | 3432 | { |
| 3306 | coding_system = coding_inherit_eol_type (Qutf_8_emacs, Qunix); | 3433 | coding_system = coding_inherit_eol_type (Qutf_8_emacs, Qunix); |
| @@ -3444,9 +3571,9 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 3444 | give up on handling REPLACE in the optimized way. */ | 3571 | give up on handling REPLACE in the optimized way. */ |
| 3445 | int giveup_match_end = 0; | 3572 | int giveup_match_end = 0; |
| 3446 | 3573 | ||
| 3447 | if (XINT (beg) != 0) | 3574 | if (beg_offset != 0) |
| 3448 | { | 3575 | { |
| 3449 | if (emacs_lseek (fd, XINT (beg), SEEK_SET) < 0) | 3576 | if (lseek (fd, beg_offset, SEEK_SET) < 0) |
| 3450 | report_file_error ("Setting file position", | 3577 | report_file_error ("Setting file position", |
| 3451 | Fcons (orig_filename, Qnil)); | 3578 | Fcons (orig_filename, Qnil)); |
| 3452 | } | 3579 | } |
| @@ -3494,7 +3621,7 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 3494 | immediate_quit = 0; | 3621 | immediate_quit = 0; |
| 3495 | /* If the file matches the buffer completely, | 3622 | /* If the file matches the buffer completely, |
| 3496 | there's no need to replace anything. */ | 3623 | there's no need to replace anything. */ |
| 3497 | if (same_at_start - BEGV_BYTE == XINT (end)) | 3624 | if (same_at_start - BEGV_BYTE == end_offset - beg_offset) |
| 3498 | { | 3625 | { |
| 3499 | emacs_close (fd); | 3626 | emacs_close (fd); |
| 3500 | specpdl_ptr--; | 3627 | specpdl_ptr--; |
| @@ -3509,16 +3636,17 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 3509 | already found that decoding is necessary, don't waste time. */ | 3636 | already found that decoding is necessary, don't waste time. */ |
| 3510 | while (!giveup_match_end) | 3637 | while (!giveup_match_end) |
| 3511 | { | 3638 | { |
| 3512 | EMACS_INT total_read, nread, bufpos, curpos, trial; | 3639 | int total_read, nread, bufpos, trial; |
| 3640 | off_t curpos; | ||
| 3513 | 3641 | ||
| 3514 | /* At what file position are we now scanning? */ | 3642 | /* At what file position are we now scanning? */ |
| 3515 | curpos = XINT (end) - (ZV_BYTE - same_at_end); | 3643 | curpos = end_offset - (ZV_BYTE - same_at_end); |
| 3516 | /* If the entire file matches the buffer tail, stop the scan. */ | 3644 | /* If the entire file matches the buffer tail, stop the scan. */ |
| 3517 | if (curpos == 0) | 3645 | if (curpos == 0) |
| 3518 | break; | 3646 | break; |
| 3519 | /* How much can we scan in the next step? */ | 3647 | /* How much can we scan in the next step? */ |
| 3520 | trial = min (curpos, sizeof buffer); | 3648 | trial = min (curpos, sizeof buffer); |
| 3521 | if (emacs_lseek (fd, curpos - trial, SEEK_SET) < 0) | 3649 | if (lseek (fd, curpos - trial, SEEK_SET) < 0) |
| 3522 | report_file_error ("Setting file position", | 3650 | report_file_error ("Setting file position", |
| 3523 | Fcons (orig_filename, Qnil)); | 3651 | Fcons (orig_filename, Qnil)); |
| 3524 | 3652 | ||
| @@ -3585,13 +3713,14 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 3585 | 3713 | ||
| 3586 | /* Don't try to reuse the same piece of text twice. */ | 3714 | /* Don't try to reuse the same piece of text twice. */ |
| 3587 | overlap = (same_at_start - BEGV_BYTE | 3715 | overlap = (same_at_start - BEGV_BYTE |
| 3588 | - (same_at_end + st.st_size - ZV)); | 3716 | - (same_at_end |
| 3717 | + (! NILP (end) ? end_offset : st.st_size) - ZV_BYTE)); | ||
| 3589 | if (overlap > 0) | 3718 | if (overlap > 0) |
| 3590 | same_at_end += overlap; | 3719 | same_at_end += overlap; |
| 3591 | 3720 | ||
| 3592 | /* Arrange to read only the nonmatching middle part of the file. */ | 3721 | /* Arrange to read only the nonmatching middle part of the file. */ |
| 3593 | XSETFASTINT (beg, XINT (beg) + (same_at_start - BEGV_BYTE)); | 3722 | beg_offset += same_at_start - BEGV_BYTE; |
| 3594 | XSETFASTINT (end, XINT (end) - (ZV_BYTE - same_at_end)); | 3723 | end_offset -= ZV_BYTE - same_at_end; |
| 3595 | 3724 | ||
| 3596 | del_range_byte (same_at_start, same_at_end, 0); | 3725 | del_range_byte (same_at_start, same_at_end, 0); |
| 3597 | /* Insert from the file at the proper position. */ | 3726 | /* Insert from the file at the proper position. */ |
| @@ -3630,13 +3759,14 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 3630 | int this_count = SPECPDL_INDEX (); | 3759 | int this_count = SPECPDL_INDEX (); |
| 3631 | int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); | 3760 | int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); |
| 3632 | Lisp_Object conversion_buffer; | 3761 | Lisp_Object conversion_buffer; |
| 3762 | struct gcpro gcpro1; | ||
| 3633 | 3763 | ||
| 3634 | conversion_buffer = code_conversion_save (1, multibyte); | 3764 | conversion_buffer = code_conversion_save (1, multibyte); |
| 3635 | 3765 | ||
| 3636 | /* First read the whole file, performing code conversion into | 3766 | /* First read the whole file, performing code conversion into |
| 3637 | CONVERSION_BUFFER. */ | 3767 | CONVERSION_BUFFER. */ |
| 3638 | 3768 | ||
| 3639 | if (emacs_lseek (fd, XINT (beg), SEEK_SET) < 0) | 3769 | if (lseek (fd, beg_offset, SEEK_SET) < 0) |
| 3640 | report_file_error ("Setting file position", | 3770 | report_file_error ("Setting file position", |
| 3641 | Fcons (orig_filename, Qnil)); | 3771 | Fcons (orig_filename, Qnil)); |
| 3642 | 3772 | ||
| @@ -3650,7 +3780,7 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 3650 | { | 3780 | { |
| 3651 | /* We read one bunch by one (READ_BUF_SIZE bytes) to allow | 3781 | /* We read one bunch by one (READ_BUF_SIZE bytes) to allow |
| 3652 | quitting while reading a huge while. */ | 3782 | quitting while reading a huge while. */ |
| 3653 | /* try is reserved in some compilers (Microsoft C) */ | 3783 | /* `try'' is reserved in some compilers (Microsoft C). */ |
| 3654 | EMACS_INT trytry = min (total - how_much, | 3784 | EMACS_INT trytry = min (total - how_much, |
| 3655 | READ_BUF_SIZE - unprocessed); | 3785 | READ_BUF_SIZE - unprocessed); |
| 3656 | 3786 | ||
| @@ -3803,7 +3933,7 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 3803 | } | 3933 | } |
| 3804 | 3934 | ||
| 3805 | if (! not_regular) | 3935 | if (! not_regular) |
| 3806 | total = XINT (end) - XINT (beg); | 3936 | total = end_offset - beg_offset; |
| 3807 | else | 3937 | else |
| 3808 | /* For a special file, all we can do is guess. */ | 3938 | /* For a special file, all we can do is guess. */ |
| 3809 | total = READ_BUF_SIZE; | 3939 | total = READ_BUF_SIZE; |
| @@ -3824,9 +3954,9 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 3824 | if (GAP_SIZE < total) | 3954 | if (GAP_SIZE < total) |
| 3825 | make_gap (total - GAP_SIZE); | 3955 | make_gap (total - GAP_SIZE); |
| 3826 | 3956 | ||
| 3827 | if (XINT (beg) != 0 || !NILP (replace)) | 3957 | if (beg_offset != 0 || !NILP (replace)) |
| 3828 | { | 3958 | { |
| 3829 | if (emacs_lseek (fd, XINT (beg), SEEK_SET) < 0) | 3959 | if (lseek (fd, beg_offset, SEEK_SET) < 0) |
| 3830 | report_file_error ("Setting file position", | 3960 | report_file_error ("Setting file position", |
| 3831 | Fcons (orig_filename, Qnil)); | 3961 | Fcons (orig_filename, Qnil)); |
| 3832 | } | 3962 | } |
| @@ -4043,6 +4173,16 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 4043 | adjust_after_insert (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted, | 4173 | adjust_after_insert (PT, PT_BYTE, PT + inserted, PT_BYTE + inserted, |
| 4044 | inserted); | 4174 | inserted); |
| 4045 | 4175 | ||
| 4176 | /* Call after-change hooks for the inserted text, aside from the case | ||
| 4177 | of normal visiting (not with REPLACE), which is done in a new buffer | ||
| 4178 | "before" the buffer is changed. */ | ||
| 4179 | if (inserted > 0 && total > 0 | ||
| 4180 | && (NILP (visit) || !NILP (replace))) | ||
| 4181 | { | ||
| 4182 | signal_after_change (PT, 0, inserted); | ||
| 4183 | update_compositions (PT, PT, CHECK_BORDER); | ||
| 4184 | } | ||
| 4185 | |||
| 4046 | /* Now INSERTED is measured in characters. */ | 4186 | /* Now INSERTED is measured in characters. */ |
| 4047 | 4187 | ||
| 4048 | handled: | 4188 | handled: |
| @@ -4119,7 +4259,7 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 4119 | /* If REPLACE is non-nil and we succeeded in not replacing the | 4259 | /* If REPLACE is non-nil and we succeeded in not replacing the |
| 4120 | beginning or end of the buffer text with the file's contents, | 4260 | beginning or end of the buffer text with the file's contents, |
| 4121 | call format-decode with `point' positioned at the beginning | 4261 | call format-decode with `point' positioned at the beginning |
| 4122 | of the buffer and `inserted' equalling the number of | 4262 | of the buffer and `inserted' equaling the number of |
| 4123 | characters in the buffer. Otherwise, format-decode might | 4263 | characters in the buffer. Otherwise, format-decode might |
| 4124 | fail to correctly analyze the beginning or end of the buffer. | 4264 | fail to correctly analyze the beginning or end of the buffer. |
| 4125 | Hence we temporarily save `point' and `inserted' here and | 4265 | Hence we temporarily save `point' and `inserted' here and |
| @@ -4213,20 +4353,11 @@ variable `last-coding-system-used' to the coding system actually used. */) | |||
| 4213 | unbind_to (count1, Qnil); | 4353 | unbind_to (count1, Qnil); |
| 4214 | } | 4354 | } |
| 4215 | 4355 | ||
| 4216 | /* Call after-change hooks for the inserted text, aside from the case | ||
| 4217 | of normal visiting (not with REPLACE), which is done in a new buffer | ||
| 4218 | "before" the buffer is changed. */ | ||
| 4219 | if (inserted > 0 && total > 0 | ||
| 4220 | && (NILP (visit) || !NILP (replace))) | ||
| 4221 | { | ||
| 4222 | signal_after_change (PT, 0, inserted); | ||
| 4223 | update_compositions (PT, PT, CHECK_BORDER); | ||
| 4224 | } | ||
| 4225 | |||
| 4226 | if (!NILP (visit) | 4356 | if (!NILP (visit) |
| 4227 | && current_buffer->modtime == -1) | 4357 | && current_buffer->modtime == -1) |
| 4228 | { | 4358 | { |
| 4229 | /* If visiting nonexistent file, return nil. */ | 4359 | /* If visiting nonexistent file, return nil. */ |
| 4360 | errno = save_errno; | ||
| 4230 | report_file_error ("Opening input file", Fcons (orig_filename, Qnil)); | 4361 | report_file_error ("Opening input file", Fcons (orig_filename, Qnil)); |
| 4231 | } | 4362 | } |
| 4232 | 4363 | ||
| @@ -4555,7 +4686,7 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 4555 | 4686 | ||
| 4556 | if (!NILP (append) && !NILP (Ffile_regular_p (filename))) | 4687 | if (!NILP (append) && !NILP (Ffile_regular_p (filename))) |
| 4557 | { | 4688 | { |
| 4558 | long ret; | 4689 | off_t ret; |
| 4559 | 4690 | ||
| 4560 | if (NUMBERP (append)) | 4691 | if (NUMBERP (append)) |
| 4561 | ret = emacs_lseek (desc, XINT (append), SEEK_CUR); | 4692 | ret = emacs_lseek (desc, XINT (append), SEEK_CUR); |
| @@ -4564,7 +4695,9 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 4564 | if (ret < 0) | 4695 | if (ret < 0) |
| 4565 | { | 4696 | { |
| 4566 | #ifdef CLASH_DETECTION | 4697 | #ifdef CLASH_DETECTION |
| 4698 | save_errno = errno; | ||
| 4567 | if (!auto_saving) unlock_file (lockname); | 4699 | if (!auto_saving) unlock_file (lockname); |
| 4700 | errno = save_errno; | ||
| 4568 | #endif /* CLASH_DETECTION */ | 4701 | #endif /* CLASH_DETECTION */ |
| 4569 | UNGCPRO; | 4702 | UNGCPRO; |
| 4570 | report_file_error ("Lseek error", Fcons (filename, Qnil)); | 4703 | report_file_error ("Lseek error", Fcons (filename, Qnil)); |
| @@ -4991,9 +5124,10 @@ Next attempt to save will certainly not complain of a discrepancy. */) | |||
| 4991 | DEFUN ("visited-file-modtime", Fvisited_file_modtime, | 5124 | DEFUN ("visited-file-modtime", Fvisited_file_modtime, |
| 4992 | Svisited_file_modtime, 0, 0, 0, | 5125 | Svisited_file_modtime, 0, 0, 0, |
| 4993 | doc: /* Return the current buffer's recorded visited file modification time. | 5126 | doc: /* Return the current buffer's recorded visited file modification time. |
| 4994 | The value is a list of the form (HIGH LOW), like the time values | 5127 | The value is a list of the form (HIGH LOW), like the time values that |
| 4995 | that `file-attributes' returns. If the current buffer has no recorded | 5128 | `file-attributes' returns. If the current buffer has no recorded file |
| 4996 | file modification time, this function returns 0. | 5129 | modification time, this function returns 0. If the visited file |
| 5130 | doesn't exist, HIGH will be -1. | ||
| 4997 | See Info node `(elisp)Modification Time' for more details. */) | 5131 | See Info node `(elisp)Modification Time' for more details. */) |
| 4998 | (void) | 5132 | (void) |
| 4999 | { | 5133 | { |
| @@ -5093,11 +5227,11 @@ auto_save_1 (void) | |||
| 5093 | { | 5227 | { |
| 5094 | if (stat (SSDATA (BVAR (current_buffer, filename)), &st) >= 0) | 5228 | if (stat (SSDATA (BVAR (current_buffer, filename)), &st) >= 0) |
| 5095 | /* But make sure we can overwrite it later! */ | 5229 | /* But make sure we can overwrite it later! */ |
| 5096 | auto_save_mode_bits = st.st_mode | 0600; | 5230 | auto_save_mode_bits = (st.st_mode | 0600) & 0777; |
| 5097 | else if ((modes = Ffile_modes (BVAR (current_buffer, filename)), | 5231 | else if ((modes = Ffile_modes (BVAR (current_buffer, filename)), |
| 5098 | INTEGERP (modes))) | 5232 | INTEGERP (modes))) |
| 5099 | /* Remote files don't cooperate with stat. */ | 5233 | /* Remote files don't cooperate with stat. */ |
| 5100 | auto_save_mode_bits = XINT (modes) | 0600; | 5234 | auto_save_mode_bits = (XINT (modes) | 0600) & 0777; |
| 5101 | } | 5235 | } |
| 5102 | 5236 | ||
| 5103 | return | 5237 | return |
| @@ -5132,16 +5266,18 @@ do_auto_save_unwind_1 (Lisp_Object value) /* used as unwind-protect function */ | |||
| 5132 | static Lisp_Object | 5266 | static Lisp_Object |
| 5133 | do_auto_save_make_dir (Lisp_Object dir) | 5267 | do_auto_save_make_dir (Lisp_Object dir) |
| 5134 | { | 5268 | { |
| 5135 | Lisp_Object mode; | 5269 | Lisp_Object result; |
| 5136 | 5270 | ||
| 5137 | call2 (Qmake_directory, dir, Qt); | 5271 | auto_saving_dir_umask = 077; |
| 5138 | XSETFASTINT (mode, 0700); | 5272 | result = call2 (Qmake_directory, dir, Qt); |
| 5139 | return Fset_file_modes (dir, mode); | 5273 | auto_saving_dir_umask = 0; |
| 5274 | return result; | ||
| 5140 | } | 5275 | } |
| 5141 | 5276 | ||
| 5142 | static Lisp_Object | 5277 | static Lisp_Object |
| 5143 | do_auto_save_eh (Lisp_Object ignore) | 5278 | do_auto_save_eh (Lisp_Object ignore) |
| 5144 | { | 5279 | { |
| 5280 | auto_saving_dir_umask = 0; | ||
| 5145 | return Qnil; | 5281 | return Qnil; |
| 5146 | } | 5282 | } |
| 5147 | 5283 | ||
| @@ -5209,7 +5345,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */) | |||
| 5209 | dir = Ffile_name_directory (listfile); | 5345 | dir = Ffile_name_directory (listfile); |
| 5210 | if (NILP (Ffile_directory_p (dir))) | 5346 | if (NILP (Ffile_directory_p (dir))) |
| 5211 | internal_condition_case_1 (do_auto_save_make_dir, | 5347 | internal_condition_case_1 (do_auto_save_make_dir, |
| 5212 | dir, Fcons (Fcons (Qfile_error, Qnil), Qnil), | 5348 | dir, Qt, |
| 5213 | do_auto_save_eh); | 5349 | do_auto_save_eh); |
| 5214 | UNGCPRO; | 5350 | UNGCPRO; |
| 5215 | } | 5351 | } |
| @@ -5284,7 +5420,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */) | |||
| 5284 | EMACS_GET_TIME (before_time); | 5420 | EMACS_GET_TIME (before_time); |
| 5285 | 5421 | ||
| 5286 | /* If we had a failure, don't try again for 20 minutes. */ | 5422 | /* If we had a failure, don't try again for 20 minutes. */ |
| 5287 | if (b->auto_save_failure_time >= 0 | 5423 | if (b->auto_save_failure_time > 0 |
| 5288 | && EMACS_SECS (before_time) - b->auto_save_failure_time < 1200) | 5424 | && EMACS_SECS (before_time) - b->auto_save_failure_time < 1200) |
| 5289 | continue; | 5425 | continue; |
| 5290 | 5426 | ||
| @@ -5363,7 +5499,7 @@ No auto-save file will be written until the buffer changes again. */) | |||
| 5363 | they're not autosaved. */ | 5499 | they're not autosaved. */ |
| 5364 | BUF_AUTOSAVE_MODIFF (current_buffer) = MODIFF; | 5500 | BUF_AUTOSAVE_MODIFF (current_buffer) = MODIFF; |
| 5365 | XSETFASTINT (BVAR (current_buffer, save_length), Z - BEG); | 5501 | XSETFASTINT (BVAR (current_buffer, save_length), Z - BEG); |
| 5366 | current_buffer->auto_save_failure_time = -1; | 5502 | current_buffer->auto_save_failure_time = 0; |
| 5367 | return Qnil; | 5503 | return Qnil; |
| 5368 | } | 5504 | } |
| 5369 | 5505 | ||
| @@ -5372,7 +5508,7 @@ DEFUN ("clear-buffer-auto-save-failure", Fclear_buffer_auto_save_failure, | |||
| 5372 | doc: /* Clear any record of a recent auto-save failure in the current buffer. */) | 5508 | doc: /* Clear any record of a recent auto-save failure in the current buffer. */) |
| 5373 | (void) | 5509 | (void) |
| 5374 | { | 5510 | { |
| 5375 | current_buffer->auto_save_failure_time = -1; | 5511 | current_buffer->auto_save_failure_time = 0; |
| 5376 | return Qnil; | 5512 | return Qnil; |
| 5377 | } | 5513 | } |
| 5378 | 5514 | ||
| @@ -5511,18 +5647,25 @@ of file names regardless of the current language environment. */); | |||
| 5511 | make_pure_c_string ("Cannot set file date")); | 5647 | make_pure_c_string ("Cannot set file date")); |
| 5512 | 5648 | ||
| 5513 | DEFVAR_LISP ("file-name-handler-alist", Vfile_name_handler_alist, | 5649 | DEFVAR_LISP ("file-name-handler-alist", Vfile_name_handler_alist, |
| 5514 | doc: /* *Alist of elements (REGEXP . HANDLER) for file names handled specially. | 5650 | doc: /* Alist of elements (REGEXP . HANDLER) for file names handled specially. |
| 5515 | If a file name matches REGEXP, then all I/O on that file is done by calling | 5651 | If a file name matches REGEXP, all I/O on that file is done by calling |
| 5516 | HANDLER. | 5652 | HANDLER. If a file name matches more than one handler, the handler |
| 5517 | 5653 | whose match starts last in the file name gets precedence. The | |
| 5518 | The first argument given to HANDLER is the name of the I/O primitive | 5654 | function `find-file-name-handler' checks this list for a handler for |
| 5519 | to be handled; the remaining arguments are the arguments that were | 5655 | its argument. |
| 5520 | passed to that primitive. For example, if you do | 5656 | |
| 5521 | (file-exists-p FILENAME) | 5657 | HANDLER should be a function. The first argument given to it is the |
| 5522 | and FILENAME is handled by HANDLER, then HANDLER is called like this: | 5658 | name of the I/O primitive to be handled; the remaining arguments are |
| 5523 | (funcall HANDLER 'file-exists-p FILENAME) | 5659 | the arguments that were passed to that primitive. For example, if you |
| 5524 | The function `find-file-name-handler' checks this list for a handler | 5660 | do (file-exists-p FILENAME) and FILENAME is handled by HANDLER, then |
| 5525 | for its argument. */); | 5661 | HANDLER is called like this: |
| 5662 | |||
| 5663 | (funcall HANDLER 'file-exists-p FILENAME) | ||
| 5664 | |||
| 5665 | Note that HANDLER must be able to handle all I/O primitives; if it has | ||
| 5666 | nothing special to do for a primitive, it should reinvoke the | ||
| 5667 | primitive to handle the operation \"the usual way\". | ||
| 5668 | See Info node `(elisp)Magic File Names' for more details. */); | ||
| 5526 | Vfile_name_handler_alist = Qnil; | 5669 | Vfile_name_handler_alist = Qnil; |
| 5527 | 5670 | ||
| 5528 | DEFVAR_LISP ("set-auto-coding-function", | 5671 | DEFVAR_LISP ("set-auto-coding-function", |