diff options
| author | Paul Eggert | 2013-12-29 10:18:45 -0800 |
|---|---|---|
| committer | Paul Eggert | 2013-12-29 10:18:45 -0800 |
| commit | a560b856b15f57889eb10be984130c285e2cb43d (patch) | |
| tree | f422337dcce0c3b4115aff096c35708ea7e587de /src | |
| parent | 830506d93af4c75edc487016c1711941e96faa04 (diff) | |
| download | emacs-a560b856b15f57889eb10be984130c285e2cb43d.tar.gz emacs-a560b856b15f57889eb10be984130c285e2cb43d.zip | |
Plain copy-file no longer chmods an existing destination.
* doc/lispref/files.texi (Changing Files): Document this.
* etc/NEWS: Document this.
* src/fileio.c (realmask): Now a static var, not a local.
(barf_or_query_if_file_exists): New arg KNOWN_TO_EXIST.
Remove arg STATPTR. All uses changed.
(Fcopy_file): Do not alter permissions of existing destinations,
unless PRESERVE-PERMISSIONS (renamed from
PRESERVE-EXTENDED-ATTRIBUTES) is non-nil.
Avoid race when testing for existing destinations and for
when input and output files are the same.
If changing the group fails, adjust both default and
preserved permissions so that access is not granted to the
wrong group.
(Fset_default_file_modes, init_fileio): Update realmask.
(Fdefault_file_modes): Use realmask instead of calling umask.
Fixes: debbugs:16133
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 17 | ||||
| -rw-r--r-- | src/fileio.c | 162 |
2 files changed, 111 insertions, 68 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 1ec84a72d2d..e1e9777fa4f 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,20 @@ | |||
| 1 | 2013-12-29 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Plain copy-file no longer chmods an existing destination (Bug#16133). | ||
| 4 | * fileio.c (realmask): Now a static var, not a local. | ||
| 5 | (barf_or_query_if_file_exists): New arg KNOWN_TO_EXIST. | ||
| 6 | Remove arg STATPTR. All uses changed. | ||
| 7 | (Fcopy_file): Do not alter permissions of existing destinations, | ||
| 8 | unless PRESERVE-PERMISSIONS (renamed from | ||
| 9 | PRESERVE-EXTENDED-ATTRIBUTES) is non-nil. | ||
| 10 | Avoid race when testing for existing destinations and for | ||
| 11 | when input and output files are the same. | ||
| 12 | If changing the group fails, adjust both default and | ||
| 13 | preserved permissions so that access is not granted to the | ||
| 14 | wrong group. | ||
| 15 | (Fset_default_file_modes, init_fileio): Update realmask. | ||
| 16 | (Fdefault_file_modes): Use realmask instead of calling umask. | ||
| 17 | |||
| 1 | 2013-12-28 Paul Eggert <eggert@cs.ucla.edu> | 18 | 2013-12-28 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 19 | ||
| 3 | Fix pipe bug with OS X emacs --daemon (Bug#16262). | 20 | Fix pipe bug with OS X emacs --daemon (Bug#16262). |
diff --git a/src/fileio.c b/src/fileio.c index 295d9d748ad..adf69c6f234 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -95,6 +95,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 95 | /* True during writing of auto-save files. */ | 95 | /* True during writing of auto-save files. */ |
| 96 | static bool auto_saving; | 96 | static bool auto_saving; |
| 97 | 97 | ||
| 98 | /* Emacs's real umask. */ | ||
| 99 | static mode_t realmask; | ||
| 100 | |||
| 98 | /* Nonzero umask during creation of auto-save directories. */ | 101 | /* Nonzero umask during creation of auto-save directories. */ |
| 99 | static mode_t auto_saving_dir_umask; | 102 | static mode_t auto_saving_dir_umask; |
| 100 | 103 | ||
| @@ -1858,20 +1861,16 @@ expand_and_dir_to_file (Lisp_Object filename, Lisp_Object defdir) | |||
| 1858 | } | 1861 | } |
| 1859 | 1862 | ||
| 1860 | /* Signal an error if the file ABSNAME already exists. | 1863 | /* Signal an error if the file ABSNAME already exists. |
| 1861 | If INTERACTIVE, ask the user whether to proceed, | 1864 | If KNOWN_TO_EXIST, the file is known to exist. |
| 1862 | and bypass the error if the user says to go ahead. | ||
| 1863 | QUERYSTRING is a name for the action that is being considered | 1865 | QUERYSTRING is a name for the action that is being considered |
| 1864 | to alter the file. | 1866 | to alter the file. |
| 1865 | 1867 | If INTERACTIVE, ask the user whether to proceed, | |
| 1866 | *STATPTR is used to store the stat information if the file exists. | 1868 | and bypass the error if the user says to go ahead. |
| 1867 | If the file does not exist, STATPTR->st_mode is set to 0. | ||
| 1868 | If STATPTR is null, we don't store into it. | ||
| 1869 | |||
| 1870 | If QUICK, ask for y or n, not yes or no. */ | 1869 | If QUICK, ask for y or n, not yes or no. */ |
| 1871 | 1870 | ||
| 1872 | static void | 1871 | static void |
| 1873 | barf_or_query_if_file_exists (Lisp_Object absname, const char *querystring, | 1872 | barf_or_query_if_file_exists (Lisp_Object absname, bool known_to_exist, |
| 1874 | bool interactive, struct stat *statptr, | 1873 | const char *querystring, bool interactive, |
| 1875 | bool quick) | 1874 | bool quick) |
| 1876 | { | 1875 | { |
| 1877 | Lisp_Object tem, encoded_filename; | 1876 | Lisp_Object tem, encoded_filename; |
| @@ -1880,14 +1879,16 @@ barf_or_query_if_file_exists (Lisp_Object absname, const char *querystring, | |||
| 1880 | 1879 | ||
| 1881 | encoded_filename = ENCODE_FILE (absname); | 1880 | encoded_filename = ENCODE_FILE (absname); |
| 1882 | 1881 | ||
| 1883 | /* `stat' is a good way to tell whether the file exists, | 1882 | if (! known_to_exist && lstat (SSDATA (encoded_filename), &statbuf) == 0) |
| 1884 | regardless of what access permissions it has. */ | ||
| 1885 | if (lstat (SSDATA (encoded_filename), &statbuf) >= 0) | ||
| 1886 | { | 1883 | { |
| 1887 | if (S_ISDIR (statbuf.st_mode)) | 1884 | if (S_ISDIR (statbuf.st_mode)) |
| 1888 | xsignal2 (Qfile_error, | 1885 | xsignal2 (Qfile_error, |
| 1889 | build_string ("File is a directory"), absname); | 1886 | build_string ("File is a directory"), absname); |
| 1887 | known_to_exist = true; | ||
| 1888 | } | ||
| 1890 | 1889 | ||
| 1890 | if (known_to_exist) | ||
| 1891 | { | ||
| 1891 | if (! interactive) | 1892 | if (! interactive) |
| 1892 | xsignal2 (Qfile_already_exists, | 1893 | xsignal2 (Qfile_already_exists, |
| 1893 | build_string ("File already exists"), absname); | 1894 | build_string ("File already exists"), absname); |
| @@ -1902,15 +1903,7 @@ barf_or_query_if_file_exists (Lisp_Object absname, const char *querystring, | |||
| 1902 | if (NILP (tem)) | 1903 | if (NILP (tem)) |
| 1903 | xsignal2 (Qfile_already_exists, | 1904 | xsignal2 (Qfile_already_exists, |
| 1904 | build_string ("File already exists"), absname); | 1905 | build_string ("File already exists"), absname); |
| 1905 | if (statptr) | ||
| 1906 | *statptr = statbuf; | ||
| 1907 | } | 1906 | } |
| 1908 | else | ||
| 1909 | { | ||
| 1910 | if (statptr) | ||
| 1911 | statptr->st_mode = 0; | ||
| 1912 | } | ||
| 1913 | return; | ||
| 1914 | } | 1907 | } |
| 1915 | 1908 | ||
| 1916 | DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 6, | 1909 | DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 6, |
| @@ -1937,16 +1930,21 @@ A prefix arg makes KEEP-TIME non-nil. | |||
| 1937 | If PRESERVE-UID-GID is non-nil, we try to transfer the | 1930 | If PRESERVE-UID-GID is non-nil, we try to transfer the |
| 1938 | uid and gid of FILE to NEWNAME. | 1931 | uid and gid of FILE to NEWNAME. |
| 1939 | 1932 | ||
| 1940 | If PRESERVE-EXTENDED-ATTRIBUTES is non-nil, we try to copy additional | 1933 | If PRESERVE-PERMISSIONS is non-nil, copy permissions of FILE to NEWNAME; |
| 1941 | attributes of FILE to NEWNAME, such as its SELinux context and ACL | 1934 | this includes the file modes, along with ACL entries and SELinux |
| 1942 | entries (depending on how Emacs was built). */) | 1935 | context if present. Otherwise, if NEWNAME is created its file |
| 1943 | (Lisp_Object file, Lisp_Object newname, Lisp_Object ok_if_already_exists, Lisp_Object keep_time, Lisp_Object preserve_uid_gid, Lisp_Object preserve_extended_attributes) | 1936 | permission bits are those of FILE, masked by the default file |
| 1937 | permissions. */) | ||
| 1938 | (Lisp_Object file, Lisp_Object newname, Lisp_Object ok_if_already_exists, | ||
| 1939 | Lisp_Object keep_time, Lisp_Object preserve_uid_gid, | ||
| 1940 | Lisp_Object preserve_permissions) | ||
| 1944 | { | 1941 | { |
| 1945 | struct stat out_st; | ||
| 1946 | Lisp_Object handler; | 1942 | Lisp_Object handler; |
| 1947 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | 1943 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
| 1948 | ptrdiff_t count = SPECPDL_INDEX (); | 1944 | ptrdiff_t count = SPECPDL_INDEX (); |
| 1949 | Lisp_Object encoded_file, encoded_newname; | 1945 | Lisp_Object encoded_file, encoded_newname; |
| 1946 | bool already_exists = false; | ||
| 1947 | mode_t new_mask; | ||
| 1950 | #if HAVE_LIBSELINUX | 1948 | #if HAVE_LIBSELINUX |
| 1951 | security_context_t con; | 1949 | security_context_t con; |
| 1952 | int conlength = 0; | 1950 | int conlength = 0; |
| @@ -1981,22 +1979,20 @@ entries (depending on how Emacs was built). */) | |||
| 1981 | if (!NILP (handler)) | 1979 | if (!NILP (handler)) |
| 1982 | RETURN_UNGCPRO (call7 (handler, Qcopy_file, file, newname, | 1980 | RETURN_UNGCPRO (call7 (handler, Qcopy_file, file, newname, |
| 1983 | ok_if_already_exists, keep_time, preserve_uid_gid, | 1981 | ok_if_already_exists, keep_time, preserve_uid_gid, |
| 1984 | preserve_extended_attributes)); | 1982 | preserve_permissions)); |
| 1985 | 1983 | ||
| 1986 | encoded_file = ENCODE_FILE (file); | 1984 | encoded_file = ENCODE_FILE (file); |
| 1987 | encoded_newname = ENCODE_FILE (newname); | 1985 | encoded_newname = ENCODE_FILE (newname); |
| 1988 | 1986 | ||
| 1987 | #ifdef WINDOWSNT | ||
| 1989 | if (NILP (ok_if_already_exists) | 1988 | if (NILP (ok_if_already_exists) |
| 1990 | || INTEGERP (ok_if_already_exists)) | 1989 | || INTEGERP (ok_if_already_exists)) |
| 1991 | barf_or_query_if_file_exists (newname, "copy to it", | 1990 | barf_or_query_if_file_exists (newname, false, "copy to it", |
| 1992 | INTEGERP (ok_if_already_exists), &out_st, 0); | 1991 | INTEGERP (ok_if_already_exists), false); |
| 1993 | else if (stat (SSDATA (encoded_newname), &out_st) < 0) | ||
| 1994 | out_st.st_mode = 0; | ||
| 1995 | 1992 | ||
| 1996 | #ifdef WINDOWSNT | ||
| 1997 | result = w32_copy_file (SSDATA (encoded_file), SSDATA (encoded_newname), | 1993 | result = w32_copy_file (SSDATA (encoded_file), SSDATA (encoded_newname), |
| 1998 | !NILP (keep_time), !NILP (preserve_uid_gid), | 1994 | !NILP (keep_time), !NILP (preserve_uid_gid), |
| 1999 | !NILP (preserve_extended_attributes)); | 1995 | !NILP (preserve_permissions)); |
| 2000 | switch (result) | 1996 | switch (result) |
| 2001 | { | 1997 | { |
| 2002 | case -1: | 1998 | case -1: |
| @@ -2022,7 +2018,7 @@ entries (depending on how Emacs was built). */) | |||
| 2022 | if (fstat (ifd, &st) != 0) | 2018 | if (fstat (ifd, &st) != 0) |
| 2023 | report_file_error ("Input file status", file); | 2019 | report_file_error ("Input file status", file); |
| 2024 | 2020 | ||
| 2025 | if (!NILP (preserve_extended_attributes)) | 2021 | if (!NILP (preserve_permissions)) |
| 2026 | { | 2022 | { |
| 2027 | #if HAVE_LIBSELINUX | 2023 | #if HAVE_LIBSELINUX |
| 2028 | if (is_selinux_enabled ()) | 2024 | if (is_selinux_enabled ()) |
| @@ -2034,32 +2030,44 @@ entries (depending on how Emacs was built). */) | |||
| 2034 | #endif | 2030 | #endif |
| 2035 | } | 2031 | } |
| 2036 | 2032 | ||
| 2037 | if (out_st.st_mode != 0 | ||
| 2038 | && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino) | ||
| 2039 | report_file_errno ("Input and output files are the same", | ||
| 2040 | list2 (file, newname), 0); | ||
| 2041 | |||
| 2042 | /* We can copy only regular files. */ | 2033 | /* We can copy only regular files. */ |
| 2043 | if (!S_ISREG (st.st_mode)) | 2034 | if (!S_ISREG (st.st_mode)) |
| 2044 | report_file_errno ("Non-regular file", file, | 2035 | report_file_errno ("Non-regular file", file, |
| 2045 | S_ISDIR (st.st_mode) ? EISDIR : EINVAL); | 2036 | S_ISDIR (st.st_mode) ? EISDIR : EINVAL); |
| 2046 | 2037 | ||
| 2047 | { | ||
| 2048 | #ifndef MSDOS | 2038 | #ifndef MSDOS |
| 2049 | int new_mask = st.st_mode & (!NILP (preserve_uid_gid) ? 0600 : 0666); | 2039 | new_mask = st.st_mode & (!NILP (preserve_uid_gid) ? 0700 : 0777); |
| 2050 | #else | 2040 | #else |
| 2051 | int new_mask = S_IREAD | S_IWRITE; | 2041 | new_mask = S_IREAD | S_IWRITE; |
| 2052 | #endif | 2042 | #endif |
| 2053 | ofd = emacs_open (SSDATA (encoded_newname), | 2043 | |
| 2054 | (O_WRONLY | O_TRUNC | O_CREAT | 2044 | ofd = emacs_open (SSDATA (encoded_newname), O_WRONLY | O_CREAT | O_EXCL, |
| 2055 | | (NILP (ok_if_already_exists) ? O_EXCL : 0)), | 2045 | new_mask); |
| 2056 | new_mask); | 2046 | if (ofd < 0 && errno == EEXIST) |
| 2057 | } | 2047 | { |
| 2048 | if (NILP (ok_if_already_exists) || INTEGERP (ok_if_already_exists)) | ||
| 2049 | barf_or_query_if_file_exists (newname, true, "copy to it", | ||
| 2050 | INTEGERP (ok_if_already_exists), false); | ||
| 2051 | already_exists = true; | ||
| 2052 | ofd = emacs_open (SSDATA (encoded_newname), O_WRONLY, 0); | ||
| 2053 | } | ||
| 2058 | if (ofd < 0) | 2054 | if (ofd < 0) |
| 2059 | report_file_error ("Opening output file", newname); | 2055 | report_file_error ("Opening output file", newname); |
| 2060 | 2056 | ||
| 2061 | record_unwind_protect_int (close_file_unwind, ofd); | 2057 | record_unwind_protect_int (close_file_unwind, ofd); |
| 2062 | 2058 | ||
| 2059 | if (already_exists) | ||
| 2060 | { | ||
| 2061 | struct stat out_st; | ||
| 2062 | if (fstat (ofd, &out_st) != 0) | ||
| 2063 | report_file_error ("Output file status", newname); | ||
| 2064 | if (st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino) | ||
| 2065 | report_file_errno ("Input and output files are the same", | ||
| 2066 | list2 (file, newname), 0); | ||
| 2067 | if (ftruncate (ofd, 0) != 0) | ||
| 2068 | report_file_error ("Truncating output file", newname); | ||
| 2069 | } | ||
| 2070 | |||
| 2063 | immediate_quit = 1; | 2071 | immediate_quit = 1; |
| 2064 | QUIT; | 2072 | QUIT; |
| 2065 | while ((n = emacs_read (ifd, buf, sizeof buf)) > 0) | 2073 | while ((n = emacs_read (ifd, buf, sizeof buf)) > 0) |
| @@ -2071,26 +2079,41 @@ entries (depending on how Emacs was built). */) | |||
| 2071 | /* Preserve the original file permissions, and if requested, also its | 2079 | /* Preserve the original file permissions, and if requested, also its |
| 2072 | owner and group. */ | 2080 | owner and group. */ |
| 2073 | { | 2081 | { |
| 2074 | mode_t mode_mask = 07777; | 2082 | mode_t preserved_permissions = st.st_mode & 07777; |
| 2083 | mode_t default_permissions = st.st_mode & 0777 & ~realmask; | ||
| 2075 | if (!NILP (preserve_uid_gid)) | 2084 | if (!NILP (preserve_uid_gid)) |
| 2076 | { | 2085 | { |
| 2077 | /* Attempt to change owner and group. If that doesn't work | 2086 | /* Attempt to change owner and group. If that doesn't work |
| 2078 | attempt to change just the group, as that is sometimes allowed. | 2087 | attempt to change just the group, as that is sometimes allowed. |
| 2079 | Adjust the mode mask to eliminate setuid or setgid bits | 2088 | Adjust the mode mask to eliminate setuid or setgid bits |
| 2080 | that are inappropriate if the owner and group are wrong. */ | 2089 | or group permissions bits that are inappropriate if the |
| 2090 | owner or group are wrong. */ | ||
| 2081 | if (fchown (ofd, st.st_uid, st.st_gid) != 0) | 2091 | if (fchown (ofd, st.st_uid, st.st_gid) != 0) |
| 2082 | { | 2092 | { |
| 2083 | mode_mask &= ~06000; | ||
| 2084 | if (fchown (ofd, -1, st.st_gid) == 0) | 2093 | if (fchown (ofd, -1, st.st_gid) == 0) |
| 2085 | mode_mask |= 02000; | 2094 | preserved_permissions &= ~04000; |
| 2095 | else | ||
| 2096 | { | ||
| 2097 | preserved_permissions &= ~06000; | ||
| 2098 | |||
| 2099 | /* Copy the other bits to the group bits, since the | ||
| 2100 | group is wrong. */ | ||
| 2101 | preserved_permissions &= ~070; | ||
| 2102 | preserved_permissions |= (preserved_permissions & 7) << 3; | ||
| 2103 | default_permissions &= ~070; | ||
| 2104 | default_permissions |= (default_permissions & 7) << 3; | ||
| 2105 | } | ||
| 2086 | } | 2106 | } |
| 2087 | } | 2107 | } |
| 2088 | 2108 | ||
| 2089 | switch (!NILP (preserve_extended_attributes) | 2109 | switch (!NILP (preserve_permissions) |
| 2090 | ? qcopy_acl (SSDATA (encoded_file), ifd, | 2110 | ? qcopy_acl (SSDATA (encoded_file), ifd, |
| 2091 | SSDATA (encoded_newname), ofd, | 2111 | SSDATA (encoded_newname), ofd, |
| 2092 | st.st_mode & mode_mask) | 2112 | preserved_permissions) |
| 2093 | : fchmod (ofd, st.st_mode & mode_mask)) | 2113 | : (already_exists |
| 2114 | || (new_mask & ~realmask) == default_permissions) | ||
| 2115 | ? 0 | ||
| 2116 | : fchmod (ofd, default_permissions)) | ||
| 2094 | { | 2117 | { |
| 2095 | case -2: report_file_error ("Copying permissions from", file); | 2118 | case -2: report_file_error ("Copying permissions from", file); |
| 2096 | case -1: report_file_error ("Copying permissions to", newname); | 2119 | case -1: report_file_error ("Copying permissions to", newname); |
| @@ -2307,8 +2330,8 @@ This is what happens in interactive use with M-x. */) | |||
| 2307 | #endif | 2330 | #endif |
| 2308 | if (NILP (ok_if_already_exists) | 2331 | if (NILP (ok_if_already_exists) |
| 2309 | || INTEGERP (ok_if_already_exists)) | 2332 | || INTEGERP (ok_if_already_exists)) |
| 2310 | barf_or_query_if_file_exists (newname, "rename to it", | 2333 | barf_or_query_if_file_exists (newname, false, "rename to it", |
| 2311 | INTEGERP (ok_if_already_exists), 0, 0); | 2334 | INTEGERP (ok_if_already_exists), false); |
| 2312 | if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0) | 2335 | if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0) |
| 2313 | { | 2336 | { |
| 2314 | int rename_errno = errno; | 2337 | int rename_errno = errno; |
| @@ -2387,8 +2410,8 @@ This is what happens in interactive use with M-x. */) | |||
| 2387 | 2410 | ||
| 2388 | if (NILP (ok_if_already_exists) | 2411 | if (NILP (ok_if_already_exists) |
| 2389 | || INTEGERP (ok_if_already_exists)) | 2412 | || INTEGERP (ok_if_already_exists)) |
| 2390 | barf_or_query_if_file_exists (newname, "make it a new name", | 2413 | barf_or_query_if_file_exists (newname, false, "make it a new name", |
| 2391 | INTEGERP (ok_if_already_exists), 0, 0); | 2414 | INTEGERP (ok_if_already_exists), false); |
| 2392 | 2415 | ||
| 2393 | unlink (SSDATA (newname)); | 2416 | unlink (SSDATA (newname)); |
| 2394 | if (link (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0) | 2417 | if (link (SSDATA (encoded_file), SSDATA (encoded_newname)) < 0) |
| @@ -2449,8 +2472,8 @@ This happens for interactive use with M-x. */) | |||
| 2449 | 2472 | ||
| 2450 | if (NILP (ok_if_already_exists) | 2473 | if (NILP (ok_if_already_exists) |
| 2451 | || INTEGERP (ok_if_already_exists)) | 2474 | || INTEGERP (ok_if_already_exists)) |
| 2452 | barf_or_query_if_file_exists (linkname, "make it a link", | 2475 | barf_or_query_if_file_exists (linkname, false, "make it a link", |
| 2453 | INTEGERP (ok_if_already_exists), 0, 0); | 2476 | INTEGERP (ok_if_already_exists), false); |
| 2454 | if (symlink (SSDATA (encoded_filename), SSDATA (encoded_linkname)) < 0) | 2477 | if (symlink (SSDATA (encoded_filename), SSDATA (encoded_linkname)) < 0) |
| 2455 | { | 2478 | { |
| 2456 | /* If we didn't complain already, silently delete existing file. */ | 2479 | /* If we didn't complain already, silently delete existing file. */ |
| @@ -3137,10 +3160,17 @@ The argument MODE should be an integer; only the low 9 bits are used. | |||
| 3137 | This setting is inherited by subprocesses. */) | 3160 | This setting is inherited by subprocesses. */) |
| 3138 | (Lisp_Object mode) | 3161 | (Lisp_Object mode) |
| 3139 | { | 3162 | { |
| 3163 | mode_t oldrealmask, oldumask, newumask; | ||
| 3140 | CHECK_NUMBER (mode); | 3164 | CHECK_NUMBER (mode); |
| 3165 | oldrealmask = realmask; | ||
| 3166 | newumask = ~ XINT (mode) & 0777; | ||
| 3141 | 3167 | ||
| 3142 | umask ((~ XINT (mode)) & 0777); | 3168 | block_input (); |
| 3169 | realmask = newumask; | ||
| 3170 | oldumask = umask (newumask); | ||
| 3171 | unblock_input (); | ||
| 3143 | 3172 | ||
| 3173 | eassert (oldumask == oldrealmask); | ||
| 3144 | return Qnil; | 3174 | return Qnil; |
| 3145 | } | 3175 | } |
| 3146 | 3176 | ||
| @@ -3149,14 +3179,7 @@ DEFUN ("default-file-modes", Fdefault_file_modes, Sdefault_file_modes, 0, 0, 0, | |||
| 3149 | The value is an integer. */) | 3179 | The value is an integer. */) |
| 3150 | (void) | 3180 | (void) |
| 3151 | { | 3181 | { |
| 3152 | mode_t realmask; | ||
| 3153 | Lisp_Object value; | 3182 | Lisp_Object value; |
| 3154 | |||
| 3155 | block_input (); | ||
| 3156 | realmask = umask (0); | ||
| 3157 | umask (realmask); | ||
| 3158 | unblock_input (); | ||
| 3159 | |||
| 3160 | XSETINT (value, (~ realmask) & 0777); | 3183 | XSETINT (value, (~ realmask) & 0777); |
| 3161 | return value; | 3184 | return value; |
| 3162 | } | 3185 | } |
| @@ -4697,7 +4720,7 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename, | |||
| 4697 | filename = Fexpand_file_name (filename, Qnil); | 4720 | filename = Fexpand_file_name (filename, Qnil); |
| 4698 | 4721 | ||
| 4699 | if (!NILP (mustbenew) && !EQ (mustbenew, Qexcl)) | 4722 | if (!NILP (mustbenew) && !EQ (mustbenew, Qexcl)) |
| 4700 | barf_or_query_if_file_exists (filename, "overwrite", 1, 0, 1); | 4723 | barf_or_query_if_file_exists (filename, false, "overwrite", true, true); |
| 4701 | 4724 | ||
| 4702 | if (STRINGP (visit)) | 4725 | if (STRINGP (visit)) |
| 4703 | visit_file = Fexpand_file_name (visit, Qnil); | 4726 | visit_file = Fexpand_file_name (visit, Qnil); |
| @@ -5765,6 +5788,9 @@ Fread_file_name (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filena | |||
| 5765 | void | 5788 | void |
| 5766 | init_fileio (void) | 5789 | init_fileio (void) |
| 5767 | { | 5790 | { |
| 5791 | realmask = umask (0); | ||
| 5792 | umask (realmask); | ||
| 5793 | |||
| 5768 | valid_timestamp_file_system = 0; | 5794 | valid_timestamp_file_system = 0; |
| 5769 | 5795 | ||
| 5770 | /* fsync can be a significant performance hit. Often it doesn't | 5796 | /* fsync can be a significant performance hit. Often it doesn't |