diff options
| author | Paul Eggert | 2012-12-12 18:17:49 -0800 |
|---|---|---|
| committer | Paul Eggert | 2012-12-12 18:17:49 -0800 |
| commit | d20704efe62cf45255252168b4f4c453a8c88430 (patch) | |
| tree | adb9aa2b1576e0433a6162909f7c5b8569e10cce /src | |
| parent | eb8006c61fee921dedba1cf708b390e12b89836d (diff) | |
| download | emacs-d20704efe62cf45255252168b4f4c453a8c88430.tar.gz emacs-d20704efe62cf45255252168b4f4c453a8c88430.zip | |
* fileio.c (Fcopy_file): Make fstat failure as serious as open failure.
fstat shouldn't fail, and if it does fail copy-file should not proceed.
Remove unnecessary S_ISLNK test, as (contra the comments) this
function can't copy symlinks. Improve quality of error message
when attempting to copy files that are neither regular files nor
directories.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 9 | ||||
| -rw-r--r-- | src/fileio.c | 94 |
2 files changed, 48 insertions, 55 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 3070fcb6e9d..53c0d93f512 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,12 @@ | |||
| 1 | 2012-12-13 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | * fileio.c (Fcopy_file): Make fstat failure as serious as open failure. | ||
| 4 | fstat shouldn't fail, and if it does fail copy-file should not proceed. | ||
| 5 | Remove unnecessary S_ISLNK test, as (contra the comments) this | ||
| 6 | function can't copy symlinks. Improve quality of error message | ||
| 7 | when attempting to copy files that are neither regular files nor | ||
| 8 | directories. | ||
| 9 | |||
| 1 | 2012-12-12 Dmitry Antipov <dmantipov@yandex.ru> | 10 | 2012-12-12 Dmitry Antipov <dmantipov@yandex.ru> |
| 2 | 11 | ||
| 3 | * dispnew.c (set_window_cursor_after_update): Use clip_to_bounds. | 12 | * dispnew.c (set_window_cursor_after_update): Use clip_to_bounds. |
diff --git a/src/fileio.c b/src/fileio.c index 56c340bfa40..d9029d29168 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -1906,7 +1906,6 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */) | |||
| 1906 | Lisp_Object handler; | 1906 | Lisp_Object handler; |
| 1907 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | 1907 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
| 1908 | ptrdiff_t count = SPECPDL_INDEX (); | 1908 | ptrdiff_t count = SPECPDL_INDEX (); |
| 1909 | bool input_file_statable_p; | ||
| 1910 | Lisp_Object encoded_file, encoded_newname; | 1909 | Lisp_Object encoded_file, encoded_newname; |
| 1911 | #if HAVE_LIBSELINUX | 1910 | #if HAVE_LIBSELINUX |
| 1912 | security_context_t con; | 1911 | security_context_t con; |
| @@ -1984,9 +1983,8 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */) | |||
| 1984 | 1983 | ||
| 1985 | record_unwind_protect (close_file_unwind, make_number (ifd)); | 1984 | record_unwind_protect (close_file_unwind, make_number (ifd)); |
| 1986 | 1985 | ||
| 1987 | /* We can only copy regular files and symbolic links. Other files are not | 1986 | if (fstat (ifd, &st) != 0) |
| 1988 | copyable by us. */ | 1987 | report_file_error ("Input file status", Fcons (file, Qnil)); |
| 1989 | input_file_statable_p = (fstat (ifd, &st) >= 0); | ||
| 1990 | 1988 | ||
| 1991 | #if HAVE_LIBSELINUX | 1989 | #if HAVE_LIBSELINUX |
| 1992 | if (!NILP (preserve_selinux_context) && is_selinux_enabled ()) | 1990 | if (!NILP (preserve_selinux_context) && is_selinux_enabled ()) |
| @@ -2005,14 +2003,12 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */) | |||
| 2005 | Fcons (file, Fcons (newname, Qnil))); | 2003 | Fcons (file, Fcons (newname, Qnil))); |
| 2006 | } | 2004 | } |
| 2007 | 2005 | ||
| 2008 | if (input_file_statable_p) | 2006 | /* We can copy only regular files. */ |
| 2007 | if (!S_ISREG (st.st_mode)) | ||
| 2009 | { | 2008 | { |
| 2010 | if (!(S_ISREG (st.st_mode)) && !(S_ISLNK (st.st_mode))) | 2009 | /* Get a better looking error message. */ |
| 2011 | { | 2010 | errno = S_ISDIR (st.st_mode) ? EISDIR : EINVAL; |
| 2012 | /* Get a better looking error message. */ | 2011 | report_file_error ("Non-regular file", Fcons (file, Qnil)); |
| 2013 | errno = EISDIR; | ||
| 2014 | report_file_error ("Non-regular file", Fcons (file, Qnil)); | ||
| 2015 | } | ||
| 2016 | } | 2012 | } |
| 2017 | 2013 | ||
| 2018 | #ifdef MSDOS | 2014 | #ifdef MSDOS |
| @@ -2023,13 +2019,8 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */) | |||
| 2023 | S_IREAD | S_IWRITE); | 2019 | S_IREAD | S_IWRITE); |
| 2024 | #else /* not MSDOS */ | 2020 | #else /* not MSDOS */ |
| 2025 | { | 2021 | { |
| 2026 | mode_t new_mask = 0666; | 2022 | mode_t new_mask = !NILP (preserve_uid_gid) ? 0600 : 0666; |
| 2027 | if (input_file_statable_p) | 2023 | new_mask &= st.st_mode; |
| 2028 | { | ||
| 2029 | if (!NILP (preserve_uid_gid)) | ||
| 2030 | new_mask = 0600; | ||
| 2031 | new_mask &= st.st_mode; | ||
| 2032 | } | ||
| 2033 | ofd = emacs_open (SSDATA (encoded_newname), | 2024 | ofd = emacs_open (SSDATA (encoded_newname), |
| 2034 | (O_WRONLY | O_TRUNC | O_CREAT | 2025 | (O_WRONLY | O_TRUNC | O_CREAT |
| 2035 | | (NILP (ok_if_already_exists) ? O_EXCL : 0)), | 2026 | | (NILP (ok_if_already_exists) ? O_EXCL : 0)), |
| @@ -2051,25 +2042,24 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */) | |||
| 2051 | #ifndef MSDOS | 2042 | #ifndef MSDOS |
| 2052 | /* Preserve the original file modes, and if requested, also its | 2043 | /* Preserve the original file modes, and if requested, also its |
| 2053 | owner and group. */ | 2044 | owner and group. */ |
| 2054 | if (input_file_statable_p) | 2045 | { |
| 2055 | { | 2046 | mode_t mode_mask = 07777; |
| 2056 | mode_t mode_mask = 07777; | 2047 | if (!NILP (preserve_uid_gid)) |
| 2057 | if (!NILP (preserve_uid_gid)) | 2048 | { |
| 2058 | { | 2049 | /* Attempt to change owner and group. If that doesn't work |
| 2059 | /* Attempt to change owner and group. If that doesn't work | 2050 | attempt to change just the group, as that is sometimes allowed. |
| 2060 | attempt to change just the group, as that is sometimes allowed. | 2051 | Adjust the mode mask to eliminate setuid or setgid bits |
| 2061 | Adjust the mode mask to eliminate setuid or setgid bits | 2052 | that are inappropriate if the owner and group are wrong. */ |
| 2062 | that are inappropriate if the owner and group are wrong. */ | 2053 | if (fchown (ofd, st.st_uid, st.st_gid) != 0) |
| 2063 | if (fchown (ofd, st.st_uid, st.st_gid) != 0) | 2054 | { |
| 2064 | { | 2055 | mode_mask &= ~06000; |
| 2065 | mode_mask &= ~06000; | 2056 | if (fchown (ofd, -1, st.st_gid) == 0) |
| 2066 | if (fchown (ofd, -1, st.st_gid) == 0) | 2057 | mode_mask |= 02000; |
| 2067 | mode_mask |= 02000; | 2058 | } |
| 2068 | } | 2059 | } |
| 2069 | } | 2060 | if (fchmod (ofd, st.st_mode & mode_mask) != 0) |
| 2070 | if (fchmod (ofd, st.st_mode & mode_mask) != 0) | 2061 | report_file_error ("Doing chmod", Fcons (newname, Qnil)); |
| 2071 | report_file_error ("Doing chmod", Fcons (newname, Qnil)); | 2062 | } |
| 2072 | } | ||
| 2073 | #endif /* not MSDOS */ | 2063 | #endif /* not MSDOS */ |
| 2074 | 2064 | ||
| 2075 | #if HAVE_LIBSELINUX | 2065 | #if HAVE_LIBSELINUX |
| @@ -2085,16 +2075,13 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */) | |||
| 2085 | } | 2075 | } |
| 2086 | #endif | 2076 | #endif |
| 2087 | 2077 | ||
| 2088 | if (input_file_statable_p) | 2078 | if (!NILP (keep_time)) |
| 2089 | { | 2079 | { |
| 2090 | if (!NILP (keep_time)) | 2080 | EMACS_TIME atime = get_stat_atime (&st); |
| 2091 | { | 2081 | EMACS_TIME mtime = get_stat_mtime (&st); |
| 2092 | EMACS_TIME atime = get_stat_atime (&st); | 2082 | if (set_file_times (ofd, SSDATA (encoded_newname), atime, mtime)) |
| 2093 | EMACS_TIME mtime = get_stat_mtime (&st); | 2083 | xsignal2 (Qfile_date_error, |
| 2094 | if (set_file_times (ofd, SSDATA (encoded_newname), atime, mtime)) | 2084 | build_string ("Cannot set file date"), newname); |
| 2095 | xsignal2 (Qfile_date_error, | ||
| 2096 | build_string ("Cannot set file date"), newname); | ||
| 2097 | } | ||
| 2098 | } | 2085 | } |
| 2099 | 2086 | ||
| 2100 | if (emacs_close (ofd) < 0) | 2087 | if (emacs_close (ofd) < 0) |
| @@ -2103,15 +2090,12 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */) | |||
| 2103 | emacs_close (ifd); | 2090 | emacs_close (ifd); |
| 2104 | 2091 | ||
| 2105 | #ifdef MSDOS | 2092 | #ifdef MSDOS |
| 2106 | if (input_file_statable_p) | 2093 | /* In DJGPP v2.0 and later, fstat usually returns true file mode bits, |
| 2107 | { | 2094 | and if it can't, it tells so. Otherwise, under MSDOS we usually |
| 2108 | /* In DJGPP v2.0 and later, fstat usually returns true file mode bits, | 2095 | get only the READ bit, which will make the copied file read-only, |
| 2109 | and if it can't, it tells so. Otherwise, under MSDOS we usually | 2096 | so it's better not to chmod at all. */ |
| 2110 | get only the READ bit, which will make the copied file read-only, | 2097 | if ((_djstat_flags & _STFAIL_WRITEBIT) == 0) |
| 2111 | so it's better not to chmod at all. */ | 2098 | chmod (SDATA (encoded_newname), st.st_mode & 07777); |
| 2112 | if ((_djstat_flags & _STFAIL_WRITEBIT) == 0) | ||
| 2113 | chmod (SDATA (encoded_newname), st.st_mode & 07777); | ||
| 2114 | } | ||
| 2115 | #endif /* MSDOS */ | 2099 | #endif /* MSDOS */ |
| 2116 | #endif /* not WINDOWSNT */ | 2100 | #endif /* not WINDOWSNT */ |
| 2117 | 2101 | ||