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
futimens(int fd,const struct timespec times[2])40*d80f1dd1SJilles Tjoelker futimens(int fd, const struct timespec times[2])
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 (times == NULL || (times[0].tv_nsec == UTIME_NOW &&
47*d80f1dd1SJilles Tjoelker times[1].tv_nsec == UTIME_NOW))
48*d80f1dd1SJilles Tjoelker tvp = NULL;
49*d80f1dd1SJilles Tjoelker else if (times[0].tv_nsec == UTIME_OMIT &&
50*d80f1dd1SJilles Tjoelker times[1].tv_nsec == UTIME_OMIT)
51*d80f1dd1SJilles Tjoelker return (0);
52*d80f1dd1SJilles Tjoelker else {
53*d80f1dd1SJilles Tjoelker if ((times[0].tv_nsec < 0 || times[0].tv_nsec > 999999999) &&
54*d80f1dd1SJilles Tjoelker times[0].tv_nsec != UTIME_NOW &&
55*d80f1dd1SJilles Tjoelker times[0].tv_nsec != UTIME_OMIT) {
56*d80f1dd1SJilles Tjoelker errno = EINVAL;
57*d80f1dd1SJilles Tjoelker return (-1);
58*d80f1dd1SJilles Tjoelker }
59*d80f1dd1SJilles Tjoelker if ((times[1].tv_nsec < 0 || times[1].tv_nsec > 999999999) &&
60*d80f1dd1SJilles Tjoelker times[1].tv_nsec != UTIME_NOW &&
61*d80f1dd1SJilles Tjoelker times[1].tv_nsec != UTIME_OMIT) {
62*d80f1dd1SJilles Tjoelker errno = EINVAL;
63*d80f1dd1SJilles Tjoelker return (-1);
64*d80f1dd1SJilles Tjoelker }
65*d80f1dd1SJilles Tjoelker tv[0].tv_sec = times[0].tv_sec;
66*d80f1dd1SJilles Tjoelker tv[0].tv_usec = times[0].tv_nsec / 1000;
67*d80f1dd1SJilles Tjoelker tv[1].tv_sec = times[1].tv_sec;
68*d80f1dd1SJilles Tjoelker tv[1].tv_usec = times[1].tv_nsec / 1000;
69*d80f1dd1SJilles Tjoelker tvp = tv;
70*d80f1dd1SJilles Tjoelker if (times[0].tv_nsec == UTIME_OMIT ||
71*d80f1dd1SJilles Tjoelker times[1].tv_nsec == UTIME_OMIT) {
72*d80f1dd1SJilles Tjoelker if (fstat(fd, &sb) == -1)
73*d80f1dd1SJilles Tjoelker return (-1);
74*d80f1dd1SJilles Tjoelker if (times[0].tv_nsec == UTIME_OMIT) {
75*d80f1dd1SJilles Tjoelker tv[0].tv_sec = sb.st_atim.tv_sec;
76*d80f1dd1SJilles Tjoelker tv[0].tv_usec = sb.st_atim.tv_nsec / 1000;
77*d80f1dd1SJilles Tjoelker }
78*d80f1dd1SJilles Tjoelker if (times[1].tv_nsec == UTIME_OMIT) {
79*d80f1dd1SJilles Tjoelker tv[1].tv_sec = sb.st_mtim.tv_sec;
80*d80f1dd1SJilles Tjoelker tv[1].tv_usec = sb.st_mtim.tv_nsec / 1000;
81*d80f1dd1SJilles Tjoelker }
82*d80f1dd1SJilles Tjoelker }
83*d80f1dd1SJilles Tjoelker if (times[0].tv_nsec == UTIME_NOW ||
84*d80f1dd1SJilles Tjoelker times[1].tv_nsec == UTIME_NOW) {
85*d80f1dd1SJilles Tjoelker if (gettimeofday(&now, NULL) == -1)
86*d80f1dd1SJilles Tjoelker return (-1);
87*d80f1dd1SJilles Tjoelker if (times[0].tv_nsec == UTIME_NOW)
88*d80f1dd1SJilles Tjoelker tv[0] = now;
89*d80f1dd1SJilles Tjoelker if (times[1].tv_nsec == UTIME_NOW)
90*d80f1dd1SJilles Tjoelker tv[1] = now;
91*d80f1dd1SJilles Tjoelker }
92*d80f1dd1SJilles Tjoelker }
93*d80f1dd1SJilles Tjoelker return (futimes(fd, tvp));
94*d80f1dd1SJilles Tjoelker }
95