summaryrefslogtreecommitdiff
path: root/m4
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2020-03-07 12:04:05 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2020-03-07 12:15:43 -0800
commit5d4cf1fef85bc24bc4cd9705ebb14150263ad707 (patch)
treeaf696ed3ba7d2d0ab31951eba9482443d36c1456 /m4
parent9f4b260c2b98ea05a02e0ab7213156ce2e60e5a9 (diff)
downloademacs-5d4cf1fef85bc24bc4cd9705ebb14150263ad707.tar.gz
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 'm4')
-rw-r--r--m4/futimens.m465
-rw-r--r--m4/gnulib-comp.m438
-rw-r--r--m4/utimensat.m469
3 files changed, 171 insertions, 1 deletions
diff --git a/m4/futimens.m4 b/m4/futimens.m4
new file mode 100644
index 00000000000..dc5cfa94119
--- /dev/null
+++ b/m4/futimens.m4
@@ -0,0 +1,65 @@
+# serial 8
+# See if we need to provide futimens replacement.
+
+dnl Copyright (C) 2009-2020 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+# Written by Eric Blake.
+
+AC_DEFUN([gl_FUNC_FUTIMENS],
+[
+ AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+ AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+ AC_CHECK_FUNCS_ONCE([futimens])
+ if test $ac_cv_func_futimens = no; then
+ HAVE_FUTIMENS=0
+ else
+ AC_CACHE_CHECK([whether futimens works],
+ [gl_cv_func_futimens_works],
+ [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+]], [[struct timespec ts[2];
+ int fd = creat ("conftest.file", 0600);
+ struct stat st;
+ if (fd < 0) return 1;
+ ts[0].tv_sec = 1;
+ ts[0].tv_nsec = UTIME_OMIT;
+ ts[1].tv_sec = 1;
+ ts[1].tv_nsec = UTIME_NOW;
+ errno = 0;
+ if (futimens (AT_FDCWD, NULL) == 0) return 2;
+ if (errno != EBADF) return 3;
+ if (futimens (fd, ts)) return 4;
+ sleep (1);
+ ts[0].tv_nsec = UTIME_NOW;
+ ts[1].tv_nsec = UTIME_OMIT;
+ if (futimens (fd, ts)) return 5;
+ if (fstat (fd, &st)) return 6;
+ if (st.st_ctime < st.st_atime) return 7;
+ ]])],
+ [gl_cv_func_futimens_works=yes],
+ [gl_cv_func_futimens_works=no],
+ [case "$host_os" in
+ # Guess no on glibc systems.
+ *-gnu* | gnu*) gl_cv_func_futimens_works="guessing no" ;;
+ # Guess no on musl systems.
+ *-musl*) gl_cv_func_futimens_works="guessing no" ;;
+ # Guess yes otherwise.
+ *) gl_cv_func_futimens_works="guessing yes" ;;
+ esac
+ ])
+ rm -f conftest.file])
+ case "$gl_cv_func_futimens_works" in
+ *yes) ;;
+ *)
+ REPLACE_FUTIMENS=1
+ ;;
+ esac
+ fi
+])
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 1465ce811b8..3228aa42b57 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -95,6 +95,7 @@ AC_DEFUN([gl_EARLY],
# Code from module fstatat:
# Code from module fsusage:
# Code from module fsync:
+ # Code from module futimens:
# Code from module getdtablesize:
# Code from module getgroups:
# Code from module getloadavg:
@@ -179,6 +180,7 @@ AC_DEFUN([gl_EARLY],
# Code from module unlocked-io:
# Code from module update-copyright:
# Code from module utimens:
+ # Code from module utimensat:
# Code from module vararrays:
# Code from module verify:
# Code from module vla:
@@ -297,6 +299,11 @@ AC_DEFUN([gl_INIT],
gl_PREREQ_FSYNC
fi
gl_UNISTD_MODULE_INDICATOR([fsync])
+ gl_FUNC_FUTIMENS
+ if test $HAVE_FUTIMENS = 0 || test $REPLACE_FUTIMENS = 1; then
+ AC_LIBOBJ([futimens])
+ fi
+ gl_SYS_STAT_MODULE_INDICATOR([futimens])
gl_GETLOADAVG
if test $HAVE_GETLOADAVG = 0; then
AC_LIBOBJ([getloadavg])
@@ -466,7 +473,11 @@ AC_DEFUN([gl_INIT],
gl_TIMESPEC
gl_UNISTD_H
gl_FUNC_GLIBC_UNLOCKED_IO
- gl_UTIMENS
+ gl_FUNC_UTIMENSAT
+ if test $HAVE_UTIMENSAT = 0 || test $REPLACE_UTIMENSAT = 1; then
+ AC_LIBOBJ([utimensat])
+ fi
+ gl_SYS_STAT_MODULE_INDICATOR([utimensat])
AC_C_VARARRAYS
gl_gnulib_enabled_260941c0e5dc67ec9e87d1fb321c300b=false
gl_gnulib_enabled_cloexec=false
@@ -485,6 +496,7 @@ AC_DEFUN([gl_INIT],
gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7=false
gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=false
gl_gnulib_enabled_strtoll=false
+ gl_gnulib_enabled_utimens=false
gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec=false
func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b ()
{
@@ -663,6 +675,13 @@ AC_DEFUN([gl_INIT],
gl_gnulib_enabled_strtoll=true
fi
}
+ func_gl_gnulib_m4code_utimens ()
+ {
+ if ! $gl_gnulib_enabled_utimens; then
+ gl_UTIMENS
+ gl_gnulib_enabled_utimens=true
+ fi
+ }
func_gl_gnulib_m4code_682e609604ccaac6be382e4ee3a4eaec ()
{
if ! $gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec; then
@@ -705,6 +724,9 @@ AC_DEFUN([gl_INIT],
if test $HAVE_FSTATAT = 0 || test $REPLACE_FSTATAT = 1; then
func_gl_gnulib_m4code_03e0aaad4cb89ca757653bd367a6ccb7
fi
+ if test $HAVE_FUTIMENS = 0 || test $REPLACE_FUTIMENS = 1; then
+ func_gl_gnulib_m4code_utimens
+ fi
if test $REPLACE_GETOPT = 1; then
func_gl_gnulib_m4code_be453cec5eecf5731a274f2de7f2db36
fi
@@ -729,6 +751,15 @@ AC_DEFUN([gl_INIT],
if test $HAVE_TIMEGM = 0 || test $REPLACE_TIMEGM = 1; then
func_gl_gnulib_m4code_5264294aa0a5557541b53c8c741f7f31
fi
+ if test $HAVE_UTIMENSAT = 0 || test $REPLACE_UTIMENSAT = 1; then
+ func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b
+ fi
+ if test $HAVE_UTIMENSAT = 0 || test $REPLACE_UTIMENSAT = 1; then
+ func_gl_gnulib_m4code_03e0aaad4cb89ca757653bd367a6ccb7
+ fi
+ if test $HAVE_UTIMENSAT = 0 || test $REPLACE_UTIMENSAT = 1; then
+ func_gl_gnulib_m4code_utimens
+ fi
m4_pattern_allow([^gl_GNULIB_ENABLED_])
AM_CONDITIONAL([gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b], [$gl_gnulib_enabled_260941c0e5dc67ec9e87d1fb321c300b])
AM_CONDITIONAL([gl_GNULIB_ENABLED_cloexec], [$gl_gnulib_enabled_cloexec])
@@ -747,6 +778,7 @@ AC_DEFUN([gl_INIT],
AM_CONDITIONAL([gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7], [$gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7])
AM_CONDITIONAL([gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c], [$gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c])
AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoll], [$gl_gnulib_enabled_strtoll])
+ AM_CONDITIONAL([gl_GNULIB_ENABLED_utimens], [$gl_gnulib_enabled_utimens])
AM_CONDITIONAL([gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec], [$gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec])
# End of code from modules
m4_ifval(gl_LIBSOURCES_LIST, [
@@ -956,6 +988,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/fsync.c
lib/ftoastr.c
lib/ftoastr.h
+ lib/futimens.c
lib/get-permissions.c
lib/getdtablesize.c
lib/getgroups.c
@@ -1063,6 +1096,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/unlocked-io.h
lib/utimens.c
lib/utimens.h
+ lib/utimensat.c
lib/verify.h
lib/vla.h
lib/warn-on-use.h
@@ -1103,6 +1137,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/fstatat.m4
m4/fsusage.m4
m4/fsync.m4
+ m4/futimens.m4
m4/getdtablesize.m4
m4/getgroups.m4
m4/getloadavg.m4
@@ -1184,6 +1219,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/unistd_h.m4
m4/unlocked-io.m4
m4/utimens.m4
+ m4/utimensat.m4
m4/utimes.m4
m4/vararrays.m4
m4/warn-on-use.m4
diff --git a/m4/utimensat.m4 b/m4/utimensat.m4
new file mode 100644
index 00000000000..2bc1bfebb5d
--- /dev/null
+++ b/m4/utimensat.m4
@@ -0,0 +1,69 @@
+# serial 6
+# See if we need to provide utimensat replacement.
+
+dnl Copyright (C) 2009-2020 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+# Written by Eric Blake.
+
+AC_DEFUN([gl_FUNC_UTIMENSAT],
+[
+ AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
+ AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+ AC_CHECK_FUNCS_ONCE([utimensat])
+ if test $ac_cv_func_utimensat = no; then
+ HAVE_UTIMENSAT=0
+ else
+ AC_CACHE_CHECK([whether utimensat works],
+ [gl_cv_func_utimensat_works],
+ [AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM([[
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+]], [[int result = 0;
+ const char *f = "conftest.file";
+ if (close (creat (f, 0600)))
+ return 1;
+ /* Test whether the AT_SYMLINK_NOFOLLOW flag is supported. */
+ {
+ if (utimensat (AT_FDCWD, f, NULL, AT_SYMLINK_NOFOLLOW))
+ result |= 2;
+ }
+ /* Test whether UTIME_NOW and UTIME_OMIT work. */
+ {
+ struct timespec ts[2];
+ ts[0].tv_sec = 1;
+ ts[0].tv_nsec = UTIME_OMIT;
+ ts[1].tv_sec = 1;
+ ts[1].tv_nsec = UTIME_NOW;
+ if (utimensat (AT_FDCWD, f, ts, 0))
+ result |= 4;
+ }
+ sleep (1);
+ {
+ struct stat st;
+ struct timespec ts[2];
+ ts[0].tv_sec = 1;
+ ts[0].tv_nsec = UTIME_NOW;
+ ts[1].tv_sec = 1;
+ ts[1].tv_nsec = UTIME_OMIT;
+ if (utimensat (AT_FDCWD, f, ts, 0))
+ result |= 8;
+ if (stat (f, &st))
+ result |= 16;
+ else if (st.st_ctime < st.st_atime)
+ result |= 32;
+ }
+ return result;
+ ]])],
+ [gl_cv_func_utimensat_works=yes],
+ [gl_cv_func_utimensat_works=no],
+ [gl_cv_func_utimensat_works="guessing yes"])])
+ if test "$gl_cv_func_utimensat_works" = no; then
+ REPLACE_UTIMENSAT=1
+ fi
+ fi
+])