Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/std/touch.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1989-2011 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
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* Glenn Fowler
23
* AT&T Research
24
*
25
* touch -- touch file times
26
*/
27
28
static const char usage[] =
29
"[-?\n@(#)$Id: touch (AT&T Research) 2004-12-12 $\n]"
30
USAGE_LICENSE
31
"[+NAME?touch - change file access, modification and status change "
32
"times]"
33
"[+DESCRIPTION?\btouch\b changes the modification time, access time or "
34
"both of each \afile\a. The modification time is the \ast_mtime\a member "
35
"of the \bstat\b(2) information and the access time is the \ast_atime\a "
36
"member. On most systems the file status change time is always set to "
37
"the current time when either the access or modification times are "
38
"changed.]"
39
"[+?If neither the \b--reference\b nor the \b--time\b options are "
40
"specified then the time used will be the \adate\a operand or the "
41
"current time if \adate\a is omitted.]"
42
"[+?If the \adate\a operand consists of 4, 6, 8, 10 or 12 digits "
43
"followed by an optional \b.\b and two digits then it is interpreted as: "
44
"\aHHMM.SS\a, \addHHMM.SS\a, \ammddHHMM.SS\a, \ammddHHMMyy.SS\a or "
45
"\ayymmddHHMM.SS\a, or \ammddHHMMccyy.SS\a or \accyymmddHHMM.SS\a. "
46
"Conflicting standards and practice allow a leading or trailing 2 or 4 "
47
"digit year for the 10 and 12 digit forms; the X/Open leading form is "
48
"used to disambiguate (\bdate\b(1) uses the trailing form.) Avoid the 10 "
49
"digit form to avoid confusion. The digit fields are:]"
50
"{"
51
"[+cc?Century - 1, 19-20.]"
52
"[+yy?Year in century, 00-99.]"
53
"[+mm?Month, 01-12.]"
54
"[+dd?Day of month, 01-31.]"
55
"[+HH?Hour, 00-23.]"
56
"[+MM?Minute, 00-59.]"
57
"[+SS?Seconds, 00-60.]"
58
"}"
59
"[a:access|atime|use?Change the access time. Do not change the "
60
"modification time unless \b--modify\b is also specified.]"
61
"[c!:create?Create the \afile\a if it does not exist, but write no "
62
"diagnostic.]"
63
"[f:force?Ignored by this implementation.]"
64
"[m:modify|mtime|modification?Change the modify time. Do not change the "
65
"access time unless \b--access\b is also specified.]"
66
"[r:reference?Use the corresponding time of \afile\a instead of the "
67
"current time.]:[file]"
68
"[s|n:change|ctime|neither?Change only the file status change time "
69
"\ast_ctime\a. Most systems summarily set \ast_ctime\a to the current "
70
"time.]"
71
"[t|d:time|date?Use the specified \adate-time\a instead of the current "
72
"date-time. Most common formats are accepted. See \btmdate\b(3) for "
73
"details. If \adate-time\a consists of 4, 6, 8, 10 or 12 digits followed "
74
"by an optional \b.\b and 2 digits and another optional \b.\b and 1 or "
75
"more digits then it is interpreted as the \adate\a operand above, "
76
"except that the leading 2 or 4 digit year form is used to disambiguate. "
77
"Avoid the 10 digit form to avoid confusion. If \b--reference\b is "
78
"specified or if \afile\a already exists then \atime\a may also be one "
79
"of:]:[date-time]"
80
"{"
81
"[+access|atime|use?The access time of the reference file.]"
82
"[+change|ctime?The change time of the reference file.]"
83
"[+modify|mtime|modification?The modify time of the reference "
84
"file.]"
85
"}"
86
"[v:verbose?Write a diagnostic for each nonexistent \afile\a.]"
87
"\n\n"
88
"[ date ]"
89
"file ...\n\n"
90
"[+CAVEATS?Some systems or file system types may limit the range of "
91
"times that can be set. These limitations may not show up until a "
92
"subsequent \bstat\b(2) call (yes, the time can be set but not checked!) "
93
"Upper limits of <0xffffffff and <0x7fffffff have been observed.]"
94
"[+SEE ALSO?\bdate\b(1), \bnmake\b(1), \butime\b(2), \btm\b(3)]"
95
;
96
97
#include <ast.h>
98
#include <ls.h>
99
#include <tmx.h>
100
#include <error.h>
101
102
#define ATIME 01
103
#define CTIME 02
104
#define MTIME 04
105
106
int
107
main(int argc, register char** argv)
108
{
109
register char* reference = 0;
110
int create = 1;
111
int set = 0;
112
int use = 0;
113
int verbose = 0;
114
115
register char* file;
116
char* e;
117
int n;
118
struct stat st;
119
Time_t t;
120
Tv_t* ap;
121
Tv_t* cp;
122
Tv_t* mp;
123
Tv_t* up;
124
Tv_t av;
125
Tv_t cv;
126
Tv_t mv;
127
Tv_t uv;
128
129
NoP(argc);
130
error_info.id = "touch";
131
up = 0;
132
for (;;)
133
{
134
switch (optget(argv, usage))
135
{
136
case 'a':
137
set |= ATIME;
138
continue;
139
case 'c':
140
create = 0;
141
continue;
142
case 'd':
143
case 't':
144
if (streq(opt_info.arg, "access") || streq(opt_info.arg, "atime") || streq(opt_info.arg, "use"))
145
use = ATIME;
146
else if (streq(opt_info.arg, "change") || streq(opt_info.arg, "ctime"))
147
use = CTIME;
148
else if (streq(opt_info.arg, "modify") || streq(opt_info.arg, "mtime") || streq(opt_info.arg, "modification"))
149
use = MTIME;
150
else
151
{
152
reference = 0;
153
t = tmxdate(opt_info.arg, &e, TMX_NOW);
154
if (*e)
155
error(3, "%s: invalid date specification", e);
156
up = &uv;
157
tmx2tv(t, up);
158
}
159
continue;
160
case 'f':
161
continue;
162
case 'm':
163
set |= MTIME;
164
continue;
165
case 'r':
166
reference = opt_info.arg;
167
continue;
168
case 's':
169
set |= CTIME;
170
continue;
171
case 'v':
172
verbose = 1;
173
continue;
174
case ':':
175
error(2, "%s", opt_info.arg);
176
break;
177
case '?':
178
error(ERROR_USAGE|4, "%s", opt_info.arg);
179
break;
180
}
181
break;
182
}
183
argv += opt_info.index;
184
if (error_info.errors || !*argv)
185
error(ERROR_USAGE|4, "%s", optusage(NiL));
186
if (reference)
187
{
188
if (stat(reference, &st))
189
error(ERROR_SYSTEM|3, "%s: not found", reference);
190
if (use)
191
{
192
up = &uv;
193
switch (use)
194
{
195
case ATIME:
196
tvgetatime(up, &st);
197
break;
198
case CTIME:
199
tvgetctime(up, &st);
200
break;
201
case MTIME:
202
tvgetmtime(up, &st);
203
break;
204
}
205
}
206
}
207
else if (!use && !up)
208
{
209
for (file = *argv; *file >= '0' && *file <= '9'; file++);
210
if (((n = (file - *argv)) == 4 || n == 6 || n == 8 || n == 10 || n == 12) && (!*file || *file == '.' && *(file + 1) >= '0' && *(file + 1) <= '9' && *(file + 2) >= '0' && *(file + 2) <= '9' && !*(file + 3)))
211
{
212
t = tmxdate(file = *argv++, &e, TMX_NOW);
213
if (*e)
214
error(3, "%s: invalid date specification", file);
215
up = &uv;
216
tmx2tv(t, up);
217
}
218
}
219
if (!set)
220
set = MTIME;
221
if (set & ATIME)
222
{
223
if (use || !reference)
224
ap = up;
225
else
226
{
227
ap = &av;
228
tvgetatime(ap, &st);
229
}
230
}
231
else
232
ap = TV_TOUCH_RETAIN;
233
if (set & CTIME)
234
{
235
if (use || !reference)
236
cp = up;
237
else
238
{
239
cp = &cv;
240
tvgetctime(cp, &st);
241
}
242
}
243
else
244
cp = TV_TOUCH_RETAIN;
245
if (set & MTIME)
246
{
247
if (use || !reference)
248
mp = up;
249
else
250
{
251
mp = &mv;
252
tvgetmtime(mp, &st);
253
}
254
}
255
else
256
mp = TV_TOUCH_RETAIN;
257
if (reference)
258
use = 0;
259
else if (use)
260
up = &uv;
261
while (file = *argv++)
262
{
263
if (use)
264
{
265
if (stat(file, &st))
266
{
267
error(2, "%s: not found", file);
268
continue;
269
}
270
switch (use)
271
{
272
case ATIME:
273
tvgetatime(up, &st);
274
break;
275
case CTIME:
276
tvgetctime(up, &st);
277
break;
278
case MTIME:
279
tvgetmtime(up, &st);
280
break;
281
}
282
if (set & ATIME)
283
ap = up;
284
if (set & CTIME)
285
cp = up;
286
if (set & MTIME)
287
mp = up;
288
}
289
if (tvtouch(file, ap, mp, cp, create))
290
if (errno != ENOENT)
291
error(ERROR_SYSTEM|2, "%s: cannot touch", file);
292
else if (verbose)
293
error(1, "%s: not found", file);
294
}
295
return error_info.errors != 0;
296
}
297
298