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