source: trunk/minix/commands/simple/touch.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 5.4 KB
Line 
1/* Touch - change file access and modification times.
2 *
3 * Usage: see end of file
4 *
5 * Conforms to P1003.2 draft 10, sec. 4.62, except that time values
6 * are not checked for validity, but passed on to mktime, so that
7 * 9301990000 will refer to Apr. 9th 1993. As a side effect, leap
8 * seconds are not handled correctly.
9 *
10 * Authors: Original author unknown. Rewritten for POSIX by
11 * Peter Holzer (hp@vmars.tuwien.ac.at).
12 *
13 * $Id: touch.c,v 1.1.1.1 2005/04/21 14:55:35 beng Exp $
14 * $Log: touch.c,v $
15 * Revision 1.1.1.1 2005/04/21 14:55:35 beng
16 * Initial import of pre-3.0.1
17 *
18 * Revision 1.1.1.1 2005/04/20 13:33:47 beng
19 * Initial import of minix 2.0.4
20 *
21 * Revision 1.8 1994/03/17 21:39:19 hjp
22 * fixed bug with 4-digit years
23 *
24 * Revision 1.7 1994/03/15 00:43:27 hjp
25 * Changes from kjb (vmd 1.6.25.1):
26 * fixed exit code
27 * nonstandard flag 0 to make file very old
28 *
29 * Revision 1.6 1994/02/12 17:26:33 hjp
30 * fixed -a and -m flags
31 *
32 * Revision 1.5 1994/02/12 16:04:13 hjp
33 * fixed bug when -t argument was not given
34 * removed debugging code
35 * run through pretty to get Minix layout
36 *
37 * Revision 1.4 1994/02/07 21:23:11 hjp
38 * POSIXified.
39 *
40 */
41
42#define _POSIX_C_SOURCE 2 /* getopt */
43#include <assert.h>
44#include <ctype.h>
45#include <sys/types.h>
46#include <sys/stat.h>
47#include <errno.h>
48#include <stdlib.h>
49#include <stdio.h>
50#include <string.h>
51#include <time.h>
52#include <fcntl.h>
53#include <unistd.h>
54#include <utime.h>
55
56#define val2(string) ((string)[0] * 10 + (string)[1] - '0' * 11)
57#define val4(string) (val2(string) * 100 + val2(string + 2))
58
59typedef enum {
60 OLD, NEW
61} formatT;
62
63char *cmnd;
64int no_creat = 0;
65unsigned int to_change = 0;
66# define ATIME 1
67# define MTIME 2
68
69_PROTOTYPE(int main, (int argc, char **argv));
70_PROTOTYPE(int doit, (char *name, struct utimbuf tvp));
71_PROTOTYPE(void usage, (void));
72_PROTOTYPE(time_t parsetime, (const char *string, formatT format));
73
74time_t parsetime(string, format)
75const char *string;
76formatT format;
77{
78 struct tm tm;
79 time_t touchtime;
80 size_t l;
81
82 l = strspn(string, "0123456789");
83 if (l % 2 == 1) return -1;
84 if (string[l] != '\0' && (string[l] != '.' || format == OLD)) {
85 return -1;
86 }
87 if (format == OLD) {
88 if (l == 10) {
89 /* Last two digits are year */
90 tm.tm_year = val2(string + 8);
91 if (tm.tm_year <= 68) tm.tm_year += 100;
92 } else if (l == 8) {
93 time(&touchtime);
94 tm = *localtime(&touchtime);
95 } else {
96 return -1;
97 }
98 } else {
99 if (l == 12) {
100 /* First four digits are year */
101 tm.tm_year = val4(string) - 1900;
102 string += 4;
103 } else if (l == 10) {
104 /* First two digits are year */
105 tm.tm_year = val2(string);
106 if (tm.tm_year <= 68) tm.tm_year += 100;
107 string += 2;
108 } else if (l == 8) {
109 time(&touchtime);
110 tm = *localtime(&touchtime);
111 } else {
112 return -1;
113 }
114 }
115 tm.tm_mon = val2(string) - 1;
116 string += 2;
117 tm.tm_mday = val2(string);
118 string += 2;
119 tm.tm_hour = val2(string);
120 string += 2;
121 tm.tm_min = val2(string);
122 string += 2;
123 if (format == NEW && string[0] == '.') {
124 if (isdigit(string[1]) && isdigit(string[2]) &&
125 string[3] == '\0') {
126 tm.tm_sec = val2(string + 1);
127 } else {
128 return -1;
129 }
130 } else {
131 tm.tm_sec = 0;
132 }
133 tm.tm_isdst = -1;
134 touchtime = mktime(&tm);
135 return touchtime;
136}
137
138
139int main(argc, argv)
140int argc;
141char **argv;
142{
143 time_t auxtime;
144 struct stat sb;
145 int c;
146 struct utimbuf touchtimes;
147 int fail = 0;
148
149 cmnd = argv[0];
150 auxtime = time((time_t *) NULL);
151 touchtimes.modtime = auxtime;
152 touchtimes.actime = auxtime;
153
154 while ((c = getopt(argc, argv, "r:t:acm0")) != EOF) {
155 switch (c) {
156 case 'r':
157 if (stat(optarg, &sb) == -1) {
158 fprintf(stderr, "%s: cannot stat %s: %s\n",
159 cmnd, optarg, strerror(errno));
160 exit(1);
161 }
162 touchtimes.modtime = sb.st_mtime;
163 touchtimes.actime = sb.st_atime;
164 break;
165 case 't':
166 auxtime = parsetime(optarg, NEW);
167 if (auxtime == (time_t) - 1) usage();
168 touchtimes.modtime = auxtime;
169 touchtimes.actime = auxtime;
170 break;
171 case 'a': to_change |= ATIME; break;
172 case 'm': to_change |= MTIME; break;
173 case 'c': no_creat = 1; break;
174 case '0':
175 touchtimes.modtime = touchtimes.actime = 0;
176 break;
177 case '?': usage(); break;
178 default: assert(0);
179 }
180 }
181 if (to_change == 0) {
182 to_change = ATIME | MTIME;
183 }
184 if (optind == argc) usage();
185
186 /* Now check for old style time argument */
187 if (strcmp(argv[optind - 1], "--") != 0 &&
188 (auxtime = parsetime(argv[optind], OLD)) != (time_t) - 1) {
189 touchtimes.modtime = auxtime;
190 touchtimes.actime = auxtime;
191 optind++;
192 if (optind == argc) usage();
193 }
194 while (optind < argc) {
195 if (doit(argv[optind], touchtimes) > 0) {
196 fprintf(stderr, "%s: cannot touch %s: %s\n",
197 cmnd, argv[optind], strerror(errno));
198 fail = 1;
199 }
200 optind++;
201 }
202 return fail ? 1 : 0;
203}
204
205
206int doit(name, tvp)
207char *name;
208struct utimbuf tvp;
209{
210 int fd;
211 struct stat sb;
212
213 if (to_change != (ATIME | MTIME)) {
214
215 if (stat(name, &sb) != -1) {
216 if (!(to_change & ATIME)) {
217 tvp.actime = sb.st_atime;
218 } else {
219 tvp.modtime = sb.st_mtime;
220 }
221 }
222 }
223 if (utime(name, &tvp) == 0) return 0;
224 if (errno != ENOENT) return 1;
225 if (no_creat == 1) return 0;
226 if ((fd = creat(name, 0666)) >= 0) {
227 if (fstat(fd, &sb) != -1) {
228 if (!(to_change & ATIME)) {
229 tvp.actime = sb.st_atime;
230 } else {
231 tvp.modtime = sb.st_mtime;
232 }
233 } else {
234 assert(0);
235 }
236 close(fd);
237 if (utime(name, &tvp) == 0) return 0;
238 }
239 return 1;
240}
241
242
243void usage()
244{
245 fprintf(stderr, "Usage: %s [-c] [-a] [-m] [-r file] [-t [CC[YY]]MMDDhhmm[.ss]] "
246 "[MMDDhhmm[YY]] file...\n", cmnd);
247 exit(1);
248}
Note: See TracBrowser for help on using the repository browser.