xref: /original-bsd/usr.bin/touch/touch.c (revision be1f24e8)
1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1988 Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)touch.c	5.1 (Berkeley) 10/02/92";
16 #endif /* not lint */
17 
18 /*
19  * Attempt to set the modify date of a file to the current date.  If the
20  * file exists, read and write its first character.  If the file doesn't
21  * exist, create it, unless -c option prevents it.  If the file is read-only,
22  * -f forces chmod'ing and touch'ing.
23  */
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 
34 static int	dontcreate;	/* set if -c option */
35 static int	force;		/* set if -f option */
36 
37 void	err __P((const char *, ...));
38 int	readwrite __P((char *, off_t));
39 int	touch __P((char *));
40 __dead	void usage __P((void));
41 
42 int
43 main(argc, argv)
44 	int argc;
45 	char *argv[];
46 {
47 	int ch, retval;
48 
49 	dontcreate = force = retval = 0;
50 	while ((ch = getopt(argc, argv, "cf")) != EOF)
51 		switch((char)ch) {
52 		case 'c':
53 			dontcreate = 1;
54 			break;
55 		case 'f':
56 			force = 1;
57 			break;
58 		case '?':
59 		default:
60 			usage();
61 		}
62 	if (!*(argv += optind))
63 		usage();
64 	do {
65 		retval |= touch(*argv);
66 	} while (*++argv);
67 	exit(retval);
68 }
69 
70 int
71 touch(filename)
72 	char *filename;
73 {
74 	struct stat sb;
75 
76 	if (stat(filename, &sb) == -1) {
77 		if (!dontcreate)
78 			return (readwrite(filename, (off_t)0));
79 		err("%s: %s", filename, strerror(ENOENT));
80 		return (1);
81 	}
82 	if ((sb.st_mode & S_IFMT) != S_IFREG) {
83 		err("%s: %s", filename, strerror(EFTYPE));
84 		return (1);
85 	}
86 	if (!access(filename, R_OK | W_OK))
87 		return (readwrite(filename, sb.st_size));
88 	if (force) {
89 		int retval;
90 
91 		if (chmod(filename, DEFFILEMODE)) {
92 			err("%s: add permissions: %s",
93 			    filename, strerror(errno));
94 			return (1);
95 		}
96 		retval = readwrite(filename, sb.st_size);
97 		if (chmod(filename, sb.st_mode)) {
98 			err("%s: restore permissions: %s",
99 			    filename, strerror(errno));
100 			return (1);
101 		}
102 		return (retval);
103 	}
104 	err("%s: cannot touch\n", filename);
105 	return (1);
106 }
107 
108 int
109 readwrite(filename, size)
110 	char *filename;
111 	off_t size;
112 {
113 	int fd;
114 	char first;
115 
116 	if (size) {
117 		fd = open(filename, O_RDWR, 0);
118 		if (fd == -1)
119 			goto error;
120 		if (read(fd, &first, 1) != 1)
121 			goto error;
122 		if (lseek(fd, (off_t)0, SEEK_SET) == -1)
123 			goto error;
124 		if (write(fd, &first, 1) != 1)
125 			goto error;
126 	} else {
127 		fd = creat(filename, DEFFILEMODE);
128 		if (fd == -1)
129 			goto error;
130 	}
131 	if (close(fd) == -1) {
132 error:		err("%s: %s", filename, strerror(errno));
133 		return (1);
134 	}
135 	return (0);
136 }
137 
138 __dead void
139 usage()
140 {
141 	fprintf(stderr, "usage: touch [-cf] file ...\n");
142 	exit(1);
143 }
144 
145 #if __STDC__
146 #include <stdarg.h>
147 #else
148 #include <varargs.h>
149 #endif
150 
151 void
152 #if __STDC__
153 err(const char *fmt, ...)
154 #else
155 err(fmt, va_alist)
156 	char *fmt;
157         va_dcl
158 #endif
159 {
160 	va_list ap;
161 #if __STDC__
162 	va_start(ap, fmt);
163 #else
164 	va_start(ap);
165 #endif
166 	(void)fprintf(stderr, "touch: ");
167 	(void)vfprintf(stderr, fmt, ap);
168 	va_end(ap);
169 	(void)fprintf(stderr, "\n");
170 }
171