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