xref: /xnu-11215.61.5/libsyscall/wrappers/utimensat.c (revision 4f1223e81cd707a65cc109d0b8ad6653699da3c4)
1*4f1223e8SApple OSS Distributions /*
2*4f1223e8SApple OSS Distributions  * Copyright (c) 2006, 2017 Apple Computer, Inc. All rights reserved.
3*4f1223e8SApple OSS Distributions  *
4*4f1223e8SApple OSS Distributions  * @APPLE_LICENSE_HEADER_START@
5*4f1223e8SApple OSS Distributions  *
6*4f1223e8SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*4f1223e8SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*4f1223e8SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*4f1223e8SApple OSS Distributions  * compliance with the License. Please obtain a copy of the License at
10*4f1223e8SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this
11*4f1223e8SApple OSS Distributions  * file.
12*4f1223e8SApple OSS Distributions  *
13*4f1223e8SApple OSS Distributions  * The Original Code and all software distributed under the License are
14*4f1223e8SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15*4f1223e8SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16*4f1223e8SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17*4f1223e8SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18*4f1223e8SApple OSS Distributions  * Please see the License for the specific language governing rights and
19*4f1223e8SApple OSS Distributions  * limitations under the License.
20*4f1223e8SApple OSS Distributions  *
21*4f1223e8SApple OSS Distributions  * @APPLE_LICENSE_HEADER_END@
22*4f1223e8SApple OSS Distributions  */
23*4f1223e8SApple OSS Distributions 
24*4f1223e8SApple OSS Distributions #include <sys/types.h>
25*4f1223e8SApple OSS Distributions #include <sys/stat.h>
26*4f1223e8SApple OSS Distributions #include <sys/attr.h>
27*4f1223e8SApple OSS Distributions #include <sys/time.h>
28*4f1223e8SApple OSS Distributions #include <sys/fcntl.h>
29*4f1223e8SApple OSS Distributions #include <unistd.h>
30*4f1223e8SApple OSS Distributions #include <strings.h>
31*4f1223e8SApple OSS Distributions 
32*4f1223e8SApple OSS Distributions extern int __gettimeofday(struct timeval *, struct timezone *);
33*4f1223e8SApple OSS Distributions extern int __commpage_gettimeofday(struct timeval *);
34*4f1223e8SApple OSS Distributions 
35*4f1223e8SApple OSS Distributions static struct timespec times_now[2] = {
36*4f1223e8SApple OSS Distributions 	{ .tv_nsec = UTIME_NOW },
37*4f1223e8SApple OSS Distributions 	{ .tv_nsec = UTIME_NOW }
38*4f1223e8SApple OSS Distributions };
39*4f1223e8SApple OSS Distributions 
40*4f1223e8SApple OSS Distributions /*
41*4f1223e8SApple OSS Distributions  * Resolve any UTIME_NOW or UTIME_OMIT and return the attributes buffer and
42*4f1223e8SApple OSS Distributions  * attributes to pass.  Assumes times_in is writable.
43*4f1223e8SApple OSS Distributions  */
44*4f1223e8SApple OSS Distributions static int
prepare_times_array_and_attrs(struct timespec times_in[2],struct timespec times_out[2],size_t * times_out_size,int * flags)45*4f1223e8SApple OSS Distributions prepare_times_array_and_attrs(struct timespec times_in[2],
46*4f1223e8SApple OSS Distributions     struct timespec times_out[2], size_t *times_out_size, int *flags)
47*4f1223e8SApple OSS Distributions {
48*4f1223e8SApple OSS Distributions 	if (times_in[0].tv_nsec == UTIME_OMIT &&
49*4f1223e8SApple OSS Distributions 	    times_in[1].tv_nsec == UTIME_OMIT) {
50*4f1223e8SApple OSS Distributions 		return 0;
51*4f1223e8SApple OSS Distributions 	}
52*4f1223e8SApple OSS Distributions 
53*4f1223e8SApple OSS Distributions 	if (times_in[0].tv_nsec == UTIME_NOW ||
54*4f1223e8SApple OSS Distributions 	    times_in[1].tv_nsec == UTIME_NOW) {
55*4f1223e8SApple OSS Distributions 		if (times_in[0].tv_nsec == UTIME_NOW &&
56*4f1223e8SApple OSS Distributions 		    times_in[1].tv_nsec == UTIME_NOW) {
57*4f1223e8SApple OSS Distributions 			*flags |= FSOPT_UTIMES_NULL;
58*4f1223e8SApple OSS Distributions 		}
59*4f1223e8SApple OSS Distributions 		struct timespec now = {};
60*4f1223e8SApple OSS Distributions 		{
61*4f1223e8SApple OSS Distributions 			/*
62*4f1223e8SApple OSS Distributions 			 * TODO: Replace with nanosecond time when available
63*4f1223e8SApple OSS Distributions 			 */
64*4f1223e8SApple OSS Distributions 			struct timeval tv;
65*4f1223e8SApple OSS Distributions 			if (__commpage_gettimeofday(&tv) != 0) {
66*4f1223e8SApple OSS Distributions 				__gettimeofday(&tv, NULL);
67*4f1223e8SApple OSS Distributions 			}
68*4f1223e8SApple OSS Distributions 			TIMEVAL_TO_TIMESPEC(&tv, &now);
69*4f1223e8SApple OSS Distributions 		}
70*4f1223e8SApple OSS Distributions 
71*4f1223e8SApple OSS Distributions 		if (times_in[0].tv_nsec == UTIME_NOW) {
72*4f1223e8SApple OSS Distributions 			times_in[0] = now;
73*4f1223e8SApple OSS Distributions 		}
74*4f1223e8SApple OSS Distributions 		if (times_in[1].tv_nsec == UTIME_NOW) {
75*4f1223e8SApple OSS Distributions 			times_in[1] = now;
76*4f1223e8SApple OSS Distributions 		}
77*4f1223e8SApple OSS Distributions 	}
78*4f1223e8SApple OSS Distributions 
79*4f1223e8SApple OSS Distributions 	int attrs = 0;
80*4f1223e8SApple OSS Distributions 	*times_out_size = 0;
81*4f1223e8SApple OSS Distributions 	struct timespec *times_cursor = times_out;
82*4f1223e8SApple OSS Distributions 	if (times_in[1].tv_nsec != UTIME_OMIT) {
83*4f1223e8SApple OSS Distributions 		attrs |= ATTR_CMN_MODTIME;
84*4f1223e8SApple OSS Distributions 		*times_cursor++ = times_in[1];
85*4f1223e8SApple OSS Distributions 		*times_out_size += sizeof(struct timespec);
86*4f1223e8SApple OSS Distributions 	}
87*4f1223e8SApple OSS Distributions 	if (times_in[0].tv_nsec != UTIME_OMIT) {
88*4f1223e8SApple OSS Distributions 		attrs |= ATTR_CMN_ACCTIME;
89*4f1223e8SApple OSS Distributions 		*times_cursor = times_in[0];
90*4f1223e8SApple OSS Distributions 		*times_out_size += sizeof(struct timespec);
91*4f1223e8SApple OSS Distributions 	}
92*4f1223e8SApple OSS Distributions 	return attrs;
93*4f1223e8SApple OSS Distributions }
94*4f1223e8SApple OSS Distributions 
95*4f1223e8SApple OSS Distributions int
futimens(int fd,const struct timespec _times_in[2])96*4f1223e8SApple OSS Distributions futimens(int fd, const struct timespec _times_in[2])
97*4f1223e8SApple OSS Distributions {
98*4f1223e8SApple OSS Distributions 	struct timespec times_in[2];
99*4f1223e8SApple OSS Distributions 	int flags_out;
100*4f1223e8SApple OSS Distributions 
101*4f1223e8SApple OSS Distributions 	if (_times_in != NULL) {
102*4f1223e8SApple OSS Distributions 		memcpy(&times_in, _times_in, sizeof(times_in));
103*4f1223e8SApple OSS Distributions 	} else {
104*4f1223e8SApple OSS Distributions 		memcpy(&times_in, times_now, sizeof(times_in));
105*4f1223e8SApple OSS Distributions 	}
106*4f1223e8SApple OSS Distributions 
107*4f1223e8SApple OSS Distributions 	size_t attrbuf_size = 0;
108*4f1223e8SApple OSS Distributions 	struct timespec times_out[2] = {};
109*4f1223e8SApple OSS Distributions 	struct attrlist a = {
110*4f1223e8SApple OSS Distributions 		.bitmapcount = ATTR_BIT_MAP_COUNT
111*4f1223e8SApple OSS Distributions 	};
112*4f1223e8SApple OSS Distributions 	a.commonattr = prepare_times_array_and_attrs(times_in, times_out, &attrbuf_size, &flags_out);
113*4f1223e8SApple OSS Distributions 
114*4f1223e8SApple OSS Distributions 	return fsetattrlist(fd, &a, &times_out, attrbuf_size, 0);
115*4f1223e8SApple OSS Distributions }
116*4f1223e8SApple OSS Distributions 
117*4f1223e8SApple OSS Distributions int
utimensat(int fd,const char * path,const struct timespec _times_in[2],int flags)118*4f1223e8SApple OSS Distributions utimensat(int fd, const char *path, const struct timespec _times_in[2], int flags)
119*4f1223e8SApple OSS Distributions {
120*4f1223e8SApple OSS Distributions 	struct timespec times_in[2];
121*4f1223e8SApple OSS Distributions 	int flags_out = 0;
122*4f1223e8SApple OSS Distributions 
123*4f1223e8SApple OSS Distributions 	if (_times_in != NULL) {
124*4f1223e8SApple OSS Distributions 		memcpy(&times_in, _times_in, sizeof(times_in));
125*4f1223e8SApple OSS Distributions 	} else {
126*4f1223e8SApple OSS Distributions 		memcpy(&times_in, times_now, sizeof(times_in));
127*4f1223e8SApple OSS Distributions 	}
128*4f1223e8SApple OSS Distributions 
129*4f1223e8SApple OSS Distributions 	size_t attrbuf_size = 0;
130*4f1223e8SApple OSS Distributions 	struct timespec times_out[2] = {};
131*4f1223e8SApple OSS Distributions 	struct attrlist a = {
132*4f1223e8SApple OSS Distributions 		.bitmapcount = ATTR_BIT_MAP_COUNT
133*4f1223e8SApple OSS Distributions 	};
134*4f1223e8SApple OSS Distributions 	a.commonattr = prepare_times_array_and_attrs(times_in, times_out, &attrbuf_size, &flags_out);
135*4f1223e8SApple OSS Distributions 
136*4f1223e8SApple OSS Distributions 	if (flags & AT_SYMLINK_NOFOLLOW) {
137*4f1223e8SApple OSS Distributions 		flags_out |= FSOPT_NOFOLLOW;
138*4f1223e8SApple OSS Distributions 	}
139*4f1223e8SApple OSS Distributions 	if (flags & AT_SYMLINK_NOFOLLOW_ANY) {
140*4f1223e8SApple OSS Distributions 		flags_out |= FSOPT_NOFOLLOW_ANY;
141*4f1223e8SApple OSS Distributions 	}
142*4f1223e8SApple OSS Distributions 
143*4f1223e8SApple OSS Distributions 	return setattrlistat(fd, path, &a, &times_out, attrbuf_size, flags_out);
144*4f1223e8SApple OSS Distributions }
145