1*d80f1dd1SJilles Tjoelker /*-
2*d80f1dd1SJilles Tjoelker * Copyright (c) 2015 Jilles Tjoelker
3*d80f1dd1SJilles Tjoelker * All rights reserved.
4*d80f1dd1SJilles Tjoelker *
5*d80f1dd1SJilles Tjoelker * Redistribution and use in source and binary forms, with or without
6*d80f1dd1SJilles Tjoelker * modification, are permitted provided that the following conditions
7*d80f1dd1SJilles Tjoelker * are met:
8*d80f1dd1SJilles Tjoelker * 1. Redistributions of source code must retain the above copyright
9*d80f1dd1SJilles Tjoelker * notice, this list of conditions and the following disclaimer.
10*d80f1dd1SJilles Tjoelker * 2. Redistributions in binary form must reproduce the above copyright
11*d80f1dd1SJilles Tjoelker * notice, this list of conditions and the following disclaimer in the
12*d80f1dd1SJilles Tjoelker * documentation and/or other materials provided with the distribution.
13*d80f1dd1SJilles Tjoelker *
14*d80f1dd1SJilles Tjoelker * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*d80f1dd1SJilles Tjoelker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*d80f1dd1SJilles Tjoelker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*d80f1dd1SJilles Tjoelker * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*d80f1dd1SJilles Tjoelker * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*d80f1dd1SJilles Tjoelker * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*d80f1dd1SJilles Tjoelker * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*d80f1dd1SJilles Tjoelker * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*d80f1dd1SJilles Tjoelker * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*d80f1dd1SJilles Tjoelker * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*d80f1dd1SJilles Tjoelker * SUCH DAMAGE.
25*d80f1dd1SJilles Tjoelker */
26*d80f1dd1SJilles Tjoelker
27*d80f1dd1SJilles Tjoelker #include <sys/cdefs.h>
28*d80f1dd1SJilles Tjoelker #include <sys/stat.h>
29*d80f1dd1SJilles Tjoelker
30*d80f1dd1SJilles Tjoelker #include <errno.h>
31*d80f1dd1SJilles Tjoelker #include <fcntl.h>
32*d80f1dd1SJilles Tjoelker #include <time.h>
33*d80f1dd1SJilles Tjoelker
34*d80f1dd1SJilles Tjoelker #ifndef UTIME_NOW
35*d80f1dd1SJilles Tjoelker #define UTIME_NOW -1
36*d80f1dd1SJilles Tjoelker #define UTIME_OMIT -2
37*d80f1dd1SJilles Tjoelker #endif
38*d80f1dd1SJilles Tjoelker
39*d80f1dd1SJilles Tjoelker int
utimensat(int fd,const char * path,const struct timespec times[2],int flag)40*d80f1dd1SJilles Tjoelker utimensat(int fd, const char *path, const struct timespec times[2], int flag)
41*d80f1dd1SJilles Tjoelker {
42*d80f1dd1SJilles Tjoelker struct timeval now, tv[2], *tvp;
43*d80f1dd1SJilles Tjoelker struct stat sb;
44*d80f1dd1SJilles Tjoelker int osreldate;
45*d80f1dd1SJilles Tjoelker
46*d80f1dd1SJilles Tjoelker if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) {
47*d80f1dd1SJilles Tjoelker errno = EINVAL;
48*d80f1dd1SJilles Tjoelker return (-1);
49*d80f1dd1SJilles Tjoelker }
50*d80f1dd1SJilles Tjoelker if (times == NULL || (times[0].tv_nsec == UTIME_NOW &&
51*d80f1dd1SJilles Tjoelker times[1].tv_nsec == UTIME_NOW))
52*d80f1dd1SJilles Tjoelker tvp = NULL;
53*d80f1dd1SJilles Tjoelker else if (times[0].tv_nsec == UTIME_OMIT &&
54*d80f1dd1SJilles Tjoelker times[1].tv_nsec == UTIME_OMIT)
55*d80f1dd1SJilles Tjoelker return (0);
56*d80f1dd1SJilles Tjoelker else {
57*d80f1dd1SJilles Tjoelker if ((times[0].tv_nsec < 0 || times[0].tv_nsec > 999999999) &&
58*d80f1dd1SJilles Tjoelker times[0].tv_nsec != UTIME_NOW &&
59*d80f1dd1SJilles Tjoelker times[0].tv_nsec != UTIME_OMIT) {
60*d80f1dd1SJilles Tjoelker errno = EINVAL;
61*d80f1dd1SJilles Tjoelker return (-1);
62*d80f1dd1SJilles Tjoelker }
63*d80f1dd1SJilles Tjoelker if ((times[1].tv_nsec < 0 || times[1].tv_nsec > 999999999) &&
64*d80f1dd1SJilles Tjoelker times[1].tv_nsec != UTIME_NOW &&
65*d80f1dd1SJilles Tjoelker times[1].tv_nsec != UTIME_OMIT) {
66*d80f1dd1SJilles Tjoelker errno = EINVAL;
67*d80f1dd1SJilles Tjoelker return (-1);
68*d80f1dd1SJilles Tjoelker }
69*d80f1dd1SJilles Tjoelker tv[0].tv_sec = times[0].tv_sec;
70*d80f1dd1SJilles Tjoelker tv[0].tv_usec = times[0].tv_nsec / 1000;
71*d80f1dd1SJilles Tjoelker tv[1].tv_sec = times[1].tv_sec;
72*d80f1dd1SJilles Tjoelker tv[1].tv_usec = times[1].tv_nsec / 1000;
73*d80f1dd1SJilles Tjoelker tvp = tv;
74*d80f1dd1SJilles Tjoelker if (times[0].tv_nsec == UTIME_OMIT ||
75*d80f1dd1SJilles Tjoelker times[1].tv_nsec == UTIME_OMIT) {
76*d80f1dd1SJilles Tjoelker if (fstatat(fd, path, &sb, flag) == -1)
77*d80f1dd1SJilles Tjoelker return (-1);
78*d80f1dd1SJilles Tjoelker if (times[0].tv_nsec == UTIME_OMIT) {
79*d80f1dd1SJilles Tjoelker tv[0].tv_sec = sb.st_atim.tv_sec;
80*d80f1dd1SJilles Tjoelker tv[0].tv_usec = sb.st_atim.tv_nsec / 1000;
81*d80f1dd1SJilles Tjoelker }
82*d80f1dd1SJilles Tjoelker if (times[1].tv_nsec == UTIME_OMIT) {
83*d80f1dd1SJilles Tjoelker tv[1].tv_sec = sb.st_mtim.tv_sec;
84*d80f1dd1SJilles Tjoelker tv[1].tv_usec = sb.st_mtim.tv_nsec / 1000;
85*d80f1dd1SJilles Tjoelker }
86*d80f1dd1SJilles Tjoelker }
87*d80f1dd1SJilles Tjoelker if (times[0].tv_nsec == UTIME_NOW ||
88*d80f1dd1SJilles Tjoelker times[1].tv_nsec == UTIME_NOW) {
89*d80f1dd1SJilles Tjoelker if (gettimeofday(&now, NULL) == -1)
90*d80f1dd1SJilles Tjoelker return (-1);
91*d80f1dd1SJilles Tjoelker if (times[0].tv_nsec == UTIME_NOW)
92*d80f1dd1SJilles Tjoelker tv[0] = now;
93*d80f1dd1SJilles Tjoelker if (times[1].tv_nsec == UTIME_NOW)
94*d80f1dd1SJilles Tjoelker tv[1] = now;
95*d80f1dd1SJilles Tjoelker }
96*d80f1dd1SJilles Tjoelker }
97*d80f1dd1SJilles Tjoelker if ((flag & AT_SYMLINK_NOFOLLOW) == 0)
98*d80f1dd1SJilles Tjoelker return (futimesat(fd, path, tvp));
99*d80f1dd1SJilles Tjoelker else if ((flag & AT_SYMLINK_NOFOLLOW) != 0 &&
100*d80f1dd1SJilles Tjoelker (fd == AT_FDCWD || path[0] == '/'))
101*d80f1dd1SJilles Tjoelker return (lutimes(path, tvp));
102*d80f1dd1SJilles Tjoelker else {
103*d80f1dd1SJilles Tjoelker errno = ENOTSUP;
104*d80f1dd1SJilles Tjoelker return (-1);
105*d80f1dd1SJilles Tjoelker }
106*d80f1dd1SJilles Tjoelker }
107