# HG changeset patch # User Paul Eggert # Date 1519146411 28800 # Node ID 5d69f74071ad52505d3d43e02772a4bd06611f40 # Parent c60b370bde7947f2b7afe567b019615e16ebc34b utimecmp: new function utimecmpat * lib/utimecmp.c: Include fcntl.h, sys/stat.h and dirname.h. Do not include utimens.h. (utimecmpat): New function, generalizing utimecmp. (utimecmp): Now a thin layer around utimecmpat. * modules/utimecmp (Depends-on): Depend on dirname-lgpl, fstatat, utimensat instead of on lstat and utimens. diff -r c60b370bde79 -r 5d69f74071ad ChangeLog --- a/ChangeLog Tue Feb 20 09:05:48 2018 -0800 +++ b/ChangeLog Tue Feb 20 09:06:51 2018 -0800 @@ -1,5 +1,13 @@ 2018-02-20 Paul Eggert + utimecmp: new function utimecmpat + * lib/utimecmp.c: Include fcntl.h, sys/stat.h and dirname.h. + Do not include utimens.h. + (utimecmpat): New function, generalizing utimecmp. + (utimecmp): Now a thin layer around utimecmpat. + * modules/utimecmp (Depends-on): Depend on dirname-lgpl, fstatat, + utimensat instead of on lstat and utimens. + same: new function same_nameat * lib/same.c: Include fcntl.h. * lib/same.c (same_nameat): New function, generalizing same_name. diff -r c60b370bde79 -r 5d69f74071ad lib/utimecmp.c --- a/lib/utimecmp.c Tue Feb 20 09:05:48 2018 -0800 +++ b/lib/utimecmp.c Tue Feb 20 09:06:51 2018 -0800 @@ -21,17 +21,19 @@ #include "utimecmp.h" +#include #include #include #include #include +#include #include #include +#include "dirname.h" #include "hash.h" #include "intprops.h" #include "stat-time.h" -#include "utimens.h" #include "verify.h" #ifndef MAX @@ -103,7 +105,8 @@ return a->dev == b->dev; } -/* Return -1, 0, 1 based on whether the destination file (with name +/* Return -1, 0, 1 based on whether the destination file (relative + to openat-like directory file descriptor DFD with name DST_NAME and status DST_STAT) is older than SRC_STAT, the same age as SRC_STAT, or newer than SRC_STAT, respectively. @@ -122,6 +125,15 @@ struct stat const *src_stat, int options) { + return utimecmpat (AT_FDCWD, dst_name, dst_stat, src_stat, options); +} + +int +utimecmpat (int dfd, char const *dst_name, + struct stat const *dst_stat, + struct stat const *src_stat, + int options) +{ /* Things to watch out for: The code uses a static hash table internally and is not safe in the @@ -216,7 +228,24 @@ /* If the system will tell us the resolution, we're set! */ if (! dst_res->exact) { - res = pathconf (dst_name, _PC_TIMESTAMP_RESOLUTION); + res = -1; + if (dfd == AT_FDCWD) + res = pathconf (dst_name, _PC_TIMESTAMP_RESOLUTION); + else + { + char *dstdir = mdir_name (dst_name); + if (dstdir) + { + int destdirfd = openat (dfd, dstdir, + O_SEARCH | O_CLOEXEC | O_DIRECTORY); + if (0 <= destdirfd) + { + res = fpathconf (destdirfd, _PC_TIMESTAMP_RESOLUTION); + close (destdirfd); + } + free (dstdir); + } + } if (0 < res) { dst_res->resolution = res; @@ -311,19 +340,13 @@ timespec[1].tv_sec = dst_m_s | (res == 2 * BILLION); timespec[1].tv_nsec = dst_m_ns + res / 9; - /* Set the modification time. But don't try to set the - modification time of symbolic links; on many hosts this sets - the time of the pointed-to file. */ - if ((S_ISLNK (dst_stat->st_mode) - ? lutimens (dst_name, timespec) - : utimens (dst_name, timespec)) != 0) + if (utimensat (dfd, dst_name, timespec, AT_SYMLINK_NOFOLLOW)) return -2; /* Read the modification time that was set. */ { - int stat_result = (S_ISLNK (dst_stat->st_mode) - ? lstat (dst_name, &dst_status) - : stat (dst_name, &dst_status)); + int stat_result + = fstatat (dfd, dst_name, &dst_status, AT_SYMLINK_NOFOLLOW); if (stat_result | (dst_status.st_mtime ^ dst_m_s) @@ -333,10 +356,7 @@ it changed. Change it back as best we can. */ timespec[1].tv_sec = dst_m_s; timespec[1].tv_nsec = dst_m_ns; - if (S_ISLNK (dst_stat->st_mode)) - lutimens (dst_name, timespec); - else - utimens (dst_name, timespec); + utimensat (dfd, dst_name, timespec, AT_SYMLINK_NOFOLLOW); } if (stat_result != 0) diff -r c60b370bde79 -r 5d69f74071ad lib/utimecmp.h --- a/lib/utimecmp.h Tue Feb 20 09:05:48 2018 -0800 +++ b/lib/utimecmp.h Tue Feb 20 09:06:51 2018 -0800 @@ -33,5 +33,7 @@ }; int utimecmp (char const *, struct stat const *, struct stat const *, int); +int utimecmpat (int, char const *, struct stat const *, struct stat const *, + int); #endif diff -r c60b370bde79 -r 5d69f74071ad modules/utimecmp --- a/modules/utimecmp Tue Feb 20 09:05:48 2018 -0800 +++ b/modules/utimecmp Tue Feb 20 09:06:51 2018 -0800 @@ -7,12 +7,13 @@ m4/utimecmp.m4 Depends-on: +dirname-lgpl +fstatat hash stat-time time -utimens +utimensat intprops -lstat stdbool stdint verify