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 extern int 23 _utimes(const char* path, const struct timeval times[2], bool traverseLink) 24 { 25 struct stat stat; 26 status_t status; 27 28 if (times != NULL) { 29 stat.st_atim.tv_sec = times[0].tv_sec; 30 stat.st_atim.tv_nsec = times[0].tv_usec * 1000; 31 32 stat.st_mtim.tv_sec = times[1].tv_sec; 33 stat.st_mtim.tv_nsec = times[1].tv_usec * 1000; 34 } else { 35 bigtime_t now = real_time_clock_usecs(); 36 stat.st_atim.tv_sec = stat.st_mtim.tv_sec = now / 1000000; 37 stat.st_atim.tv_nsec = stat.st_mtim.tv_nsec = (now % 1000000) * 1000; 38 } 39 40 // traverseLeafLink == true 41 status = _kern_write_stat(-1, path, traverseLink, &stat, 42 sizeof(struct stat), B_STAT_MODIFICATION_TIME | B_STAT_ACCESS_TIME); 43 44 RETURN_AND_SET_ERRNO(status); 45 } 46 47 48 int 49 utimes(const char* path, const struct timeval times[2]) 50 { 51 return _utimes(path, times, true); 52 } 53 54 55 int 56 utimensat(int fd, const char *path, const struct timespec times[2], int flag) 57 { 58 struct stat stat; 59 status_t status; 60 uint32 mask = 0; 61 62 // Init the stat time fields to the current time, if at least one time is 63 // supposed to be set to it. 64 if (times == NULL || times[0].tv_nsec == UTIME_NOW 65 || times[1].tv_nsec == UTIME_NOW) { 66 bigtime_t now = real_time_clock_usecs(); 67 stat.st_atim.tv_sec = stat.st_mtim.tv_sec = now / 1000000; 68 stat.st_atim.tv_nsec = stat.st_mtim.tv_nsec = (now % 1000000) * 1000; 69 } 70 71 if (times != NULL) { 72 // access time 73 if (times[0].tv_nsec != UTIME_OMIT) { 74 mask |= B_STAT_ACCESS_TIME; 75 76 if (times[0].tv_nsec != UTIME_NOW) { 77 if (times[0].tv_nsec < 0 || times[0].tv_nsec > 999999999) 78 RETURN_AND_SET_ERRNO(EINVAL); 79 } 80 81 stat.st_atim = times[0]; 82 } 83 84 // modified time 85 if (times[1].tv_nsec != UTIME_OMIT) { 86 mask |= B_STAT_MODIFICATION_TIME; 87 88 if (times[1].tv_nsec != UTIME_NOW) { 89 if (times[1].tv_nsec < 0 || times[1].tv_nsec > 999999999) 90 RETURN_AND_SET_ERRNO(EINVAL); 91 } 92 93 stat.st_mtim = times[1]; 94 } 95 } else 96 mask |= B_STAT_ACCESS_TIME | B_STAT_MODIFICATION_TIME; 97 98 // set the times -- as per spec we even need to do this, if both have 99 // UTIME_OMIT set 100 status = _kern_write_stat(fd, path, (flag & AT_SYMLINK_NOFOLLOW) == 0, 101 &stat, sizeof(struct stat), mask); 102 103 RETURN_AND_SET_ERRNO(status); 104 } 105 106 107 int 108 futimens(int fd, const struct timespec times[2]) 109 { 110 return utimensat(fd, NULL, times, 0); 111 } 112