1 /* Test24: opendir, readdir, rewinddir, closedir Author: Jan-Mark Wams */ 2 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> 15 16 void chk_dir(DIR * dirpntr); 17 void test24a(void); 18 void test24b(void); 19 void test24c(void); 20 void makelongnames(void); 21 22 #define OVERFLOW_DIR_NR (OPEN_MAX + 1) 23 int max_error = 4; 24 #include "common.h" 25 26 #define ITERATIONS 5 27 28 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) 32 33 int subtest = 1; 34 int superuser; 35 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 */ 40 41 int main(int argc, char *argv[]) 42 { 43 int i, m = 0xFFFF; 44 45 start(24); 46 if (argc == 2) m = atoi(argv[1]); 47 makelongnames(); 48 superuser = (geteuid() == 0); 49 50 for (i = 0; i < ITERATIONS; i++) { 51 if (m & 0001) test24a(); 52 if (m & 0002) test24b(); 53 if (m & 0004) test24c(); 54 } 55 quit(); 56 57 return(-1); /* Unreachable */ 58 } 59 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; 68 69 subtest = 1; 70 71 System("rm -rf ../DIR_24/*"); 72 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 */ 90 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(".."); 96 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 */ 103 } 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 */ 110 } 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 */ 124 } 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 */ 128 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 */ 137 } 138 139 if (closedir(dirp) != 0) e(28); /* It should be closable */ 140 141 stat("foo", &st1); /* get stat */ 142 time(&time1); 143 while (time1 >= time((time_t *)0)) 144 ; 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 */ 149 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; 160 } 161 if (closedir(dirp) != 0) e(35); /* close parent's foo */ 162 } 163 164 void test24b() 165 { 166 /* See what happens with too many dir's open. Check if file size seems ok, 167 * and independency. 168 */ 169 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; 176 177 subtest = 2; 178 179 System("rm -rf ../DIR_24/*"); 180 181 max_name_length = name_max("."); 182 name = malloc(max_name_length + 2); 183 memset(name, '\0', max_name_length + 2); 184 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; 190 } 191 } 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! */ 196 } 197 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' */ 216 } 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. */ 220 } 221 222 /* Check upper and lower bound. */ 223 if (name[0] != 'X') e(9); 224 if (name[max_name_length + 1] != '\0') e(10); 225 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); 247 } 248 249 void test24c() 250 { 251 /* Test whether wrong things go wrong right. */ 252 253 DIR *dirp; 254 int does_truncate; 255 256 subtest = 3; 257 258 System("rm -rf ../DIR_24/*"); 259 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); 269 } 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); 274 } 275 System("chmod 777 foo"); 276 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 */ 283 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); 290 } 291 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); 297 } 298 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; 308 309 subtest = 4; 310 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; 316 } 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 */ 335 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); 344 345 subtest = oldsubtest; 346 } 347 348 void makelongnames() 349 { 350 register int i; 351 int max_name_length; 352 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'; 359 360 for (i = 0; i < PATH_MAX - 1; i++) { /* idem path */ 361 MaxPath[i++] = '.'; 362 MaxPath[i] = '/'; 363 } 364 MaxPath[PATH_MAX - 1] = '\0'; 365 366 strcpy(ToLongName, MaxName); /* copy them Max to ToLong */ 367 strcpy(ToLongPath, MaxPath); 368 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 */ 373 } 374