1 /* @(#)lutimens.c 1.4 19/07/31 Copyright 2013-2019 J. Schilling */
2 /*
3 * Emulate the behavior of lutimens(const char *name,
4 * const struct timespec times[2])
5 *
6 * Copyright (c) 2013-2019 J. Schilling
7 */
8 /*
9 * The contents of this file are subject to the terms of the
10 * Common Development and Distribution License, Version 1.0 only
11 * (the "License"). You may not use this file except in compliance
12 * with the License.
13 *
14 * See the file CDDL.Schily.txt in this distribution for details.
15 * A copy of the CDDL is also available via the Internet at
16 * http://www.opensource.org/licenses/cddl1.txt
17 *
18 * When distributing Covered Code, include this CDDL HEADER in each
19 * file and include the License file CDDL.Schily.txt from this distribution.
20 */
21
22 /*
23 * If we neither have utimensat() nor lutimes()/lutime(), we need to call
24 * lstat() and since this is not a predictable call, we always compile this
25 * module in largefile mode.
26 */
27 #define USE_LARGEFILES
28
29 #include <schily/unistd.h>
30 #include <schily/types.h>
31 #include <schily/time.h>
32 #include <schily/utime.h>
33 #include <schily/fcntl.h>
34 #include <schily/stat.h>
35 #include <schily/errno.h>
36 #include <schily/standard.h>
37 #include <schily/schily.h>
38
39 #ifndef HAVE_LUTIMENS
40
41 #ifndef HAVE_LSTAT
42 #define lstat stat
43 #endif
44
45 EXPORT int
lutimens(name,times)46 lutimens(name, times)
47 const char *name;
48 const struct timespec times[2];
49 {
50 #ifdef HAVE_UTIMENSAT
51 return (utimensat(AT_FDCWD, name, times, AT_SYMLINK_NOFOLLOW));
52 #else
53 #ifdef HAVE_LUTIMES
54 struct timeval tv[2];
55
56 if (times == NULL)
57 return (lutimes(name, NULL));
58 tv[0].tv_sec = times[0].tv_sec;
59 tv[0].tv_usec = times[0].tv_nsec/1000;
60 tv[1].tv_sec = times[1].tv_sec;
61 tv[1].tv_usec = times[1].tv_nsec/1000;
62 return (lutimes(name, tv));
63
64 #else
65 #ifdef HAVE_LUTIME
66 struct utimbuf ut;
67
68 if (times == NULL)
69 return (lutime(name, NULL));
70 ut.actime = times[0].tv_sec;
71 ut.modtime = times[1].tv_sec;
72
73 return (lutime(name, &ut));
74 #else
75 /*
76 * Without lstat(), we expect that there are no symlinks either.
77 */
78 struct stat sb;
79
80 if (lstat(name, &sb) >= 0) {
81 if (!S_ISLNK(sb.st_mode))
82 return (utimens(name, times));
83 } else {
84 /*
85 * Keep errno (e.g. ENAMETOOLONG)
86 */
87 return (-1);
88 }
89 #ifdef ENOSYS
90 seterrno(ENOSYS);
91 #else
92 seterrno(EINVAL);
93 #endif
94 return (-1);
95 #endif
96 #endif
97 #endif
98 }
99
100 #endif /* HAVE_UTIMENS */
101