1 /* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2006-2009, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include <sys/time.h> 9 10 #include <errno.h> 11 12 #include <NodeMonitor.h> 13 14 #include <errno_private.h> 15 #include <syscalls.h> 16 #include <syscall_utils.h> 17 18 19 int 20 _utimes(const char* path, const struct timeval times[2], bool traverseLink); 21 22 23 int 24 _utimes(const char* path, const struct timeval times[2], bool traverseLink) 25 { 26 struct stat stat; 27 status_t status; 28 29 if (times != NULL) { 30 stat.st_atim.tv_sec = times[0].tv_sec; 31 stat.st_atim.tv_nsec = times[0].tv_usec * 1000; 32 33 stat.st_mtim.tv_sec = times[1].tv_sec; 34 stat.st_mtim.tv_nsec = times[1].tv_usec * 1000; 35 } else { 36 bigtime_t now = real_time_clock_usecs(); 37 stat.st_atim.tv_sec = stat.st_mtim.tv_sec = now / 1000000; 38 stat.st_atim.tv_nsec = stat.st_mtim.tv_nsec = (now % 1000000) * 1000; 39 } 40 41 // traverseLeafLink == true 42 status = _kern_write_stat(AT_FDCWD, path, traverseLink, &stat, 43 sizeof(struct stat), B_STAT_MODIFICATION_TIME | B_STAT_ACCESS_TIME); 44 45 RETURN_AND_SET_ERRNO(status); 46 } 47 48 49 int 50 utimes(const char* path, const struct timeval times[2]) 51 { 52 return _utimes(path, times, true); 53 } 54 55 56 int 57 utimensat(int fd, const char *path, const struct timespec times[2], int flag) 58 { 59 struct stat stat; 60 status_t status; 61 uint32 mask = 0; 62 63 // Init the stat time fields to the current time, if at least one time is 64 // supposed to be set to it. 65 if (times == NULL || times[0].tv_nsec == UTIME_NOW 66 || times[1].tv_nsec == UTIME_NOW) { 67 bigtime_t now = real_time_clock_usecs(); 68 stat.st_atim.tv_sec = stat.st_mtim.tv_sec = now / 1000000; 69 stat.st_atim.tv_nsec = stat.st_mtim.tv_nsec = (now % 1000000) * 1000; 70 } 71 72 if (times != NULL) { 73 // access time 74 if (times[0].tv_nsec != UTIME_OMIT) { 75 mask |= B_STAT_ACCESS_TIME; 76 77 if (times[0].tv_nsec != UTIME_NOW) { 78 if (times[0].tv_nsec < 0 || times[0].tv_nsec > 999999999) 79 RETURN_AND_SET_ERRNO(EINVAL); 80 } 81 82 stat.st_atim = times[0]; 83 } 84 85 // modified time 86 if (times[1].tv_nsec != UTIME_OMIT) { 87 mask |= B_STAT_MODIFICATION_TIME; 88 89 if (times[1].tv_nsec != UTIME_NOW) { 90 if (times[1].tv_nsec < 0 || times[1].tv_nsec > 999999999) 91 RETURN_AND_SET_ERRNO(EINVAL); 92 } 93 94 stat.st_mtim = times[1]; 95 } 96 } else 97 mask |= B_STAT_ACCESS_TIME | B_STAT_MODIFICATION_TIME; 98 99 // set the times -- as per spec we even need to do this, if both have 100 // UTIME_OMIT set 101 status = _kern_write_stat(fd, path, (flag & AT_SYMLINK_NOFOLLOW) == 0, 102 &stat, sizeof(struct stat), mask); 103 104 RETURN_AND_SET_ERRNO(status); 105 } 106 107 108 int 109 futimens(int fd, const struct timespec times[2]) 110 { 111 return utimensat(fd, NULL, times, 0); 112 } 113