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(×_in, _times_in, sizeof(times_in));
103*4f1223e8SApple OSS Distributions } else {
104*4f1223e8SApple OSS Distributions memcpy(×_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, ×_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(×_in, _times_in, sizeof(times_in));
125*4f1223e8SApple OSS Distributions } else {
126*4f1223e8SApple OSS Distributions memcpy(×_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, ×_out, attrbuf_size, flags_out);
144*4f1223e8SApple OSS Distributions }
145