1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"@(#)ctime_001_pos.c	1.1	07/05/25 SMI"
28 
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <utime.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 
39 #define	ST_ATIME 0
40 #define	ST_CTIME 1
41 #define	ST_MTIME 2
42 
43 #define	ALL_MODE (mode_t)(S_IRWXU|S_IRWXG|S_IRWXO)
44 
45 typedef struct timetest {
46 	int	type;
47 	char	*name;
48 	int	(*func)(const char *pfile);
49 } timetest_t;
50 
51 #ifdef __stc_assertion__
52 
53 /*
54  * ID: ctime_001_pos
55  *
56  * DESCRIPTION:
57  * 	Verify time will be changed correctly according to relevant operating.
58  *
59  * STRATEGY:
60  *	1. Define time test array.
61  *	2. loop each item in this array.
62  *	3. Verify the time will be changed after relevant operating.
63  *
64  * TESTABILITY: explicit
65  *
66  * TEST_AUTOMATION_LEVEL: automated
67  *
68  * CODING_STATUS: COMPLETED (2007-01-30)
69  *
70  */
71 
72 #endif	/* __stc_assertion__ */
73 
74 /*
75  * Get file specific time information.
76  */
77 int get_file_time(char *pfile, int what, time_t *ptr);
78 
79 int do_read(const char *pfile);
80 int do_write(const char *pfile);
81 int do_link(const char *pfile);
82 int do_creat(const char *pfile);
83 int do_utime(const char *pfile);
84 int do_chmod(const char *pfile);
85 int do_chown(const char *pfile);
86 
87 static char tfile[BUFSIZ] = { 0 };
88 static char msg[BUFSIZ] = { 0 };
89 
90 static timetest_t timetest_table[] = {
91 	{ ST_ATIME,	"st_atime",	do_read		},
92 	{ ST_ATIME,	"st_atime",	do_utime	},
93 	{ ST_MTIME,	"st_mtime",	do_creat	},
94 	{ ST_MTIME,	"st_mtime",	do_write	},
95 	{ ST_MTIME,	"st_mtime",	do_utime	},
96 	{ ST_CTIME,	"st_ctime",	do_creat	},
97 	{ ST_CTIME,	"st_ctime",	do_write	},
98 	{ ST_CTIME,	"st_ctime",	do_chmod	},
99 	{ ST_CTIME,	"st_ctime",	do_chown 	},
100 	{ ST_CTIME,	"st_ctime",	do_link		},
101 	{ ST_CTIME,	"st_ctime",	do_utime	},
102 };
103 
104 #define	NCOMMAND (sizeof (timetest_table) / sizeof (timetest_table[0]))
105 
106 int
107 main(int argc, char *argv[])
108 {
109 	int i, ret, fd;
110 	const char *env_names[2] = {"TESTDIR", "TESTFILE"};
111 	char *env_vals[2];
112 
113 	/*
114 	 * Get envirnment variable value
115 	 */
116 	for (i = 0; i < sizeof (env_names) / sizeof (char *); i++) {
117 		if ((env_vals[i] = getenv(env_names[i])) == NULL) {
118 			fprintf(stderr, "getenv(%s) returned NULL\n",
119 			    env_names[i]);
120 			exit(1);
121 		}
122 	}
123 	(void) snprintf(tfile, sizeof (tfile), "%s/%s", env_vals[0],
124 	    env_vals[1]);
125 
126 	/*
127 	 * If the test file is existing, remove it firstly
128 	 */
129 	if (access(tfile, F_OK) == 0) {
130 		unlink(tfile);
131 	}
132 	fd = open(tfile, O_WRONLY | O_CREAT | O_TRUNC, ALL_MODE);
133 	if (fd < 0) {
134 		perror("open");
135 		exit(1);
136 	}
137 	(void) close(fd);
138 
139 	for (i = 0; i < NCOMMAND; i++) {
140 		time_t t1, t2;
141 
142 		/*
143 		 * Get original time before operating.
144 		 */
145 		ret = get_file_time(tfile, timetest_table[i].type, &t1);
146 		if (ret != 0) {
147 			fprintf(stderr,
148 			    "ERROR: get_file_time(%s, %d, &t1) returned %d\n",
149 			    tfile, timetest_table[i].type, ret);
150 			exit(1);
151 		}
152 
153 		/*
154 		 * Sleep 2 seconds to be sure that the timeofday has changed,
155 		 * then invoke command on given file
156 		 */
157 		sleep(2);
158 		timetest_table[i].func(tfile);
159 
160 		/*
161 		 * Get time after operating.
162 		 */
163 		ret = get_file_time(tfile, timetest_table[i].type, &t2);
164 		if (ret != 0) {
165 			fprintf(stderr, "get_file_time(%s, %d, &t2)\n",
166 			    tfile, timetest_table[i].type);
167 			exit(1);
168 		}
169 
170 		if (t1 == t2) {
171 			fprintf(stderr, "%s: t1(%ld) == t2(%ld)\n",
172 			    timetest_table[i].name, (long)t1, (long)t2);
173 			exit(1);
174 		}
175 	}
176 
177 	(void) unlink(tfile);
178 
179 	return (0);
180 }
181 
182 int
183 get_file_time(char *pfile, int what, time_t *ptr)
184 {
185 	struct stat stat_buf;
186 
187 	if (pfile == NULL || ptr == NULL) {
188 		return (-1);
189 	}
190 
191 	if (stat(pfile, &stat_buf) == -1) {
192 		return (-1);
193 	}
194 
195 	switch (what) {
196 		case ST_ATIME:
197 			*ptr = stat_buf.st_atime;
198 			return (0);
199 		case ST_CTIME:
200 			*ptr = stat_buf.st_ctime;
201 			return (0);
202 		case ST_MTIME:
203 			*ptr = stat_buf.st_mtime;
204 			return (0);
205 		default:
206 			return (-1);
207 	}
208 }
209 
210 int
211 do_read(const char *pfile)
212 {
213 	int fd, ret = 0;
214 	char buf[BUFSIZ] = { 0 };
215 
216 	if (pfile == NULL) {
217 		return (-1);
218 	}
219 
220 	if ((fd = open(pfile, O_RDONLY, ALL_MODE)) == -1) {
221 		return (-1);
222 	}
223 	if (read(fd, buf, sizeof (buf)) == -1) {
224 		ret = errno;
225 	}
226 	(void) close(fd);
227 
228 	if (ret != 0) {
229 		fprintf(stderr, "read(%d, buf, %zu)\n", fd, sizeof (buf));
230 		exit(1);
231 	}
232 
233 	return (ret);
234 }
235 
236 int
237 do_write(const char *pfile)
238 {
239 	int fd, ret = 0;
240 	char buf[BUFSIZ] = "call function do_write()";
241 
242 	if (pfile == NULL) {
243 		return (-1);
244 	}
245 
246 	if ((fd = open(pfile, O_WRONLY, ALL_MODE)) == -1) {
247 		return (-1);
248 	}
249 	if (write(fd, buf, strlen(buf)) == -1) {
250 		ret = errno;
251 	}
252 	(void) close(fd);
253 
254 	if (ret != 0) {
255 		fprintf(stderr, "write(%d, buf, %zu)\n", fd, strlen(buf));
256 		exit(1);
257 	}
258 
259 	return (ret);
260 }
261 
262 int
263 do_link(const char *pfile)
264 {
265 	int ret = 0;
266 	char link_file[BUFSIZ] = { 0 };
267 	char *ptr = link_file;
268 
269 	if (pfile == NULL) {
270 		return (-1);
271 	}
272 
273 	/*
274 	 * Figure out source file directory name, and create
275 	 * the link file in the same directory.
276 	 */
277 	snprintf(link_file, sizeof (link_file), "%s", pfile);
278 	ptr = strrchr(link_file, '/');
279 	snprintf(ptr + 1,
280 	    sizeof (link_file) - (ptr + 1 - link_file), "link_file");
281 
282 	if (link(pfile, link_file) == -1) {
283 		ret = errno;
284 	}
285 	if (ret != 0) {
286 		fprintf(stderr, "link(%s, %s)\n", pfile, link_file);
287 		exit(1);
288 	}
289 
290 	unlink(link_file);
291 	return (ret);
292 }
293 
294 int
295 do_creat(const char *pfile)
296 {
297 	int fd, ret = 0;
298 
299 	if (pfile == NULL) {
300 		return (-1);
301 	}
302 
303 	if ((fd = creat(pfile, ALL_MODE)) == -1) {
304 		ret = errno;
305 	}
306 	if (fd != -1) {
307 		(void) close(fd);
308 	}
309 
310 	if (ret != 0) {
311 		fprintf(stderr, "creat(%s, ALL_MODE)\n", pfile);
312 		exit(1);
313 	}
314 
315 	return (ret);
316 }
317 
318 int
319 do_utime(const char *pfile)
320 {
321 	int ret = 0;
322 
323 	if (pfile == NULL) {
324 		return (-1);
325 	}
326 
327 	/*
328 	 * Times of the file are set to the current time
329 	 */
330 	if (utime(pfile, NULL) == -1) {
331 		ret = errno;
332 	}
333 	if (ret != 0) {
334 		fprintf(stderr, "utime(%s, NULL)\n", pfile);
335 		exit(1);
336 	}
337 
338 	return (ret);
339 }
340 
341 int
342 do_chmod(const char *pfile)
343 {
344 	int ret = 0;
345 
346 	if (pfile == NULL) {
347 		return (-1);
348 	}
349 
350 	if (chmod(pfile, ALL_MODE) == -1) {
351 		ret = errno;
352 	}
353 	if (ret != 0) {
354 		fprintf(stderr, "chmod(%s, ALL_MODE)\n", pfile);
355 		exit(1);
356 	}
357 
358 	return (ret);
359 }
360 
361 int
362 do_chown(const char *pfile)
363 {
364 	int ret = 0;
365 
366 	if (pfile == NULL) {
367 		return (-1);
368 	}
369 
370 	if (chown(pfile, getuid(), getgid()) == -1) {
371 		ret = errno;
372 	}
373 	if (ret != 0) {
374 		fprintf(stderr, "chown(%s, %d, %d)\n", pfile, (int)getuid(),
375 		    (int)getgid());
376 		exit(1);
377 	}
378 
379 	return (ret);
380 }
381