diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2011-07-18 23:10:15 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2011-07-18 23:10:15 -0700 |
commit | 7403ff044d82d390bdc4cdd3954448daedcd4571 (patch) | |
tree | 2f5ce508e4b20d5641ebd6c86ca61bc8dab401cc /src/fileio.c | |
parent | d3411f89d34bd1009cae738f917abf477be09882 (diff) | |
parent | 15e3a074a6ebdcefd828a1ba14a5a12ff9921034 (diff) | |
download | emacs-7403ff044d82d390bdc4cdd3954448daedcd4571.tar.gz |
Merge from trunk.
Diffstat (limited to 'src/fileio.c')
-rw-r--r-- | src/fileio.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/src/fileio.c b/src/fileio.c index af11e927059..60ee35bb399 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -38,8 +38,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <selinux/context.h> #endif -#include <ignore-value.h> - #include "lisp.h" #include "intervals.h" #include "buffer.h" @@ -1939,10 +1937,19 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */) | (NILP (ok_if_already_exists) ? O_EXCL : 0), S_IREAD | S_IWRITE); #else /* not MSDOS */ - ofd = emacs_open (SSDATA (encoded_newname), - O_WRONLY | O_TRUNC | O_CREAT - | (NILP (ok_if_already_exists) ? O_EXCL : 0), - 0666); + { + int new_mask = 0666; + if (input_file_statable_p) + { + if (!NILP (preserve_uid_gid)) + new_mask = 0600; + new_mask &= st.st_mode; + } + ofd = emacs_open (SSDATA (encoded_newname), + (O_WRONLY | O_TRUNC | O_CREAT + | (NILP (ok_if_already_exists) ? O_EXCL : 0)), + new_mask); + } #endif /* not MSDOS */ if (ofd < 0) report_file_error ("Opening output file", Fcons (newname, Qnil)); @@ -1961,9 +1968,21 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */) owner and group. */ if (input_file_statable_p) { + int mode_mask = 07777; if (!NILP (preserve_uid_gid)) - ignore_value (fchown (ofd, st.st_uid, st.st_gid)); - if (fchmod (ofd, st.st_mode & 07777) != 0) + { + /* Attempt to change owner and group. If that doesn't work + attempt to change just the group, as that is sometimes allowed. + Adjust the mode mask to eliminate setuid or setgid bits + that are inappropriate if the owner and group are wrong. */ + if (fchown (ofd, st.st_uid, st.st_gid) != 0) + { + mode_mask &= ~06000; + if (fchown (ofd, -1, st.st_gid) == 0) + mode_mask |= 02000; + } + } + if (fchmod (ofd, st.st_mode & mode_mask) != 0) report_file_error ("Doing chmod", Fcons (newname, Qnil)); } #endif /* not MSDOS */ |