test7.c

Go to the documentation of this file.
00001 /* POSIX test program (7).                      Author: Andy Tanenbaum */
00002 
00003 /* The following POSIX calls are tested:
00004  *      pipe(), mkfifo(), fcntl()
00005  */
00006 
00007 #include <sys/types.h>
00008 #include <sys/stat.h>
00009 #include <sys/wait.h>
00010 #include <errno.h>
00011 #include <fcntl.h>
00012 #include <limits.h>
00013 #include <signal.h>
00014 #include <stdlib.h>
00015 #include <string.h>
00016 #include <unistd.h>
00017 #include <stdio.h>
00018 
00019 #define ITERATIONS        4
00020 #define MAX_ERROR 4
00021 #define ITEMS  32
00022 #define READ   10
00023 #define WRITE  20
00024 #define UNLOCK 30
00025 #define U      70
00026 #define L      80
00027 
00028 char buf[ITEMS] = {0,1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1,0,1,2,3,4,5,6,7,8,9};
00029 
00030 int subtest, errct, xfd;
00031 int whence = SEEK_SET, func_code = F_SETLK;
00032 extern char **environ;
00033 
00034 _PROTOTYPE(int main, (int argc, char *argv []));
00035 _PROTOTYPE(void test7a, (void));
00036 _PROTOTYPE(void test7b, (void));
00037 _PROTOTYPE(void test7c, (void));
00038 _PROTOTYPE(void test7d, (void));
00039 _PROTOTYPE(void test7e, (void));
00040 _PROTOTYPE(void test7f, (void));
00041 _PROTOTYPE(void test7g, (void));
00042 _PROTOTYPE(void test7h, (void));
00043 _PROTOTYPE(void test7i, (void));
00044 _PROTOTYPE(void test7j, (void));
00045 _PROTOTYPE(void cloexec_test, (void));
00046 _PROTOTYPE(int set, (int how, int first, int last));
00047 _PROTOTYPE(int locked, (int b));
00048 _PROTOTYPE(void e, (int n));
00049 _PROTOTYPE(void sigfunc, (int s));
00050 _PROTOTYPE(void quit, (void));
00051 
00052 int main(argc, argv)
00053 int argc;
00054 char *argv[];
00055 {
00056 
00057   int i, m = 0xFFFF;
00058 
00059   sync();
00060 
00061   if (argc == 2) m = atoi(argv[1]);
00062   if (m == 0) cloexec_test();   /* important; do not remove this! */
00063   printf("Test  7 ");
00064   fflush(stdout);
00065 
00066   system("rm -rf DIR_07; mkdir DIR_07");
00067   chdir("DIR_07");
00068 
00069   for (i = 0; i < ITERATIONS; i++) {
00070         if (m & 00001) test7a();
00071         if (m & 00002) test7b();
00072         if (m & 00004) test7c();
00073         if (m & 00010) test7d();
00074         if (m & 00020) test7e();
00075         if (m & 00040) test7f();
00076         if (m & 00100) test7g();
00077         if (m & 00200) test7h();
00078         if (m & 00400) test7i();
00079         if (m & 01000) test7j();
00080   }
00081   quit();
00082   return(-1);                   /* impossible */
00083 }
00084 
00085 void test7a()
00086 {
00087 /* Test pipe(). */
00088 
00089   int i, fd[2], ect;
00090   char buf2[ITEMS+1];
00091 
00092   /* Create a pipe, write on it, and read it back. */
00093   subtest = 1;
00094   if (pipe(fd) != 0) e(1);
00095   if (write(fd[1], buf, ITEMS) != ITEMS) e(2);
00096   buf2[0] = 0;
00097   if (read(fd[0], buf2, ITEMS+1) != ITEMS) e(3);
00098   ect = 0;
00099   for (i = 0; i < ITEMS; i++) if (buf[i] != buf2[i]) ect++;
00100   if (ect != 0) e(4);
00101   if (close(fd[0]) != 0) e(5);
00102   if (close(fd[1]) != 0) e(6);
00103 
00104   /* Error test.  Keep opening pipes until it fails.  Check error code. */
00105   errno = 0;
00106   while (1) {
00107         if (pipe(fd) < 0) break;
00108   }
00109   if (errno != EMFILE) e(7);
00110 
00111   /* Close all the pipes. */
00112   for (i = 3; i < OPEN_MAX; i++) close(i);
00113 }
00114 
00115 void test7b()
00116 {
00117 /* Test mkfifo(). */
00118 
00119   int fdr, fdw, status;
00120   char buf2[ITEMS+1];
00121   int efork;
00122 
00123   /* Create a fifo, write on it, and read it back. */
00124   subtest = 2;
00125   if (mkfifo("T7.b", 0777) != 0) e(1);
00126   switch (fork()) {
00127   case -1:
00128         efork = errno;
00129         printf("Fork failed: %s (%d)\n", strerror(efork), efork);
00130         exit(1);
00131   case 0:
00132         /* Child reads from the fifo. */
00133         if ( (fdr = open("T7.b", O_RDONLY)) < 0) e(5);
00134         if (read(fdr, buf2, ITEMS+1) != ITEMS) e(6);
00135         if (strcmp(buf, buf2) != 0) e(7);
00136         if (close(fdr) != 0) e(8);
00137         exit(0);
00138   default:
00139         /* Parent writes on the fifo. */
00140         if ( (fdw = open("T7.b", O_WRONLY)) < 0) e(2);
00141         if (write(fdw, buf, ITEMS) != ITEMS) e(3);
00142         wait(&status);
00143         if (close(fdw) != 0) e(4);
00144   }
00145 
00146   /* Check some error conditions. */
00147   if (mkfifo("T7.b", 0777) != -1) e(9);
00148   errno = 0;
00149   if (mkfifo("a/b/c", 0777) != -1) e(10);
00150   if (errno != ENOENT) e(11);
00151   errno = 0;
00152   if (mkfifo("", 0777) != -1) e(12);
00153   if (errno != ENOENT) e(13);
00154   errno = 0;
00155   if (mkfifo("T7.b/x", 0777) != -1) e(14);
00156   if (errno != ENOTDIR) e(15);
00157   if (unlink("T7.b") != 0) e(16);
00158 
00159   /* Now check fifos and the O_NONBLOCK flag. */
00160   if (mkfifo("T7.b", 0600) != 0) e(17);
00161   errno = 0;
00162   if (open("T7.b", O_WRONLY | O_NONBLOCK) != -1) e(18);
00163   if (errno != ENXIO) e(19);
00164   if ( (fdr = open("T7.b", O_RDONLY | O_NONBLOCK)) < 0) e(20);
00165   if (fork()) {
00166         /* Parent reads from fdr. */
00167         wait(&status);          /* but first make sure writer has already run*/
00168         if ( ( (status>>8) & 0377) != 77) e(21);
00169         if (read(fdr, buf2, ITEMS+1) != ITEMS) e(22);
00170         if (strcmp(buf, buf2) != 0) e(23);
00171         if (close(fdr) != 0) e(24);
00172   } else {
00173         /* Child opens the fifo for writing and writes to it. */
00174         if ( (fdw = open("T7.b", O_WRONLY | O_NONBLOCK)) < 0) e(25);
00175         if (write(fdw, buf, ITEMS) != ITEMS) e(26);
00176         if (close(fdw) != 0) e(27);
00177         exit(77);
00178   }
00179   
00180   if (unlink("T7.b") != 0) e(28);
00181 }
00182 
00183 void test7c()
00184 {
00185 /* Test fcntl(). */
00186 
00187   int fd, m, s, newfd, newfd2;
00188   struct stat stat1, stat2, stat3;
00189 
00190   subtest = 3;
00191   errno = -100;
00192   if ( (fd = creat("T7.c", 0777)) < 0) e(1);
00193 
00194   /* Turn the per-file-descriptor flags on and off. */
00195   if (fcntl(fd, F_GETFD) != 0) e(2);    /* FD_CLOEXEC is initially off */
00196   if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) e(3);/* turn it on */
00197   if (fcntl(fd, F_GETFD) != FD_CLOEXEC) e(4);   /* should be on now */
00198   if (fcntl(fd, F_SETFD, 0) != 0) e(5);         /* turn it off */
00199   if (fcntl(fd, F_GETFD) != 0) e(6);            /* should be off now */
00200 
00201   /* Turn the open-file-description flags on and off. Start with O_APPEND. */
00202   m = O_WRONLY;
00203   if (fcntl(fd, F_GETFL) != m) e(7);    /* O_APPEND, O_NONBLOCK are off */
00204   if (fcntl(fd, F_SETFL, O_APPEND) != 0) e(8);   /* turn on O_APPEND */
00205   if (fcntl(fd, F_GETFL) != (O_APPEND | m)) e(9);/* should be on now */
00206   if (fcntl(fd, F_SETFL, 0) != 0) e(10);         /* turn it off */
00207   if (fcntl(fd, F_GETFL) != m) e(11);            /* should be off now */
00208   
00209   /* Turn the open-file-description flags on and off. Now try O_NONBLOCK.  */
00210   if (fcntl(fd, F_SETFL, O_NONBLOCK) != 0) e(12);      /* turn on O_NONBLOCK */
00211   if (fcntl(fd, F_GETFL) != (O_NONBLOCK | m)) e(13);   /* should be on now */
00212   if (fcntl(fd, F_SETFL, 0) != 0) e(14);               /* turn it off */
00213   if (fcntl(fd, F_GETFL) != m) e(15);                  /* should be off now */
00214   
00215   /* Now both at once. */
00216   if (fcntl(fd, F_SETFL, O_APPEND|O_NONBLOCK) != 0) e(16);
00217   if (fcntl(fd, F_GETFL) != (O_NONBLOCK | O_APPEND | m)) e(17);
00218   if (fcntl(fd, F_SETFL, 0) != 0) e(18);
00219   if (fcntl(fd, F_GETFL) != m) e(19);
00220 
00221   /* Now test F_DUPFD. */
00222   if ( (newfd = fcntl(fd, F_DUPFD, 0)) != 4) e(20);     /* 0-4 open */
00223   if ( (newfd2 = fcntl(fd, F_DUPFD, 0)) != 5) e(21);    /* 0-5 open */
00224   if (close(newfd) != 0) e(22);                         /* 0-3, 5 open */
00225   if ( (newfd = fcntl(fd, F_DUPFD, 0)) != 4) e(23);     /* 0-5 open */
00226   if (close(newfd) != 0) e(24);                         /* 0-3, 5 open */
00227   if ( (newfd = fcntl(fd, F_DUPFD, 5)) != 6) e(25);     /* 0-3, 5, 6 open */
00228   if (close(newfd2) != 0) e(26);                        /* 0-3, 6 open */
00229   
00230   /* O_APPEND should be inherited, but FD_CLOEXEC should be cleared.  Check. */
00231   if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) e(26);/* turn FD_CLOEXEC on */
00232   if (fcntl(fd, F_SETFL, O_APPEND) != 0) e(27);  /* turn O_APPEND on */
00233   if ( (newfd2 = fcntl(fd, F_DUPFD, 10)) != 10) e(28);  /* 0-3, 6, 10 open */
00234   if (fcntl(newfd2, F_GETFD) != 0) e(29);       /* FD_CLOEXEC must be 0 */
00235   if (fcntl(newfd2, F_GETFL) != (O_APPEND | m)) e(30);  /* O_APPEND set */
00236   if (fcntl(fd, F_SETFD, 0) != 0) e(31);/* turn FD_CLOEXEC off */
00237 
00238   /* Check if newfd and newfd2 are the same inode. */
00239   if (fstat(fd, &stat1) != 0) e(32);
00240   if (fstat(fd, &stat2) != 0) e(33);
00241   if (fstat(fd, &stat3) != 0) e(34);
00242   if (stat1.st_dev != stat2.st_dev) e(35);
00243   if (stat1.st_dev != stat3.st_dev) e(36);
00244   if (stat1.st_ino != stat2.st_ino) e(37);
00245   if (stat1.st_ino != stat3.st_ino) e(38);
00246 
00247   /* Now check on the FD_CLOEXEC flag.  Set it for fd (3) and newfd2 (10) */
00248   if (fd != 3 || newfd2 != 10 || newfd != 6) e(39);
00249   if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) e(40);       /* close 3 on exec */
00250   if (fcntl(newfd2, F_SETFD, FD_CLOEXEC) != 0) e(41);   /* close 10 on exec */
00251   if (fcntl(newfd, F_SETFD, 0) != 0) e(42);             /* don't close 6 */
00252   if (fork()) {
00253         wait(&s);               /* parent just waits */
00254         if (WEXITSTATUS(s) != 0) e(43);
00255   } else {
00256         execle("../test7", "test7", "0", (char *) 0, environ);
00257         exit(1);                /* the impossible never happens, right? */
00258   }
00259   
00260   /* Finally, close all the files. */
00261   if (fcntl(fd, F_SETFD, 0) != 0) e(44);        /* FD_CLOEXEC off */
00262   if (fcntl(newfd2, F_SETFD, 0) != 0) e(45);    /* FD_CLOEXEC off */
00263   if (close(fd) != 0) e(46);
00264   if (close(newfd) != 0) e(47);
00265   if (close(newfd2) != 0) e(48);
00266 }
00267 
00268 void test7d()
00269 {
00270 /* Test file locking. */
00271 
00272   subtest = 4;
00273  
00274   if ( (xfd = creat("T7.d", 0777)) != 3) e(1);
00275   close(xfd);
00276   if ( (xfd = open("T7.d", O_RDWR)) < 0) e(2);
00277   if (write(xfd, buf, ITEMS) != ITEMS) e(3);
00278   if (set(WRITE, 0, 3) != 0) e(4);
00279   if (set(WRITE, 5, 9) != 0) e(5);
00280   if (set(UNLOCK, 0, 3) != 0) e(6);
00281   if (set(UNLOCK, 4, 9) != 0) e(7);
00282 
00283   if (set(READ, 1, 4) != 0) e(8);
00284   if (set(READ, 4, 7) != 0) e(9);
00285   if (set(UNLOCK, 4, 7) != 0) e(10);
00286   if (set(UNLOCK, 1, 4) != 0) e(11);
00287 
00288   if (set(WRITE, 0, 3) != 0) e(12);
00289   if (set(WRITE, 5, 7) != 0) e(13);
00290   if (set(WRITE, 9 ,10) != 0) e(14);
00291   if (set(UNLOCK, 0, 4) != 0) e(15);
00292   if (set(UNLOCK, 0, 7) != 0) e(16);
00293   if (set(UNLOCK, 0, 2000) != 0) e(17);
00294 
00295   if (set(WRITE, 0, 3) != 0) e(18);
00296   if (set(WRITE, 5, 7) != 0) e(19);
00297   if (set(WRITE, 9 ,10) != 0) e(20);
00298   if (set(UNLOCK, 0, 100) != 0) e(21);
00299 
00300   if (set(WRITE, 0, 9) != 0) e(22);
00301   if (set(UNLOCK, 8, 9) != 0) e(23);
00302   if (set(UNLOCK, 0, 2) != 0) e(24);
00303   if (set(UNLOCK, 5, 5) != 0) e(25);
00304   if (set(UNLOCK, 4, 6) != 0) e(26);
00305   if (set(UNLOCK, 3, 3) != 0) e(27);
00306   if (set(UNLOCK, 7, 7) != 0) e(28);
00307 
00308   if (set(WRITE, 0, 10) != 0) e(29);
00309   if (set(UNLOCK, 0, 1000) != 0) e(30);
00310 
00311   /* Up until now, all locks have been disjoint.  Now try conflicts. */
00312   if (set(WRITE, 0, 4) != 0) e(31);
00313   if (set(WRITE, 4, 7) != 0) e(32);     /* owner may lock same byte twice */
00314   if (set(WRITE, 5, 10) != 0) e(33);
00315   if (set(UNLOCK, 0, 11) != 0) e(34);
00316 
00317   /* File is now unlocked. Length 0 means whole file. */
00318   if (set(WRITE, 2, 1) != 0) e(35);     /* this locks whole file */
00319   if (set(WRITE, 9,10) != 0) e(36);     /* a process can relock its file */
00320   if (set(WRITE, 3, 3) != 0) e(37);
00321   if (set(UNLOCK, 0, -1) != 0) e(38);   /* file is now unlocked. */
00322 
00323   /* Test F_GETLK. */
00324   if (set(WRITE, 2, 3) != 0) e(39);
00325   if (locked(1) != U) e(40);
00326   if (locked(2) != L) e(41);
00327   if (locked(3) != L) e(42);
00328   if (locked(4) != U) e(43);
00329   if (set(UNLOCK, 2, 3) != 0) e(44);
00330   if (locked(2) != U) e(45);
00331   if (locked(3) != U) e(46);
00332 
00333   close(xfd);
00334 }
00335 
00336 void test7e()
00337 {
00338 /* Test to see if SETLKW blocks as it should. */
00339 
00340   int pid, s;
00341 
00342   subtest = 5;
00343  
00344   if ( (xfd = creat("T7.e", 0777)) != 3) e(1);
00345   if (close(xfd) != 0) e(2);
00346   if ( (xfd = open("T7.e", O_RDWR)) < 0) e(3);
00347   if (write(xfd, buf, ITEMS) != ITEMS) e(4);
00348   if (set(WRITE, 0, 3) != 0) e(5);
00349 
00350   if ( (pid = fork()) ) {
00351         /* Parent waits until child has started before signaling it. */
00352         while (access("T7.e1", 0) != 0) ;
00353         unlink("T7.e1");
00354         sleep(1);
00355         if (kill(pid, SIGKILL) < 0) e(6);
00356         if (wait(&s) != pid) e(7);
00357   } else {
00358         /* Child tries to lock and should block. */
00359         if (creat("T7.e1", 0777) < 0) e(8);
00360         func_code = F_SETLKW;
00361         if (set(WRITE, 0, 3) != 0) e(9);        /* should block */
00362         errno = -1000;
00363         e(10);                  /* process should be killed by signal */
00364         exit(0);                /* should never happen */
00365   }
00366   close(xfd);
00367 }
00368 
00369 void test7f()
00370 {
00371 /* Test to see if SETLKW gives EINTR when interrupted. */
00372 
00373   int pid, s;
00374 
00375   subtest = 6;
00376  
00377   if ( (xfd = creat("T7.f", 0777)) != 3) e(1);
00378   if (close(xfd) != 0) e(2);
00379   if ( (xfd = open("T7.f", O_RDWR)) < 0) e(3);
00380   if (write(xfd, buf, ITEMS) != ITEMS) e(4);
00381   if (set(WRITE, 0, 3) != 0) e(5);
00382 
00383   if ( (pid = fork()) ) {
00384         /* Parent waits until child has started before signaling it. */
00385         while (access("T7.f1", 0) != 0) ;
00386         unlink("T7.f1");
00387         sleep(1);
00388         if (kill(pid, SIGTERM) < 0) e(6);
00389         if (wait(&s) != pid) e(7);
00390         if ( (s>>8) != 19) e(8);
00391   } else {
00392         /* Child tries to lock and should block.
00393          * `signal(SIGTERM, sigfunc);' to set the signal handler is inadequate
00394          * because on systems like BSD the sigaction flags for signal include
00395          * `SA_RESTART' so syscalls are restarted after they have been
00396          * interrupted by a signal.
00397          */
00398         struct sigaction sa, osa;
00399 
00400         sa.sa_handler = sigfunc;
00401         sigemptyset(&sa.sa_mask);
00402         sa.sa_flags = 0;
00403         if (sigaction(SIGTERM, &sa, &osa) < 0) e(999);
00404         if (creat("T7.f1", 0777) < 0) e(9);
00405         func_code = F_SETLKW;
00406         if (set(WRITE, 0, 3) != -1) e(10);      /* should block */
00407         if (errno != EINTR) e(11);      /* signal should release it */
00408         exit(19);
00409   }
00410   close(xfd);
00411 }
00412 
00413 void test7g()
00414 {
00415 /* Test to see if SETLKW unlocks when the needed lock becomes available. */
00416 
00417   int pid, s;
00418 
00419   subtest = 7;
00420  
00421   if ( (xfd = creat("T7.g", 0777)) != 3) e(1);
00422   if (close(xfd) != 0) e(2);
00423   if ( (xfd = open("T7.g", O_RDWR)) < 0) e(3);
00424   if (write(xfd, buf, ITEMS) != ITEMS) e(4);
00425   if (set(WRITE, 0, 3) != 0) e(5);      /* bytes 0 to 3 are now locked */
00426 
00427   if ( (pid = fork()) ) {
00428         /* Parent waits for child to start. */
00429         while (access("T7.g1", 0) != 0) ;
00430         unlink("T7.g1");
00431         sleep(1);
00432         if (set(UNLOCK, 0, 3) != 0) e(5);
00433         if (wait(&s) != pid) e(6);
00434         if ( (s >> 8) != 29) e(7);
00435   } else {
00436         /* Child tells parent it is alive, then tries to lock and is blocked.*/
00437         func_code = F_SETLKW;   
00438         if (creat("T7.g1", 0777) < 0) e(8);
00439         if (set(WRITE, 3, 3) != 0) e(9);        /* process must block now */
00440         if (set(UNLOCK, 3, 3) != 0) e(10);
00441         exit(29);
00442   }
00443   close(xfd);
00444 }
00445 
00446 void test7h()
00447 {
00448 /* Test to see what happens if two processed block on the same lock. */
00449 
00450   int pid, pid2, s, w;
00451 
00452   subtest = 8;
00453  
00454   if ( (xfd = creat("T7.h", 0777)) != 3) e(1);
00455   if (close(xfd) != 0) e(2);
00456   if ( (xfd = open("T7.h", O_RDWR)) < 0) e(3);
00457   if (write(xfd, buf, ITEMS) != ITEMS) e(4);
00458   if (set(WRITE, 0, 3) != 0) e(5);      /* bytes 0 to 3 are now locked */
00459 
00460   if ( (pid = fork()) ) {
00461         if ( (pid2 = fork()) ) {
00462                 /* Parent waits for child to start. */
00463                 while (access("T7.h1", 0) != 0) ;
00464                 while (access("T7.h2", 0) != 0) ;
00465                 unlink("T7.h1");
00466                 unlink("T7.h2");
00467                 sleep(1);
00468                 if (set(UNLOCK, 0, 3) != 0) e(6);
00469                 w = wait(&s);
00470                 if (w != pid && w != pid2) e(7);
00471                 s = s >> 8;
00472                 if (s != 39 && s != 49) e(8);
00473                 w = wait(&s);
00474                 if (w != pid && w != pid2) e(9);
00475                 s = s >> 8;
00476                 if (s != 39 && s != 49) e(10);
00477         } else {
00478                 func_code = F_SETLKW;   
00479                 if (creat("T7.h1", 0777) < 0) e(11);
00480                 if (set(WRITE, 0, 0) != 0) e(12);       /* block now */
00481                 if (set(UNLOCK, 0, 0) != 0) e(13);
00482                 exit(39);
00483         }
00484   } else {
00485         /* Child tells parent it is alive, then tries to lock and is blocked.*/
00486         func_code = F_SETLKW;   
00487         if (creat("T7.h2", 0777) < 0) e(14);
00488         if (set(WRITE, 0, 1) != 0) e(15);       /* process must block now */
00489         if (set(UNLOCK, 0, 1) != 0) e(16);
00490         exit(49);
00491   }
00492   close(xfd);
00493 }
00494 
00495 void test7i()
00496 {
00497 /* Check error conditions for fcntl(). */
00498 
00499   int tfd, i;
00500 
00501   subtest = 9;
00502  
00503   errno = 0;
00504   if ( (xfd = creat("T7.i", 0777)) != 3) e(1);
00505   if (close(xfd) != 0) e(2);
00506   if ( (xfd = open("T7.i", O_RDWR)) < 0) e(3);
00507   if (write(xfd, buf, ITEMS) != ITEMS) e(4);
00508   if (set(WRITE, 0, 3) != 0) e(5);      /* bytes 0 to 3 are now locked */
00509   if (set(WRITE, 0, 0) != 0) e(6);
00510   if (errno != 0) e(7);
00511   errno = 0;
00512   if (set(WRITE, 3, 3) != 0) e(8);
00513   if (errno != 0) e(9);
00514   tfd = xfd;                    /* hold good value */
00515   xfd = -99;
00516   errno = 0;
00517   if (set(WRITE, 0, 0) != -1) e(10);
00518   if (errno != EBADF) e(11);
00519 
00520   errno = 0;  
00521   if ( (xfd = open("T7.i", O_WRONLY)) < 0) e(12);
00522   if (set(READ, 0, 0) != -1) e(13);
00523   if (errno != EBADF) e(14);
00524   if (close(xfd) != 0) e(15);
00525 
00526   errno = 0;  
00527   if ( (xfd = open("T7.i", O_RDONLY)) < 0) e(16);
00528   if (set(WRITE, 0, 0) != -1) e(17);
00529   if (errno != EBADF) e(18);
00530   if (close(xfd) != 0) e(19);
00531   xfd = tfd;                    /* restore legal xfd value */
00532 
00533   /* Check for EINVAL. */
00534   errno = 0;
00535   if (fcntl(xfd, F_DUPFD, OPEN_MAX) != -1) e(20);
00536   if (errno != EINVAL) e(21);
00537   errno = 0;
00538   if (fcntl(xfd, F_DUPFD, -1) != -1) e(22);
00539   if (errno != EINVAL) e(23);
00540 
00541   xfd = 0;                      /* stdin does not support locking */
00542   errno = 0;
00543   if (set(READ, 0, 0) != -1) e(24);
00544   if (errno != EINVAL) e(25);
00545   xfd = tfd;
00546 
00547   /* Check ENOLCK. */
00548   for (i = 0; i < ITEMS; i++) {
00549         if (set(WRITE, i, i) == 0) continue;
00550         if (errno != ENOLCK) {
00551                 e(26);
00552                 break;
00553         }
00554   }
00555 
00556   /* Check EMFILE. */
00557   for (i = xfd + 1; i < OPEN_MAX; i++) open("T7.i", 0); /* use up all fds */
00558   errno = 0;
00559   if (fcntl(xfd, F_DUPFD, 0) != -1) e(27);      /* No fds left */
00560   if (errno != EMFILE) e(28);
00561 
00562   for (i = xfd; i < OPEN_MAX; i++) if (close(i) != 0) e(29);
00563 }
00564 
00565 void test7j()
00566 {
00567 /* Test file locking with two processes. */
00568 
00569   int s;
00570 
00571   subtest = 10;
00572  
00573   if ( (xfd = creat("T7.j", 0777)) != 3) e(1);
00574   close(xfd);
00575   if ( (xfd = open("T7.j", O_RDWR)) < 0) e(2);
00576   if (write(xfd, buf, ITEMS) != ITEMS) e(3);
00577   if (set(WRITE, 0, 4) != 0) e(4);      /* lock belongs to parent */
00578   if (set(READ, 10, 16) != 0) e(5);     /* lock belongs to parent */
00579 
00580   /* Up until now, all locks have been disjoint.  Now try conflicts. */
00581   if (fork()) {
00582         /* Parent just waits for child to finish. */
00583         wait(&s);
00584   } else {
00585         /* Child does the testing. */
00586         errno = -100;
00587         if (set(WRITE, 5, 7) < 0) e(6); /* should work */
00588         if (set(WRITE, 4, 7) >= 0) e(7);        /* child may not lock byte 4 */
00589         if (errno != EACCES && errno != EAGAIN) e(8);
00590         if (set(WRITE, 5, 9) != 0) e(9);
00591         if (set(UNLOCK, 5, 9) != 0) e(10);
00592         if (set(READ, 9, 17) < 0) e(11);        /* shared READ lock is ok */
00593         exit(0);
00594   }
00595   close(xfd);
00596 }
00597 
00598 void cloexec_test()
00599 {
00600 /* To text whether the FD_CLOEXEC flag actually causes files to be
00601  * closed upon exec, we have to exec something.  The test is carried
00602  * out by forking, and then having the child exec test7 itself, but
00603  * with argument 0.  This is detected, and control comes here.
00604  * File descriptors 3 and 10 should be closed here, and 10 open.
00605  */
00606 
00607   if (close(3) == 0) e(1001);   /* close should fail; it was closed on exec */
00608   if (close(6) != 0) e(1002);   /* close should succeed */
00609   if (close(10) == 0) e(1003);  /* close should fail */
00610   fflush(stdout);
00611   exit(0);
00612 }
00613 
00614 int set(how, first, last)
00615 int how, first, last;
00616 {
00617   int r;
00618   struct flock flock;
00619 
00620   if (how == READ) flock.l_type = F_RDLCK;
00621   if (how == WRITE) flock.l_type = F_WRLCK;
00622   if (how == UNLOCK) flock.l_type = F_UNLCK;
00623   flock.l_whence = whence;
00624   flock.l_start = (long) first;
00625   flock.l_len = (long) last - (long) first + 1;
00626   r = fcntl(xfd, func_code, &flock);
00627   if (r != -1) 
00628         return(0);
00629   else
00630         return(-1);
00631 }
00632 
00633 int locked(b)
00634 int b;
00635 /* Test to see if byte b is locked.  Return L or U */
00636 {
00637   struct flock flock;
00638   pid_t pid;
00639   int status;
00640 
00641   flock.l_type = F_WRLCK;
00642   flock.l_whence = whence;
00643   flock.l_start = (long) b;
00644   flock.l_len = 1;
00645 
00646   /* Process' own locks are invisible to F_GETLK, so fork a child to test. */
00647   pid = fork();
00648   if (pid == 0) {
00649         if (fcntl(xfd, F_GETLK, &flock) != 0) e(2000);
00650         exit(flock.l_type == F_UNLCK ? U : L);  
00651   }
00652   if (pid == -1) e(2001);
00653   if (fcntl(xfd, F_GETLK, &flock) != 0) e(2002);
00654   if (flock.l_type != F_UNLCK) e(2003);
00655   if (wait(&status) != pid) e(2004);
00656   if (!WIFEXITED(status)) e(2005);
00657   return(WEXITSTATUS(status));
00658 }
00659 
00660 void e(n)
00661 int n;
00662 {
00663   int err_num = errno;          /* save errno in case printf clobbers it */
00664 
00665   printf("Subtest %d,  error %d  errno=%d  ", subtest, n, errno);
00666   fflush(stdout);
00667   errno = err_num;              /* restore errno, just in case */
00668   perror("");
00669   if (errct++ > MAX_ERROR) {
00670         printf("Too many errors; test aborted\n");
00671         chdir("..");
00672         system("rm -rf DIR*");
00673         exit(1);
00674   }
00675 }
00676 
00677 void sigfunc(s)
00678 int s;                          /* for ANSI */
00679 {
00680 }
00681 
00682 void quit()
00683 {
00684 
00685   chdir("..");
00686   system("rm -rf DIR*");
00687 
00688   if (errct == 0) {
00689         printf("ok\n");
00690         exit(0);
00691   } else {
00692         printf("%d errors\n", errct);
00693         exit(1);
00694   }
00695 }

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