1 /* Test24: opendir, readdir, rewinddir, closedir Author: Jan-Mark Wams */
16 void chk_dir(DIR * dirpntr
);
20 void makelongnames(void);
22 #define OVERFLOW_DIR_NR (OPEN_MAX + 1)
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)
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
[])
45 if (argc
== 2) m
= atoi(argv
[1]);
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();
56 return(-1); /* Unreachable */
60 { /* Test normal operations. */
63 int j
, ret
, fd
, flags
;
70 System("rm -rf ../DIR_24/*");
72 if ((fd
= dup(0)) != 3) e(1); /* dup stdin */
73 close(fd
); /* free the fd again */
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");
92 System("touch f1 f2 f3 f4 f5"); /* make f1 .. f5 */
93 System("rm f[24]"); /* creat `holes' in entrys */
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);
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 */
129 if ((dirp
= opendir(".//")) == ((DIR *) NULL
)) e(25); /* open foo again */
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 */
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 */
150 case -1: printf("Can't fork\n"); break;
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 */
157 if (wait(&stat_loc
) == -1) e(34); /* PARENT wait()'s */
160 if (closedir(dirp
) != 0) e(35); /* close parent's foo */
165 /* See what happens with too many dir's open. Check if file size seems ok,
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;
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);
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");
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 */
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)
211 else if (strcmp(".", dep
->d_name
) == 0)
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);
249 /* Test whether wrong things go wrong right. */
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);
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);
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 */
285 if (errno
!= ENOENT
) e(18);
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 */
305 int oldsubtest
= subtest
;
309 for (i
= 0; i
< 5; i
++) { /* 3 files and `.' and `..' == 5 entrys */
311 if (dep
== DIRENT0
) { /* not einough */
312 if (dep
== DIRENT0
) e(1);
316 if (strcmp(fname
, ".") == 0)
318 else if (strcmp(fname
, "..") == 0)
320 else if (strcmp(fname
, "f1") == 0)
322 else if (strcmp(fname
, "f2") == 0)
324 else if (strcmp(fname
, "f3") == 0)
326 else if (strcmp(fname
, "f4") == 0)
328 else if (strcmp(fname
, "f5") == 0)
332 } /* do next dir entry */
334 if (dot
!= 1) e(2); /* Check the entrys */
335 if (dotdot
!= 1) e(3);
341 if (other
!= 0) e(9);
343 subtest
= oldsubtest
;
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 */
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 */