xref: /titanic_54/usr/src/ucbcmd/touch/touch.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #ifndef lint
28*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
29*7c478bd9Sstevel@tonic-gate #endif
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #include <stdio.h>
32*7c478bd9Sstevel@tonic-gate #include <ctype.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
37*7c478bd9Sstevel@tonic-gate #include <time.h>
38*7c478bd9Sstevel@tonic-gate #include <errno.h>
39*7c478bd9Sstevel@tonic-gate #include <unistd.h>
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #define	isleap(y) (((y) % 4) == 0 && ((y) % 100) != 0 || ((y) % 400) == 0)
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate struct	stat	stbuf;
44*7c478bd9Sstevel@tonic-gate int	status;
45*7c478bd9Sstevel@tonic-gate #ifdef S5EMUL
46*7c478bd9Sstevel@tonic-gate int dmsize[12]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
47*7c478bd9Sstevel@tonic-gate #endif S5EMUL
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate static char usage[] =
50*7c478bd9Sstevel@tonic-gate #ifdef S5EMUL
51*7c478bd9Sstevel@tonic-gate 		"[-amc] [mmddhhmm[yy]]";
52*7c478bd9Sstevel@tonic-gate #else /*!S5EMUL*/
53*7c478bd9Sstevel@tonic-gate 		"[-amcf]";
54*7c478bd9Sstevel@tonic-gate int	force = 0;
55*7c478bd9Sstevel@tonic-gate int	nowrite;
56*7c478bd9Sstevel@tonic-gate #endif /*!S5EMUL*/
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate int	mflg=1, aflg=1, cflg=0, nflg=0;
59*7c478bd9Sstevel@tonic-gate char	*prog;
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate #ifdef S5EMUL
62*7c478bd9Sstevel@tonic-gate char	*cbp;
63*7c478bd9Sstevel@tonic-gate #endif S5EMUL
64*7c478bd9Sstevel@tonic-gate time_t	time();
65*7c478bd9Sstevel@tonic-gate off_t	lseek();
66*7c478bd9Sstevel@tonic-gate time_t	timelocal(), timegm();
67*7c478bd9Sstevel@tonic-gate struct timeval timbuf;
68*7c478bd9Sstevel@tonic-gate static void timestruc_to_timeval(timestruc_t *, struct timeval *);
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate #ifdef S5EMUL
71*7c478bd9Sstevel@tonic-gate struct tm *
72*7c478bd9Sstevel@tonic-gate gtime()
73*7c478bd9Sstevel@tonic-gate {
74*7c478bd9Sstevel@tonic-gate 	static struct tm newtime;
75*7c478bd9Sstevel@tonic-gate 	long nt;
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate 	newtime.tm_mon = gpair() - 1;
78*7c478bd9Sstevel@tonic-gate 	newtime.tm_mday = gpair();
79*7c478bd9Sstevel@tonic-gate 	newtime.tm_hour = gpair();
80*7c478bd9Sstevel@tonic-gate 	if (newtime.tm_hour == 24) {
81*7c478bd9Sstevel@tonic-gate 		newtime.tm_hour = 0;
82*7c478bd9Sstevel@tonic-gate 		newtime.tm_mday++;
83*7c478bd9Sstevel@tonic-gate 	}
84*7c478bd9Sstevel@tonic-gate 	newtime.tm_min = gpair();
85*7c478bd9Sstevel@tonic-gate 	newtime.tm_sec = 0;
86*7c478bd9Sstevel@tonic-gate 	newtime.tm_year = gpair();
87*7c478bd9Sstevel@tonic-gate 	if (newtime.tm_year < 0) {
88*7c478bd9Sstevel@tonic-gate 		(void) time(&nt);
89*7c478bd9Sstevel@tonic-gate 		newtime.tm_year = localtime(&nt)->tm_year;
90*7c478bd9Sstevel@tonic-gate 	}
91*7c478bd9Sstevel@tonic-gate 	return (&newtime);
92*7c478bd9Sstevel@tonic-gate }
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate gpair()
95*7c478bd9Sstevel@tonic-gate {
96*7c478bd9Sstevel@tonic-gate 	register int c, d;
97*7c478bd9Sstevel@tonic-gate 	register char *cp;
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate 	cp = cbp;
100*7c478bd9Sstevel@tonic-gate 	if (*cp == 0)
101*7c478bd9Sstevel@tonic-gate 		return (-1);
102*7c478bd9Sstevel@tonic-gate 	c = (*cp++ - '0') * 10;
103*7c478bd9Sstevel@tonic-gate 	if (c<0 || c>100)
104*7c478bd9Sstevel@tonic-gate 		return (-1);
105*7c478bd9Sstevel@tonic-gate 	if (*cp == 0)
106*7c478bd9Sstevel@tonic-gate 		return (-1);
107*7c478bd9Sstevel@tonic-gate 	if ((d = *cp++ - '0') < 0 || d > 9)
108*7c478bd9Sstevel@tonic-gate 		return (-1);
109*7c478bd9Sstevel@tonic-gate 	cbp = cp;
110*7c478bd9Sstevel@tonic-gate 	return (c+d);
111*7c478bd9Sstevel@tonic-gate }
112*7c478bd9Sstevel@tonic-gate #endif /*S5EMUL*/
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate main(argc, argv)
115*7c478bd9Sstevel@tonic-gate 	int argc;
116*7c478bd9Sstevel@tonic-gate 	char *argv[];
117*7c478bd9Sstevel@tonic-gate {
118*7c478bd9Sstevel@tonic-gate 	register c;
119*7c478bd9Sstevel@tonic-gate #ifdef S5EMUL
120*7c478bd9Sstevel@tonic-gate 	int days_in_month;
121*7c478bd9Sstevel@tonic-gate 	struct tm *tp;
122*7c478bd9Sstevel@tonic-gate #endif S5EMUL
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate 	int errflg=0, optc;
125*7c478bd9Sstevel@tonic-gate 	extern char *optarg;
126*7c478bd9Sstevel@tonic-gate 	extern int optind;
127*7c478bd9Sstevel@tonic-gate 	extern int opterr;
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate 	prog = argv[0];
130*7c478bd9Sstevel@tonic-gate 	opterr = 0;			/* disable getopt() error msgs */
131*7c478bd9Sstevel@tonic-gate 	while ((optc=getopt(argc, argv, "amcf")) != EOF)
132*7c478bd9Sstevel@tonic-gate 		switch (optc) {
133*7c478bd9Sstevel@tonic-gate 		case 'm':
134*7c478bd9Sstevel@tonic-gate 			mflg++;
135*7c478bd9Sstevel@tonic-gate 			aflg--;
136*7c478bd9Sstevel@tonic-gate 			break;
137*7c478bd9Sstevel@tonic-gate 		case 'a':
138*7c478bd9Sstevel@tonic-gate 			aflg++;
139*7c478bd9Sstevel@tonic-gate 			mflg--;
140*7c478bd9Sstevel@tonic-gate 			break;
141*7c478bd9Sstevel@tonic-gate 		case 'c':
142*7c478bd9Sstevel@tonic-gate 			cflg++;
143*7c478bd9Sstevel@tonic-gate 			break;
144*7c478bd9Sstevel@tonic-gate #ifndef S5EMUL
145*7c478bd9Sstevel@tonic-gate 		case 'f':
146*7c478bd9Sstevel@tonic-gate 			force++;	/* SysV version ignores -f */
147*7c478bd9Sstevel@tonic-gate 			break;
148*7c478bd9Sstevel@tonic-gate #endif /*!S5EMUL*/
149*7c478bd9Sstevel@tonic-gate 		case '?':
150*7c478bd9Sstevel@tonic-gate 			errflg++;
151*7c478bd9Sstevel@tonic-gate 		}
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	if (((argc-optind) < 1) || errflg) {
154*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "usage: %s %s file ...\n", prog, usage);
155*7c478bd9Sstevel@tonic-gate 		exit(2);
156*7c478bd9Sstevel@tonic-gate 	}
157*7c478bd9Sstevel@tonic-gate 	status = 0;
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate #ifdef S5EMUL
160*7c478bd9Sstevel@tonic-gate 	if (!isnumber(argv[optind])) {	/* BSD version only sets Present */
161*7c478bd9Sstevel@tonic-gate #endif /*S5EMUL*/
162*7c478bd9Sstevel@tonic-gate 		if ((aflg <= 0) || (mflg <= 0))
163*7c478bd9Sstevel@tonic-gate 			(void) gettimeofday(&timbuf, NULL);
164*7c478bd9Sstevel@tonic-gate 		else
165*7c478bd9Sstevel@tonic-gate 			nflg++;		/* no -a, -m, or date seen */
166*7c478bd9Sstevel@tonic-gate #ifdef S5EMUL
167*7c478bd9Sstevel@tonic-gate 	} else {			/* SysV version sets arbitrary date */
168*7c478bd9Sstevel@tonic-gate 		cbp = (char *)argv[optind++];
169*7c478bd9Sstevel@tonic-gate 		if ((tp = gtime()) == NULL) {
170*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: bad date conversion\n",
171*7c478bd9Sstevel@tonic-gate 			    prog);
172*7c478bd9Sstevel@tonic-gate 			exit(2);
173*7c478bd9Sstevel@tonic-gate 		}
174*7c478bd9Sstevel@tonic-gate 		days_in_month = dmsize[tp->tm_mon];
175*7c478bd9Sstevel@tonic-gate 		if (tp->tm_mon == 1 && isleap(tp->tm_year + 1900))
176*7c478bd9Sstevel@tonic-gate 			days_in_month = 29;	/* February in leap year */
177*7c478bd9Sstevel@tonic-gate 		if (tp->tm_mon < 0 || tp->tm_mon > 11 ||
178*7c478bd9Sstevel@tonic-gate 		    tp->tm_mday < 1 || tp->tm_mday > days_in_month ||
179*7c478bd9Sstevel@tonic-gate 		    tp->tm_hour < 0 || tp->tm_hour > 23 ||
180*7c478bd9Sstevel@tonic-gate 		    tp->tm_min < 0 || tp->tm_min > 59 ||
181*7c478bd9Sstevel@tonic-gate 		    tp->tm_sec < 0 || tp->tm_sec > 59) {
182*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: bad date conversion\n",
183*7c478bd9Sstevel@tonic-gate 			    prog);
184*7c478bd9Sstevel@tonic-gate 			exit(2);
185*7c478bd9Sstevel@tonic-gate 		}
186*7c478bd9Sstevel@tonic-gate 		timbuf = timelocal(tp);
187*7c478bd9Sstevel@tonic-gate 	}
188*7c478bd9Sstevel@tonic-gate #endif /*S5EMUL*/
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 	for (c = optind; c < argc; c++) {
191*7c478bd9Sstevel@tonic-gate 		if (touch(argv[c]) < 0)
192*7c478bd9Sstevel@tonic-gate 			status++;
193*7c478bd9Sstevel@tonic-gate 	}
194*7c478bd9Sstevel@tonic-gate 	exit(status);
195*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
196*7c478bd9Sstevel@tonic-gate }
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate int
199*7c478bd9Sstevel@tonic-gate touch(filename)
200*7c478bd9Sstevel@tonic-gate 	char *filename;
201*7c478bd9Sstevel@tonic-gate {
202*7c478bd9Sstevel@tonic-gate 	struct timeval times[2];
203*7c478bd9Sstevel@tonic-gate 	register int fd;
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate 	if (stat(filename, &stbuf)) {
206*7c478bd9Sstevel@tonic-gate 		/*
207*7c478bd9Sstevel@tonic-gate 		 * if stat failed for reasons other than ENOENT,
208*7c478bd9Sstevel@tonic-gate 		 * the file should not be created, since this
209*7c478bd9Sstevel@tonic-gate 		 * can clobber the contents of an existing file
210*7c478bd9Sstevel@tonic-gate 		 * (for example, a large file that results in overflow).
211*7c478bd9Sstevel@tonic-gate 		 */
212*7c478bd9Sstevel@tonic-gate 		if (errno != ENOENT) {
213*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,"%s: cannot stat ", prog);
214*7c478bd9Sstevel@tonic-gate 			perror(filename);
215*7c478bd9Sstevel@tonic-gate 			return (-1);
216*7c478bd9Sstevel@tonic-gate 		} else if (cflg) {
217*7c478bd9Sstevel@tonic-gate 			return (-1);
218*7c478bd9Sstevel@tonic-gate 		}
219*7c478bd9Sstevel@tonic-gate 		else if ((fd = creat(filename, 0666)) < 0) {
220*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: cannot create ", prog);
221*7c478bd9Sstevel@tonic-gate 			perror(filename);
222*7c478bd9Sstevel@tonic-gate 			return (-1);
223*7c478bd9Sstevel@tonic-gate 		}
224*7c478bd9Sstevel@tonic-gate 		else {
225*7c478bd9Sstevel@tonic-gate 			(void) close(fd);
226*7c478bd9Sstevel@tonic-gate 			if (stat(filename, &stbuf)) {
227*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,"%s: cannot stat ", prog);
228*7c478bd9Sstevel@tonic-gate 				perror(filename);
229*7c478bd9Sstevel@tonic-gate 				return (-1);
230*7c478bd9Sstevel@tonic-gate 			}
231*7c478bd9Sstevel@tonic-gate 		}
232*7c478bd9Sstevel@tonic-gate 		if (nflg)
233*7c478bd9Sstevel@tonic-gate 			return (0);
234*7c478bd9Sstevel@tonic-gate 	}
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate 	times[0] = times[1] = timbuf;
237*7c478bd9Sstevel@tonic-gate 	if (mflg <= 0)
238*7c478bd9Sstevel@tonic-gate 		timestruc_to_timeval(&stbuf.st_mtim, times + 1);
239*7c478bd9Sstevel@tonic-gate 	if (aflg <= 0)
240*7c478bd9Sstevel@tonic-gate 		timestruc_to_timeval(&stbuf.st_atim, times);
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate #ifndef S5EMUL
243*7c478bd9Sstevel@tonic-gate 	/*
244*7c478bd9Sstevel@tonic-gate 	 * Since utime() allows the owner to change file times without
245*7c478bd9Sstevel@tonic-gate 	 * regard to access permission, enforce BSD semantics here
246*7c478bd9Sstevel@tonic-gate 	 * (cannot touch if read-only and not -f).
247*7c478bd9Sstevel@tonic-gate 	 */
248*7c478bd9Sstevel@tonic-gate 	nowrite = access(filename, R_OK|W_OK);
249*7c478bd9Sstevel@tonic-gate 	if (nowrite && !force) {
250*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
251*7c478bd9Sstevel@tonic-gate 		    "%s: cannot touch %s: no write permission\n",
252*7c478bd9Sstevel@tonic-gate 		    prog, filename);
253*7c478bd9Sstevel@tonic-gate 		return (-1);
254*7c478bd9Sstevel@tonic-gate 	}
255*7c478bd9Sstevel@tonic-gate #endif /*!S5EMUL*/
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 	if (utimes(filename, nflg ? NULL : times)) {
258*7c478bd9Sstevel@tonic-gate 		if (nflg && (errno != EROFS) && (errno != EACCES)) {
259*7c478bd9Sstevel@tonic-gate 			/*
260*7c478bd9Sstevel@tonic-gate 			 * If utime() failed to set the Present, it
261*7c478bd9Sstevel@tonic-gate 			 * could be a BSD server that is complaining.
262*7c478bd9Sstevel@tonic-gate 			 * If that's the case, try the old read/write trick.
263*7c478bd9Sstevel@tonic-gate 			 */
264*7c478bd9Sstevel@tonic-gate 			return (oldtouch(filename, &stbuf));
265*7c478bd9Sstevel@tonic-gate 		}
266*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,"%s: cannot change times on ", prog);
267*7c478bd9Sstevel@tonic-gate 		perror(filename);
268*7c478bd9Sstevel@tonic-gate 		return (-1);
269*7c478bd9Sstevel@tonic-gate 	}
270*7c478bd9Sstevel@tonic-gate 	return (0);
271*7c478bd9Sstevel@tonic-gate }
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate int
274*7c478bd9Sstevel@tonic-gate oldtouch(filename, statp)
275*7c478bd9Sstevel@tonic-gate 	char *filename;
276*7c478bd9Sstevel@tonic-gate 	register struct stat *statp;
277*7c478bd9Sstevel@tonic-gate {
278*7c478bd9Sstevel@tonic-gate 	int rwstatus;
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate 	if ((statp->st_mode & S_IFMT) != S_IFREG) {
281*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
282*7c478bd9Sstevel@tonic-gate 		    "%s: %s: only owner may touch special files on this filesystem\n",
283*7c478bd9Sstevel@tonic-gate 		    prog, filename);
284*7c478bd9Sstevel@tonic-gate 		return (-1);
285*7c478bd9Sstevel@tonic-gate 	}
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate #ifndef S5EMUL
288*7c478bd9Sstevel@tonic-gate 	if (nowrite && force) {
289*7c478bd9Sstevel@tonic-gate 		if (chmod(filename, 0666)) {
290*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "%s: could not chmod ", prog);
291*7c478bd9Sstevel@tonic-gate 			perror(filename);
292*7c478bd9Sstevel@tonic-gate 			return (-1);
293*7c478bd9Sstevel@tonic-gate 		}
294*7c478bd9Sstevel@tonic-gate 		rwstatus = readwrite(filename, statp->st_size);
295*7c478bd9Sstevel@tonic-gate 		if (chmod(filename, (int)statp->st_mode)) {
296*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "%s: could not chmod back ", prog);
297*7c478bd9Sstevel@tonic-gate 			perror(filename);
298*7c478bd9Sstevel@tonic-gate 			return (-1);
299*7c478bd9Sstevel@tonic-gate 		}
300*7c478bd9Sstevel@tonic-gate 		return (rwstatus);
301*7c478bd9Sstevel@tonic-gate 	} else
302*7c478bd9Sstevel@tonic-gate #endif /*!S5EMUL*/
303*7c478bd9Sstevel@tonic-gate 		return (readwrite(filename, statp->st_size));
304*7c478bd9Sstevel@tonic-gate }
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate int
307*7c478bd9Sstevel@tonic-gate readwrite(filename, size)
308*7c478bd9Sstevel@tonic-gate 	char	*filename;
309*7c478bd9Sstevel@tonic-gate 	off_t	size;
310*7c478bd9Sstevel@tonic-gate {
311*7c478bd9Sstevel@tonic-gate 	int fd;
312*7c478bd9Sstevel@tonic-gate 	char first;
313*7c478bd9Sstevel@tonic-gate 
314*7c478bd9Sstevel@tonic-gate 	if (size) {
315*7c478bd9Sstevel@tonic-gate 		if ((fd = open(filename, 2)) < 0)
316*7c478bd9Sstevel@tonic-gate 			goto error;
317*7c478bd9Sstevel@tonic-gate 		if (read(fd, &first, 1) != 1)
318*7c478bd9Sstevel@tonic-gate 			goto closeerror;
319*7c478bd9Sstevel@tonic-gate 		if (lseek(fd, 0L, 0) == -1)
320*7c478bd9Sstevel@tonic-gate 			goto closeerror;
321*7c478bd9Sstevel@tonic-gate 		if (write(fd, &first, 1) != 1)
322*7c478bd9Sstevel@tonic-gate 			goto closeerror;
323*7c478bd9Sstevel@tonic-gate 	} else {
324*7c478bd9Sstevel@tonic-gate 		if ((fd = creat(filename, 0666)) < 0)
325*7c478bd9Sstevel@tonic-gate 			goto error;
326*7c478bd9Sstevel@tonic-gate 	}
327*7c478bd9Sstevel@tonic-gate 	if (close(fd) < 0)
328*7c478bd9Sstevel@tonic-gate 		goto error;
329*7c478bd9Sstevel@tonic-gate 	return (0);
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate closeerror:
332*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
333*7c478bd9Sstevel@tonic-gate error:
334*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "%s: could not touch ", prog);
335*7c478bd9Sstevel@tonic-gate 	perror(filename);
336*7c478bd9Sstevel@tonic-gate 	return (-1);
337*7c478bd9Sstevel@tonic-gate }
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate #ifdef S5EMUL
340*7c478bd9Sstevel@tonic-gate isnumber(s)
341*7c478bd9Sstevel@tonic-gate 	char *s;
342*7c478bd9Sstevel@tonic-gate {
343*7c478bd9Sstevel@tonic-gate 	register c;
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate 	while (c = *s++)
346*7c478bd9Sstevel@tonic-gate 		if (!isdigit(c))
347*7c478bd9Sstevel@tonic-gate 			return (0);
348*7c478bd9Sstevel@tonic-gate 	return (1);
349*7c478bd9Sstevel@tonic-gate }
350*7c478bd9Sstevel@tonic-gate #endif S5EMUL
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate /*
353*7c478bd9Sstevel@tonic-gate  * nanoseconds are rounded off to microseconds by flooring.
354*7c478bd9Sstevel@tonic-gate  */
355*7c478bd9Sstevel@tonic-gate static void
356*7c478bd9Sstevel@tonic-gate timestruc_to_timeval(timestruc_t *ts, struct timeval *tv)
357*7c478bd9Sstevel@tonic-gate {
358*7c478bd9Sstevel@tonic-gate 	tv->tv_sec = ts->tv_sec;
359*7c478bd9Sstevel@tonic-gate 	tv->tv_usec = ts->tv_nsec / 1000;
360*7c478bd9Sstevel@tonic-gate }
361