diff --git a/src/libfaketime.c b/src/libfaketime.c index f8d7479..eadd6b4 100644 --- a/src/libfaketime.c +++ b/src/libfaketime.c @@ -1351,9 +1351,22 @@ int utimes(const char *filename, const struct timeval times[2]) return result; } +static int fake_current_realtime(struct timespec *tp) +{ + int result; + + DONT_FAKE_TIME(result = (*real_clock_gettime)(CLOCK_REALTIME, tp)); + if (result == -1) + { + return -1; + } + + return fake_clock_gettime(CLOCK_REALTIME, tp); +} + /* This conditionally offsets 2 timespec values. The caller's out_times array * always contains valid translated values, even if in_times was NULL. */ -static void fake_two_timespec(const struct timespec in_times[2], struct timespec out_times[2]) +static int fake_two_timespec(const struct timespec in_times[2], struct timespec out_times[2]) { if (in_times == NULL) /* Translate NULL into 2 UTIME_NOW values */ { @@ -1362,7 +1375,7 @@ static void fake_two_timespec(const struct timespec in_times[2], struct timespec in_times = out_times; } struct timespec now; - now.tv_nsec = UTIME_OMIT; /* Wait to grab the current time to see if it's actually needed */ + int have_fake_now = 0; int j; for (j = 0; j <= 1; j++) { @@ -1371,11 +1384,15 @@ static void fake_two_timespec(const struct timespec in_times[2], struct timespec { if (fake_utime_disabled && in_times[j].tv_nsec == UTIME_NOW) { /* The user wants their given fake times left alone but they requested NOW, so turn it into fake NOW */ - if (now.tv_nsec == UTIME_OMIT) /* did we grab "now" yet? */ + if (!have_fake_now) { - DONT_FAKE_TIME(real_clock_gettime(CLOCK_REALTIME, &now)); + if (fake_current_realtime(&now) == -1) + { + return -1; + } + have_fake_now = 1; } - timeradd2(&now, &user_offset, &out_times[j], n); + out_times[j] = now; } else if (out_times != in_times) { /* Just preserve the input value */ @@ -1387,6 +1404,7 @@ static void fake_two_timespec(const struct timespec in_times[2], struct timespec timersub2(&in_times[j], &user_offset, &out_times[j], n); } } + return 0; } #ifdef MACOS_DYLD_INTERPOSE @@ -1400,7 +1418,10 @@ int utimensat(int dirfd, const char *filename, const struct timespec times[2], i int result; struct timespec tn[2]; - fake_two_timespec(times, tn); + if (fake_two_timespec(times, tn) == -1) + { + return -1; + } #ifdef MACOS_DYLD_INTERPOSE DONT_FAKE_TIME(result = utimensat(dirfd, filename, tn, flags)); #else @@ -1420,7 +1441,10 @@ int futimens(int fd, const struct timespec times[2]) int result; struct timespec tn[2]; - fake_two_timespec(times, tn); + if (fake_two_timespec(times, tn) == -1) + { + return -1; + } #ifdef MACOS_DYLD_INTERPOSE DONT_FAKE_TIME(result = futimens(fd, tn)); #else diff --git a/test/timetest.c b/test/timetest.c index 6c41634..e559b42 100644 --- a/test/timetest.c +++ b/test/timetest.c @@ -19,6 +19,7 @@ */ #define _GNU_SOURCE +#include #include #include #include @@ -56,6 +57,69 @@ static int fake_monotonic_clock = 0; static int fake_monotonic_clock = 1; #endif +static void test_utimens_now(void) +{ + char path[] = "/tmp/libfaketime-utimensat-XXXXXX"; + struct timespec now_times[2]; + int fd; + + fd = mkstemp(path); + if (fd == -1) + { + perror("mkstemp"); + exit(EXIT_FAILURE); + } + + if (utimensat(AT_FDCWD, path, NULL, 0) == -1) + { + perror("utimensat(NULL)"); + unlink(path); + exit(EXIT_FAILURE); + } + + if (futimens(fd, NULL) == -1) + { + perror("futimens(NULL)"); + close(fd); + unlink(path); + exit(EXIT_FAILURE); + } + + now_times[0].tv_sec = now_times[1].tv_sec = 0; + now_times[0].tv_nsec = now_times[1].tv_nsec = UTIME_NOW; + + if (utimensat(AT_FDCWD, path, now_times, 0) == -1) + { + perror("utimensat(UTIME_NOW)"); + close(fd); + unlink(path); + exit(EXIT_FAILURE); + } + + if (futimens(fd, now_times) == -1) + { + perror("futimens(UTIME_NOW)"); + close(fd); + unlink(path); + exit(EXIT_FAILURE); + } + + if (close(fd) == -1) + { + perror("close"); + unlink(path); + exit(EXIT_FAILURE); + } + + if (unlink(path) == -1) + { + perror("unlink"); + exit(EXIT_FAILURE); + } + + printf("utimensat()/futimens(): NOW handling passed\n"); +} + static void handler(int sig, siginfo_t *si, void *uc) { @@ -305,6 +369,7 @@ printf("%s", 0 == 1 ? argv[0] : ""); printf("gettimeofday() : Current date and time: %s", ctime(&tv.tv_sec)); #ifndef __APPLE__ + test_utimens_now(); if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) { perror("sigprocmask");