fix and simplify futimesat fallback in utimensat
[musl] / src / stat / utimensat.c
1 #include <sys/stat.h>
2 #include <sys/time.h>
3 #include <fcntl.h>
4 #include <errno.h>
5 #include "syscall.h"
6
7 int utimensat(int fd, const char *path, const struct timespec times[2], int flags)
8 {
9         if (times && times[0].tv_nsec==UTIME_NOW && times[1].tv_nsec==UTIME_NOW)
10                 times = 0;
11         int r = __syscall(SYS_utimensat, fd, path, times, flags);
12 #ifdef SYS_futimesat
13         if (r != -ENOSYS || flags) return __syscall_ret(r);
14         struct timeval *tv = 0, tmp[2];
15         if (times) {
16                 int i;
17                 tv = tmp;
18                 for (i=0; i<2; i++) {
19                         if (times[i].tv_nsec >= 1000000000ULL) {
20                                 if (times[i].tv_nsec == UTIME_NOW
21                                  || times[i].tv_nsec == UTIME_OMIT)
22                                         return __syscall_ret(-ENOSYS);
23                                 return __syscall_ret(-EINVAL);
24                         }
25                         tmp[i].tv_sec = times[i].tv_sec;
26                         tmp[i].tv_usec = times[i].tv_nsec / 1000;
27                 }
28         }
29
30         r = __syscall(SYS_futimesat, fd, path, tv);
31         if (r != -ENOSYS || fd != AT_FDCWD) return __syscall_ret(r);
32         r = __syscall(SYS_utimes, path, tv);
33 #endif
34         return __syscall_ret(r);
35 }