Mercurial > gnulib
changeset 39249:5d69f74071ad
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.
author | Paul Eggert <eggert@cs.ucla.edu> |
---|---|
date | Tue, 20 Feb 2018 09:06:51 -0800 |
parents | c60b370bde79 |
children | c85653e2475a |
files | ChangeLog lib/utimecmp.c lib/utimecmp.h modules/utimecmp |
diffstat | 4 files changed, 49 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- 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 <eggert@cs.ucla.edu> + 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.
--- 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 <fcntl.h> #include <limits.h> #include <stdbool.h> #include <stdint.h> #include <stdlib.h> +#include <sys/stat.h> #include <time.h> #include <unistd.h> +#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)