summaryrefslogtreecommitdiff
path: root/src/fileio.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2011-07-18 23:10:15 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2011-07-18 23:10:15 -0700
commit7403ff044d82d390bdc4cdd3954448daedcd4571 (patch)
tree2f5ce508e4b20d5641ebd6c86ca61bc8dab401cc /src/fileio.c
parentd3411f89d34bd1009cae738f917abf477be09882 (diff)
parent15e3a074a6ebdcefd828a1ba14a5a12ff9921034 (diff)
downloademacs-7403ff044d82d390bdc4cdd3954448daedcd4571.tar.gz
Merge from trunk.
Diffstat (limited to 'src/fileio.c')
-rw-r--r--src/fileio.c35
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 */