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)
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)
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
[])
46 if (argc
== 2) m
= atoi(argv
[1]);
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();
57 return(-1); /* Unreachable */
61 { /* Test normal operations. */
64 int j
, ret
, fd
, flags
;
71 System("rm -rf ../DIR_24/*");
73 if ((fd
= dup(0)) != 3) e(1); /* dup stdin */
74 close(fd
); /* free the fd again */
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");
93 System("touch f1 f2 f3 f4 f5"); /* make f1 .. f5 */
94 System("rm f[24]"); /* creat `holes' in entrys */
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);
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 */
130 if ((dirp
= opendir(".//")) == ((DIR *) NULL
)) e(25); /* open foo again */
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 */
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 */
151 case -1: printf("Can't fork\n"); break;
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 */
158 if (wait(&stat_loc
) == -1) e(34); /* PARENT wait()'s */
161 if (closedir(dirp
) != 0) e(35); /* close parent's foo */
166 /* See what happens with too many dir's open. Check if file size seems ok,
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;
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);
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");
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 */
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)
212 else if (strcmp(".", dep
->d_name
) == 0)
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);
251 /* Test whether wrong things go wrong right. */
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);
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);
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 */
287 if (errno
!= ENOENT
) e(18);
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 */
307 int oldsubtest
= subtest
;
311 for (i
= 0; i
< 5; i
++) { /* 3 files and `.' and `..' == 5 entrys */
313 if (dep
== DIRENT0
) { /* not einough */
314 if (dep
== DIRENT0
) e(1);
318 if (strcmp(fname
, ".") == 0)
320 else if (strcmp(fname
, "..") == 0)
322 else if (strcmp(fname
, "f1") == 0)
324 else if (strcmp(fname
, "f2") == 0)
326 else if (strcmp(fname
, "f3") == 0)
328 else if (strcmp(fname
, "f4") == 0)
330 else if (strcmp(fname
, "f5") == 0)
334 } /* do next dir entry */
336 if (dot
!= 1) e(2); /* Check the entrys */
337 if (dotdot
!= 1) e(3);
343 if (other
!= 0) e(9);
345 subtest
= oldsubtest
;
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 */
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 */