1 /* vi: set sw=4 ts=4: */
2 /* testcase for futimens(2)
3  * Copyright (C) 2009 Bernhard Reutner-Fischer <uClibc@uClibc.org>
4  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
5  */
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <errno.h>
9 #include <stdlib.h>
10 #include <fcntl.h>
11 #include <stdio.h>
12 #include <unistd.h>
13 
14 struct
15 {
16 	char *name; /* name of file to open */
17 	int flags; /* flags for file descriptor */
18 	const struct timespec ts[2];
19 	int err; /* expected errno */
20 } tests [] =
21 {
22 	{"futimens.tst", (O_CREAT|O_TRUNC), {{0,0},{0,0}}, 0},
23 	{"futimens.tst", (O_CREAT|O_TRUNC), {{99,0},{0,0}}, 0},
24 	{"futimens.tst", (O_CREAT|O_TRUNC), {{0,99},{0,0}}, 0},
25 	{"futimens.tst", (O_CREAT|O_TRUNC), {{0,0},{99,0}}, 0},
26 	{"futimens.tst", (O_CREAT|O_TRUNC), {{0,0},{0,99}}, 0},
27 	{"futimens.tst", (O_CREAT|O_TRUNC), {{11,2},{3,4}}, 0},
28 };
do_test(int argc,char ** argv)29 int do_test(int argc, char **argv) {
30 	char *name;
31 	int i, errors;
32 	errors = argc - argc + 0;
33 	unsigned has_stat_nsec = 0;
34 	{
35 		struct stat probe;
36 		/* Let's attempt an educated guess if this filesystem supports
37 		 * nanosecond mtime.  */
38 		if ((!stat(".", &probe)) && probe.st_mtim.tv_nsec)
39 			has_stat_nsec = 1;
40 		else if ((!stat(argv[0], &probe)) && probe.st_mtim.tv_nsec)
41 			has_stat_nsec = 1;
42 	}
43 	for (i=0; i < (int) (sizeof(tests)/sizeof(tests[0])); ++i) {
44 		int err, fd;
45 		struct stat sb;
46 		name = tests[i].name;
47 		if (*name != '.')
48 			unlink(name);
49 		fd = open(name, tests[i].flags, 0660);
50 		if (fd < 0)
51 			abort();
52 		errno = 0;
53 		err = futimens(fd, tests[i].ts);
54 		if ((errno && !err) || (!errno && err)) {
55 			err = errno;
56 			printf("FAILED test %d (errno and return value disagree)\n", i);
57 			++errors;
58 		} else
59 			err = errno;
60 		if (err != tests[i].err) {
61 			printf("FAILED test %d (expected errno %d, got %d)\n",
62 				i, tests[i].err, err);
63 			++errors;
64 			continue;
65 		}
66 		if (stat(name, &sb) < 0) {
67 			printf("FAILED test %d (verification)\n", i);
68 			++errors;
69 			continue;
70 		} else {
71 			unsigned wrong = tests[i].ts[0].tv_sec != sb.st_atim.tv_sec ||
72 						tests[i].ts[0].tv_nsec != sb.st_atim.tv_nsec ||
73 						tests[i].ts[1].tv_sec != sb.st_mtim.tv_sec ||
74 						tests[i].ts[1].tv_nsec != sb.st_mtim.tv_nsec;
75 			if (wrong) {
76 				if (tests[i].ts[0].tv_sec != sb.st_atim.tv_sec) {
77 					printf("FAILED test %d (access time, sec: expected %ld, got %ld)\n",
78 						i, tests[i].ts[0].tv_sec, sb.st_atim.tv_sec);
79 						++errors;
80 				}
81 				if (tests[i].ts[0].tv_nsec != sb.st_atim.tv_nsec) {
82 					printf("FAILED test %d (access time, nsec: expected %ld, got %ld)\n",
83 						i, tests[i].ts[0].tv_nsec, sb.st_atim.tv_nsec);
84 					errors += has_stat_nsec;
85 				}
86 
87 				if (tests[i].ts[1].tv_sec != sb.st_mtim.tv_sec) {
88 					printf("FAILED test %d (modification time, sec: expected %ld, got %ld)\n",
89 						i, tests[i].ts[1].tv_sec, sb.st_mtim.tv_sec);
90 						++errors;
91 				}
92 				if (tests[i].ts[1].tv_nsec != sb.st_mtim.tv_nsec) {
93 					printf("FAILED test %d (modification time, nsec: expected %ld, got %ld)\n",
94 						i, tests[i].ts[1].tv_nsec, sb.st_mtim.tv_nsec);
95 					errors += has_stat_nsec;
96 				}
97 			}
98 		}
99 	}
100 	if (*name != '.')
101 		unlink(name);
102 	printf("%d errors.\n", errors);
103 	return (!errors) ? EXIT_SUCCESS : EXIT_FAILURE;
104 }
105 #include <test-skeleton.c>
106