Xv6 with picoc & Linkage editor  v1.0
The project delineate mutual cohesion between c library, linkage editor ( linker), interpreter and operating system by porting the same on xv6 kernel
usertests.c
00001 #include "param.h"
00002 #include "types.h"
00003 #include "stat.h"
00004 #include "user.h"
00005 #include "fs.h"
00006 #include "fcntl.h"
00007 #include "syscall.h"
00008 #include "traps.h"
00009 #include "memlayout.h"
00010 
00011 char buf[8192];
00012 char name[3];
00013 char *echoargv[] = { "echo", "ALL", "TESTS", "PASSED", 0 };
00014 int stdout = 1;
00015 
00016 // simple file system tests
00017 
00018 void
00019 opentest(void)
00020 {
00021   int fd;
00022 
00023   printf(stdout, "open test\n");
00024   fd = open("echo", 0);
00025   if(fd < 0){
00026     printf(stdout, "open echo failed!\n");
00027     exit(1);
00028   }
00029   close(fd);
00030   fd = open("doesnotexist", 0);
00031   if(fd >= 0){
00032     printf(stdout, "open doesnotexist succeeded!\n");
00033     exit(1);
00034   }
00035   printf(stdout, "open test ok\n");
00036 }
00037 
00038 void
00039 writetest(void)
00040 {
00041   int fd;
00042   int i;
00043 
00044   printf(stdout, "small file test\n");
00045   fd = open("small", O_CREATE|O_RDWR);
00046   if(fd >= 0){
00047     printf(stdout, "creat small succeeded; ok\n");
00048   } else {
00049     printf(stdout, "error: creat small failed!\n");
00050     exit(1);
00051   }
00052   for(i = 0; i < 100; i++){
00053     if(write(fd, "aaaaaaaaaa", 10) != 10){
00054       printf(stdout, "error: write aa %d new file failed\n", i);
00055       exit(1);
00056     }
00057     if(write(fd, "bbbbbbbbbb", 10) != 10){
00058       printf(stdout, "error: write bb %d new file failed\n", i);
00059       exit(1);
00060     }
00061   }
00062   printf(stdout, "writes ok\n");
00063   close(fd);
00064   fd = open("small", O_RDONLY);
00065   if(fd >= 0){
00066     printf(stdout, "open small succeeded ok\n");
00067   } else {
00068     printf(stdout, "error: open small failed!\n");
00069     exit(1);
00070   }
00071   i = read(fd, buf, 2000);
00072   if(i == 2000){
00073     printf(stdout, "read succeeded ok\n");
00074   } else {
00075     printf(stdout, "read failed\n");
00076     exit(1);
00077   }
00078   close(fd);
00079 
00080   if(unlink("small") < 0){
00081     printf(stdout, "unlink small failed\n");
00082     exit(1);
00083   }
00084   printf(stdout, "small file test ok\n");
00085 }
00086 
00087 void
00088 writetest1(void)
00089 {
00090   int i, fd, n;
00091 
00092   printf(stdout, "big files test\n");
00093 
00094   fd = open("big", O_CREATE|O_RDWR);
00095   if(fd < 0){
00096     printf(stdout, "error: creat big failed!\n");
00097     exit(1);
00098   }
00099 
00100   for(i = 0; i < MAXFILE; i++){
00101     ((int*)buf)[0] = i;
00102     if(write(fd, buf, 512) != 512){
00103       printf(stdout, "error: write big file failed\n", i);
00104       exit(1);
00105     }
00106   }
00107 
00108   close(fd);
00109 
00110   fd = open("big", O_RDONLY);
00111   if(fd < 0){
00112     printf(stdout, "error: open big failed!\n");
00113     exit(1);
00114   }
00115 
00116   n = 0;
00117   for(;;){
00118     i = read(fd, buf, 512);
00119     if(i == 0){
00120       if(n == MAXFILE - 1){
00121         printf(stdout, "read only %d blocks from big", n);
00122         exit(1);
00123       }
00124       break;
00125     } else if(i != 512){
00126       printf(stdout, "read failed %d\n", i);
00127       exit(1);
00128     }
00129     if(((int*)buf)[0] != n){
00130       printf(stdout, "read content of block %d is %d\n",
00131              n, ((int*)buf)[0]);
00132       exit(1);
00133     }
00134     n++;
00135   }
00136   close(fd);
00137   if(unlink("big") < 0){
00138     printf(stdout, "unlink big failed\n");
00139     exit(1);
00140   }
00141   printf(stdout, "big files ok\n");
00142 }
00143 
00144 void
00145 createtest(void)
00146 {
00147   int i, fd;
00148 
00149   printf(stdout, "many creates, followed by unlink test\n");
00150 
00151   name[0] = 'a';
00152   name[2] = '\0';
00153   for(i = 0; i < 52; i++){
00154     name[1] = '0' + i;
00155     fd = open(name, O_CREATE|O_RDWR);
00156     close(fd);
00157   }
00158   name[0] = 'a';
00159   name[2] = '\0';
00160   for(i = 0; i < 52; i++){
00161     name[1] = '0' + i;
00162     unlink(name);
00163   }
00164   printf(stdout, "many creates, followed by unlink; ok\n");
00165 }
00166 
00167 void dirtest(void)
00168 {
00169   printf(stdout, "mkdir test\n");
00170 
00171   if(mkdir("dir0") < 0){
00172     printf(stdout, "mkdir failed\n");
00173     exit(1);
00174   }
00175 
00176   if(chdir("dir0") < 0){
00177     printf(stdout, "chdir dir0 failed\n");
00178     exit(1);
00179   }
00180 
00181   if(chdir("..") < 0){
00182     printf(stdout, "chdir .. failed\n");
00183     exit(1);
00184   }
00185 
00186   if(unlink("dir0") < 0){
00187     printf(stdout, "unlink dir0 failed\n");
00188     exit(1);
00189   }
00190   printf(stdout, "mkdir test\n");
00191 }
00192 
00193 void
00194 exectest(void)
00195 {
00196   printf(stdout, "exec test\n");
00197   if(exec("echo", echoargv) < 0){
00198     printf(stdout, "exec echo failed\n");
00199     exit(1);
00200   }
00201 }
00202 
00203 // simple fork and pipe read/write
00204 
00205 void
00206 pipe1(void)
00207 {
00208   int fds[2], pid;
00209   int seq, i, n, cc, total;
00210 
00211   if(pipe(fds) != 0){
00212     printf(1, "pipe() failed\n");
00213     exit(1);
00214   }
00215   pid = fork();
00216   seq = 0;
00217   if(pid == 0){
00218     close(fds[0]);
00219     for(n = 0; n < 5; n++){
00220       for(i = 0; i < 1033; i++)
00221         buf[i] = seq++;
00222       if(write(fds[1], buf, 1033) != 1033){
00223         printf(1, "pipe1 oops 1\n");
00224         exit(1);
00225       }
00226     }
00227     exit(1);
00228   } else if(pid > 0){
00229     close(fds[1]);
00230     total = 0;
00231     cc = 1;
00232     while((n = read(fds[0], buf, cc)) > 0){
00233       for(i = 0; i < n; i++){
00234         if((buf[i] & 0xff) != (seq++ & 0xff)){
00235           printf(1, "pipe1 oops 2\n");
00236           return;
00237         }
00238       }
00239       total += n;
00240       cc = cc * 2;
00241       if(cc > sizeof(buf))
00242         cc = sizeof(buf);
00243     }
00244     if(total != 5 * 1033){
00245       printf(1, "pipe1 oops 3 total %d\n", total);
00246       exit(1);
00247     }
00248     close(fds[0]);
00249     wait();
00250   } else {
00251     printf(1, "fork() failed\n");
00252     exit(1);
00253   }
00254   printf(1, "pipe1 ok\n");
00255 }
00256 
00257 // meant to be run w/ at most two CPUs
00258 void
00259 preempt(void)
00260 {
00261   int pid1, pid2, pid3;
00262   int pfds[2];
00263 
00264   printf(1, "preempt: ");
00265   pid1 = fork();
00266   if(pid1 == 0)
00267     for(;;)
00268       ;
00269 
00270   pid2 = fork();
00271   if(pid2 == 0)
00272     for(;;)
00273       ;
00274 
00275   pipe(pfds);
00276   pid3 = fork();
00277   if(pid3 == 0){
00278     close(pfds[0]);
00279     if(write(pfds[1], "x", 1) != 1)
00280       printf(1, "preempt write error");
00281     close(pfds[1]);
00282     for(;;)
00283       ;
00284   }
00285 
00286   close(pfds[1]);
00287   if(read(pfds[0], buf, sizeof(buf)) != 1){
00288     printf(1, "preempt read error");
00289     return;
00290   }
00291   close(pfds[0]);
00292   printf(1, "kill... ");
00293   kill(pid1);
00294   kill(pid2);
00295   kill(pid3);
00296   printf(1, "wait... ");
00297   wait();
00298   wait();
00299   wait();
00300   printf(1, "preempt ok\n");
00301 }
00302 
00303 // try to find any races between exit and wait
00304 void
00305 exitwait(void)
00306 {
00307   int i, pid;
00308 
00309   for(i = 0; i < 100; i++){
00310     pid = fork();
00311     if(pid < 0){
00312       printf(1, "fork failed\n");
00313       return;
00314     }
00315     if(pid){
00316       if(wait() != pid){
00317         printf(1, "wait wrong pid\n");
00318         return;
00319       }
00320     } else {
00321       exit(1);
00322     }
00323   }
00324   printf(1, "exitwait ok\n");
00325 }
00326 
00327 void
00328 mem(void)
00329 {
00330   void *m1, *m2;
00331   int pid, ppid;
00332 
00333   printf(1, "mem test\n");
00334   ppid = getpid();
00335   if((pid = fork()) == 0){
00336     m1 = 0;
00337     while((m2 = malloc(10001)) != 0){
00338       *(char**)m2 = m1;
00339       m1 = m2;
00340     }
00341     while(m1){
00342       m2 = *(char**)m1;
00343       free(m1);
00344       m1 = m2;
00345     }
00346     m1 = malloc(1024*20);
00347     if(m1 == 0){
00348       printf(1, "couldn't allocate mem?!!\n");
00349       kill(ppid);
00350       exit(1);
00351     }
00352     free(m1);
00353     printf(1, "mem ok\n");
00354     exit(1);
00355   } else {
00356     wait();
00357   }
00358 }
00359 
00360 // More file system tests
00361 
00362 // two processes write to the same file descriptor
00363 // is the offset shared? does inode locking work?
00364 void
00365 sharedfd(void)
00366 {
00367   int fd, pid, i, n, nc, np;
00368   char buf[10];
00369 
00370   printf(1, "sharedfd test\n");
00371 
00372   unlink("sharedfd");
00373   fd = open("sharedfd", O_CREATE|O_RDWR);
00374   if(fd < 0){
00375     printf(1, "fstests: cannot open sharedfd for writing");
00376     return;
00377   }
00378   pid = fork();
00379   memset(buf, pid==0?'c':'p', sizeof(buf));
00380   for(i = 0; i < 1000; i++){
00381     if(write(fd, buf, sizeof(buf)) != sizeof(buf)){
00382       printf(1, "fstests: write sharedfd failed\n");
00383       break;
00384     }
00385   }
00386   if(pid == 0)
00387     exit(1);
00388   else
00389     wait();
00390   close(fd);
00391   fd = open("sharedfd", 0);
00392   if(fd < 0){
00393     printf(1, "fstests: cannot open sharedfd for reading\n");
00394     return;
00395   }
00396   nc = np = 0;
00397   while((n = read(fd, buf, sizeof(buf))) > 0){
00398     for(i = 0; i < sizeof(buf); i++){
00399       if(buf[i] == 'c')
00400         nc++;
00401       if(buf[i] == 'p')
00402         np++;
00403     }
00404   }
00405   close(fd);
00406   unlink("sharedfd");
00407   if(nc == 10000 && np == 10000){
00408     printf(1, "sharedfd ok\n");
00409   } else {
00410     printf(1, "sharedfd oops %d %d\n", nc, np);
00411     exit(1);
00412   }
00413 }
00414 
00415 // two processes write two different files at the same
00416 // time, to test block allocation.
00417 void
00418 twofiles(void)
00419 {
00420   int fd, pid, i, j, n, total;
00421   char *fname;
00422 
00423   printf(1, "twofiles test\n");
00424 
00425   unlink("f1");
00426   unlink("f2");
00427 
00428   pid = fork();
00429   if(pid < 0){
00430     printf(1, "fork failed\n");
00431     exit(1);
00432   }
00433 
00434   fname = pid ? "f1" : "f2";
00435   fd = open(fname, O_CREATE | O_RDWR);
00436   if(fd < 0){
00437     printf(1, "create failed\n");
00438     exit(1);
00439   }
00440 
00441   memset(buf, pid?'p':'c', 512);
00442   for(i = 0; i < 12; i++){
00443     if((n = write(fd, buf, 500)) != 500){
00444       printf(1, "write failed %d\n", n);
00445       exit(1);
00446     }
00447   }
00448   close(fd);
00449   if(pid)
00450     wait();
00451   else
00452     exit(1);
00453 
00454   for(i = 0; i < 2; i++){
00455     fd = open(i?"f1":"f2", 0);
00456     total = 0;
00457     while((n = read(fd, buf, sizeof(buf))) > 0){
00458       for(j = 0; j < n; j++){
00459         if(buf[j] != (i?'p':'c')){
00460           printf(1, "wrong char\n");
00461           exit(1);
00462         }
00463       }
00464       total += n;
00465     }
00466     close(fd);
00467     if(total != 12*500){
00468       printf(1, "wrong length %d\n", total);
00469       exit(1);
00470     }
00471   }
00472 
00473   unlink("f1");
00474   unlink("f2");
00475 
00476   printf(1, "twofiles ok\n");
00477 }
00478 
00479 // two processes create and delete different files in same directory
00480 void
00481 createdelete(void)
00482 {
00483   enum { N = 20 };
00484   int pid, i, fd;
00485   char name[32];
00486 
00487   printf(1, "createdelete test\n");
00488   pid = fork();
00489   if(pid < 0){
00490     printf(1, "fork failed\n");
00491     exit(1);
00492   }
00493 
00494   name[0] = pid ? 'p' : 'c';
00495   name[2] = '\0';
00496   for(i = 0; i < N; i++){
00497     name[1] = '0' + i;
00498     fd = open(name, O_CREATE | O_RDWR);
00499     if(fd < 0){
00500       printf(1, "create failed\n");
00501       exit(1);
00502     }
00503     close(fd);
00504     if(i > 0 && (i % 2 ) == 0){
00505       name[1] = '0' + (i / 2);
00506       if(unlink(name) < 0){
00507         printf(1, "unlink failed\n");
00508         exit(1);
00509       }
00510     }
00511   }
00512 
00513   if(pid==0)
00514     exit(1);
00515   else
00516     wait();
00517 
00518   for(i = 0; i < N; i++){
00519     name[0] = 'p';
00520     name[1] = '0' + i;
00521     fd = open(name, 0);
00522     if((i == 0 || i >= N/2) && fd < 0){
00523       printf(1, "oops createdelete %s didn't exist\n", name);
00524       exit(1);
00525     } else if((i >= 1 && i < N/2) && fd >= 0){
00526       printf(1, "oops createdelete %s did exist\n", name);
00527       exit(1);
00528     }
00529     if(fd >= 0)
00530       close(fd);
00531 
00532     name[0] = 'c';
00533     name[1] = '0' + i;
00534     fd = open(name, 0);
00535     if((i == 0 || i >= N/2) && fd < 0){
00536       printf(1, "oops createdelete %s didn't exist\n", name);
00537       exit(1);
00538     } else if((i >= 1 && i < N/2) && fd >= 0){
00539       printf(1, "oops createdelete %s did exist\n", name);
00540       exit(1);
00541     }
00542     if(fd >= 0)
00543       close(fd);
00544   }
00545 
00546   for(i = 0; i < N; i++){
00547     name[0] = 'p';
00548     name[1] = '0' + i;
00549     unlink(name);
00550     name[0] = 'c';
00551     unlink(name);
00552   }
00553 
00554   printf(1, "createdelete ok\n");
00555 }
00556 
00557 // can I unlink a file and still read it?
00558 void
00559 unlinkread(void)
00560 {
00561   int fd, fd1;
00562 
00563   printf(1, "unlinkread test\n");
00564   fd = open("unlinkread", O_CREATE | O_RDWR);
00565   if(fd < 0){
00566     printf(1, "create unlinkread failed\n");
00567     exit(1);
00568   }
00569   write(fd, "hello", 5);
00570   close(fd);
00571 
00572   fd = open("unlinkread", O_RDWR);
00573   if(fd < 0){
00574     printf(1, "open unlinkread failed\n");
00575     exit(1);
00576   }
00577   if(unlink("unlinkread") != 0){
00578     printf(1, "unlink unlinkread failed\n");
00579     exit(1);
00580   }
00581 
00582   fd1 = open("unlinkread", O_CREATE | O_RDWR);
00583   write(fd1, "yyy", 3);
00584   close(fd1);
00585 
00586   if(read(fd, buf, sizeof(buf)) != 5){
00587     printf(1, "unlinkread read failed");
00588     exit(1);
00589   }
00590   if(buf[0] != 'h'){
00591     printf(1, "unlinkread wrong data\n");
00592     exit(1);
00593   }
00594   if(write(fd, buf, 10) != 10){
00595     printf(1, "unlinkread write failed\n");
00596     exit(1);
00597   }
00598   close(fd);
00599   unlink("unlinkread");
00600   printf(1, "unlinkread ok\n");
00601 }
00602 
00603 void
00604 linktest(void)
00605 {
00606   int fd;
00607 
00608   printf(1, "linktest\n");
00609 
00610   unlink("lf1");
00611   unlink("lf2");
00612 
00613   fd = open("lf1", O_CREATE|O_RDWR);
00614   if(fd < 0){
00615     printf(1, "create lf1 failed\n");
00616     exit(1);
00617   }
00618   if(write(fd, "hello", 5) != 5){
00619     printf(1, "write lf1 failed\n");
00620     exit(1);
00621   }
00622   close(fd);
00623 
00624   if(link("lf1", "lf2") < 0){
00625     printf(1, "link lf1 lf2 failed\n");
00626     exit(1);
00627   }
00628   unlink("lf1");
00629 
00630   if(open("lf1", 0) >= 0){
00631     printf(1, "unlinked lf1 but it is still there!\n");
00632     exit(1);
00633   }
00634 
00635   fd = open("lf2", 0);
00636   if(fd < 0){
00637     printf(1, "open lf2 failed\n");
00638     exit(1);
00639   }
00640   if(read(fd, buf, sizeof(buf)) != 5){
00641     printf(1, "read lf2 failed\n");
00642     exit(1);
00643   }
00644   close(fd);
00645 
00646   if(link("lf2", "lf2") >= 0){
00647     printf(1, "link lf2 lf2 succeeded! oops\n");
00648     exit(1);
00649   }
00650 
00651   unlink("lf2");
00652   if(link("lf2", "lf1") >= 0){
00653     printf(1, "link non-existant succeeded! oops\n");
00654     exit(1);
00655   }
00656 
00657   if(link(".", "lf1") >= 0){
00658     printf(1, "link . lf1 succeeded! oops\n");
00659     exit(1);
00660   }
00661 
00662   printf(1, "linktest ok\n");
00663 }
00664 
00665 // test concurrent create/link/unlink of the same file
00666 void
00667 concreate(void)
00668 {
00669   char file[3];
00670   int i, pid, n, fd;
00671   char fa[40];
00672   struct {
00673     ushort inum;
00674     char name[14];
00675   } de;
00676 
00677   printf(1, "concreate test\n");
00678   file[0] = 'C';
00679   file[2] = '\0';
00680   for(i = 0; i < 40; i++){
00681     file[1] = '0' + i;
00682     unlink(file);
00683     pid = fork();
00684     if(pid && (i % 3) == 1){
00685       link("C0", file);
00686     } else if(pid == 0 && (i % 5) == 1){
00687       link("C0", file);
00688     } else {
00689       fd = open(file, O_CREATE | O_RDWR);
00690       if(fd < 0){
00691         printf(1, "concreate create %s failed\n", file);
00692         exit(1);
00693       }
00694       close(fd);
00695     }
00696     if(pid == 0)
00697       exit(1);
00698     else
00699       wait();
00700   }
00701 
00702   memset(fa, 0, sizeof(fa));
00703   fd = open(".", 0);
00704   n = 0;
00705   while(read(fd, &de, sizeof(de)) > 0){
00706     if(de.inum == 0)
00707       continue;
00708     if(de.name[0] == 'C' && de.name[2] == '\0'){
00709       i = de.name[1] - '0';
00710       if(i < 0 || i >= sizeof(fa)){
00711         printf(1, "concreate weird file %s\n", de.name);
00712         exit(1);
00713       }
00714       if(fa[i]){
00715         printf(1, "concreate duplicate file %s\n", de.name);
00716         exit(1);
00717       }
00718       fa[i] = 1;
00719       n++;
00720     }
00721   }
00722   close(fd);
00723 
00724   if(n != 40){
00725     printf(1, "concreate not enough files in directory listing\n");
00726     exit(1);
00727   }
00728 
00729   for(i = 0; i < 40; i++){
00730     file[1] = '0' + i;
00731     pid = fork();
00732     if(pid < 0){
00733       printf(1, "fork failed\n");
00734       exit(1);
00735     }
00736     if(((i % 3) == 0 && pid == 0) ||
00737        ((i % 3) == 1 && pid != 0)){
00738       close(open(file, 0));
00739       close(open(file, 0));
00740       close(open(file, 0));
00741       close(open(file, 0));
00742     } else {
00743       unlink(file);
00744       unlink(file);
00745       unlink(file);
00746       unlink(file);
00747     }
00748     if(pid == 0)
00749       exit(1);
00750     else
00751       wait();
00752   }
00753 
00754   printf(1, "concreate ok\n");
00755 }
00756 
00757 // another concurrent link/unlink/create test,
00758 // to look for deadlocks.
00759 void
00760 linkunlink()
00761 {
00762   int pid, i;
00763 
00764   printf(1, "linkunlink test\n");
00765 
00766   unlink("x");
00767   pid = fork();
00768   if(pid < 0){
00769     printf(1, "fork failed\n");
00770     exit(1);
00771   }
00772 
00773   unsigned int x = (pid ? 1 : 97);
00774   for(i = 0; i < 100; i++){
00775     x = x * 1103515245 + 12345;
00776     if((x % 3) == 0){
00777       close(open("x", O_RDWR | O_CREATE));
00778     } else if((x % 3) == 1){
00779       link("cat", "x");
00780     } else {
00781       unlink("x");
00782     }
00783   }
00784 
00785   if(pid)
00786     wait();
00787   else 
00788     exit(1);
00789 
00790   printf(1, "linkunlink ok\n");
00791 }
00792 
00793 // directory that uses indirect blocks
00794 void
00795 bigdir(void)
00796 {
00797   int i, fd;
00798   char name[10];
00799 
00800   printf(1, "bigdir test\n");
00801   unlink("bd");
00802 
00803   fd = open("bd", O_CREATE);
00804   if(fd < 0){
00805     printf(1, "bigdir create failed\n");
00806     exit(1);
00807   }
00808   close(fd);
00809 
00810   for(i = 0; i < 500; i++){
00811     name[0] = 'x';
00812     name[1] = '0' + (i / 64);
00813     name[2] = '0' + (i % 64);
00814     name[3] = '\0';
00815     if(link("bd", name) != 0){
00816       printf(1, "bigdir link failed\n");
00817       exit(1);
00818     }
00819   }
00820 
00821   unlink("bd");
00822   for(i = 0; i < 500; i++){
00823     name[0] = 'x';
00824     name[1] = '0' + (i / 64);
00825     name[2] = '0' + (i % 64);
00826     name[3] = '\0';
00827     if(unlink(name) != 0){
00828       printf(1, "bigdir unlink failed");
00829       exit(1);
00830     }
00831   }
00832 
00833   printf(1, "bigdir ok\n");
00834 }
00835 
00836 void
00837 subdir(void)
00838 {
00839   int fd, cc;
00840 
00841   printf(1, "subdir test\n");
00842 
00843   unlink("ff");
00844   if(mkdir("dd") != 0){
00845     printf(1, "subdir mkdir dd failed\n");
00846     exit(1);
00847   }
00848 
00849   fd = open("dd/ff", O_CREATE | O_RDWR);
00850   if(fd < 0){
00851     printf(1, "create dd/ff failed\n");
00852     exit(1);
00853   }
00854   write(fd, "ff", 2);
00855   close(fd);
00856   
00857   if(unlink("dd") >= 0){
00858     printf(1, "unlink dd (non-empty dir) succeeded!\n");
00859     exit(1);
00860   }
00861 
00862   if(mkdir("/dd/dd") != 0){
00863     printf(1, "subdir mkdir dd/dd failed\n");
00864     exit(1);
00865   }
00866 
00867   fd = open("dd/dd/ff", O_CREATE | O_RDWR);
00868   if(fd < 0){
00869     printf(1, "create dd/dd/ff failed\n");
00870     exit(1);
00871   }
00872   write(fd, "FF", 2);
00873   close(fd);
00874 
00875   fd = open("dd/dd/../ff", 0);
00876   if(fd < 0){
00877     printf(1, "open dd/dd/../ff failed\n");
00878     exit(1);
00879   }
00880   cc = read(fd, buf, sizeof(buf));
00881   if(cc != 2 || buf[0] != 'f'){
00882     printf(1, "dd/dd/../ff wrong content\n");
00883     exit(1);
00884   }
00885   close(fd);
00886 
00887   if(link("dd/dd/ff", "dd/dd/ffff") != 0){
00888     printf(1, "link dd/dd/ff dd/dd/ffff failed\n");
00889     exit(1);
00890   }
00891 
00892   if(unlink("dd/dd/ff") != 0){
00893     printf(1, "unlink dd/dd/ff failed\n");
00894     exit(1);
00895   }
00896   if(open("dd/dd/ff", O_RDONLY) >= 0){
00897     printf(1, "open (unlinked) dd/dd/ff succeeded\n");
00898     exit(1);
00899   }
00900 
00901   if(chdir("dd") != 0){
00902     printf(1, "chdir dd failed\n");
00903     exit(1);
00904   }
00905   if(chdir("dd/../../dd") != 0){
00906     printf(1, "chdir dd/../../dd failed\n");
00907     exit(1);
00908   }
00909   if(chdir("dd/../../../dd") != 0){
00910     printf(1, "chdir dd/../../dd failed\n");
00911     exit(1);
00912   }
00913   if(chdir("./..") != 0){
00914     printf(1, "chdir ./.. failed\n");
00915     exit(1);
00916   }
00917 
00918   fd = open("dd/dd/ffff", 0);
00919   if(fd < 0){
00920     printf(1, "open dd/dd/ffff failed\n");
00921     exit(1);
00922   }
00923   if(read(fd, buf, sizeof(buf)) != 2){
00924     printf(1, "read dd/dd/ffff wrong len\n");
00925     exit(1);
00926   }
00927   close(fd);
00928 
00929   if(open("dd/dd/ff", O_RDONLY) >= 0){
00930     printf(1, "open (unlinked) dd/dd/ff succeeded!\n");
00931     exit(1);
00932   }
00933 
00934   if(open("dd/ff/ff", O_CREATE|O_RDWR) >= 0){
00935     printf(1, "create dd/ff/ff succeeded!\n");
00936     exit(1);
00937   }
00938   if(open("dd/xx/ff", O_CREATE|O_RDWR) >= 0){
00939     printf(1, "create dd/xx/ff succeeded!\n");
00940     exit(1);
00941   }
00942   if(open("dd", O_CREATE) >= 0){
00943     printf(1, "create dd succeeded!\n");
00944     exit(1);
00945   }
00946   if(open("dd", O_RDWR) >= 0){
00947     printf(1, "open dd rdwr succeeded!\n");
00948     exit(1);
00949   }
00950   if(open("dd", O_WRONLY) >= 0){
00951     printf(1, "open dd wronly succeeded!\n");
00952     exit(1);
00953   }
00954   if(link("dd/ff/ff", "dd/dd/xx") == 0){
00955     printf(1, "link dd/ff/ff dd/dd/xx succeeded!\n");
00956     exit(1);
00957   }
00958   if(link("dd/xx/ff", "dd/dd/xx") == 0){
00959     printf(1, "link dd/xx/ff dd/dd/xx succeeded!\n");
00960     exit(1);
00961   }
00962   if(link("dd/ff", "dd/dd/ffff") == 0){
00963     printf(1, "link dd/ff dd/dd/ffff succeeded!\n");
00964     exit(1);
00965   }
00966   if(mkdir("dd/ff/ff") == 0){
00967     printf(1, "mkdir dd/ff/ff succeeded!\n");
00968     exit(1);
00969   }
00970   if(mkdir("dd/xx/ff") == 0){
00971     printf(1, "mkdir dd/xx/ff succeeded!\n");
00972     exit(1);
00973   }
00974   if(mkdir("dd/dd/ffff") == 0){
00975     printf(1, "mkdir dd/dd/ffff succeeded!\n");
00976     exit(1);
00977   }
00978   if(unlink("dd/xx/ff") == 0){
00979     printf(1, "unlink dd/xx/ff succeeded!\n");
00980     exit(1);
00981   }
00982   if(unlink("dd/ff/ff") == 0){
00983     printf(1, "unlink dd/ff/ff succeeded!\n");
00984     exit(1);
00985   }
00986   if(chdir("dd/ff") == 0){
00987     printf(1, "chdir dd/ff succeeded!\n");
00988     exit(1);
00989   }
00990   if(chdir("dd/xx") == 0){
00991     printf(1, "chdir dd/xx succeeded!\n");
00992     exit(1);
00993   }
00994 
00995   if(unlink("dd/dd/ffff") != 0){
00996     printf(1, "unlink dd/dd/ff failed\n");
00997     exit(1);
00998   }
00999   if(unlink("dd/ff") != 0){
01000     printf(1, "unlink dd/ff failed\n");
01001     exit(1);
01002   }
01003   if(unlink("dd") == 0){
01004     printf(1, "unlink non-empty dd succeeded!\n");
01005     exit(1);
01006   }
01007   if(unlink("dd/dd") < 0){
01008     printf(1, "unlink dd/dd failed\n");
01009     exit(1);
01010   }
01011   if(unlink("dd") < 0){
01012     printf(1, "unlink dd failed\n");
01013     exit(1);
01014   }
01015 
01016   printf(1, "subdir ok\n");
01017 }
01018 
01019 // test writes that are larger than the log.
01020 void
01021 bigwrite(void)
01022 {
01023   int fd, sz;
01024 
01025   printf(1, "bigwrite test\n");
01026 
01027   unlink("bigwrite");
01028   for(sz = 499; sz < 12*512; sz += 471){
01029     fd = open("bigwrite", O_CREATE | O_RDWR);
01030     if(fd < 0){
01031       printf(1, "cannot create bigwrite\n");
01032       exit(1);
01033     }
01034     int i;
01035     for(i = 0; i < 2; i++){
01036       int cc = write(fd, buf, sz);
01037       if(cc != sz){
01038         printf(1, "write(%d) ret %d\n", sz, cc);
01039         exit(1);
01040       }
01041     }
01042     close(fd);
01043     unlink("bigwrite");
01044   }
01045 
01046   printf(1, "bigwrite ok\n");
01047 }
01048 
01049 void
01050 bigfile(void)
01051 {
01052   int fd, i, total, cc;
01053 
01054   printf(1, "bigfile test\n");
01055 
01056   unlink("bigfile");
01057   fd = open("bigfile", O_CREATE | O_RDWR);
01058   if(fd < 0){
01059     printf(1, "cannot create bigfile");
01060     exit(1);
01061   }
01062   for(i = 0; i < 20; i++){
01063     memset(buf, i, 600);
01064     if(write(fd, buf, 600) != 600){
01065       printf(1, "write bigfile failed\n");
01066       exit(1);
01067     }
01068   }
01069   close(fd);
01070 
01071   fd = open("bigfile", 0);
01072   if(fd < 0){
01073     printf(1, "cannot open bigfile\n");
01074     exit(1);
01075   }
01076   total = 0;
01077   for(i = 0; ; i++){
01078     cc = read(fd, buf, 300);
01079     if(cc < 0){
01080       printf(1, "read bigfile failed\n");
01081       exit(1);
01082     }
01083     if(cc == 0)
01084       break;
01085     if(cc != 300){
01086       printf(1, "short read bigfile\n");
01087       exit(1);
01088     }
01089     if(buf[0] != i/2 || buf[299] != i/2){
01090       printf(1, "read bigfile wrong data\n");
01091       exit(1);
01092     }
01093     total += cc;
01094   }
01095   close(fd);
01096   if(total != 20*600){
01097     printf(1, "read bigfile wrong total\n");
01098     exit(1);
01099   }
01100   unlink("bigfile");
01101 
01102   printf(1, "bigfile test ok\n");
01103 }
01104 
01105 void
01106 fourteen(void)
01107 {
01108   int fd;
01109 
01110   // DIRSIZ is 14.
01111   printf(1, "fourteen test\n");
01112 
01113   if(mkdir("12345678901234") != 0){
01114     printf(1, "mkdir 12345678901234 failed\n");
01115     exit(1);
01116   }
01117   if(mkdir("12345678901234/123456789012345") != 0){
01118     printf(1, "mkdir 12345678901234/123456789012345 failed\n");
01119     exit(1);
01120   }
01121   fd = open("123456789012345/123456789012345/123456789012345", O_CREATE);
01122   if(fd < 0){
01123     printf(1, "create 123456789012345/123456789012345/123456789012345 failed\n");
01124     exit(1);
01125   }
01126   close(fd);
01127   fd = open("12345678901234/12345678901234/12345678901234", 0);
01128   if(fd < 0){
01129     printf(1, "open 12345678901234/12345678901234/12345678901234 failed\n");
01130     exit(1);
01131   }
01132   close(fd);
01133 
01134   if(mkdir("12345678901234/12345678901234") == 0){
01135     printf(1, "mkdir 12345678901234/12345678901234 succeeded!\n");
01136     exit(1);
01137   }
01138   if(mkdir("123456789012345/12345678901234") == 0){
01139     printf(1, "mkdir 12345678901234/123456789012345 succeeded!\n");
01140     exit(1);
01141   }
01142 
01143   printf(1, "fourteen ok\n");
01144 }
01145 
01146 void
01147 rmdot(void)
01148 {
01149   printf(1, "rmdot test\n");
01150   if(mkdir("dots") != 0){
01151     printf(1, "mkdir dots failed\n");
01152     exit(1);
01153   }
01154   if(chdir("dots") != 0){
01155     printf(1, "chdir dots failed\n");
01156     exit(1);
01157   }
01158   if(unlink(".") == 0){
01159     printf(1, "rm . worked!\n");
01160     exit(1);
01161   }
01162   if(unlink("..") == 0){
01163     printf(1, "rm .. worked!\n");
01164     exit(1);
01165   }
01166   if(chdir("/") != 0){
01167     printf(1, "chdir / failed\n");
01168     exit(1);
01169   }
01170   if(unlink("dots/.") == 0){
01171     printf(1, "unlink dots/. worked!\n");
01172     exit(1);
01173   }
01174   if(unlink("dots/..") == 0){
01175     printf(1, "unlink dots/.. worked!\n");
01176     exit(1);
01177   }
01178   if(unlink("dots") != 0){
01179     printf(1, "unlink dots failed!\n");
01180     exit(1);
01181   }
01182   printf(1, "rmdot ok\n");
01183 }
01184 
01185 void
01186 dirfile(void)
01187 {
01188   int fd;
01189 
01190   printf(1, "dir vs file\n");
01191 
01192   fd = open("dirfile", O_CREATE);
01193   if(fd < 0){
01194     printf(1, "create dirfile failed\n");
01195     exit(1);
01196   }
01197   close(fd);
01198   if(chdir("dirfile") == 0){
01199     printf(1, "chdir dirfile succeeded!\n");
01200     exit(1);
01201   }
01202   fd = open("dirfile/xx", 0);
01203   if(fd >= 0){
01204     printf(1, "create dirfile/xx succeeded!\n");
01205     exit(1);
01206   }
01207   fd = open("dirfile/xx", O_CREATE);
01208   if(fd >= 0){
01209     printf(1, "create dirfile/xx succeeded!\n");
01210     exit(1);
01211   }
01212   if(mkdir("dirfile/xx") == 0){
01213     printf(1, "mkdir dirfile/xx succeeded!\n");
01214     exit(1);
01215   }
01216   if(unlink("dirfile/xx") == 0){
01217     printf(1, "unlink dirfile/xx succeeded!\n");
01218     exit(1);
01219   }
01220   if(link("README", "dirfile/xx") == 0){
01221     printf(1, "link to dirfile/xx succeeded!\n");
01222     exit(1);
01223   }
01224   if(unlink("dirfile") != 0){
01225     printf(1, "unlink dirfile failed!\n");
01226     exit(1);
01227   }
01228 
01229   fd = open(".", O_RDWR);
01230   if(fd >= 0){
01231     printf(1, "open . for writing succeeded!\n");
01232     exit(1);
01233   }
01234   fd = open(".", 0);
01235   if(write(fd, "x", 1) > 0){
01236     printf(1, "write . succeeded!\n");
01237     exit(1);
01238   }
01239   close(fd);
01240 
01241   printf(1, "dir vs file OK\n");
01242 }
01243 
01244 // test that iput() is called at the end of _namei()
01245 void
01246 iref(void)
01247 {
01248   int i, fd;
01249 
01250   printf(1, "empty file name\n");
01251 
01252   // the 50 is NINODE
01253   for(i = 0; i < 50 + 1; i++){
01254     if(mkdir("irefd") != 0){
01255       printf(1, "mkdir irefd failed\n");
01256       exit(1);
01257     }
01258     if(chdir("irefd") != 0){
01259       printf(1, "chdir irefd failed\n");
01260       exit(1);
01261     }
01262 
01263     mkdir("");
01264     link("README", "");
01265     fd = open("", O_CREATE);
01266     if(fd >= 0)
01267       close(fd);
01268     fd = open("xx", O_CREATE);
01269     if(fd >= 0)
01270       close(fd);
01271     unlink("xx");
01272   }
01273 
01274   chdir("/");
01275   printf(1, "empty file name OK\n");
01276 }
01277 
01278 // test that fork fails gracefully
01279 // the forktest binary also does this, but it runs out of proc entries first.
01280 // inside the bigger usertests binary, we run out of memory first.
01281 void
01282 forktest(void)
01283 {
01284   int n, pid;
01285 
01286   printf(1, "fork test\n");
01287 
01288   for(n=0; n<1000; n++){
01289     pid = fork();
01290     if(pid < 0)
01291       break;
01292     if(pid == 0)
01293       exit(1);
01294   }
01295   
01296   if(n == 1000){
01297     printf(1, "fork claimed to work 1000 times!\n");
01298     exit(1);
01299   }
01300   
01301   for(; n > 0; n--){
01302     if(wait() < 0){
01303       printf(1, "wait stopped early\n");
01304       exit(1);
01305     }
01306   }
01307   
01308   if(wait() != -1){
01309     printf(1, "wait got too many\n");
01310     exit(1);
01311   }
01312   
01313   printf(1, "fork test OK\n");
01314 }
01315 
01316 void
01317 sbrktest(void)
01318 {
01319   int fds[2], pid, pids[10], ppid;
01320   char *a, *b, *c, *lastaddr, *oldbrk, *p, scratch;
01321   uint amt;
01322 
01323   printf(stdout, "sbrk test\n");
01324   oldbrk = sbrk(0);
01325 
01326   // can one sbrk() less than a page?
01327   a = sbrk(0);
01328   int i;
01329   for(i = 0; i < 5000; i++){ 
01330     b = sbrk(1);
01331     if(b != a){
01332       printf(stdout, "sbrk test failed %d %x %x\n", i, a, b);
01333       exit(1);
01334     }
01335     *b = 1;
01336     a = b + 1;
01337   }
01338   pid = fork();
01339   if(pid < 0){
01340     printf(stdout, "sbrk test fork failed\n");
01341     exit(1);
01342   }
01343   c = sbrk(1);
01344   c = sbrk(1);
01345   if(c != a + 1){
01346     printf(stdout, "sbrk test failed post-fork\n");
01347     exit(1);
01348   }
01349   if(pid == 0)
01350     exit(1);
01351   wait();
01352 
01353   // can one grow address space to something big?
01354 #define BIG (100*1024*1024)
01355   a = sbrk(0);
01356   amt = (BIG) - (uint)a;
01357   p = sbrk(amt);
01358   if (p != a) { 
01359     printf(stdout, "sbrk test failed to grow big address space; enough phys mem?\n");
01360     exit(1);
01361   }
01362   lastaddr = (char*) (BIG-1);
01363   *lastaddr = 99;
01364 
01365   // can one de-allocate?
01366   a = sbrk(0);
01367   c = sbrk(-4096);
01368   if(c == (char*)0xffffffff){
01369     printf(stdout, "sbrk could not deallocate\n");
01370     exit(1);
01371   }
01372   c = sbrk(0);
01373   if(c != a - 4096){
01374     printf(stdout, "sbrk deallocation produced wrong address, a %x c %x\n", a, c);
01375     exit(1);
01376   }
01377 
01378   // can one re-allocate that page?
01379   a = sbrk(0);
01380   c = sbrk(4096);
01381   if(c != a || sbrk(0) != a + 4096){
01382     printf(stdout, "sbrk re-allocation failed, a %x c %x\n", a, c);
01383     exit(1);
01384   }
01385   if(*lastaddr == 99){
01386     // should be zero
01387     printf(stdout, "sbrk de-allocation didn't really deallocate\n");
01388     exit(1);
01389   }
01390 
01391   a = sbrk(0);
01392   c = sbrk(-(sbrk(0) - oldbrk));
01393   if(c != a){
01394     printf(stdout, "sbrk downsize failed, a %x c %x\n", a, c);
01395     exit(1);
01396   }
01397   
01398   // can we read the kernel's memory?
01399   for(a = (char*)(KERNBASE); a < (char*) (KERNBASE+2000000); a += 50000){
01400     ppid = getpid();
01401     pid = fork();
01402     if(pid < 0){
01403       printf(stdout, "fork failed\n");
01404       exit(1);
01405     }
01406     if(pid == 0){
01407       printf(stdout, "oops could read %x = %x\n", a, *a);
01408       kill(ppid);
01409       exit(1);
01410     }
01411     wait();
01412   }
01413 
01414   // if we run the system out of memory, does it clean up the last
01415   // failed allocation?
01416   if(pipe(fds) != 0){
01417     printf(1, "pipe() failed\n");
01418     exit(1);
01419   }
01420   for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){
01421     if((pids[i] = fork()) == 0){
01422       // allocate a lot of memory
01423       sbrk(BIG - (uint)sbrk(0));
01424       write(fds[1], "x", 1);
01425       // sit around until killed
01426       for(;;) sleep(1000);
01427     }
01428     if(pids[i] != -1)
01429       read(fds[0], &scratch, 1);
01430   }
01431   // if those failed allocations freed up the pages they did allocate,
01432   // we'll be able to allocate here
01433   c = sbrk(4096);
01434   for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){
01435     if(pids[i] == -1)
01436       continue;
01437     kill(pids[i]);
01438     wait();
01439   }
01440   if(c == (char*)0xffffffff){
01441     printf(stdout, "failed sbrk leaked memory\n");
01442     exit(1);
01443   }
01444 
01445   if(sbrk(0) > oldbrk)
01446     sbrk(-(sbrk(0) - oldbrk));
01447 
01448   printf(stdout, "sbrk test OK\n");
01449 }
01450 
01451 void
01452 validateint(int *p)
01453 {
01454   int res;
01455   asm("mov %%esp, %%ebx\n\t"
01456       "mov %3, %%esp\n\t"
01457       "int %2\n\t"
01458       "mov %%ebx, %%esp" :
01459       "=a" (res) :
01460       "a" (SYS_sleep), "n" (T_SYSCALL), "c" (p) :
01461       "ebx");
01462 }
01463 
01464 void
01465 validatetest(void)
01466 {
01467   int hi, pid;
01468   uint p;
01469 
01470   printf(stdout, "validate test\n");
01471   hi = 1100*1024;
01472 
01473   for(p = 0; p <= (uint)hi; p += 4096){
01474     if((pid = fork()) == 0){
01475       // try to crash the kernel by passing in a badly placed integer
01476       validateint((int*)p);
01477       exit(1);
01478     }
01479     sleep(0);
01480     sleep(0);
01481     kill(pid);
01482     wait();
01483 
01484     // try to crash the kernel by passing in a bad string pointer
01485     if(link("nosuchfile", (char*)p) != -1){
01486       printf(stdout, "link should not succeed\n");
01487       exit(1);
01488     }
01489   }
01490 
01491   printf(stdout, "validate ok\n");
01492 }
01493 
01494 // does unintialized data start out zero?
01495 char uninit[10000];
01496 void
01497 bsstest(void)
01498 {
01499   int i;
01500 
01501   printf(stdout, "bss test\n");
01502   for(i = 0; i < sizeof(uninit); i++){
01503     if(uninit[i] != '\0'){
01504       printf(stdout, "bss test failed\n");
01505       exit(1);
01506     }
01507   }
01508   printf(stdout, "bss test ok\n");
01509 }
01510 
01511 // does exec return an error if the arguments
01512 // are larger than a page? or does it write
01513 // below the stack and wreck the instructions/data?
01514 void
01515 bigargtest(void)
01516 {
01517   int pid, fd;
01518 
01519   unlink("bigarg-ok");
01520   pid = fork();
01521   if(pid == 0){
01522     static char *args[MAXARG];
01523     int i;
01524     for(i = 0; i < MAXARG-1; i++)
01525       args[i] = "bigargs test: failed\n                                                                                                                                                                                                       ";
01526     args[MAXARG-1] = 0;
01527     printf(stdout, "bigarg test\n");
01528     exec("echo", args);
01529     printf(stdout, "bigarg test ok\n");
01530     fd = open("bigarg-ok", O_CREATE);
01531     close(fd);
01532     exit(1);
01533   } else if(pid < 0){
01534     printf(stdout, "bigargtest: fork failed\n");
01535     exit(1);
01536   }
01537   wait();
01538   fd = open("bigarg-ok", 0);
01539   if(fd < 0){
01540     printf(stdout, "bigarg test failed!\n");
01541     exit(1);
01542   }
01543   close(fd);
01544   unlink("bigarg-ok");
01545 }
01546 
01547 // what happens when the file system runs out of blocks?
01548 // answer: balloc panics, so this test is not useful.
01549 void
01550 fsfull()
01551 {
01552   int nfiles;
01553   int fsblocks = 0;
01554 
01555   printf(1, "fsfull test\n");
01556 
01557   for(nfiles = 0; ; nfiles++){
01558     char name[64];
01559     name[0] = 'f';
01560     name[1] = '0' + nfiles / 1000;
01561     name[2] = '0' + (nfiles % 1000) / 100;
01562     name[3] = '0' + (nfiles % 100) / 10;
01563     name[4] = '0' + (nfiles % 10);
01564     name[5] = '\0';
01565     printf(1, "writing %s\n", name);
01566     int fd = open(name, O_CREATE|O_RDWR);
01567     if(fd < 0){
01568       printf(1, "open %s failed\n", name);
01569       break;
01570     }
01571     int total = 0;
01572     while(1){
01573       int cc = write(fd, buf, 512);
01574       if(cc < 512)
01575         break;
01576       total += cc;
01577       fsblocks++;
01578     }
01579     printf(1, "wrote %d bytes\n", total);
01580     close(fd);
01581     if(total == 0)
01582       break;
01583   }
01584 
01585   while(nfiles >= 0){
01586     char name[64];
01587     name[0] = 'f';
01588     name[1] = '0' + nfiles / 1000;
01589     name[2] = '0' + (nfiles % 1000) / 100;
01590     name[3] = '0' + (nfiles % 100) / 10;
01591     name[4] = '0' + (nfiles % 10);
01592     name[5] = '\0';
01593     unlink(name);
01594     nfiles--;
01595   }
01596 
01597   printf(1, "fsfull test finished\n");
01598 }
01599 
01600 unsigned long randstate = 1;
01601 unsigned int
01602 rand()
01603 {
01604   randstate = randstate * 1664525 + 1013904223;
01605   return randstate;
01606 }
01607 
01608 int
01609 main(int argc, char *argv[])
01610 {
01611   printf(1, "usertests starting\n");
01612 
01613   if(open("usertests.ran", 0) >= 0){
01614     printf(1, "already ran user tests -- rebuild fs.img\n");
01615     exit(1);
01616   }
01617   close(open("usertests.ran", O_CREATE));
01618 
01619   bigargtest();
01620   bigwrite();
01621   bigargtest();
01622   bsstest();
01623   sbrktest();
01624   validatetest();
01625 
01626   opentest();
01627   writetest();
01628   writetest1();
01629   createtest();
01630 
01631   mem();
01632   pipe1();
01633   preempt();
01634   exitwait();
01635 
01636   rmdot();
01637   fourteen();
01638   bigfile();
01639   subdir();
01640   concreate();
01641   linkunlink();
01642   linktest();
01643   unlinkread();
01644   createdelete();
01645   twofiles();
01646   sharedfd();
01647   dirfile();
01648   iref();
01649   forktest();
01650   bigdir(); // slow
01651 
01652   exectest();
01653 
01654   exit(1);
01655 }
 All Data Structures