utimensat.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. #include <sys/stat.h>
  2. #include <sys/time.h>
  3. #include <fcntl.h>
  4. #include <errno.h>
  5. #include "syscall.h"
  6. #define IS32BIT(x) !((x)+0x80000000ULL>>32)
  7. #define NS_SPECIAL(ns) ((ns)==UTIME_NOW || (ns)==UTIME_OMIT)
  8. int utimensat(int fd, const char *path, const struct timespec times[2], int flags)
  9. {
  10. int r;
  11. if (times && times[0].tv_nsec==UTIME_NOW && times[1].tv_nsec==UTIME_NOW)
  12. times = 0;
  13. #ifdef SYS_utimensat_time64
  14. r = -ENOSYS;
  15. time_t s0=0, s1=0;
  16. long ns0=0, ns1=0;
  17. if (times) {
  18. ns0 = times[0].tv_nsec;
  19. ns1 = times[1].tv_nsec;
  20. if (!NS_SPECIAL(ns0)) s0 = times[0].tv_sec;
  21. if (!NS_SPECIAL(ns1)) s1 = times[1].tv_sec;
  22. }
  23. if (SYS_utimensat == SYS_utimensat_time64 || !IS32BIT(s0) || !IS32BIT(s1))
  24. r = __syscall(SYS_utimensat_time64, fd, path, times ?
  25. ((long long[]){s0, ns0, s1, ns1}) : 0, flags);
  26. if (SYS_utimensat == SYS_utimensat_time64 || r!=-ENOSYS)
  27. return __syscall_ret(r);
  28. if (!IS32BIT(s0) || !IS32BIT(s1))
  29. return __syscall_ret(-ENOTSUP);
  30. r = __syscall(SYS_utimensat, fd, path,
  31. times ? ((long[]){s0, ns0, s1, ns1}) : 0, flags);
  32. #else
  33. r = __syscall(SYS_utimensat, fd, path, times, flags);
  34. #endif
  35. #ifdef SYS_futimesat
  36. if (r != -ENOSYS || flags) return __syscall_ret(r);
  37. long *tv=0, tmp[4];
  38. if (times) {
  39. int i;
  40. tv = tmp;
  41. for (i=0; i<2; i++) {
  42. if (times[i].tv_nsec >= 1000000000ULL) {
  43. if (NS_SPECIAL(times[i].tv_nsec))
  44. return __syscall_ret(-ENOSYS);
  45. return __syscall_ret(-EINVAL);
  46. }
  47. tmp[2*i+0] = times[i].tv_sec;
  48. tmp[2*i+1] = times[i].tv_nsec / 1000;
  49. }
  50. }
  51. r = __syscall(SYS_futimesat, fd, path, tv);
  52. if (r != -ENOSYS || fd != AT_FDCWD) return __syscall_ret(r);
  53. r = __syscall(SYS_utimes, path, tv);
  54. #endif
  55. return __syscall_ret(r);
  56. }