tests: print error locations verbosely
[minix.git] / test / test24.c
blob2f741c12108798c58b409aeaeccefdbf85cdcab8
1 /* Test24: opendir, readdir, rewinddir, closedir Author: Jan-Mark Wams */
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <sys/wait.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <limits.h>
10 #include <fcntl.h>
11 #include <dirent.h>
12 #include <errno.h>
13 #include <time.h>
14 #include <stdio.h>
16 void chk_dir(DIR * dirpntr);
17 void test24a(void);
18 void test24b(void);
19 void test24c(void);
20 void makelongnames(void);
22 #define OVERFLOW_DIR_NR (OPEN_MAX + 1)
23 #define MAX_ERROR 4
24 #define ITERATIONS 5
26 #include "common.c"
28 #define DIRENT0 ((struct dirent *) NULL)
29 #define System(cmd) if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
30 #define Chdir(dir) if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
32 int subtest = 1;
33 int superuser;
35 char *MaxName; /* Name of maximum length */
36 char MaxPath[PATH_MAX]; /* Same for path */
37 char *ToLongName; /* Name of maximum +1 length */
38 char ToLongPath[PATH_MAX + 1]; /* Same for path, both too long */
40 int main(int argc, char *argv[])
42 int i, m = 0xFFFF;
44 start(24);
45 if (argc == 2) m = atoi(argv[1]);
46 makelongnames();
47 superuser = (geteuid() == 0);
49 for (i = 0; i < ITERATIONS; i++) {
50 if (m & 0001) test24a();
51 if (m & 0002) test24b();
52 if (m & 0004) test24c();
54 quit();
56 return(-1); /* Unreachable */
59 void test24a()
60 { /* Test normal operations. */
61 int fd3, fd4, fd5;
62 DIR *dirp;
63 int j, ret, fd, flags;
64 struct stat st1, st2;
65 int stat_loc;
66 time_t time1;
68 subtest = 1;
70 System("rm -rf ../DIR_24/*");
72 if ((fd = dup(0)) != 3) e(1); /* dup stdin */
73 close(fd); /* free the fd again */
74 errno= 0;
75 dirp = opendir("/"); /* open "/" */
76 if (dirp == ((DIR *) NULL)) e(2); /* has to succseed */
77 if (errno != 0) e(3); /* success implies errno didn't change */
78 if ((fd = dup(0)) <= 2) e(4); /* dup stdin */
79 if (fd > 3) { /* if opendir() uses fd 3 */
80 flags = fcntl(3, F_GETFD); /* get fd fags of 3 */
81 if (!(flags & FD_CLOEXEC)) e(5); /* it should be closed on */
82 } /* exec..() calls */
83 close(fd); /* free the fd again */
84 ret = closedir(dirp); /* close, we don't need it */
85 if (ret == -1) e(6); /* closedir () unsucces full */
86 if (ret != 0) e(7); /* should be 0 or -1 */
87 if ((fd = dup(0)) != 3) e(8); /* see if next fd is same */
88 close(fd); /* free the fd again */
90 System("rm -rf foo; mkdir foo");
91 Chdir("foo");
92 System("touch f1 f2 f3 f4 f5"); /* make f1 .. f5 */
93 System("rm f[24]"); /* creat `holes' in entrys */
94 Chdir("..");
96 if ((dirp = opendir("foo")) == ((DIR *) NULL)) e(9); /* open foo */
97 chk_dir(dirp); /* test if foo's ok */
98 for (j = 0; j < 10; j++) {
99 errno = j * 47 % 7; /* there should */
100 if (readdir(dirp) != DIRENT0) e(10); /* be nomore dir */
101 if (errno != j * 47 % 7) e(11); /* entrys */
103 rewinddir(dirp); /* rewind foo */
104 chk_dir(dirp); /* test foosok */
105 for (j = 0; j < 10; j++) {
106 errno = j * 23 % 7; /* there should */
107 if (readdir(dirp) != DIRENT0) e(12); /* be nomore dir */
108 if (errno != j * 23 % 7) e(13); /* entrys */
110 if ((fd4 = creat("foo/f4", 0666)) <= 2) e(14); /* Open a file. */
111 System("rm foo/f4"); /* Kill entry. */
112 rewinddir(dirp); /* Rewind foo. */
113 if ((fd3 = open("foo/f3", O_WRONLY)) <= 2) e(15); /* Open more files. */
114 if ((fd5 = open("foo/f5", O_WRONLY)) <= 2) e(16);
115 if (write(fd3, "Hello", 6) != 6) e(17);
116 if (write(fd4, "Hello", 6) != 6) e(18); /* write some data */
117 if (close(fd5) != 0) e(19);
118 chk_dir(dirp);
119 for (j = 0; j < 10; j++) {
120 errno = j * 101 % 7; /* there should */
121 if (readdir(dirp) != DIRENT0) e(20); /* be nomore dir */
122 if (errno != j * 101 % 7) e(21); /* entrys */
124 if (close(fd4) != 0) e(22); /* shouldn't matter */
125 if (close(fd3) != 0) e(23); /* when we do this */
126 if (closedir(dirp) != 0) e(24); /* close foo again */
128 Chdir("foo");
129 if ((dirp = opendir(".//")) == ((DIR *) NULL)) e(25); /* open foo again */
130 Chdir("..");
131 chk_dir(dirp); /* foosok? */
132 for (j = 0; j < 10; j++) {
133 errno = (j * 101) % 7; /* there should */
134 if (readdir(dirp) != DIRENT0) e(26); /* be nomore dir */
135 if (errno != (j * 101) % 7) e(27); /* entrys */
138 if (closedir(dirp) != 0) e(28); /* It should be closable */
140 stat("foo", &st1); /* get stat */
141 time(&time1);
142 while (time1 >= time((time_t *)0))
144 if ((dirp = opendir("foo")) == ((DIR *) NULL)) e(29); /* open, */
145 if (readdir(dirp) == DIRENT0) e(30); /* read and */
146 stat("foo", &st2); /* get new stat */
147 if (st1.st_atime > st2.st_atime) e(31); /* st_atime check */
149 switch (fork()) {
150 case -1: printf("Can't fork\n"); break;
151 case 0:
152 rewinddir(dirp); /* rewind childs dirp */
153 if (readdir(dirp) == DIRENT0) e(32); /* read should be ok */
154 if (closedir(dirp) != 0) e(33); /* close child'd foo */
155 exit(0); /* 0 stops here */
156 default:
157 if (wait(&stat_loc) == -1) e(34); /* PARENT wait()'s */
158 break;
160 if (closedir(dirp) != 0) e(35); /* close parent's foo */
163 void test24b()
165 /* See what happens with too many dir's open. Check if file size seems ok,
166 * and independency.
169 int i, j; /* i = highest open dir count */
170 DIR *dirp[OVERFLOW_DIR_NR], *dp;
171 struct dirent *dep, *dep1, *dep2;
172 char *name; /* buffer for file name, and count */
173 int dot = 0, dotdot = 0;
174 int max_name_length;
176 subtest = 2;
178 System("rm -rf ../DIR_24/*");
180 max_name_length = name_max(".");
181 name = malloc(max_name_length + 2);
182 memset(name, '\0', max_name_length + 2);
184 for (i = 0; i < OVERFLOW_DIR_NR; i++) {
185 dirp[i] = opendir("/");
186 if (dirp[i] == ((DIR *) NULL)) {
187 if (errno != EMFILE) e(1);
188 break;
191 if (i <= 4) e(2); /* sounds resanable */
192 if (i >= OVERFLOW_DIR_NR) e(3); /* might be to small */
193 for (j = 0; j < i; j++) {
194 if (closedir(dirp[(j + 5) % i]) != 0) e(4); /* neat! */
197 /* Now check if number of bytes in d_name can go up till NAME_MAX */
198 System("rm -rf foo; mkdir foo");
199 Chdir("foo");
200 name[0] = 0;
201 for (i = 0; i <= max_name_length; i++) {
202 if (strcat(name, "X") != name) e(5);
203 close(creat(name, 0666)); /* fails once on */
204 } /* XX..XX, 1 too long */
205 Chdir("..");
206 /* Now change i-th X to Y in name buffer record file of length i. */
207 if ((dp = opendir("foo")) == ((DIR *) NULL)) e(6);
208 while ((dep = readdir(dp)) != DIRENT0) {
209 if (strcmp("..", dep->d_name) == 0)
210 dotdot++;
211 else if (strcmp(".", dep->d_name) == 0)
212 dot++;
213 else
214 name[strlen(dep->d_name)] += 1; /* 'X' + 1 == 'Y' */
216 if (closedir(dp) != 0) e(7);
217 for (i = 1; i <= max_name_length; i++) { /* Check if every length */
218 if (name[i] != 'Y') e(8); /* has been seen once. */
221 /* Check upper and lower bound. */
222 if (name[0] != 'X') e(9);
223 if (name[max_name_length + 1] != '\0') e(10);
225 /* Now check if two simultaniouse open dirs do the same */
226 if ((dirp[1] = opendir("foo")) == ((DIR *) NULL)) e(11);
227 if ((dirp[2] = opendir("foo")) == ((DIR *) NULL)) e(12);
228 if ((dep1 = readdir(dirp[1])) == DIRENT0) e(13);
229 if ((dep2 = readdir(dirp[2])) == DIRENT0) e(14);
230 if (dep1->d_name == dep2->d_name) e(15); /* 1 & 2 Should be */
231 strcpy(name, dep2->d_name); /* differand buffers */
232 if (strcmp(dep1->d_name, name) != 0) e(16); /* But hold the same */
233 if ((dep1 = readdir(dirp[1])) == DIRENT0) e(17);
234 if ((dep1 = readdir(dirp[1])) == DIRENT0) e(18); /* lose some entries */
235 if ((dep1 = readdir(dirp[1])) == DIRENT0) e(19); /* Using dirp 1 has */
236 if (dep1->d_name == dep2->d_name) e(20); /* no effect on 2 */
237 if (strcmp(dep2->d_name, name) != 0) e(21);
238 rewinddir(dirp[1]); /* Rewinding dirp 1 */
239 if ((dep2 = readdir(dirp[2])) == DIRENT0) e(22); /* can't effect 2 */
240 if (strcmp(dep2->d_name, name) == 0) e(23); /* Must be next */
241 if (closedir(dirp[1]) != 0) e(24); /* Closing dirp 1 */
242 if ((dep2 = readdir(dirp[2])) == DIRENT0) e(25); /* can't effect 2 */
243 if (strcmp(dep2->d_name, name) == 0) e(26); /* Must be next */
244 if (closedir(dirp[2]) != 0) e(27);
247 void test24c()
249 /* Test whether wrong things go wrong right. */
251 DIR *dirp;
252 int does_truncate;
254 subtest = 3;
256 System("rm -rf ../DIR_24/*");
258 if (opendir("foo/bar/nono") != ((DIR *) NULL)) e(1); /* nonexistent */
259 if (errno != ENOENT) e(2);
260 System("mkdir foo; chmod 677 foo"); /* foo inaccesable */
261 if (opendir("foo/bar/nono") != ((DIR *) NULL)) e(3);
262 if (superuser) {
263 if (errno != ENOENT) e(4); /* su has access */
264 System("chmod 377 foo");
265 if ((dirp = opendir("foo")) == ((DIR *) NULL)) e(5);
266 if (closedir(dirp) != 0) e(6);
268 if (!superuser) {
269 if (errno != EACCES) e(7); /* we don't ;-) */
270 System("chmod 377 foo");
271 if (opendir("foo") != ((DIR *) NULL)) e(8);
273 System("chmod 777 foo");
275 if (mkdir(MaxName, 0777) != 0) e(9); /* make longdir */
276 if ((dirp = opendir(MaxName)) == ((DIR *) NULL)) e(10); /* open it */
277 if (closedir(dirp) != 0) e(11); /* close it */
278 if (rmdir(MaxName) != 0) e(12); /* then remove it */
279 if ((dirp = opendir(MaxPath)) == ((DIR *) NULL)) e(13); /* open '.' */
280 if (closedir(dirp) != 0) e(14); /* close it */
282 does_truncate = does_fs_truncate();
283 if (opendir(ToLongName) != ((DIR *) NULL)) e(17); /* is too long */
284 if (does_truncate) {
285 if (errno != ENOENT) e(18);
286 } else {
287 if (errno != ENAMETOOLONG) e(19);
290 if (opendir(ToLongPath) != ((DIR *) NULL)) e(20); /* path is too long */
291 if (errno != ENAMETOOLONG) e(21);
292 System("touch foo/abc"); /* make a file */
293 if (opendir("foo/abc") != ((DIR *) NULL)) e(22); /* not a dir */
294 if (errno != ENOTDIR) e(23);
297 void chk_dir(dirp) /* dir should contain */
298 DIR *dirp; /* (`f1', `f3', `f5', `.', `..') */
299 { /* no more, no less */
300 int f1 = 0, f2 = 0, f3 = 0, f4 = 0, f5 = 0, /* counters for all */
301 other = 0, dot = 0, dotdot = 0; /* possible entrys */
302 int i;
303 struct dirent *dep;
304 char *fname;
305 int oldsubtest = subtest;
307 subtest = 4;
309 for (i = 0; i < 5; i++) { /* 3 files and `.' and `..' == 5 entrys */
310 dep = readdir(dirp);
311 if (dep == DIRENT0) { /* not einough */
312 if (dep == DIRENT0) e(1);
313 break;
315 fname = dep->d_name;
316 if (strcmp(fname, ".") == 0)
317 dot++;
318 else if (strcmp(fname, "..") == 0)
319 dotdot++;
320 else if (strcmp(fname, "f1") == 0)
321 f1++;
322 else if (strcmp(fname, "f2") == 0)
323 f2++;
324 else if (strcmp(fname, "f3") == 0)
325 f3++;
326 else if (strcmp(fname, "f4") == 0)
327 f4++;
328 else if (strcmp(fname, "f5") == 0)
329 f5++;
330 else
331 other++;
332 } /* do next dir entry */
334 if (dot != 1) e(2); /* Check the entrys */
335 if (dotdot != 1) e(3);
336 if (f1 != 1) e(4);
337 if (f3 != 1) e(5);
338 if (f5 != 1) e(6);
339 if (f2 != 0) e(7);
340 if (f4 != 0) e(8);
341 if (other != 0) e(9);
343 subtest = oldsubtest;
346 void makelongnames()
348 register int i;
349 int max_name_length;
351 max_name_length = name_max("."); /* Aka NAME_MAX, but not every FS supports
352 * the same length, hence runtime check */
353 MaxName = malloc(max_name_length + 1);
354 ToLongName = malloc(max_name_length + 1 + 1); /* Name of maximum +1 length */
355 memset(MaxName, 'a', max_name_length);
356 MaxName[max_name_length] = '\0';
358 for (i = 0; i < PATH_MAX - 1; i++) { /* idem path */
359 MaxPath[i++] = '.';
360 MaxPath[i] = '/';
362 MaxPath[PATH_MAX - 1] = '\0';
364 strcpy(ToLongName, MaxName); /* copy them Max to ToLong */
365 strcpy(ToLongPath, MaxPath);
367 ToLongName[max_name_length] = 'a';
368 ToLongName[max_name_length+1] = '\0';/* extend ToLongName by one too many */
369 ToLongPath[PATH_MAX - 1] = '/';
370 ToLongPath[PATH_MAX] = '\0'; /* inc ToLongPath by one */