test24.c

Go to the documentation of this file.
00001 /* Test24: opendir, readdir, rewinddir, closedir       Author: Jan-Mark Wams */
00002 
00003 #include <sys/types.h>
00004 #include <sys/stat.h>
00005 #include <sys/wait.h>
00006 #include <string.h>
00007 #include <stdlib.h>
00008 #include <unistd.h>
00009 #include <limits.h>
00010 #include <fcntl.h>
00011 #include <dirent.h>
00012 #include <errno.h>
00013 #include <time.h>
00014 #include <stdio.h>
00015 
00016 _PROTOTYPE(void main, (int argc, char *argv[]));
00017 _PROTOTYPE(void chk_dir, (DIR * dirpntr));
00018 _PROTOTYPE(void test24a, (void));
00019 _PROTOTYPE(void test24b, (void));
00020 _PROTOTYPE(void test24c, (void));
00021 _PROTOTYPE(void makelongnames, (void));
00022 _PROTOTYPE(void e, (int number));
00023 _PROTOTYPE(void quit, (void));
00024 
00025 #define OVERFLOW_DIR_NR (OPEN_MAX + 1)
00026 #define MAX_ERROR       4
00027 #define ITERATIONS 5
00028 
00029 #define DIRENT0 ((struct dirent *) NULL)
00030 #define System(cmd)     if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
00031 #define Chdir(dir)      if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
00032 
00033 int errct = 0;
00034 int subtest = 1;
00035 int superuser;
00036 
00037 char MaxName[NAME_MAX + 1];     /* Name of maximum length */
00038 char MaxPath[PATH_MAX];         /* Same for path */
00039 char ToLongName[NAME_MAX + 2];  /* Name of maximum +1 length */
00040 char ToLongPath[PATH_MAX + 1];  /* Same for path, both too long */
00041 
00042 void main(argc, argv)
00043 int argc;
00044 char *argv[];
00045 {
00046   int i, m = 0xFFFF;
00047 
00048   sync();
00049   if (argc == 2) m = atoi(argv[1]);
00050   printf("Test 24 ");
00051   fflush(stdout);
00052   System("rm -rf DIR_24; mkdir DIR_24");
00053   Chdir("DIR_24");
00054   makelongnames();
00055   superuser = (geteuid() == 0);
00056 
00057   for (i = 0; i < ITERATIONS; i++) {
00058         if (m & 0001) test24a();
00059         if (m & 0002) test24b();
00060         if (m & 0004) test24c();
00061   }
00062   quit();
00063 }
00064 
00065 void test24a()
00066 {                               /* Test normal operations. */
00067   int fd3, fd4, fd5;
00068   DIR *dirp;
00069   int j, ret, fd, flags;
00070   struct stat st1, st2;
00071   int stat_loc;
00072   time_t time1;
00073 
00074   subtest = 1;
00075 
00076   System("rm -rf ../DIR_24/*");
00077 
00078   if ((fd = dup(0)) != 3) e(1); /* dup stdin */
00079   close(fd);                    /* free the fd again */
00080   dirp = opendir("/");          /* open "/" */
00081   if (dirp == ((DIR *) NULL)) e(2);     /* has to succseed */
00082   if ((fd = dup(0)) <= 2) e(3); /* dup stdin */
00083   if (fd > 3) {                 /* if opendir() uses fd 3 */
00084         flags = fcntl(3, F_GETFD);      /* get fd fags of 3 */
00085         if (!(flags & FD_CLOEXEC)) e(4);        /* it should be closed on */
00086   }                             /* exec..() calls */
00087   close(fd);                    /* free the fd again */
00088   ret = closedir(dirp);         /* close, we don't need it */
00089   if (ret == -1) e(5);          /* closedir () unsucces full */
00090   if (ret != 0) e(6);           /* should be 0 or -1 */
00091   if ((fd = dup(0)) != 3) e(7); /* see if next fd is same */
00092   close(fd);                    /* free the fd again */
00093 
00094   System("rm -rf foo; mkdir foo");
00095   Chdir("foo");
00096   System("touch f1 f2 f3 f4 f5");       /* make f1 .. f5 */
00097   System("rm f[24]");           /* creat `holes' in entrys */
00098   Chdir("..");
00099 
00100   if ((dirp = opendir("foo")) == ((DIR *) NULL)) e(8);  /* open foo */
00101   chk_dir(dirp);                /* test if foo's ok */
00102   for (j = 0; j < 10; j++) {
00103         errno = j * 47 % 7;     /* there should */
00104         if (readdir(dirp) != DIRENT0) e(9);     /* be nomore dir */
00105         if (errno != j * 47 % 7) e(10); /* entrys */
00106   }
00107   rewinddir(dirp);              /* rewind foo */
00108   chk_dir(dirp);                /* test foosok */
00109   for (j = 0; j < 10; j++) {
00110         errno = j * 23 % 7;     /* there should */
00111         if (readdir(dirp) != DIRENT0) e(11);    /* be nomore dir */
00112         if (errno != j * 23 % 7) e(12); /* entrys */
00113   }
00114   if ((fd4 = creat("foo/f4", 0666)) <= 2) e(13);        /* Open a file. */
00115   System("rm foo/f4");          /* Kill entry. */
00116   rewinddir(dirp);              /* Rewind foo. */
00117   if ((fd3 = open("foo/f3", O_WRONLY)) <= 2) e(14);     /* Open more files. */
00118   if ((fd5 = open("foo/f5", O_WRONLY)) <= 2) e(15);
00119   if (write(fd3, "Hello", 6) != 6) e(16);
00120   if (write(fd4, "Hello", 6) != 6) e(17);       /* write some data */
00121   if (close(fd5) != 0) e(18);
00122   chk_dir(dirp);
00123   for (j = 0; j < 10; j++) {
00124         errno = j * 101 % 7;    /* there should */
00125         if (readdir(dirp) != DIRENT0) e(19);    /* be nomore dir */
00126         if (errno != j * 101 % 7) e(20);        /* entrys */
00127   }
00128   if (close(fd4) != 0) e(21);   /* shouldn't matter */
00129   if (close(fd3) != 0) e(22);   /* when we do this */
00130   if (closedir(dirp) != 0) e(23);       /* close foo again */
00131 
00132   Chdir("foo");
00133   if ((dirp = opendir(".//")) == ((DIR *) NULL)) e(24); /* open foo again */
00134   Chdir("..");
00135   chk_dir(dirp);                /* foosok? */
00136   for (j = 0; j < 10; j++) {
00137         errno = (j * 101) % 7;  /* there should */
00138         if (readdir(dirp) != DIRENT0) e(25);    /* be nomore dir */
00139         if (errno != (j * 101) % 7) e(26);      /* entrys */
00140   }
00141 
00142   if (closedir(dirp) != 0) e(27);       /* It should be closable */
00143 
00144   stat("foo", &st1);            /* get stat */
00145   time(&time1);
00146   while (time1 >= time((time_t *)0))
00147         ;
00148   if ((dirp = opendir("foo")) == ((DIR *) NULL)) e(28); /* open, */
00149   if (readdir(dirp) == DIRENT0) e(29);  /* read and */
00150   stat("foo", &st2);            /* get new stat */
00151   if (st1.st_atime > st2.st_atime) e(30);       /* st_atime check */
00152 
00153   switch (fork()) {
00154       case -1:  printf("Can't fork\n"); break;
00155       case 0:
00156         rewinddir(dirp);        /* rewind childs dirp */
00157         if (readdir(dirp) == DIRENT0) e(31);    /* read should be ok */
00158         if (closedir(dirp) != 0) e(32); /* close child'd foo */
00159         exit(0);                /* 0 stops here */
00160       default:
00161         if (wait(&stat_loc) == -1) e(33);       /* PARENT wait()'s */
00162         break;
00163   }
00164   if (closedir(dirp) != 0) e(34);       /* close parent's foo */
00165 }
00166 
00167 void test24b()
00168 {
00169 /* See what happens with too many dir's open.  Check if file size seems ok, 
00170  * and independency.
00171  */
00172 
00173   int i, j;                     /* i = highest open dir count */
00174   DIR *dirp[OVERFLOW_DIR_NR], *dp;
00175   struct dirent *dep, *dep1, *dep2;
00176   char name[NAME_MAX + 2];      /* buffer for file name, and count */
00177   int dot = 0, dotdot = 0;
00178 
00179   subtest = 2;
00180 
00181   System("rm -rf ../DIR_24/*");
00182 
00183   for (i = 0; i < OVERFLOW_DIR_NR; i++) {
00184         dirp[i] = opendir("/");
00185         if (dirp[i] == ((DIR *) NULL)) {
00186                 if (errno != EMFILE) e(1);
00187                 break;
00188         }
00189   }
00190   if (i <= 4) e(2);             /* sounds resanable */
00191   if (i >= OVERFLOW_DIR_NR) e(3);       /* might be to small */
00192   for (j = 0; j < i; j++) {
00193         if (closedir(dirp[(j + 5) % i]) != 0) e(4);     /* neat! */
00194   }
00195 
00196   /* Now check if number of bytes in d_name can go up till NAME_MAX */
00197   System("rm -rf foo; mkdir foo");
00198   Chdir("foo");
00199   name[0] = 0;
00200   for (i = 0; i <= NAME_MAX; i++) {
00201         if (strcat(name, "X") != name) e(5);
00202         close(creat(name, 0666));       /* fails once on */
00203   }                             /* XX..XX, 1 too long */
00204   Chdir("..");
00205   /* Now change i-th X to Y in name buffer record file of length i. */
00206   if ((dp = opendir("foo")) == ((DIR *) NULL)) e(6);
00207   while ((dep = readdir(dp)) != DIRENT0) {
00208         if (strcmp("..", dep->d_name) == 0)
00209                 dotdot++;
00210         else if (strcmp(".", dep->d_name) == 0)
00211                 dot++;
00212         else
00213                 name[strlen(dep->d_name)] += 1; /* 'X' + 1 == 'Y' */
00214   }
00215   if (closedir(dp) != 0) e(7);
00216   for (i = 1; i <= NAME_MAX; i++) {     /* Check if every length */
00217         if (name[i] != 'Y') e(8);       /* has been seen once. */
00218   }
00219 
00220   /* Check upper and lower bound. */
00221   if (name[0] != 'X') e(9);
00222   if (name[NAME_MAX + 1] != '\0') e(10);
00223 
00224   /* Now check if two simultaniouse open dirs do the same */
00225   if ((dirp[1] = opendir("foo")) == ((DIR *) NULL)) e(11);
00226   if ((dirp[2] = opendir("foo")) == ((DIR *) NULL)) e(12);
00227   if ((dep1 = readdir(dirp[1])) == DIRENT0) e(13);
00228   if ((dep2 = readdir(dirp[2])) == DIRENT0) e(14);
00229   if (dep1->d_name == dep2->d_name) e(15);      /* 1 & 2 Should be */
00230   strcpy(name, dep2->d_name);   /* differand buffers */
00231   if (strcmp(dep1->d_name, name) != 0) e(16);   /* But hold the same */
00232   if ((dep1 = readdir(dirp[1])) == DIRENT0) e(17);
00233   if ((dep1 = readdir(dirp[1])) == DIRENT0) e(18);      /* lose some entries */
00234   if ((dep1 = readdir(dirp[1])) == DIRENT0) e(19);      /* Using dirp 1 has */
00235   if (dep1->d_name == dep2->d_name) e(20);      /* no effect on 2 */
00236   if (strcmp(dep2->d_name, name) != 0) e(21);
00237   rewinddir(dirp[1]);           /* Rewinding dirp 1 */
00238   if ((dep2 = readdir(dirp[2])) == DIRENT0) e(22);      /* can't effect 2 */
00239   if (strcmp(dep2->d_name, name) == 0) e(23);   /* Must be next */
00240   if (closedir(dirp[1]) != 0) e(24);    /* Closing dirp 1 */
00241   if ((dep2 = readdir(dirp[2])) == DIRENT0) e(25);      /* can't effect 2 */
00242   if (strcmp(dep2->d_name, name) == 0) e(26);   /* Must be next */
00243   if (closedir(dirp[2]) != 0) e(27);
00244 }
00245 
00246 void test24c()
00247 {
00248 /* Test whether wrong things go wrong right. */
00249 
00250   DIR *dirp;
00251 
00252   subtest = 3;
00253 
00254   System("rm -rf ../DIR_24/*");
00255 
00256   if (opendir("foo/bar/nono") != ((DIR *) NULL)) e(1);  /* nonexistent */
00257   if (errno != ENOENT) e(2);
00258   System("mkdir foo; chmod 677 foo");   /* foo inaccesable */
00259   if (opendir("foo/bar/nono") != ((DIR *) NULL)) e(3);
00260   if (superuser) {
00261         if (errno != ENOENT) e(4);      /* su has access */
00262         System("chmod 377 foo");
00263         if ((dirp = opendir("foo")) == ((DIR *) NULL)) e(5);
00264         if (closedir(dirp) != 0) e(6);
00265   }
00266   if (!superuser) {
00267         if (errno != EACCES) e(7);      /* we don't ;-) */
00268         System("chmod 377 foo");
00269         if (opendir("foo") != ((DIR *) NULL)) e(8);
00270   }
00271   System("chmod 777 foo");
00272 
00273   if (mkdir(MaxName, 0777) != 0) e(9);  /* make longdir */
00274   if ((dirp = opendir(MaxName)) == ((DIR *) NULL)) e(10);       /* open it */
00275   if (closedir(dirp) != 0) e(11);       /* close it */
00276   if (rmdir(MaxName) != 0) e(12);       /* then remove it */
00277   if ((dirp = opendir(MaxPath)) == ((DIR *) NULL)) e(13);       /* open '.'  */
00278   if (closedir(dirp) != 0) e(14);       /* close it */
00279 #if 0 /* XXX - anything could happen with the bad pointer */
00280   if (closedir(dirp) != -1) e(15);      /* close it again */
00281   if (closedir(dirp) != -1) e(16);      /* and again */
00282 #endif /* 0 */
00283   if (opendir(ToLongName) != ((DIR *) NULL)) e(17);     /* is too long */
00284 #ifdef _POSIX_NO_TRUNC
00285 # if _POSIX_NO_TRUNC - 0 != -1
00286   if (errno != ENAMETOOLONG) e(18);
00287 # else
00288   if (errno != ENOENT) e(19);
00289 # endif
00290 #else
00291 # include "error, this case requires dynamic checks and is not handled"
00292 #endif
00293   if (opendir(ToLongPath) != ((DIR *) NULL)) e(20);     /* path is too long */
00294   if (errno != ENAMETOOLONG) e(21);
00295   System("touch foo/abc");      /* make a file */
00296   if (opendir("foo/abc") != ((DIR *) NULL)) e(22);      /* not a dir */
00297   if (errno != ENOTDIR) e(23);
00298 }
00299 
00300 void chk_dir(dirp)              /* dir should contain             */
00301 DIR *dirp;                      /* (`f1', `f3', `f5', `.', `..')  */
00302 {                               /* no more, no less               */
00303   int f1 = 0, f2 = 0, f3 = 0, f4 = 0, f5 = 0,   /* counters for all */
00304    other = 0, dot = 0, dotdot = 0;      /* possible entrys */
00305   int i;
00306   struct dirent *dep;
00307   char *fname;
00308   int oldsubtest = subtest;
00309 
00310   subtest = 4;
00311 
00312   for (i = 0; i < 5; i++) {     /* 3 files and `.' and `..' == 5 entrys */
00313         dep = readdir(dirp);
00314         if (dep == DIRENT0) {   /* not einough */
00315                 if (dep == DIRENT0) e(1);
00316                 break;
00317         }
00318         fname = dep->d_name;
00319         if (strcmp(fname, ".") == 0)
00320                 dot++;
00321         else if (strcmp(fname, "..") == 0)
00322                 dotdot++;
00323         else if (strcmp(fname, "f1") == 0)
00324                 f1++;
00325         else if (strcmp(fname, "f2") == 0)
00326                 f2++;
00327         else if (strcmp(fname, "f3") == 0)
00328                 f3++;
00329         else if (strcmp(fname, "f4") == 0)
00330                 f4++;
00331         else if (strcmp(fname, "f5") == 0)
00332                 f5++;
00333         else
00334                 other++;
00335   }                             /* do next dir entry */
00336 
00337   if (dot != 1) e(2);           /* Check the entrys */
00338   if (dotdot != 1) e(3);
00339   if (f1 != 1) e(4);
00340   if (f3 != 1) e(5);
00341   if (f5 != 1) e(6);
00342   if (f2 != 0) e(7);
00343   if (f4 != 0) e(8);
00344   if (other != 0) e(9);
00345 
00346   subtest = oldsubtest;
00347 }
00348 
00349 void makelongnames()
00350 {
00351   register int i;
00352 
00353   memset(MaxName, 'a', NAME_MAX);
00354   MaxName[NAME_MAX] = '\0';
00355   for (i = 0; i < PATH_MAX - 1; i++) {  /* idem path */
00356         MaxPath[i++] = '.';
00357         MaxPath[i] = '/';
00358   }
00359   MaxPath[PATH_MAX - 1] = '\0';
00360 
00361   strcpy(ToLongName, MaxName);  /* copy them Max to ToLong */
00362   strcpy(ToLongPath, MaxPath);
00363 
00364   ToLongName[NAME_MAX] = 'a';
00365   ToLongName[NAME_MAX + 1] = '\0';      /* extend ToLongName by one too many */
00366   ToLongPath[PATH_MAX - 1] = '/';
00367   ToLongPath[PATH_MAX] = '\0';  /* inc ToLongPath by one */
00368 }
00369 
00370 void e(n)
00371 int n;
00372 {
00373   int err_num = errno;          /* Save in case printf clobbers it. */
00374 
00375   printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
00376   errno = err_num;
00377   perror("");
00378   if (errct++ > MAX_ERROR) {
00379         printf("Too many errors; test aborted\n");
00380         chdir("..");
00381         system("rm -rf DIR*");
00382         exit(1);
00383   }
00384   errno = 0;
00385 }
00386 
00387 void quit()
00388 {
00389   Chdir("..");
00390   System("rm -rf DIR_24");
00391 
00392   if (errct == 0) {
00393         printf("ok\n");
00394         exit(0);
00395   } else {
00396         printf("%d errors\n", errct);
00397         exit(1);
00398   }
00399 }

Generated on Fri Apr 14 22:57:34 2006 for minix by  doxygen 1.4.6