···11+#define __SYSCALL_32BIT_ARG_BYTES 20
22+#include "SYS.h"
33+44+#ifndef SYS_setattrlistat
55+#error "SYS_setattrlistat not defined. The header files libsyscall is building against do not match syscalls.master."
66+#endif
77+88+#if defined(__i386__) || defined(__x86_64__)
99+__SYSCALL2(_setattrlistat, setattrlistat, 6, cerror_nocancel)
1010+#endif
1111+
+134
src/kernel/libsyscall/wrappers/utimensat.c
···11+/*
22+ * Copyright (c) 2006, 2017 Apple Computer, Inc. All rights reserved.
33+ *
44+ * @APPLE_LICENSE_HEADER_START@
55+ *
66+ * This file contains Original Code and/or Modifications of Original Code
77+ * as defined in and that are subject to the Apple Public Source License
88+ * Version 2.0 (the 'License'). You may not use this file except in
99+ * compliance with the License. Please obtain a copy of the License at
1010+ * http://www.opensource.apple.com/apsl/ and read it before using this
1111+ * file.
1212+ *
1313+ * The Original Code and all software distributed under the License are
1414+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1515+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
1616+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
1717+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
1818+ * Please see the License for the specific language governing rights and
1919+ * limitations under the License.
2020+ *
2121+ * @APPLE_LICENSE_HEADER_END@
2222+ */
2323+2424+#include <sys/types.h>
2525+#include <sys/stat.h>
2626+#include <sys/attr.h>
2727+#include <sys/time.h>
2828+#include <sys/fcntl.h>
2929+#include <unistd.h>
3030+#include <strings.h>
3131+3232+extern int __gettimeofday(struct timeval *, struct timezone *);
3333+extern int __commpage_gettimeofday(struct timeval *);
3434+3535+static struct timespec times_now[2] = {
3636+ { .tv_nsec = UTIME_NOW },
3737+ { .tv_nsec = UTIME_NOW }
3838+};
3939+4040+/*
4141+ * Resolve any UTIME_NOW or UTIME_OMIT and return the attributes buffer and
4242+ * attributes to pass. Assumes times_in is writable.
4343+ */
4444+static int
4545+prepare_times_array_and_attrs(struct timespec times_in[2],
4646+ struct timespec times_out[2], size_t *times_out_size)
4747+{
4848+ if (times_in[0].tv_nsec == UTIME_OMIT &&
4949+ times_in[1].tv_nsec == UTIME_OMIT) {
5050+ return 0;
5151+ }
5252+5353+ if (times_in[0].tv_nsec == UTIME_NOW ||
5454+ times_in[1].tv_nsec == UTIME_NOW) {
5555+ struct timespec now = {};
5656+ {
5757+ /*
5858+ * TODO: Replace with nanosecond time when available
5959+ */
6060+ struct timeval tv;
6161+ if (__commpage_gettimeofday(&tv) != 0) {
6262+ __gettimeofday(&tv, NULL);
6363+ }
6464+ TIMEVAL_TO_TIMESPEC(&tv, &now);
6565+ }
6666+6767+ if (times_in[0].tv_nsec == UTIME_NOW) {
6868+ times_in[0] = now;
6969+ }
7070+ if (times_in[1].tv_nsec == UTIME_NOW) {
7171+ times_in[1] = now;
7272+ }
7373+ }
7474+7575+ int attrs = 0;
7676+ *times_out_size = 0;
7777+ struct timespec *times_cursor = times_out;
7878+ if (times_in[1].tv_nsec != UTIME_OMIT) {
7979+ attrs |= ATTR_CMN_MODTIME;
8080+ *times_cursor++ = times_in[1];
8181+ *times_out_size += sizeof(struct timespec);
8282+ }
8383+ if (times_in[0].tv_nsec != UTIME_OMIT) {
8484+ attrs |= ATTR_CMN_ACCTIME;
8585+ *times_cursor = times_in[0];
8686+ *times_out_size += sizeof(struct timespec);
8787+ }
8888+ return attrs;
8989+}
9090+9191+int
9292+futimens(int fd, const struct timespec _times_in[2])
9393+{
9494+ struct timespec times_in[2];
9595+ if (_times_in != NULL) {
9696+ memcpy(×_in, _times_in, sizeof(times_in));
9797+ } else {
9898+ memcpy(×_in, times_now, sizeof(times_in));
9999+ }
100100+101101+ size_t attrbuf_size = 0;
102102+ struct timespec times_out[2] = {};
103103+ struct attrlist a = {
104104+ .bitmapcount = ATTR_BIT_MAP_COUNT
105105+ };
106106+ a.commonattr = prepare_times_array_and_attrs(times_in, times_out, &attrbuf_size);
107107+108108+ return fsetattrlist(fd, &a, ×_out, attrbuf_size, 0);
109109+}
110110+111111+int
112112+utimensat(int fd, const char *path, const struct timespec _times_in[2], int flags)
113113+{
114114+ struct timespec times_in[2];
115115+ if (_times_in != NULL) {
116116+ memcpy(×_in, _times_in, sizeof(times_in));
117117+ } else {
118118+ memcpy(×_in, times_now, sizeof(times_in));
119119+ }
120120+121121+ size_t attrbuf_size = 0;
122122+ struct timespec times_out[2] = {};
123123+ struct attrlist a = {
124124+ .bitmapcount = ATTR_BIT_MAP_COUNT
125125+ };
126126+ a.commonattr = prepare_times_array_and_attrs(times_in, times_out, &attrbuf_size);
127127+128128+ int flags_out = 0;
129129+ if (flags & AT_SYMLINK_NOFOLLOW) {
130130+ flags_out |= FSOPT_NOFOLLOW;
131131+ }
132132+133133+ return setattrlistat(fd, path, &a, ×_out, attrbuf_size, flags_out);
134134+}