xref: /illumos-gate/usr/src/test/zfs-tests/tests/functional/ctime/ctime_001_pos.c (revision b7daf79982d77b491ef9662483cd4549e0e5da9a)
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 /*
28  * Copyright (c) 2013 by Delphix. All rights reserved.
29  */
30 
31 
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <utime.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <strings.h>
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <libgen.h>
42 
43 #define	ST_ATIME 0
44 #define	ST_CTIME 1
45 #define	ST_MTIME 2
46 
47 #define	ALL_MODE (mode_t)(S_IRWXU|S_IRWXG|S_IRWXO)
48 
49 typedef struct timetest {
50 	int	type;
51 	char	*name;
52 	int	(*func)(const char *pfile);
53 } timetest_t;
54 
55 static char tfile[BUFSIZ] = { 0 };
56 
57 extern int errno;
58 
59 /*
60  * DESCRIPTION:
61  * 	Verify time will be changed correctly after each operation.
62  *
63  * STRATEGY:
64  *	1. Define time test array.
65  *	2. Loop through each item in this array.
66  *	3. Verify the time is changed after each operation.
67  *
68  */
69 
70 static int
71 get_file_time(const char *pfile, int what, time_t *ptr)
72 {
73 	struct stat stat_buf;
74 
75 	if (pfile == NULL || ptr == NULL) {
76 		return (-1);
77 	}
78 
79 	if (stat(pfile, &stat_buf) == -1) {
80 		return (-1);
81 	}
82 
83 	switch (what) {
84 		case ST_ATIME:
85 			*ptr = stat_buf.st_atime;
86 			return (0);
87 		case ST_CTIME:
88 			*ptr = stat_buf.st_ctime;
89 			return (0);
90 		case ST_MTIME:
91 			*ptr = stat_buf.st_mtime;
92 			return (0);
93 		default:
94 			return (-1);
95 	}
96 }
97 
98 static int
99 do_read(const char *pfile)
100 {
101 	int fd, ret = 0;
102 	char buf[BUFSIZ] = { 0 };
103 
104 	if (pfile == NULL) {
105 		return (-1);
106 	}
107 
108 	if ((fd = open(pfile, O_RDONLY, ALL_MODE)) == -1) {
109 		return (-1);
110 	}
111 	if (read(fd, buf, sizeof (buf)) == -1) {
112 		(void) fprintf(stderr, "read(%d, buf, %d) failed with errno "
113 		    "%d\n", fd, sizeof (buf), errno);
114 		return (1);
115 	}
116 	(void) close(fd);
117 
118 	return (ret);
119 }
120 
121 static int
122 do_write(const char *pfile)
123 {
124 	int fd, ret = 0;
125 	char buf[BUFSIZ] = "call function do_write()";
126 
127 	if (pfile == NULL) {
128 		return (-1);
129 	}
130 
131 	if ((fd = open(pfile, O_WRONLY, ALL_MODE)) == -1) {
132 		return (-1);
133 	}
134 	if (write(fd, buf, strlen(buf)) == -1) {
135 		(void) fprintf(stderr, "write(%d, buf, %d) failed with errno "
136 		    "%d\n", fd, strlen(buf), errno);
137 		return (1);
138 	}
139 	(void) close(fd);
140 
141 	return (ret);
142 }
143 
144 static int
145 do_link(const char *pfile)
146 {
147 	int ret = 0;
148 	char link_file[BUFSIZ] = { 0 };
149 	char *dname;
150 
151 	if (pfile == NULL) {
152 		return (-1);
153 	}
154 
155 	/*
156 	 * Figure out source file directory name, and create
157 	 * the link file in the same directory.
158 	 */
159 	dname = dirname(strdup(pfile));
160 	(void) snprintf(link_file, BUFSIZ, "%s/%s", dname, "link_file");
161 
162 	if (link(pfile, link_file) == -1) {
163 		(void) fprintf(stderr, "link(%s, %s) failed with errno %d\n",
164 		    pfile, link_file, errno);
165 		free((void *)dirname);
166 		return (1);
167 	}
168 
169 	(void) unlink(link_file);
170 	free((void *)dirname);
171 	return (ret);
172 }
173 
174 static int
175 do_creat(const char *pfile)
176 {
177 	int fd, ret = 0;
178 
179 	if (pfile == NULL) {
180 		return (-1);
181 	}
182 
183 	if ((fd = creat(pfile, ALL_MODE)) == -1) {
184 		(void) fprintf(stderr, "creat(%s, ALL_MODE) failed with errno "
185 		    "%d\n", pfile, errno);
186 		return (1);
187 	}
188 	(void) close(fd);
189 
190 	return (ret);
191 }
192 
193 static int
194 do_utime(const char *pfile)
195 {
196 	int ret = 0;
197 
198 	if (pfile == NULL) {
199 		return (-1);
200 	}
201 
202 	/*
203 	 * Times of the file are set to the current time
204 	 */
205 	if (utime(pfile, NULL) == -1) {
206 		(void) fprintf(stderr, "utime(%s, NULL) failed with errno "
207 		    "%d\n", pfile, errno);
208 		return (1);
209 	}
210 
211 	return (ret);
212 }
213 
214 static int
215 do_chmod(const char *pfile)
216 {
217 	int ret = 0;
218 
219 	if (pfile == NULL) {
220 		return (-1);
221 	}
222 
223 	if (chmod(pfile, ALL_MODE) == -1) {
224 		(void) fprintf(stderr, "chmod(%s, ALL_MODE) failed with "
225 		    "errno %d\n", pfile, errno);
226 		return (1);
227 	}
228 
229 	return (ret);
230 }
231 
232 static int
233 do_chown(const char *pfile)
234 {
235 	int ret = 0;
236 
237 	if (pfile == NULL) {
238 		return (-1);
239 	}
240 
241 	if (chown(pfile, getuid(), getgid()) == -1) {
242 		(void) fprintf(stderr, "chown(%s, %d, %d) failed with errno "
243 		    "%d\n", pfile, (int)getuid(), (int)getgid(), errno);
244 		return (1);
245 	}
246 
247 	return (ret);
248 }
249 
250 static void
251 cleanup(void)
252 {
253 	if ((strlen(tfile) != 0) && (access(tfile, F_OK) == 0)) {
254 		(void) unlink(tfile);
255 	}
256 }
257 
258 static timetest_t timetest_table[] = {
259 	{ ST_ATIME,	"st_atime",	do_read		},
260 	{ ST_ATIME,	"st_atime",	do_utime	},
261 	{ ST_MTIME,	"st_mtime",	do_creat	},
262 	{ ST_MTIME,	"st_mtime",	do_write	},
263 	{ ST_MTIME,	"st_mtime",	do_utime	},
264 	{ ST_CTIME,	"st_ctime",	do_creat	},
265 	{ ST_CTIME,	"st_ctime",	do_write	},
266 	{ ST_CTIME,	"st_ctime",	do_chmod	},
267 	{ ST_CTIME,	"st_ctime",	do_chown 	},
268 	{ ST_CTIME,	"st_ctime",	do_link		},
269 	{ ST_CTIME,	"st_ctime",	do_utime	},
270 };
271 
272 #define	NCOMMAND (sizeof (timetest_table) / sizeof (timetest_table[0]))
273 
274 /* ARGSUSED */
275 int
276 main(int argc, char *argv[])
277 {
278 	int i, ret, fd;
279 	char *penv[] = {"TESTDIR", "TESTFILE0"};
280 
281 	(void) fprintf(stdout, "Verify [acm]time is modified appropriately.\n");
282 	(void) atexit(cleanup);
283 
284 	/*
285 	 * Get the environment variable values.
286 	 */
287 	for (i = 0; i < sizeof (penv) / sizeof (char *); i++) {
288 		if ((penv[i] = getenv(penv[i])) == NULL) {
289 			(void) fprintf(stderr, "getenv(penv[%d])\n", i);
290 			return (1);
291 		}
292 	}
293 	(void) snprintf(tfile, sizeof (tfile), "%s/%s", penv[0], penv[1]);
294 
295 	/*
296 	 * If the test file is exists, remove it first.
297 	 */
298 	if (access(tfile, F_OK) == 0) {
299 		(void) unlink(tfile);
300 	}
301 	ret = 0;
302 	if ((fd = open(tfile, O_WRONLY | O_CREAT | O_TRUNC, ALL_MODE)) == -1) {
303 		(void) fprintf(stderr, "open(%s) failed: %d\n", tfile, errno);
304 		return (1);
305 	}
306 	(void) close(fd);
307 
308 	for (i = 0; i < NCOMMAND; i++) {
309 		time_t t1, t2;
310 
311 		/*
312 		 * Get original time before operating.
313 		 */
314 		ret = get_file_time(tfile, timetest_table[i].type, &t1);
315 		if (ret != 0) {
316 			(void) fprintf(stderr, "get_file_time(%s %d) = %d\n",
317 			    tfile, timetest_table[i].type, ret);
318 			return (1);
319 		}
320 
321 		/*
322 		 * Sleep 2 seconds, then invoke command on given file
323 		 */
324 		(void) sleep(2);
325 		timetest_table[i].func(tfile);
326 
327 		/*
328 		 * Get time after operating.
329 		 */
330 		ret = get_file_time(tfile, timetest_table[i].type, &t2);
331 		if (ret != 0) {
332 			(void) fprintf(stderr, "get_file_time(%s %d) = %d\n",
333 			    tfile, timetest_table[i].type, ret);
334 			return (1);
335 		}
336 
337 		if (t1 == t2) {
338 			(void) fprintf(stderr, "%s: t1(%ld) == t2(%ld)\n",
339 			    timetest_table[i].name, (long)t1, (long)t2);
340 			return (1);
341 		} else {
342 			(void) fprintf(stderr, "%s: t1(%ld) != t2(%ld)\n",
343 			    timetest_table[i].name, (long)t1, (long)t2);
344 		}
345 	}
346 
347 	(void) fprintf(stdout, "PASS\n");
348 	return (0);
349 }
350