aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2013-12-29 10:18:45 -0800
committerPaul Eggert2013-12-29 10:18:45 -0800
commita560b856b15f57889eb10be984130c285e2cb43d (patch)
treef422337dcce0c3b4115aff096c35708ea7e587de
parent830506d93af4c75edc487016c1711941e96faa04 (diff)
downloademacs-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
-rw-r--r--doc/lispref/ChangeLog5
-rw-r--r--doc/lispref/files.texi11
-rw-r--r--etc/ChangeLog5
-rw-r--r--etc/NEWS10
-rw-r--r--src/ChangeLog17
-rw-r--r--src/fileio.c162
6 files changed, 134 insertions, 76 deletions
diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog
index 2ebab695514..3de4ae598fe 100644
--- a/doc/lispref/ChangeLog
+++ b/doc/lispref/ChangeLog
@@ -1,3 +1,8 @@
12013-12-29 Paul Eggert <eggert@cs.ucla.edu>
2
3 Plain copy-file no longer chmods an existing destination (Bug#16133).
4 * files.texi (Changing Files): Document this.
5
12013-12-28 Chong Yidong <cyd@gnu.org> 62013-12-28 Chong Yidong <cyd@gnu.org>
2 7
3 * modes.texi (Auto Major Mode): Document interpreter-mode-alist 8 * modes.texi (Auto Major Mode): Document interpreter-mode-alist
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index c1eae5eefa3..01eef350ddf 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -1563,8 +1563,6 @@ some operating systems.) If setting the time gets an error,
1563interactive call, a prefix argument specifies a non-@code{nil} value 1563interactive call, a prefix argument specifies a non-@code{nil} value
1564for @var{time}. 1564for @var{time}.
1565 1565
1566This function copies the file modes, too.
1567
1568If argument @var{preserve-uid-gid} is @code{nil}, we let the operating 1566If argument @var{preserve-uid-gid} is @code{nil}, we let the operating
1569system decide the user and group ownership of the new file (this is 1567system decide the user and group ownership of the new file (this is
1570usually set to the user running Emacs). If @var{preserve-uid-gid} is 1568usually set to the user running Emacs). If @var{preserve-uid-gid} is
@@ -1572,10 +1570,11 @@ non-@code{nil}, we attempt to copy the user and group ownership of the
1572file. This works only on some operating systems, and only if you have 1570file. This works only on some operating systems, and only if you have
1573the correct permissions to do so. 1571the correct permissions to do so.
1574 1572
1575If the optional argument @var{preserve-extended-attributes} is 1573If the optional argument @var{preserve-permissions} is non-@code{nil},
1576non-@code{nil}, and Emacs has been built with the appropriate support, 1574this function copies the file's permissions, such as its file modes,
1577this function attempts to copy the file's extended attributes, such as 1575its SELinux context, and ACL entries (@pxref{File Attributes}).
1578its SELinux context and ACL entries (@pxref{File Attributes}). 1576Otherwise, if the destination is created its file permission bits are
1577those of the source, masked by the default file permissions.
1579@end deffn 1578@end deffn
1580 1579
1581@deffn Command make-symbolic-link filename newname &optional ok-if-exists 1580@deffn Command make-symbolic-link filename newname &optional ok-if-exists
diff --git a/etc/ChangeLog b/etc/ChangeLog
index 8a4b8fb774c..bde366da14f 100644
--- a/etc/ChangeLog
+++ b/etc/ChangeLog
@@ -1,3 +1,8 @@
12013-12-29 Paul Eggert <eggert@cs.ucla.edu>
2
3 Plain copy-file no longer chmods an existing destination (Bug#16133).
4 * NEWS: Document this.
5
12013-12-26 João Távora <joaotavora@gmail.com> 62013-12-26 João Távora <joaotavora@gmail.com>
2 7
3 * NEWS: Describe new features of Electric Pair mode. 8 * NEWS: Describe new features of Electric Pair mode.
diff --git a/etc/NEWS b/etc/NEWS
index 49a2d8e6c9b..c1e3784d9f6 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -952,6 +952,12 @@ alist of extended attributes as returned by the new function
952`file-extended-attributes'. The attributes can be applied to another 952`file-extended-attributes'. The attributes can be applied to another
953file using `set-file-extended-attributes'. 953file using `set-file-extended-attributes'.
954 954
955** By default `copy-file' no longer copies file permission bits to an
956existing destination; and it sets the file permission bits of a newly
957created destination to those of the source, masked by the default file
958permissions. To copy the file permission bits, pass t as the
959PRESERVE-PERMISSIONS argument of `copy-file'.
960
955+++ 961+++
956** `visited-file-modtime' now returns -1 for nonexistent files. 962** `visited-file-modtime' now returns -1 for nonexistent files.
957Formerly it returned a list (-1 LOW USEC PSEC), but this was ambiguous 963Formerly it returned a list (-1 LOW USEC PSEC), but this was ambiguous
@@ -1100,8 +1106,8 @@ platforms, and nobody seems to have noticed or cared.
1100 1106
1101+++ 1107+++
1102*** The 6th argument to `copy-file' has been renamed to 1108*** The 6th argument to `copy-file' has been renamed to
1103PRESERVE-EXTENDED-ATTRIBUTES as it now handles both SELinux context 1109PRESERVE-PERMISSIONS as it now handles ACL entries and the traditional
1104and ACL entries. 1110Unix file permission bits as well as SELinux context.
1105 1111
1106+++ 1112+++
1107*** The function `file-ownership-preserved-p' now has an optional 1113*** The function `file-ownership-preserved-p' now has an optional
diff --git a/src/ChangeLog b/src/ChangeLog
index 1ec84a72d2d..e1e9777fa4f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,20 @@
12013-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
12013-12-28 Paul Eggert <eggert@cs.ucla.edu> 182013-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. */
96static bool auto_saving; 96static bool auto_saving;
97 97
98/* Emacs's real umask. */
99static mode_t realmask;
100
98/* Nonzero umask during creation of auto-save directories. */ 101/* Nonzero umask during creation of auto-save directories. */
99static mode_t auto_saving_dir_umask; 102static 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
1872static void 1871static void
1873barf_or_query_if_file_exists (Lisp_Object absname, const char *querystring, 1872barf_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
1916DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 6, 1909DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 6,
@@ -1937,16 +1930,21 @@ A prefix arg makes KEEP-TIME non-nil.
1937If PRESERVE-UID-GID is non-nil, we try to transfer the 1930If PRESERVE-UID-GID is non-nil, we try to transfer the
1938uid and gid of FILE to NEWNAME. 1931uid and gid of FILE to NEWNAME.
1939 1932
1940If PRESERVE-EXTENDED-ATTRIBUTES is non-nil, we try to copy additional 1933If PRESERVE-PERMISSIONS is non-nil, copy permissions of FILE to NEWNAME;
1941attributes of FILE to NEWNAME, such as its SELinux context and ACL 1934this includes the file modes, along with ACL entries and SELinux
1942entries (depending on how Emacs was built). */) 1935context 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) 1936permission bits are those of FILE, masked by the default file
1937permissions. */)
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.
3137This setting is inherited by subprocesses. */) 3160This 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,
3149The value is an integer. */) 3179The 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
5765void 5788void
5766init_fileio (void) 5789init_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