summaryrefslogtreecommitdiff
path: root/src/metastore.c
diff options
context:
space:
mode:
authorPrzemyslaw Pawelczyk <przemoc@gmail.com>2022-05-21 16:01:23 +0200
committerPrzemyslaw Pawelczyk <przemoc@gmail.com>2022-05-21 16:01:23 +0200
commita20cb5571cf8271a52344c0320e65bc2369ecddd (patch)
treedcedd5e84c4e032ffb1fc297a6b3abfa73241d65 /src/metastore.c
parent72c21c112b209b2d092de2fd1750b6741bb187e3 (diff)
metastore.c: Do not skip nanoseconds when applying mtime.
Apply mtime using utimensat() instead of utime(), which not only supports setting nanoseconds, but also omitting atime change (last access time), and working on symlinks - we use all of that. Reported-by: Björn Haßler <bjohas@users.noreply.github.com>
Diffstat (limited to 'src/metastore.c')
-rw-r--r--src/metastore.c22
1 files changed, 10 insertions, 12 deletions
diff --git a/src/metastore.c b/src/metastore.c
index c6f48cf..bf6f416 100644
--- a/src/metastore.c
+++ b/src/metastore.c
@@ -24,7 +24,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <getopt.h>
-#include <utime.h>
+#include <fcntl.h>
#if !defined(NO_XATTR) || !(NO_XATTR+0)
# include <sys/xattr.h>
@@ -144,7 +144,7 @@ compare_fix(struct metaentry *real, struct metaentry *stored, int cmp)
struct passwd *owner;
gid_t gid = -1;
uid_t uid = -1;
- struct utimbuf tbuf;
+ struct timespec times[2];
unsigned i;
if (!real && !stored) {
@@ -222,16 +222,14 @@ compare_fix(struct metaentry *real, struct metaentry *stored, int cmp)
msg(MSG_DEBUG, "\tchmod failed: %s\n", strerror(errno));
}
- /* FIXME: Use utimensat here, or even better - lutimensat */
- if ((cmp & DIFF_MTIME) && S_ISLNK(real->mode)) {
- msg(MSG_NORMAL, "%s:\tsymlink, not changing mtime\n", real->path);
- } else if (cmp & DIFF_MTIME) {
- msg(MSG_NORMAL, "%s:\tchanging mtime from %ld to %ld\n",
- real->path, real->mtime, stored->mtime);
- tbuf.actime = stored->mtime;
- tbuf.modtime = stored->mtime;
- if (utime(real->path, &tbuf)) {
- msg(MSG_DEBUG, "\tutime failed: %s\n", strerror(errno));
+ if (cmp & DIFF_MTIME) {
+ msg(MSG_NORMAL, "%s:\tchanging mtime from %ld.%09d to %ld.%09d\n",
+ real->path, real->mtime, real->mtimensec, stored->mtime, stored->mtimensec);
+ times[0].tv_nsec = UTIME_OMIT; // atime (last access time)
+ times[1].tv_sec = stored->mtime; // mtime (last modification time)
+ times[1].tv_nsec = stored->mtimensec;
+ if (utimensat(AT_FDCWD, real->path, times, AT_SYMLINK_NOFOLLOW)) {
+ msg(MSG_DEBUG, "\tutimensat failed: %s\n", strerror(errno));
return;
}
}