aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2020-03-07 12:04:05 -0800
committerPaul Eggert2020-03-07 12:15:43 -0800
commit5d4cf1fef85bc24bc4cd9705ebb14150263ad707 (patch)
treeaf696ed3ba7d2d0ab31951eba9482443d36c1456 /src
parent9f4b260c2b98ea05a02e0ab7213156ce2e60e5a9 (diff)
downloademacs-5d4cf1fef85bc24bc4cd9705ebb14150263ad707.tar.gz
emacs-5d4cf1fef85bc24bc4cd9705ebb14150263ad707.zip
Add ‘nofollow’ flag to set-file-times
This is a companion to the recent set-file-modes patch. It adds support for a ‘nofollow’ flag to set-file-times (Bug#39773). Like the set-file-modes patch, it needs work in the w32 port. * admin/merge-gnulib (GNULIB_MODULES): Add futimens, utimensat. Remove utimens. * doc/lispref/files.texi (Changing Files): * etc/NEWS: Mention the change. * lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate. * lisp/files.el (copy-directory): * lisp/gnus/gnus-cloud.el (gnus-cloud-replace-file): * lisp/net/tramp-adb.el (tramp-adb-handle-copy-file): * lisp/net/tramp-smb.el (tramp-smb-handle-copy-file): * lisp/tar-mode.el (tar-copy): * test/lisp/filenotify-tests.el (file-notify-test03-events): * test/lisp/files-tests.el: (files-tests-file-name-non-special-set-file-times): * test/lisp/net/tramp-tests.el (tramp-test22-file-times): When setting file times, avoid following symbolic links when the file is not supposed to be a symbolic link. * lib/futimens.c, lib/utimensat.c, m4/futimens.m4, m4/utimensat.m4: New files, copied from Gnulib. * lisp/gnus/gnus-cloud.el (gnus-cloud-replace-file): When creating a file that is not supposed to exist already, use the excl flag to check this. * lisp/net/tramp-adb.el (tramp-adb-handle-set-file-times): * lisp/net/tramp-sh.el (tramp-sh-handle-set-file-times): * lisp/net/tramp-sudoedit.el (tramp-sudoedit-handle-set-file-times): Accept an optional FLAG arg that is currently ignored, and add a FIXME comment for it. * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-set-file-times): * src/fileio.c (Fset_file_times): Support an optional FLAG arg. * src/fileio.c (Fcopy_file): Use futimens instead of set_file_times, as it’s simpler and is a POSIX API. * src/sysdep.c (set_file_times): Move from here ... * src/w32.c (set_file_times): ... to here, and make it static, since it is now used only in w32.c. Presumably w32.c should also add support for futimens and utimensat (the POSIX APIs, which Emacs now uses) and it can remove fdutimens (the Gnulib API, which Emacs no longer uses).
Diffstat (limited to 'src')
-rw-r--r--src/fileio.c51
-rw-r--r--src/sysdep.c15
-rw-r--r--src/systime.h3
-rw-r--r--src/w32.c15
4 files changed, 41 insertions, 43 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 2532f5233c4..82fd7989206 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2253,9 +2253,8 @@ permissions. */)
2253 2253
2254 if (!NILP (keep_time)) 2254 if (!NILP (keep_time))
2255 { 2255 {
2256 struct timespec atime = get_stat_atime (&st); 2256 struct timespec ts[] = { get_stat_atime (&st), get_stat_mtime (&st) };
2257 struct timespec mtime = get_stat_mtime (&st); 2257 if (futimens (ofd, ts) != 0)
2258 if (set_file_times (ofd, SSDATA (encoded_newname), atime, mtime) != 0)
2259 xsignal2 (Qfile_date_error, 2258 xsignal2 (Qfile_date_error,
2260 build_string ("Cannot set file date"), newname); 2259 build_string ("Cannot set file date"), newname);
2261 } 2260 }
@@ -3430,39 +3429,41 @@ The value is an integer. */)
3430} 3429}
3431 3430
3432 3431
3433DEFUN ("set-file-times", Fset_file_times, Sset_file_times, 1, 2, 0, 3432DEFUN ("set-file-times", Fset_file_times, Sset_file_times, 1, 3, 0,
3434 doc: /* Set times of file FILENAME to TIMESTAMP. 3433 doc: /* Set times of file FILENAME to TIMESTAMP.
3435Set both access and modification times. 3434If optional FLAG is `nofollow', do not follow FILENAME if it is a
3436Return t on success, else nil. 3435symbolic link. Set both access and modification times. Return t on
3437Use the current time if TIMESTAMP is nil. TIMESTAMP is in the format of 3436success, else nil. Use the current time if TIMESTAMP is nil.
3438`current-time'. */) 3437TIMESTAMP is in the format of `current-time'. */)
3439 (Lisp_Object filename, Lisp_Object timestamp) 3438 (Lisp_Object filename, Lisp_Object timestamp, Lisp_Object flag)
3440{ 3439{
3441 Lisp_Object absname, encoded_absname; 3440 int nofollow = symlink_nofollow_flag (flag);
3442 Lisp_Object handler;
3443 struct timespec t = lisp_time_argument (timestamp);
3444 3441
3445 absname = Fexpand_file_name (filename, BVAR (current_buffer, directory)); 3442 struct timespec ts[2];
3443 if (!NILP (timestamp))
3444 ts[0] = ts[1] = lisp_time_argument (timestamp);
3445 else
3446 ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW;
3446 3447
3447 /* If the file name has special constructs in it, 3448 /* If the file name has special constructs in it,
3448 call the corresponding file name handler. */ 3449 call the corresponding file name handler. */
3449 handler = Ffind_file_name_handler (absname, Qset_file_times); 3450 Lisp_Object
3451 absname = Fexpand_file_name (filename, BVAR (current_buffer, directory)),
3452 handler = Ffind_file_name_handler (absname, Qset_file_times);
3450 if (!NILP (handler)) 3453 if (!NILP (handler))
3451 return call3 (handler, Qset_file_times, absname, timestamp); 3454 return call4 (handler, Qset_file_times, absname, timestamp, flag);
3452 3455
3453 encoded_absname = ENCODE_FILE (absname); 3456 Lisp_Object encoded_absname = ENCODE_FILE (absname);
3454 3457
3455 { 3458 if (utimensat (AT_FDCWD, SSDATA (encoded_absname), ts, nofollow) != 0)
3456 if (set_file_times (-1, SSDATA (encoded_absname), t, t) != 0) 3459 {
3457 {
3458#ifdef MSDOS 3460#ifdef MSDOS
3459 /* Setting times on a directory always fails. */ 3461 /* Setting times on a directory always fails. */
3460 if (file_directory_p (encoded_absname)) 3462 if (file_directory_p (encoded_absname))
3461 return Qnil; 3463 return Qnil;
3462#endif 3464#endif
3463 report_file_error ("Setting file times", absname); 3465 report_file_error ("Setting file times", absname);
3464 } 3466 }
3465 }
3466 3467
3467 return Qt; 3468 return Qt;
3468} 3469}
diff --git a/src/sysdep.c b/src/sysdep.c
index e8e8bbfb502..149d80f19ec 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -2752,21 +2752,6 @@ emacs_perror (char const *message)
2752 errno = err; 2752 errno = err;
2753} 2753}
2754 2754
2755/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2756 ATIME and MTIME, respectively.
2757 FD must be either negative -- in which case it is ignored --
2758 or a file descriptor that is open on FILE.
2759 If FD is nonnegative, then FILE can be NULL. */
2760int
2761set_file_times (int fd, const char *filename,
2762 struct timespec atime, struct timespec mtime)
2763{
2764 struct timespec timespec[2];
2765 timespec[0] = atime;
2766 timespec[1] = mtime;
2767 return fdutimens (fd, filename, timespec);
2768}
2769
2770/* Rename directory SRCFD's entry SRC to directory DSTFD's entry DST. 2755/* Rename directory SRCFD's entry SRC to directory DSTFD's entry DST.
2771 This is like renameat except that it fails if DST already exists, 2756 This is like renameat except that it fails if DST already exists,
2772 or if this operation is not supported atomically. Return 0 if 2757 or if this operation is not supported atomically. Return 0 if
diff --git a/src/systime.h b/src/systime.h
index 00ca4a1c58d..b59a3d1c690 100644
--- a/src/systime.h
+++ b/src/systime.h
@@ -67,9 +67,6 @@ timespec_valid_p (struct timespec t)
67 return t.tv_nsec >= 0; 67 return t.tv_nsec >= 0;
68} 68}
69 69
70/* defined in sysdep.c */
71extern int set_file_times (int, const char *, struct timespec, struct timespec);
72
73/* defined in keyboard.c */ 70/* defined in keyboard.c */
74extern void set_waiting_for_input (struct timespec *); 71extern void set_waiting_for_input (struct timespec *);
75 72
diff --git a/src/w32.c b/src/w32.c
index cf1a3b37678..40f286ad6cf 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -3189,6 +3189,21 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2])
3189 } 3189 }
3190} 3190}
3191 3191
3192/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
3193 ATIME and MTIME, respectively.
3194 FD must be either negative -- in which case it is ignored --
3195 or a file descriptor that is open on FILE.
3196 If FD is nonnegative, then FILE can be NULL. */
3197static int
3198set_file_times (int fd, const char *filename,
3199 struct timespec atime, struct timespec mtime)
3200{
3201 struct timespec timespec[2];
3202 timespec[0] = atime;
3203 timespec[1] = mtime;
3204 return fdutimens (fd, filename, timespec);
3205}
3206
3192 3207
3193/* ------------------------------------------------------------------------- */ 3208/* ------------------------------------------------------------------------- */
3194/* IO support and wrapper functions for the Windows API. */ 3209/* IO support and wrapper functions for the Windows API. */