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