Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/tm/tvtouch.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1985-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
20
* *
21
***********************************************************************/
22
#pragma prototyped
23
/*
24
* Glenn Fowler
25
* AT&T Research
26
*
27
* Tv_t conversion support
28
*/
29
30
#if defined(__STDPP__directive) && defined(__STDPP__hide)
31
__STDPP__directive pragma pp:hide utime
32
#else
33
#define utime ______utime
34
#endif
35
36
#ifndef _ATFILE_SOURCE
37
#define _ATFILE_SOURCE 1
38
#endif
39
40
#include <ast.h>
41
#include <ls.h>
42
#include <tv.h>
43
#include <times.h>
44
#include <error.h>
45
46
#include "FEATURE/tvlib"
47
48
#if _hdr_utime && _lib_utime
49
#include <utime.h>
50
#endif
51
52
#if defined(__STDPP__directive) && defined(__STDPP__hide)
53
__STDPP__directive pragma pp:nohide utime
54
#else
55
#undef utime
56
#endif
57
58
#if _lib_utime
59
#if _hdr_utime
60
extern int utime(const char*, const struct utimbuf*);
61
#else
62
extern int utime(const char*, const time_t*);
63
#endif
64
#endif
65
66
#define NS(n) (((uint32_t)(n))<1000000000L?(n):0)
67
68
/*
69
* touch path <atime,mtime,ctime>
70
* Tv_t==0 uses current time
71
* Tv_t==TV_TOUCH_RETAIN retains path value if it exists, current time otherwise
72
* otherwise it is exact time
73
* file created if it doesn't exist and (flags&TV_TOUCH_CREATE)
74
* symlink not followed if (flags&TV_TOUCH_PHYSICAL)
75
* cv most likely ignored on most implementations
76
*
77
* NOTE: when *at() calls are integrated TV_TOUCH_* should be advertized!
78
*/
79
80
#define TV_TOUCH_CREATE 1
81
#define TV_TOUCH_PHYSICAL 2
82
83
#if !defined(UTIME_NOW) || !defined(UTIME_OMIT) || defined(__stub_utimensat)
84
#undef _lib_utimensat
85
#endif
86
87
int
88
tvtouch(const char* path, register const Tv_t* av, register const Tv_t* mv, const Tv_t* cv, int flags)
89
{
90
int fd;
91
int mode;
92
int oerrno;
93
struct stat st;
94
Tv_t now;
95
#if _lib_utimets || _lib_utimensat
96
struct timespec ts[2];
97
#endif
98
#if _lib_utimes
99
struct timeval am[2];
100
#else
101
#if _hdr_utime
102
struct utimbuf am;
103
#else
104
time_t am[2];
105
#endif
106
#endif
107
108
oerrno = errno;
109
#if _lib_utimensat
110
if (!av)
111
{
112
ts[0].tv_sec = 0;
113
ts[0].tv_nsec = UTIME_NOW;
114
}
115
else if (av == TV_TOUCH_RETAIN)
116
{
117
ts[0].tv_sec = 0;
118
ts[0].tv_nsec = UTIME_OMIT;
119
}
120
else
121
{
122
ts[0].tv_sec = av->tv_sec;
123
ts[0].tv_nsec = NS(av->tv_nsec);
124
}
125
if (!mv)
126
{
127
ts[1].tv_sec = 0;
128
ts[1].tv_nsec = UTIME_NOW;
129
}
130
else if (mv == TV_TOUCH_RETAIN)
131
{
132
ts[1].tv_sec = 0;
133
ts[1].tv_nsec = UTIME_OMIT;
134
}
135
else
136
{
137
ts[1].tv_sec = mv->tv_sec;
138
ts[1].tv_nsec = NS(mv->tv_nsec);
139
}
140
if (!cv && av == TV_TOUCH_RETAIN && mv == TV_TOUCH_RETAIN && !stat(path, &st) && !chmod(path, st.st_mode & S_IPERM))
141
return 0;
142
if (!utimensat(AT_FDCWD, path, ts[0].tv_nsec == UTIME_NOW && ts[1].tv_nsec == UTIME_NOW ? (struct timespec*)0 : ts, (flags & TV_TOUCH_PHYSICAL) ? AT_SYMLINK_NOFOLLOW : 0))
143
return 0;
144
if (errno != ENOSYS)
145
{
146
if (errno != ENOENT || !(flags & TV_TOUCH_CREATE))
147
return -1;
148
umask(mode = umask(0));
149
mode = (~mode) & (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
150
if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_cloexec, mode)) < 0)
151
return -1;
152
close(fd);
153
errno = oerrno;
154
if ((ts[0].tv_nsec != UTIME_NOW || ts[1].tv_nsec != UTIME_NOW) && utimensat(AT_FDCWD, path, ts, (flags & TV_TOUCH_PHYSICAL) ? AT_SYMLINK_NOFOLLOW : 0))
155
return -1;
156
return 0;
157
}
158
#endif
159
if ((av == TV_TOUCH_RETAIN || mv == TV_TOUCH_RETAIN) && stat(path, &st))
160
{
161
errno = oerrno;
162
if (av == TV_TOUCH_RETAIN)
163
av = 0;
164
if (mv == TV_TOUCH_RETAIN)
165
mv = 0;
166
}
167
if (!av || !mv)
168
{
169
tvgettime(&now);
170
if (!av)
171
av = (const Tv_t*)&now;
172
if (!mv)
173
mv = (const Tv_t*)&now;
174
}
175
#if _lib_utimets
176
if (av == TV_TOUCH_RETAIN)
177
{
178
ts[0].tv_sec = st.st_atime;
179
ts[0].tv_nsec = ST_ATIME_NSEC_GET(&st);
180
}
181
else
182
{
183
ts[0].tv_sec = av->tv_sec;
184
ts[0].tv_nsec = NS(av->tv_nsec);
185
}
186
if (mv == TV_TOUCH_RETAIN)
187
{
188
ts[1].tv_sec = st.st_mtime;
189
ts[1].tv_nsec = ST_MTIME_NSEC_GET(&st);
190
}
191
else
192
{
193
ts[1].tv_sec = mv->tv_sec;
194
ts[1].tv_nsec = NS(mv->tv_nsec);
195
}
196
if (!utimets(path, ts))
197
return 0;
198
if (errno != ENOENT && av == (const Tv_t*)&now && mv == (const Tv_t*)&now && !utimets(path, NiL))
199
{
200
errno = oerrno;
201
return 0;
202
}
203
#else
204
#if _lib_utimes
205
if (av == TV_TOUCH_RETAIN)
206
{
207
am[0].tv_sec = st.st_atime;
208
am[0].tv_usec = ST_ATIME_NSEC_GET(&st) / 1000;
209
}
210
else
211
{
212
am[0].tv_sec = av->tv_sec;
213
am[0].tv_usec = NS(av->tv_nsec) / 1000;
214
}
215
if (mv == TV_TOUCH_RETAIN)
216
{
217
am[1].tv_sec = st.st_mtime;
218
am[1].tv_usec = ST_MTIME_NSEC_GET(&st) / 1000;
219
}
220
else
221
{
222
am[1].tv_sec = mv->tv_sec;
223
am[1].tv_usec = NS(mv->tv_nsec) / 1000;
224
}
225
if (!utimes(path, am))
226
return 0;
227
if (errno != ENOENT && av == (const Tv_t*)&now && mv == (const Tv_t*)&now && !utimes(path, NiL))
228
{
229
errno = oerrno;
230
return 0;
231
}
232
#else
233
#if _lib_utime
234
am.actime = (av == TV_TOUCH_RETAIN) ? st.st_atime : av->tv_sec;
235
am.modtime = (mv == TV_TOUCH_RETAIN) ? st.st_mtime : mv->tv_sec;
236
if (!utime(path, &am))
237
return 0;
238
#if _lib_utime_now
239
if (errno != ENOENT && av == (const Tv_t*)&now && mv == (const Tv_t*)&now && !utime(path, NiL))
240
{
241
errno = oerrno;
242
return 0;
243
}
244
#endif
245
#endif
246
#endif
247
if (!access(path, F_OK))
248
{
249
if (av != (const Tv_t*)&now || mv != (const Tv_t*)&now)
250
{
251
errno = EINVAL;
252
return -1;
253
}
254
if ((fd = open(path, O_RDWR|O_cloexec)) >= 0)
255
{
256
char c;
257
258
if (read(fd, &c, 1) == 1)
259
{
260
if (c = (lseek(fd, 0L, 0) == 0L && write(fd, &c, 1) == 1))
261
errno = oerrno;
262
close(fd);
263
if (c)
264
return 0;
265
}
266
close(fd);
267
}
268
}
269
#endif
270
if (errno != ENOENT || !(flags & TV_TOUCH_CREATE))
271
return -1;
272
umask(mode = umask(0));
273
mode = (~mode) & (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
274
if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_cloexec, mode)) < 0)
275
return -1;
276
close(fd);
277
errno = oerrno;
278
if (av == (const Tv_t*)&now && mv == (const Tv_t*)&now)
279
return 0;
280
#if _lib_utimets
281
return utimets(path, ts);
282
#else
283
#if _lib_utimes
284
return utimes(path, am);
285
#else
286
#if _lib_utime
287
return utime(path, &am);
288
#else
289
errno = EINVAL;
290
return -1;
291
#endif
292
#endif
293
#endif
294
295
}
296
297