fix and simplify futimesat fallback in utimensat
authorRich Felker <dalias@aerifal.cx>
Sat, 27 Jul 2019 14:20:01 +0000 (10:20 -0400)
committerRich Felker <dalias@aerifal.cx>
Sat, 27 Jul 2019 17:43:13 +0000 (13:43 -0400)
previously the fallback wrongly failed with EINVAL rather than ENOSYS
when UTIME_NOW was used with one component but not both. commit
dd5f50da6f6c3df5647e922e47f8568a8896a752 introduced this behavior when
initially adding the fallback support.

instead, detect the case where both are UTIME_NOW early and replace
with a null times pointer; this may improve performance slightly (less
copy from user), and removes the complex logic from the fallback case.
it also makes things slightly simpler for adding time64 code paths.

src/stat/utimensat.c

index 159c8be..49d74c2 100644 (file)
@@ -6,6 +6,8 @@
 
 int utimensat(int fd, const char *path, const struct timespec times[2], int flags)
 {
+       if (times && times[0].tv_nsec==UTIME_NOW && times[1].tv_nsec==UTIME_NOW)
+               times = 0;
        int r = __syscall(SYS_utimensat, fd, path, times, flags);
 #ifdef SYS_futimesat
        if (r != -ENOSYS || flags) return __syscall_ret(r);
@@ -15,12 +17,8 @@ int utimensat(int fd, const char *path, const struct timespec times[2], int flag
                tv = tmp;
                for (i=0; i<2; i++) {
                        if (times[i].tv_nsec >= 1000000000ULL) {
-                               if (times[i].tv_nsec == UTIME_NOW &&
-                                   times[1-i].tv_nsec == UTIME_NOW) {
-                                       tv = 0;
-                                       break;
-                               }
-                               if (times[i].tv_nsec == UTIME_OMIT)
+                               if (times[i].tv_nsec == UTIME_NOW
+                                || times[i].tv_nsec == UTIME_OMIT)
                                        return __syscall_ret(-ENOSYS);
                                return __syscall_ret(-EINVAL);
                        }