test23.c

Go to the documentation of this file.
00001 /* test23: chdir(), getcwd()    Author: Jan-Mark Wams (jms@cs.vu.nl) */
00002 
00003 #include <sys/types.h>
00004 #include <sys/stat.h>
00005 #include <sys/dir.h>
00006 #include <limits.h>
00007 #include <errno.h>
00008 #include <unistd.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 #include <fcntl.h>
00012 #include <stdio.h>
00013 
00014 #define MAX_ERROR 4
00015 #define ITERATIONS 3
00016 
00017 #define System(cmd)     if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
00018 #define Chdir(dir)      if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
00019 
00020 int errct;
00021 int subtest;
00022 int superuser;                  /* True if we are root. */
00023 
00024 char cwd[PATH_MAX];             /* Space for path names. */
00025 char cwd2[PATH_MAX];
00026 char buf[PATH_MAX];
00027 char MaxName[NAME_MAX + 1];     /* Name of maximum length */
00028 char MaxPath[PATH_MAX];         /* Same for path */
00029 char ToLongName[NAME_MAX + 2];  /* Name of maximum +1 length */
00030 char ToLongPath[PATH_MAX + 1];  /* Same for path, both too long */
00031 
00032 _PROTOTYPE(void main, (int argc, char *argv[]));
00033 _PROTOTYPE(void test23a, (void));
00034 _PROTOTYPE(void test23b, (void));
00035 _PROTOTYPE(void test23c, (void));
00036 _PROTOTYPE(void makelongnames, (void)); /* Fill MaxName etc. */
00037 _PROTOTYPE(char *last_index, (char *string, int ch));
00038 _PROTOTYPE(char *my_getcwd, (char *buf, int size));
00039 _PROTOTYPE(void e, (int number));
00040 _PROTOTYPE(void quit, (void));
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 23 ");
00051   fflush(stdout);
00052   System("rm -rf DIR_23; mkdir DIR_23");
00053   Chdir("DIR_23");
00054   makelongnames();
00055   superuser = (geteuid() == 0);
00056 
00057   for (i = 0; i < ITERATIONS; i++) {
00058         if (m & 0001) test23a();        /* Test normal operation */
00059         if (m & 0002) test23b();        /* Test critical operation */
00060         if (m & 0004) test23c();        /* Test error operation */
00061   }
00062 
00063   quit();
00064 }
00065 
00066 void test23a()
00067 {                               /* Test normal operation. */
00068   register int i;
00069 
00070   subtest = 1;
00071 
00072   System("rm -rf ../DIR_23/*");
00073 
00074   /* Let's do some fiddeling with path names. */
00075   if (getcwd(cwd, PATH_MAX) != cwd) e(1);
00076   if (chdir(cwd) != 0) e(2);
00077   if (getcwd(buf, PATH_MAX) != buf) e(3);
00078   if (strcmp(buf, cwd) != 0) e(4);
00079   if (chdir(".") != 0) e(5);
00080   if (getcwd(buf, PATH_MAX) != buf) e(6);
00081   if (strcmp(buf, cwd) != 0) e(7);
00082   if (chdir("./././.") != 0) e(8);
00083   if (getcwd(buf, PATH_MAX) != buf) e(9);
00084   if (strcmp(buf, cwd) != 0) e(10);
00085 
00086   /* Creat a working dir named "foo", remove any previous residues. */
00087   System("rm -rf foo");
00088   if (mkdir("foo", 0777) != 0) e(11);
00089 
00090   /* Do some more fiddeling with path names. */
00091   if (chdir("foo/.././foo/..") != 0) e(12);     /* change to cwd */
00092   if (getcwd(buf, PATH_MAX) != buf) e(13);
00093   if (strcmp(buf, cwd) != 0) e(13);
00094   if (chdir("foo") != 0) e(14); /* change to foo */
00095   if (chdir("..") != 0) e(15);  /* and back again */
00096   if (getcwd(buf, PATH_MAX) != buf) e(16);
00097   if (strcmp(buf, cwd) != 0) e(17);
00098 
00099   /* Make 30 sub dirs, eg. ./bar/bar/bar/bar/bar...... */
00100   System("rm -rf bar");         /* get ridd of bar */
00101   for (i = 0; i < 30; i++) {
00102         if (mkdir("bar", 0777) != 0) e(18);
00103         if (chdir("bar") != 0) e(19);   /* change to bar */
00104   }
00105   for (i = 0; i < 30; i++) {
00106         if (chdir("..") != 0) e(20);    /* and back again */
00107         if (rmdir("bar") != 0) e(21);
00108   }
00109 
00110   /* Make sure we are back where we started. */
00111   if (getcwd(buf, PATH_MAX) != buf) e(22);
00112   if (strcmp(buf, cwd) != 0) e(23);
00113   System("rm -rf bar");         /* just incase */
00114 
00115   /* Do some normal checks on `Chdir()' and `getcwd()' */
00116   if (chdir("/") != 0) e(24);
00117   if (getcwd(buf, PATH_MAX) != buf) e(25);
00118   if (strcmp(buf, "/") != 0) e(26);
00119   if (chdir("..") != 0) e(27);  /* go to parent of / */
00120   if (getcwd(buf, PATH_MAX) != buf) e(28);
00121   if (strcmp(buf, "/") != 0) e(29);
00122   if (chdir(cwd) != 0) e(30);
00123   if (getcwd(buf, PATH_MAX) != buf) e(31);
00124   if (strcmp(buf, cwd) != 0) e(32);
00125   if (chdir("/etc") != 0) e(33);        /* /etc might be on RAM */
00126   if (getcwd(buf, PATH_MAX) != buf) e(34);      /* might make a difference */
00127   if (strcmp(buf, "/etc") != 0) e(35);
00128   if (chdir(cwd) != 0) e(36);
00129   if (getcwd(buf, PATH_MAX) != buf) e(37);
00130   if (strcmp(buf, cwd) != 0) e(38);
00131   if (chdir(".//.//") != 0) e(39);      /* .//.// == current dir */
00132   if (getcwd(buf, PATH_MAX) != buf) e(40);
00133   if (strcmp(buf, cwd) != 0) e(41);     /* we might be at '/' */
00134 #ifdef _MINIX
00135   /* XXX - my_getcwd() is old rubbish.  It reads the directory directly instead
00136    * of through the directory library.  It uses a fixed size buffer instead of
00137    * a size related to PATH_MAX, NAME_MAX or the size required.
00138    */
00139   if (my_getcwd(buf, PATH_MAX) != buf) e(42);   /* get cwd my way */
00140   if (strcmp(cwd, buf) != 0) e(43);
00141 #endif
00142   System("rm -rf foo");
00143 }
00144 
00145 void test23b()
00146 {                               /* Test critical values. */
00147   subtest = 2;
00148 
00149   System("rm -rf ../DIR_23/*");
00150 
00151   /* Fiddle with the size (2nt) parameter of `getcwd ()'. */
00152   if (getcwd(cwd, PATH_MAX) != cwd) e(1);       /* get cwd */
00153   if (getcwd(buf, strlen(cwd)) != (char *) 0) e(2);   /* size 1 to small */
00154   if (errno != ERANGE) e(3);
00155   if (getcwd(buf, PATH_MAX) != buf) e(4);
00156   if (strcmp(buf, cwd) != 0) e(5);
00157   Chdir(cwd);                   /* getcwd might cd / */
00158   if (getcwd(buf, strlen(cwd) + 1) != buf) e(6);        /* size just ok */
00159   if (getcwd(buf, PATH_MAX) != buf) e(7);
00160   if (strcmp(buf, cwd) != 0) e(8);
00161 
00162   /* Let's see how "MaxName" and "ToLongName" are handled. */
00163   if (mkdir(MaxName, 0777) != 0) e(9);
00164   if (chdir(MaxName) != 0) e(10);
00165   if (chdir("..") != 0) e(11);
00166   if (rmdir(MaxName) != 0) e(12);
00167   if (getcwd(buf, PATH_MAX) != buf) e(13);
00168   if (strcmp(buf, cwd) != 0) e(14);
00169   if (chdir(MaxPath) != 0) e(15);
00170   if (getcwd(buf, PATH_MAX) != buf) e(16);
00171   if (strcmp(buf, cwd) != 0) e(17);
00172 
00173   if (chdir(ToLongName) != -1) e(18);
00174 #ifdef _POSIX_NO_TRUNC
00175 # if _POSIX_NO_TRUNC - 0 != -1
00176   if (errno != ENAMETOOLONG) e(20);
00177 # else
00178   if (errno != ENOENT) e(20);
00179 # endif
00180 #else
00181 # include "error, this case requires dynamic checks and is not handled"
00182 #endif
00183 
00184   if (getcwd(buf, PATH_MAX) != buf) e(21);
00185   if (strcmp(buf, cwd) != 0) e(22);
00186   if (chdir(ToLongPath) != -1) e(23);
00187   if (errno != ENAMETOOLONG) e(24);
00188   if (getcwd(buf, PATH_MAX) != buf) e(25);
00189   if (strcmp(buf, cwd) != 0) e(26);
00190 }
00191 
00192 void test23c()
00193 {                               /* Check reaction to errors */
00194   subtest = 3;
00195 
00196   System("rm -rf ../DIR_23/*");
00197 
00198   if (getcwd(cwd, PATH_MAX) != cwd) e(1);       /* get cwd */
00199 
00200   /* Creat a working dir named "foo", remove any previous residues. */
00201   System("rm -rf foo; mkdir foo");
00202 
00203   /* Check some obviouse errors. */
00204   if (chdir("") != -1) e(2);
00205   if (errno != ENOENT) e(3);
00206   if (getcwd(buf, PATH_MAX) != buf) e(4);
00207   if (strcmp(buf, cwd) != 0) e(5);
00208   if (getcwd(buf, 0) != (char *) 0) e(6);
00209   if (errno != EINVAL) e(7);
00210   if (getcwd(buf, PATH_MAX) != buf) e(8);
00211   if (strcmp(buf, cwd) != 0) e(9);
00212   if (getcwd(buf, 0) != (char *) 0) e(10);
00213   if (errno != EINVAL) e(11);
00214   if (getcwd(buf, PATH_MAX) != buf) e(12);
00215   if (strcmp(buf, cwd) != 0) e(13);
00216   if (chdir(cwd) != 0) e(14);   /* getcwd might be buggy. */
00217 
00218   /* Change the mode of foo, and check the effect. */
00219   if (chdir("foo") != 0) e(15); /* change to foo */
00220   if (mkdir("bar", 0777) != 0) e(16);   /* make a new dir bar */
00221   if (getcwd(cwd2, PATH_MAX) != cwd2) e(17);    /* get the new cwd */
00222   if (getcwd(buf, 3) != (char *) 0) e(18);      /* size is too small */
00223   if (errno != ERANGE) e(19);
00224   if (getcwd(buf, PATH_MAX) != buf) e(20);
00225   if (strcmp(buf, cwd2) != 0) e(21);
00226   Chdir(cwd2);                  /* getcwd() might cd / */
00227   System("chmod 377 .");        /* make foo unreadable */
00228   if (getcwd(buf, PATH_MAX) != buf) e(22);      /* dir not readable */
00229   if (getcwd(buf, PATH_MAX) != buf) e(23);
00230   if (strcmp(buf, cwd2) != 0) e(24);
00231   if (chdir("bar") != 0) e(25); /* at .../foo/bar */
00232   if (!superuser) {
00233         if (getcwd(buf, PATH_MAX) != (char *) 0) e(26);
00234         if (errno != EACCES) e(27);
00235   }
00236   if (superuser) {
00237         if (getcwd(buf, PATH_MAX) != buf) e(28);
00238   }
00239   if (chdir(cwd2) != 0) e(29);
00240   if (getcwd(buf, PATH_MAX) != buf) e(30);
00241   if (strcmp(buf, cwd2) != 0) e(31);
00242   System("chmod 677 .");        /* make foo inaccessable */
00243   if (!superuser) {
00244         if (getcwd(buf, PATH_MAX) != (char *) 0) e(32); /* try to get cwd */
00245         if (errno != EACCES) e(33);     /* but no access */
00246         if (chdir("..") != -1) e(34);   /* try to get back */
00247         if (errno != EACCES) e(35);     /* again no access */
00248         if (chdir(cwd) != 0) e(36);     /* get back to cwd */
00249         /* `Chdir()' might do path optimizing, it shouldn't. */
00250         if (chdir("foo/..") != -1) e(37);       /* no op */
00251         if (chdir("foo") != -1) e(38);  /* try to cd to foo */
00252         if (errno != EACCES) e(39);     /* no have access */
00253         if (getcwd(buf, PATH_MAX) != buf) e(40);
00254         if (strcmp(buf, cwd) != 0) e(41);
00255   }
00256   if (superuser) {
00257         if (getcwd(buf, PATH_MAX) != buf) e(42);
00258         if (strcmp(buf, cwd2) != 0) e(43);
00259         if (chdir("..") != 0) e(44);    /* get back to cwd */
00260         if (chdir("foo") != 0) e(45);   /* get back to foo */
00261         if (chdir(cwd) != 0) e(46);     /* get back to cwd */
00262   }
00263   if (getcwd(buf, PATH_MAX) != buf) e(47);      /* check we are */
00264   if (strcmp(buf, cwd) != 0) e(48);     /* back at cwd. */
00265   Chdir(cwd);                   /* just in case... */
00266 
00267   if (chdir("/etc/passwd") != -1) e(49);        /* try to change to a file */
00268   if (errno != ENOTDIR) e(50);
00269   if (getcwd(buf, PATH_MAX) != buf) e(51);
00270   if (strcmp(buf, cwd) != 0) e(52);
00271   if (chdir("/notexist") != -1) e(53);
00272   if (errno != ENOENT) e(54);
00273   if (getcwd(buf, PATH_MAX) != buf) e(55);
00274   if (strcmp(buf, cwd) != 0) e(56);
00275   System("chmod 777 foo");
00276   if (chdir("foo") != 0) e(57);
00277 
00278   /* XXX - this comment was botched by 'pretty'. */
00279   /* * Since `foo' is the cwd, it should not be removeable but * if it
00280    * were, this code would be found here; *
00281    * 
00282    *  System ("cd .. ; rm -rf foo");    remove foo *  if (chdir (".")
00283    * != -1) e();                try go to. *  if (errno != ENOENT) e();
00284    * hould not be an entry *  if (chdir ("..") != -1) e();      try
00285    * to get back *  if (errno != ENOENT) e();           should not be
00286    * an entry *  if (getcwd (buf, PATH_MAX) != (char *)0) e(); don't
00287    * know where we are *
00288    * 
00289    * What should errno be now ? The cwd might be gone if te superuser *
00290    * removed the cwd. (Might even have linked it first.) But this *
00291    * testing should be done by the test program for `rmdir()'. */
00292   if (chdir(cwd) != 0) e(58);
00293 }
00294 
00295 void makelongnames()
00296 {
00297   register int i;
00298 
00299   memset(MaxName, 'a', NAME_MAX);
00300   MaxName[NAME_MAX] = '\0';
00301   for (i = 0; i < PATH_MAX - 1; i++) {  /* idem path */
00302         MaxPath[i++] = '.';
00303         MaxPath[i] = '/';
00304   }
00305   MaxPath[PATH_MAX - 1] = '\0';
00306 
00307   strcpy(ToLongName, MaxName);  /* copy them Max to ToLong */
00308   strcpy(ToLongPath, MaxPath);
00309 
00310   ToLongName[NAME_MAX] = 'a';
00311   ToLongName[NAME_MAX + 1] = '\0';      /* extend ToLongName by one too many */
00312   ToLongPath[PATH_MAX - 1] = '/';
00313   ToLongPath[PATH_MAX] = '\0';  /* inc ToLongPath by one */
00314 }
00315 
00316 /* The following code, is take from pwd written by Adri Koppes */
00317 
00318 /* My_getcwd() helper. */
00319 char *last_index(string, ch)
00320 char *string;
00321 char ch;
00322 {
00323   register char *retval = '\0';
00324 
00325   while (*string != '\0') {
00326         if (*string == ch) retval = string;
00327         string++;
00328   }
00329   return(retval);
00330 }
00331 
00332 char *my_getcwd(buf, size)
00333 char *buf;
00334 int size;
00335 {                               /* should be like getcwd() */
00336   int sd;
00337   register int fd;
00338   register char *n;
00339   char name[128];
00340   struct stat s, st, sk;
00341   struct direct d;
00342 
00343   if (size <= 0) return(char *) 0;
00344 
00345   *buf = '\0';
00346   *name = '\0';
00347   stat(".", &s);
00348   do {
00349         if ((fd = open("..", O_RDONLY)) < 0) return(char *) 0;
00350         st.st_dev = s.st_dev;
00351         st.st_ino = s.st_ino;
00352         stat("..", &s);
00353         Chdir("..");
00354         sd = sizeof(struct direct);
00355         if (s.st_dev == st.st_dev) {
00356                 do {
00357                         if (read(fd, (char *) &d, sd) < sd) return(char *) 0;
00358                 } while (d.d_ino != st.st_ino);
00359         } else {
00360                 do {
00361                         if (read(fd, (char *) &d, sd) < sd) return(char *) 0;
00362                         stat(d.d_name, &sk);
00363                 } while ((sk.st_dev != st.st_dev) ||
00364                          (sk.st_ino != st.st_ino));
00365         }
00366         close(fd);
00367         if (strcmp(".", d.d_name) != 0) {
00368                 strcat(name, "/");
00369                 strcat(name, d.d_name);
00370         }
00371   } while ((s.st_ino != st.st_ino) || (s.st_dev != st.st_dev));
00372   if (*name == '\0')
00373         strncat(buf, "/", size);
00374   else
00375         while ((n = last_index(name, '/')) != NULL) {
00376                 n[NAME_MAX] = '\0';
00377                 strncat(buf, n, size - strlen(buf));
00378                 *n = '\0';
00379         }
00380   strncat(buf, name, size - strlen(buf));
00381   buf[size - 1] = '\0';
00382   Chdir(buf);                   /* get back there */
00383   return buf;
00384 }
00385 
00386 void e(n)
00387 int n;
00388 {
00389   int err_num = errno;          /* Save in case printf clobbers it. */
00390 
00391   printf("Subtest %d,  error %d  errno=%d: ", subtest, n, errno);
00392   errno = err_num;
00393   perror("");
00394   if (errct++ > MAX_ERROR) {
00395         printf("Too many errors; test aborted\n");
00396         chdir("..");
00397         system("rm -rf DIR*");
00398         exit(1);
00399   }
00400   errno = 0;
00401 }
00402 
00403 void quit()
00404 {
00405   Chdir("..");
00406   System("rm -rf DIR_23");
00407 
00408   if (errct == 0) {
00409         printf("ok\n");
00410         exit(0);
00411   } else {
00412         printf("%d errors\n", errct);
00413         exit(1);
00414   }
00415 }

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