root/usertests.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. iputtest
  2. exitiputtest
  3. openiputtest
  4. opentest
  5. writetest
  6. writetest1
  7. createtest
  8. dirtest
  9. exectest
  10. pipe1
  11. preempt
  12. exitwait
  13. mem
  14. sharedfd
  15. fourfiles
  16. createdelete
  17. unlinkread
  18. linktest
  19. concreate
  20. linkunlink
  21. bigdir
  22. subdir
  23. bigwrite
  24. bigfile
  25. fourteen
  26. rmdot
  27. dirfile
  28. iref
  29. forktest
  30. sbrktest
  31. validateint
  32. validatetest
  33. bsstest
  34. bigargtest
  35. fsfull
  36. uio
  37. argptest
  38. rand
  39. main

   1 #include "param.h"
   2 #include "types.h"
   3 #include "stat.h"
   4 #include "user.h"
   5 #include "fs.h"
   6 #include "fcntl.h"
   7 #include "syscall.h"
   8 #include "traps.h"
   9 #include "memlayout.h"
  10 
  11 char buf[8192];
  12 char name[3];
  13 char *echoargv[] = { "echo", "ALL", "TESTS", "PASSED", 0 };
  14 int stdout = 1;
  15 
  16 // does chdir() call iput(p->cwd) in a transaction?
  17 void
  18 iputtest(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
  19 {
  20   printf(stdout, "iput test\n");
  21 
  22   if(mkdir("iputdir") < 0){
  23     printf(stdout, "mkdir failed\n");
  24     exit();
  25   }
  26   if(chdir("iputdir") < 0){
  27     printf(stdout, "chdir iputdir failed\n");
  28     exit();
  29   }
  30   if(unlink("../iputdir") < 0){
  31     printf(stdout, "unlink ../iputdir failed\n");
  32     exit();
  33   }
  34   if(chdir("/") < 0){
  35     printf(stdout, "chdir / failed\n");
  36     exit();
  37   }
  38   printf(stdout, "iput test ok\n");
  39 }
  40 
  41 // does exit() call iput(p->cwd) in a transaction?
  42 void
  43 exitiputtest(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
  44 {
  45   int pid;
  46 
  47   printf(stdout, "exitiput test\n");
  48 
  49   pid = fork();
  50   if(pid < 0){
  51     printf(stdout, "fork failed\n");
  52     exit();
  53   }
  54   if(pid == 0){
  55     if(mkdir("iputdir") < 0){
  56       printf(stdout, "mkdir failed\n");
  57       exit();
  58     }
  59     if(chdir("iputdir") < 0){
  60       printf(stdout, "child chdir failed\n");
  61       exit();
  62     }
  63     if(unlink("../iputdir") < 0){
  64       printf(stdout, "unlink ../iputdir failed\n");
  65       exit();
  66     }
  67     exit();
  68   }
  69   wait();
  70   printf(stdout, "exitiput test ok\n");
  71 }
  72 
  73 // does the error path in open() for attempt to write a
  74 // directory call iput() in a transaction?
  75 // needs a hacked kernel that pauses just after the namei()
  76 // call in sys_open():
  77 //    if((ip = namei(path)) == 0)
  78 //      return -1;
  79 //    {
  80 //      int i;
  81 //      for(i = 0; i < 10000; i++)
  82 //        yield();
  83 //    }
  84 void
  85 openiputtest(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
  86 {
  87   int pid;
  88 
  89   printf(stdout, "openiput test\n");
  90   if(mkdir("oidir") < 0){
  91     printf(stdout, "mkdir oidir failed\n");
  92     exit();
  93   }
  94   pid = fork();
  95   if(pid < 0){
  96     printf(stdout, "fork failed\n");
  97     exit();
  98   }
  99   if(pid == 0){
 100     int fd = open("oidir", O_RDWR);
 101     if(fd >= 0){
 102       printf(stdout, "open directory for write succeeded\n");
 103       exit();
 104     }
 105     exit();
 106   }
 107   sleep(1);
 108   if(unlink("oidir") != 0){
 109     printf(stdout, "unlink failed\n");
 110     exit();
 111   }
 112   wait();
 113   printf(stdout, "openiput test ok\n");
 114 }
 115 
 116 // simple file system tests
 117 
 118 void
 119 opentest(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 120 {
 121   int fd;
 122 
 123   printf(stdout, "open test\n");
 124   fd = open("echo", 0);
 125   if(fd < 0){
 126     printf(stdout, "open echo failed!\n");
 127     exit();
 128   }
 129   close(fd);
 130   fd = open("doesnotexist", 0);
 131   if(fd >= 0){
 132     printf(stdout, "open doesnotexist succeeded!\n");
 133     exit();
 134   }
 135   printf(stdout, "open test ok\n");
 136 }
 137 
 138 void
 139 writetest(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 140 {
 141   int fd;
 142   int i;
 143 
 144   printf(stdout, "small file test\n");
 145   fd = open("small", O_CREATE|O_RDWR);
 146   if(fd >= 0){
 147     printf(stdout, "creat small succeeded; ok\n");
 148   } else {
 149     printf(stdout, "error: creat small failed!\n");
 150     exit();
 151   }
 152   for(i = 0; i < 100; i++){
 153     if(write(fd, "aaaaaaaaaa", 10) != 10){
 154       printf(stdout, "error: write aa %d new file failed\n", i);
 155       exit();
 156     }
 157     if(write(fd, "bbbbbbbbbb", 10) != 10){
 158       printf(stdout, "error: write bb %d new file failed\n", i);
 159       exit();
 160     }
 161   }
 162   printf(stdout, "writes ok\n");
 163   close(fd);
 164   fd = open("small", O_RDONLY);
 165   if(fd >= 0){
 166     printf(stdout, "open small succeeded ok\n");
 167   } else {
 168     printf(stdout, "error: open small failed!\n");
 169     exit();
 170   }
 171   i = read(fd, buf, 2000);
 172   if(i == 2000){
 173     printf(stdout, "read succeeded ok\n");
 174   } else {
 175     printf(stdout, "read failed\n");
 176     exit();
 177   }
 178   close(fd);
 179 
 180   if(unlink("small") < 0){
 181     printf(stdout, "unlink small failed\n");
 182     exit();
 183   }
 184   printf(stdout, "small file test ok\n");
 185 }
 186 
 187 void
 188 writetest1(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 189 {
 190   int i, fd, n;
 191 
 192   printf(stdout, "big files test\n");
 193 
 194   fd = open("big", O_CREATE|O_RDWR);
 195   if(fd < 0){
 196     printf(stdout, "error: creat big failed!\n");
 197     exit();
 198   }
 199 
 200   for(i = 0; i < MAXFILE; i++){
 201     ((int*)buf)[0] = i;
 202     if(write(fd, buf, 512) != 512){
 203       printf(stdout, "error: write big file failed\n", i);
 204       exit();
 205     }
 206   }
 207 
 208   close(fd);
 209 
 210   fd = open("big", O_RDONLY);
 211   if(fd < 0){
 212     printf(stdout, "error: open big failed!\n");
 213     exit();
 214   }
 215 
 216   n = 0;
 217   for(;;){
 218     i = read(fd, buf, 512);
 219     if(i == 0){
 220       if(n == MAXFILE - 1){
 221         printf(stdout, "read only %d blocks from big", n);
 222         exit();
 223       }
 224       break;
 225     } else if(i != 512){
 226       printf(stdout, "read failed %d\n", i);
 227       exit();
 228     }
 229     if(((int*)buf)[0] != n){
 230       printf(stdout, "read content of block %d is %d\n",
 231              n, ((int*)buf)[0]);
 232       exit();
 233     }
 234     n++;
 235   }
 236   close(fd);
 237   if(unlink("big") < 0){
 238     printf(stdout, "unlink big failed\n");
 239     exit();
 240   }
 241   printf(stdout, "big files ok\n");
 242 }
 243 
 244 void
 245 createtest(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 246 {
 247   int i, fd;
 248 
 249   printf(stdout, "many creates, followed by unlink test\n");
 250 
 251   name[0] = 'a';
 252   name[2] = '\0';
 253   for(i = 0; i < 52; i++){
 254     name[1] = '0' + i;
 255     fd = open(name, O_CREATE|O_RDWR);
 256     close(fd);
 257   }
 258   name[0] = 'a';
 259   name[2] = '\0';
 260   for(i = 0; i < 52; i++){
 261     name[1] = '0' + i;
 262     unlink(name);
 263   }
 264   printf(stdout, "many creates, followed by unlink; ok\n");
 265 }
 266 
 267 void dirtest(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 268 {
 269   printf(stdout, "mkdir test\n");
 270 
 271   if(mkdir("dir0") < 0){
 272     printf(stdout, "mkdir failed\n");
 273     exit();
 274   }
 275 
 276   if(chdir("dir0") < 0){
 277     printf(stdout, "chdir dir0 failed\n");
 278     exit();
 279   }
 280 
 281   if(chdir("..") < 0){
 282     printf(stdout, "chdir .. failed\n");
 283     exit();
 284   }
 285 
 286   if(unlink("dir0") < 0){
 287     printf(stdout, "unlink dir0 failed\n");
 288     exit();
 289   }
 290   printf(stdout, "mkdir test ok\n");
 291 }
 292 
 293 void
 294 exectest(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 295 {
 296   printf(stdout, "exec test\n");
 297   if(exec("echo", echoargv) < 0){
 298     printf(stdout, "exec echo failed\n");
 299     exit();
 300   }
 301 }
 302 
 303 // simple fork and pipe read/write
 304 
 305 void
 306 pipe1(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 307 {
 308   int fds[2], pid;
 309   int seq, i, n, cc, total;
 310 
 311   if(pipe(fds) != 0){
 312     printf(1, "pipe() failed\n");
 313     exit();
 314   }
 315   pid = fork();
 316   seq = 0;
 317   if(pid == 0){
 318     close(fds[0]);
 319     for(n = 0; n < 5; n++){
 320       for(i = 0; i < 1033; i++)
 321         buf[i] = seq++;
 322       if(write(fds[1], buf, 1033) != 1033){
 323         printf(1, "pipe1 oops 1\n");
 324         exit();
 325       }
 326     }
 327     exit();
 328   } else if(pid > 0){
 329     close(fds[1]);
 330     total = 0;
 331     cc = 1;
 332     while((n = read(fds[0], buf, cc)) > 0){
 333       for(i = 0; i < n; i++){
 334         if((buf[i] & 0xff) != (seq++ & 0xff)){
 335           printf(1, "pipe1 oops 2\n");
 336           return;
 337         }
 338       }
 339       total += n;
 340       cc = cc * 2;
 341       if(cc > sizeof(buf))
 342         cc = sizeof(buf);
 343     }
 344     if(total != 5 * 1033){
 345       printf(1, "pipe1 oops 3 total %d\n", total);
 346       exit();
 347     }
 348     close(fds[0]);
 349     wait();
 350   } else {
 351     printf(1, "fork() failed\n");
 352     exit();
 353   }
 354   printf(1, "pipe1 ok\n");
 355 }
 356 
 357 // meant to be run w/ at most two CPUs
 358 void
 359 preempt(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 360 {
 361   int pid1, pid2, pid3;
 362   int pfds[2];
 363 
 364   printf(1, "preempt: ");
 365   pid1 = fork();
 366   if(pid1 == 0)
 367     for(;;)
 368       ;
 369 
 370   pid2 = fork();
 371   if(pid2 == 0)
 372     for(;;)
 373       ;
 374 
 375   pipe(pfds);
 376   pid3 = fork();
 377   if(pid3 == 0){
 378     close(pfds[0]);
 379     if(write(pfds[1], "x", 1) != 1)
 380       printf(1, "preempt write error");
 381     close(pfds[1]);
 382     for(;;)
 383       ;
 384   }
 385 
 386   close(pfds[1]);
 387   if(read(pfds[0], buf, sizeof(buf)) != 1){
 388     printf(1, "preempt read error");
 389     return;
 390   }
 391   close(pfds[0]);
 392   printf(1, "kill... ");
 393   kill(pid1);
 394   kill(pid2);
 395   kill(pid3);
 396   printf(1, "wait... ");
 397   wait();
 398   wait();
 399   wait();
 400   printf(1, "preempt ok\n");
 401 }
 402 
 403 // try to find any races between exit and wait
 404 void
 405 exitwait(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 406 {
 407   int i, pid;
 408 
 409   for(i = 0; i < 100; i++){
 410     pid = fork();
 411     if(pid < 0){
 412       printf(1, "fork failed\n");
 413       return;
 414     }
 415     if(pid){
 416       if(wait() != pid){
 417         printf(1, "wait wrong pid\n");
 418         return;
 419       }
 420     } else {
 421       exit();
 422     }
 423   }
 424   printf(1, "exitwait ok\n");
 425 }
 426 
 427 void
 428 mem(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 429 {
 430   void *m1, *m2;
 431   int pid, ppid;
 432 
 433   printf(1, "mem test\n");
 434   ppid = getpid();
 435   if((pid = fork()) == 0){
 436     m1 = 0;
 437     while((m2 = malloc(10001)) != 0){
 438       *(char**)m2 = m1;
 439       m1 = m2;
 440     }
 441     while(m1){
 442       m2 = *(char**)m1;
 443       free(m1);
 444       m1 = m2;
 445     }
 446     m1 = malloc(1024*20);
 447     if(m1 == 0){
 448       printf(1, "couldn't allocate mem?!!\n");
 449       kill(ppid);
 450       exit();
 451     }
 452     free(m1);
 453     printf(1, "mem ok\n");
 454     exit();
 455   } else {
 456     wait();
 457   }
 458 }
 459 
 460 // More file system tests
 461 
 462 // two processes write to the same file descriptor
 463 // is the offset shared? does inode locking work?
 464 void
 465 sharedfd(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 466 {
 467   int fd, pid, i, n, nc, np;
 468   char buf[10];
 469 
 470   printf(1, "sharedfd test\n");
 471 
 472   unlink("sharedfd");
 473   fd = open("sharedfd", O_CREATE|O_RDWR);
 474   if(fd < 0){
 475     printf(1, "fstests: cannot open sharedfd for writing");
 476     return;
 477   }
 478   pid = fork();
 479   memset(buf, pid==0?'c':'p', sizeof(buf));
 480   for(i = 0; i < 1000; i++){
 481     if(write(fd, buf, sizeof(buf)) != sizeof(buf)){
 482       printf(1, "fstests: write sharedfd failed\n");
 483       break;
 484     }
 485   }
 486   if(pid == 0)
 487     exit();
 488   else
 489     wait();
 490   close(fd);
 491   fd = open("sharedfd", 0);
 492   if(fd < 0){
 493     printf(1, "fstests: cannot open sharedfd for reading\n");
 494     return;
 495   }
 496   nc = np = 0;
 497   while((n = read(fd, buf, sizeof(buf))) > 0){
 498     for(i = 0; i < sizeof(buf); i++){
 499       if(buf[i] == 'c')
 500         nc++;
 501       if(buf[i] == 'p')
 502         np++;
 503     }
 504   }
 505   close(fd);
 506   unlink("sharedfd");
 507   if(nc == 10000 && np == 10000){
 508     printf(1, "sharedfd ok\n");
 509   } else {
 510     printf(1, "sharedfd oops %d %d\n", nc, np);
 511     exit();
 512   }
 513 }
 514 
 515 // four processes write different files at the same
 516 // time, to test block allocation.
 517 void
 518 fourfiles(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 519 {
 520   int fd, pid, i, j, n, total, pi;
 521   char *names[] = { "f0", "f1", "f2", "f3" };
 522   char *fname;
 523 
 524   printf(1, "fourfiles test\n");
 525 
 526   for(pi = 0; pi < 4; pi++){
 527     fname = names[pi];
 528     unlink(fname);
 529 
 530     pid = fork();
 531     if(pid < 0){
 532       printf(1, "fork failed\n");
 533       exit();
 534     }
 535 
 536     if(pid == 0){
 537       fd = open(fname, O_CREATE | O_RDWR);
 538       if(fd < 0){
 539         printf(1, "create failed\n");
 540         exit();
 541       }
 542 
 543       memset(buf, '0'+pi, 512);
 544       for(i = 0; i < 12; i++){
 545         if((n = write(fd, buf, 500)) != 500){
 546           printf(1, "write failed %d\n", n);
 547           exit();
 548         }
 549       }
 550       exit();
 551     }
 552   }
 553 
 554   for(pi = 0; pi < 4; pi++){
 555     wait();
 556   }
 557 
 558   for(i = 0; i < 2; i++){
 559     fname = names[i];
 560     fd = open(fname, 0);
 561     total = 0;
 562     while((n = read(fd, buf, sizeof(buf))) > 0){
 563       for(j = 0; j < n; j++){
 564         if(buf[j] != '0'+i){
 565           printf(1, "wrong char\n");
 566           exit();
 567         }
 568       }
 569       total += n;
 570     }
 571     close(fd);
 572     if(total != 12*500){
 573       printf(1, "wrong length %d\n", total);
 574       exit();
 575     }
 576     unlink(fname);
 577   }
 578 
 579   printf(1, "fourfiles ok\n");
 580 }
 581 
 582 // four processes create and delete different files in same directory
 583 void
 584 createdelete(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 585 {
 586   enum { N = 20 };
 587   int pid, i, fd, pi;
 588   char name[32];
 589 
 590   printf(1, "createdelete test\n");
 591 
 592   for(pi = 0; pi < 4; pi++){
 593     pid = fork();
 594     if(pid < 0){
 595       printf(1, "fork failed\n");
 596       exit();
 597     }
 598 
 599     if(pid == 0){
 600       name[0] = 'p' + pi;
 601       name[2] = '\0';
 602       for(i = 0; i < N; i++){
 603         name[1] = '0' + i;
 604         fd = open(name, O_CREATE | O_RDWR);
 605         if(fd < 0){
 606           printf(1, "create failed\n");
 607           exit();
 608         }
 609         close(fd);
 610         if(i > 0 && (i % 2 ) == 0){
 611           name[1] = '0' + (i / 2);
 612           if(unlink(name) < 0){
 613             printf(1, "unlink failed\n");
 614             exit();
 615           }
 616         }
 617       }
 618       exit();
 619     }
 620   }
 621 
 622   for(pi = 0; pi < 4; pi++){
 623     wait();
 624   }
 625 
 626   name[0] = name[1] = name[2] = 0;
 627   for(i = 0; i < N; i++){
 628     for(pi = 0; pi < 4; pi++){
 629       name[0] = 'p' + pi;
 630       name[1] = '0' + i;
 631       fd = open(name, 0);
 632       if((i == 0 || i >= N/2) && fd < 0){
 633         printf(1, "oops createdelete %s didn't exist\n", name);
 634         exit();
 635       } else if((i >= 1 && i < N/2) && fd >= 0){
 636         printf(1, "oops createdelete %s did exist\n", name);
 637         exit();
 638       }
 639       if(fd >= 0)
 640         close(fd);
 641     }
 642   }
 643 
 644   for(i = 0; i < N; i++){
 645     for(pi = 0; pi < 4; pi++){
 646       name[0] = 'p' + i;
 647       name[1] = '0' + i;
 648       unlink(name);
 649     }
 650   }
 651 
 652   printf(1, "createdelete ok\n");
 653 }
 654 
 655 // can I unlink a file and still read it?
 656 void
 657 unlinkread(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 658 {
 659   int fd, fd1;
 660 
 661   printf(1, "unlinkread test\n");
 662   fd = open("unlinkread", O_CREATE | O_RDWR);
 663   if(fd < 0){
 664     printf(1, "create unlinkread failed\n");
 665     exit();
 666   }
 667   write(fd, "hello", 5);
 668   close(fd);
 669 
 670   fd = open("unlinkread", O_RDWR);
 671   if(fd < 0){
 672     printf(1, "open unlinkread failed\n");
 673     exit();
 674   }
 675   if(unlink("unlinkread") != 0){
 676     printf(1, "unlink unlinkread failed\n");
 677     exit();
 678   }
 679 
 680   fd1 = open("unlinkread", O_CREATE | O_RDWR);
 681   write(fd1, "yyy", 3);
 682   close(fd1);
 683 
 684   if(read(fd, buf, sizeof(buf)) != 5){
 685     printf(1, "unlinkread read failed");
 686     exit();
 687   }
 688   if(buf[0] != 'h'){
 689     printf(1, "unlinkread wrong data\n");
 690     exit();
 691   }
 692   if(write(fd, buf, 10) != 10){
 693     printf(1, "unlinkread write failed\n");
 694     exit();
 695   }
 696   close(fd);
 697   unlink("unlinkread");
 698   printf(1, "unlinkread ok\n");
 699 }
 700 
 701 void
 702 linktest(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 703 {
 704   int fd;
 705 
 706   printf(1, "linktest\n");
 707 
 708   unlink("lf1");
 709   unlink("lf2");
 710 
 711   fd = open("lf1", O_CREATE|O_RDWR);
 712   if(fd < 0){
 713     printf(1, "create lf1 failed\n");
 714     exit();
 715   }
 716   if(write(fd, "hello", 5) != 5){
 717     printf(1, "write lf1 failed\n");
 718     exit();
 719   }
 720   close(fd);
 721 
 722   if(link("lf1", "lf2") < 0){
 723     printf(1, "link lf1 lf2 failed\n");
 724     exit();
 725   }
 726   unlink("lf1");
 727 
 728   if(open("lf1", 0) >= 0){
 729     printf(1, "unlinked lf1 but it is still there!\n");
 730     exit();
 731   }
 732 
 733   fd = open("lf2", 0);
 734   if(fd < 0){
 735     printf(1, "open lf2 failed\n");
 736     exit();
 737   }
 738   if(read(fd, buf, sizeof(buf)) != 5){
 739     printf(1, "read lf2 failed\n");
 740     exit();
 741   }
 742   close(fd);
 743 
 744   if(link("lf2", "lf2") >= 0){
 745     printf(1, "link lf2 lf2 succeeded! oops\n");
 746     exit();
 747   }
 748 
 749   unlink("lf2");
 750   if(link("lf2", "lf1") >= 0){
 751     printf(1, "link non-existant succeeded! oops\n");
 752     exit();
 753   }
 754 
 755   if(link(".", "lf1") >= 0){
 756     printf(1, "link . lf1 succeeded! oops\n");
 757     exit();
 758   }
 759 
 760   printf(1, "linktest ok\n");
 761 }
 762 
 763 // test concurrent create/link/unlink of the same file
 764 void
 765 concreate(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 766 {
 767   char file[3];
 768   int i, pid, n, fd;
 769   char fa[40];
 770   struct {
 771     ushort inum;
 772     char name[14];
 773   } de;
 774 
 775   printf(1, "concreate test\n");
 776   file[0] = 'C';
 777   file[2] = '\0';
 778   for(i = 0; i < 40; i++){
 779     file[1] = '0' + i;
 780     unlink(file);
 781     pid = fork();
 782     if(pid && (i % 3) == 1){
 783       link("C0", file);
 784     } else if(pid == 0 && (i % 5) == 1){
 785       link("C0", file);
 786     } else {
 787       fd = open(file, O_CREATE | O_RDWR);
 788       if(fd < 0){
 789         printf(1, "concreate create %s failed\n", file);
 790         exit();
 791       }
 792       close(fd);
 793     }
 794     if(pid == 0)
 795       exit();
 796     else
 797       wait();
 798   }
 799 
 800   memset(fa, 0, sizeof(fa));
 801   fd = open(".", 0);
 802   n = 0;
 803   while(read(fd, &de, sizeof(de)) > 0){
 804     if(de.inum == 0)
 805       continue;
 806     if(de.name[0] == 'C' && de.name[2] == '\0'){
 807       i = de.name[1] - '0';
 808       if(i < 0 || i >= sizeof(fa)){
 809         printf(1, "concreate weird file %s\n", de.name);
 810         exit();
 811       }
 812       if(fa[i]){
 813         printf(1, "concreate duplicate file %s\n", de.name);
 814         exit();
 815       }
 816       fa[i] = 1;
 817       n++;
 818     }
 819   }
 820   close(fd);
 821 
 822   if(n != 40){
 823     printf(1, "concreate not enough files in directory listing\n");
 824     exit();
 825   }
 826 
 827   for(i = 0; i < 40; i++){
 828     file[1] = '0' + i;
 829     pid = fork();
 830     if(pid < 0){
 831       printf(1, "fork failed\n");
 832       exit();
 833     }
 834     if(((i % 3) == 0 && pid == 0) ||
 835        ((i % 3) == 1 && pid != 0)){
 836       close(open(file, 0));
 837       close(open(file, 0));
 838       close(open(file, 0));
 839       close(open(file, 0));
 840     } else {
 841       unlink(file);
 842       unlink(file);
 843       unlink(file);
 844       unlink(file);
 845     }
 846     if(pid == 0)
 847       exit();
 848     else
 849       wait();
 850   }
 851 
 852   printf(1, "concreate ok\n");
 853 }
 854 
 855 // another concurrent link/unlink/create test,
 856 // to look for deadlocks.
 857 void
 858 linkunlink()
     /* [previous][next][first][last][top][bottom][index][help]  */
 859 {
 860   int pid, i;
 861 
 862   printf(1, "linkunlink test\n");
 863 
 864   unlink("x");
 865   pid = fork();
 866   if(pid < 0){
 867     printf(1, "fork failed\n");
 868     exit();
 869   }
 870 
 871   unsigned int x = (pid ? 1 : 97);
 872   for(i = 0; i < 100; i++){
 873     x = x * 1103515245 + 12345;
 874     if((x % 3) == 0){
 875       close(open("x", O_RDWR | O_CREATE));
 876     } else if((x % 3) == 1){
 877       link("cat", "x");
 878     } else {
 879       unlink("x");
 880     }
 881   }
 882 
 883   if(pid)
 884     wait();
 885   else
 886     exit();
 887 
 888   printf(1, "linkunlink ok\n");
 889 }
 890 
 891 // directory that uses indirect blocks
 892 void
 893 bigdir(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 894 {
 895   int i, fd;
 896   char name[10];
 897 
 898   printf(1, "bigdir test\n");
 899   unlink("bd");
 900 
 901   fd = open("bd", O_CREATE);
 902   if(fd < 0){
 903     printf(1, "bigdir create failed\n");
 904     exit();
 905   }
 906   close(fd);
 907 
 908   for(i = 0; i < 500; i++){
 909     name[0] = 'x';
 910     name[1] = '0' + (i / 64);
 911     name[2] = '0' + (i % 64);
 912     name[3] = '\0';
 913     if(link("bd", name) != 0){
 914       printf(1, "bigdir link failed\n");
 915       exit();
 916     }
 917   }
 918 
 919   unlink("bd");
 920   for(i = 0; i < 500; i++){
 921     name[0] = 'x';
 922     name[1] = '0' + (i / 64);
 923     name[2] = '0' + (i % 64);
 924     name[3] = '\0';
 925     if(unlink(name) != 0){
 926       printf(1, "bigdir unlink failed");
 927       exit();
 928     }
 929   }
 930 
 931   printf(1, "bigdir ok\n");
 932 }
 933 
 934 void
 935 subdir(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 936 {
 937   int fd, cc;
 938 
 939   printf(1, "subdir test\n");
 940 
 941   unlink("ff");
 942   if(mkdir("dd") != 0){
 943     printf(1, "subdir mkdir dd failed\n");
 944     exit();
 945   }
 946 
 947   fd = open("dd/ff", O_CREATE | O_RDWR);
 948   if(fd < 0){
 949     printf(1, "create dd/ff failed\n");
 950     exit();
 951   }
 952   write(fd, "ff", 2);
 953   close(fd);
 954 
 955   if(unlink("dd") >= 0){
 956     printf(1, "unlink dd (non-empty dir) succeeded!\n");
 957     exit();
 958   }
 959 
 960   if(mkdir("/dd/dd") != 0){
 961     printf(1, "subdir mkdir dd/dd failed\n");
 962     exit();
 963   }
 964 
 965   fd = open("dd/dd/ff", O_CREATE | O_RDWR);
 966   if(fd < 0){
 967     printf(1, "create dd/dd/ff failed\n");
 968     exit();
 969   }
 970   write(fd, "FF", 2);
 971   close(fd);
 972 
 973   fd = open("dd/dd/../ff", 0);
 974   if(fd < 0){
 975     printf(1, "open dd/dd/../ff failed\n");
 976     exit();
 977   }
 978   cc = read(fd, buf, sizeof(buf));
 979   if(cc != 2 || buf[0] != 'f'){
 980     printf(1, "dd/dd/../ff wrong content\n");
 981     exit();
 982   }
 983   close(fd);
 984 
 985   if(link("dd/dd/ff", "dd/dd/ffff") != 0){
 986     printf(1, "link dd/dd/ff dd/dd/ffff failed\n");
 987     exit();
 988   }
 989 
 990   if(unlink("dd/dd/ff") != 0){
 991     printf(1, "unlink dd/dd/ff failed\n");
 992     exit();
 993   }
 994   if(open("dd/dd/ff", O_RDONLY) >= 0){
 995     printf(1, "open (unlinked) dd/dd/ff succeeded\n");
 996     exit();
 997   }
 998 
 999   if(chdir("dd") != 0){
1000     printf(1, "chdir dd failed\n");
1001     exit();
1002   }
1003   if(chdir("dd/../../dd") != 0){
1004     printf(1, "chdir dd/../../dd failed\n");
1005     exit();
1006   }
1007   if(chdir("dd/../../../dd") != 0){
1008     printf(1, "chdir dd/../../dd failed\n");
1009     exit();
1010   }
1011   if(chdir("./..") != 0){
1012     printf(1, "chdir ./.. failed\n");
1013     exit();
1014   }
1015 
1016   fd = open("dd/dd/ffff", 0);
1017   if(fd < 0){
1018     printf(1, "open dd/dd/ffff failed\n");
1019     exit();
1020   }
1021   if(read(fd, buf, sizeof(buf)) != 2){
1022     printf(1, "read dd/dd/ffff wrong len\n");
1023     exit();
1024   }
1025   close(fd);
1026 
1027   if(open("dd/dd/ff", O_RDONLY) >= 0){
1028     printf(1, "open (unlinked) dd/dd/ff succeeded!\n");
1029     exit();
1030   }
1031 
1032   if(open("dd/ff/ff", O_CREATE|O_RDWR) >= 0){
1033     printf(1, "create dd/ff/ff succeeded!\n");
1034     exit();
1035   }
1036   if(open("dd/xx/ff", O_CREATE|O_RDWR) >= 0){
1037     printf(1, "create dd/xx/ff succeeded!\n");
1038     exit();
1039   }
1040   if(open("dd", O_CREATE) >= 0){
1041     printf(1, "create dd succeeded!\n");
1042     exit();
1043   }
1044   if(open("dd", O_RDWR) >= 0){
1045     printf(1, "open dd rdwr succeeded!\n");
1046     exit();
1047   }
1048   if(open("dd", O_WRONLY) >= 0){
1049     printf(1, "open dd wronly succeeded!\n");
1050     exit();
1051   }
1052   if(link("dd/ff/ff", "dd/dd/xx") == 0){
1053     printf(1, "link dd/ff/ff dd/dd/xx succeeded!\n");
1054     exit();
1055   }
1056   if(link("dd/xx/ff", "dd/dd/xx") == 0){
1057     printf(1, "link dd/xx/ff dd/dd/xx succeeded!\n");
1058     exit();
1059   }
1060   if(link("dd/ff", "dd/dd/ffff") == 0){
1061     printf(1, "link dd/ff dd/dd/ffff succeeded!\n");
1062     exit();
1063   }
1064   if(mkdir("dd/ff/ff") == 0){
1065     printf(1, "mkdir dd/ff/ff succeeded!\n");
1066     exit();
1067   }
1068   if(mkdir("dd/xx/ff") == 0){
1069     printf(1, "mkdir dd/xx/ff succeeded!\n");
1070     exit();
1071   }
1072   if(mkdir("dd/dd/ffff") == 0){
1073     printf(1, "mkdir dd/dd/ffff succeeded!\n");
1074     exit();
1075   }
1076   if(unlink("dd/xx/ff") == 0){
1077     printf(1, "unlink dd/xx/ff succeeded!\n");
1078     exit();
1079   }
1080   if(unlink("dd/ff/ff") == 0){
1081     printf(1, "unlink dd/ff/ff succeeded!\n");
1082     exit();
1083   }
1084   if(chdir("dd/ff") == 0){
1085     printf(1, "chdir dd/ff succeeded!\n");
1086     exit();
1087   }
1088   if(chdir("dd/xx") == 0){
1089     printf(1, "chdir dd/xx succeeded!\n");
1090     exit();
1091   }
1092 
1093   if(unlink("dd/dd/ffff") != 0){
1094     printf(1, "unlink dd/dd/ff failed\n");
1095     exit();
1096   }
1097   if(unlink("dd/ff") != 0){
1098     printf(1, "unlink dd/ff failed\n");
1099     exit();
1100   }
1101   if(unlink("dd") == 0){
1102     printf(1, "unlink non-empty dd succeeded!\n");
1103     exit();
1104   }
1105   if(unlink("dd/dd") < 0){
1106     printf(1, "unlink dd/dd failed\n");
1107     exit();
1108   }
1109   if(unlink("dd") < 0){
1110     printf(1, "unlink dd failed\n");
1111     exit();
1112   }
1113 
1114   printf(1, "subdir ok\n");
1115 }
1116 
1117 // test writes that are larger than the log.
1118 void
1119 bigwrite(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1120 {
1121   int fd, sz;
1122 
1123   printf(1, "bigwrite test\n");
1124 
1125   unlink("bigwrite");
1126   for(sz = 499; sz < 12*512; sz += 471){
1127     fd = open("bigwrite", O_CREATE | O_RDWR);
1128     if(fd < 0){
1129       printf(1, "cannot create bigwrite\n");
1130       exit();
1131     }
1132     int i;
1133     for(i = 0; i < 2; i++){
1134       int cc = write(fd, buf, sz);
1135       if(cc != sz){
1136         printf(1, "write(%d) ret %d\n", sz, cc);
1137         exit();
1138       }
1139     }
1140     close(fd);
1141     unlink("bigwrite");
1142   }
1143 
1144   printf(1, "bigwrite ok\n");
1145 }
1146 
1147 void
1148 bigfile(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1149 {
1150   int fd, i, total, cc;
1151 
1152   printf(1, "bigfile test\n");
1153 
1154   unlink("bigfile");
1155   fd = open("bigfile", O_CREATE | O_RDWR);
1156   if(fd < 0){
1157     printf(1, "cannot create bigfile");
1158     exit();
1159   }
1160   for(i = 0; i < 20; i++){
1161     memset(buf, i, 600);
1162     if(write(fd, buf, 600) != 600){
1163       printf(1, "write bigfile failed\n");
1164       exit();
1165     }
1166   }
1167   close(fd);
1168 
1169   fd = open("bigfile", 0);
1170   if(fd < 0){
1171     printf(1, "cannot open bigfile\n");
1172     exit();
1173   }
1174   total = 0;
1175   for(i = 0; ; i++){
1176     cc = read(fd, buf, 300);
1177     if(cc < 0){
1178       printf(1, "read bigfile failed\n");
1179       exit();
1180     }
1181     if(cc == 0)
1182       break;
1183     if(cc != 300){
1184       printf(1, "short read bigfile\n");
1185       exit();
1186     }
1187     if(buf[0] != i/2 || buf[299] != i/2){
1188       printf(1, "read bigfile wrong data\n");
1189       exit();
1190     }
1191     total += cc;
1192   }
1193   close(fd);
1194   if(total != 20*600){
1195     printf(1, "read bigfile wrong total\n");
1196     exit();
1197   }
1198   unlink("bigfile");
1199 
1200   printf(1, "bigfile test ok\n");
1201 }
1202 
1203 void
1204 fourteen(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1205 {
1206   int fd;
1207 
1208   // DIRSIZ is 14.
1209   printf(1, "fourteen test\n");
1210 
1211   if(mkdir("12345678901234") != 0){
1212     printf(1, "mkdir 12345678901234 failed\n");
1213     exit();
1214   }
1215   if(mkdir("12345678901234/123456789012345") != 0){
1216     printf(1, "mkdir 12345678901234/123456789012345 failed\n");
1217     exit();
1218   }
1219   fd = open("123456789012345/123456789012345/123456789012345", O_CREATE);
1220   if(fd < 0){
1221     printf(1, "create 123456789012345/123456789012345/123456789012345 failed\n");
1222     exit();
1223   }
1224   close(fd);
1225   fd = open("12345678901234/12345678901234/12345678901234", 0);
1226   if(fd < 0){
1227     printf(1, "open 12345678901234/12345678901234/12345678901234 failed\n");
1228     exit();
1229   }
1230   close(fd);
1231 
1232   if(mkdir("12345678901234/12345678901234") == 0){
1233     printf(1, "mkdir 12345678901234/12345678901234 succeeded!\n");
1234     exit();
1235   }
1236   if(mkdir("123456789012345/12345678901234") == 0){
1237     printf(1, "mkdir 12345678901234/123456789012345 succeeded!\n");
1238     exit();
1239   }
1240 
1241   printf(1, "fourteen ok\n");
1242 }
1243 
1244 void
1245 rmdot(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1246 {
1247   printf(1, "rmdot test\n");
1248   if(mkdir("dots") != 0){
1249     printf(1, "mkdir dots failed\n");
1250     exit();
1251   }
1252   if(chdir("dots") != 0){
1253     printf(1, "chdir dots failed\n");
1254     exit();
1255   }
1256   if(unlink(".") == 0){
1257     printf(1, "rm . worked!\n");
1258     exit();
1259   }
1260   if(unlink("..") == 0){
1261     printf(1, "rm .. worked!\n");
1262     exit();
1263   }
1264   if(chdir("/") != 0){
1265     printf(1, "chdir / failed\n");
1266     exit();
1267   }
1268   if(unlink("dots/.") == 0){
1269     printf(1, "unlink dots/. worked!\n");
1270     exit();
1271   }
1272   if(unlink("dots/..") == 0){
1273     printf(1, "unlink dots/.. worked!\n");
1274     exit();
1275   }
1276   if(unlink("dots") != 0){
1277     printf(1, "unlink dots failed!\n");
1278     exit();
1279   }
1280   printf(1, "rmdot ok\n");
1281 }
1282 
1283 void
1284 dirfile(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1285 {
1286   int fd;
1287 
1288   printf(1, "dir vs file\n");
1289 
1290   fd = open("dirfile", O_CREATE);
1291   if(fd < 0){
1292     printf(1, "create dirfile failed\n");
1293     exit();
1294   }
1295   close(fd);
1296   if(chdir("dirfile") == 0){
1297     printf(1, "chdir dirfile succeeded!\n");
1298     exit();
1299   }
1300   fd = open("dirfile/xx", 0);
1301   if(fd >= 0){
1302     printf(1, "create dirfile/xx succeeded!\n");
1303     exit();
1304   }
1305   fd = open("dirfile/xx", O_CREATE);
1306   if(fd >= 0){
1307     printf(1, "create dirfile/xx succeeded!\n");
1308     exit();
1309   }
1310   if(mkdir("dirfile/xx") == 0){
1311     printf(1, "mkdir dirfile/xx succeeded!\n");
1312     exit();
1313   }
1314   if(unlink("dirfile/xx") == 0){
1315     printf(1, "unlink dirfile/xx succeeded!\n");
1316     exit();
1317   }
1318   if(link("README", "dirfile/xx") == 0){
1319     printf(1, "link to dirfile/xx succeeded!\n");
1320     exit();
1321   }
1322   if(unlink("dirfile") != 0){
1323     printf(1, "unlink dirfile failed!\n");
1324     exit();
1325   }
1326 
1327   fd = open(".", O_RDWR);
1328   if(fd >= 0){
1329     printf(1, "open . for writing succeeded!\n");
1330     exit();
1331   }
1332   fd = open(".", 0);
1333   if(write(fd, "x", 1) > 0){
1334     printf(1, "write . succeeded!\n");
1335     exit();
1336   }
1337   close(fd);
1338 
1339   printf(1, "dir vs file OK\n");
1340 }
1341 
1342 // test that iput() is called at the end of _namei()
1343 void
1344 iref(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1345 {
1346   int i, fd;
1347 
1348   printf(1, "empty file name\n");
1349 
1350   // the 50 is NINODE
1351   for(i = 0; i < 50 + 1; i++){
1352     if(mkdir("irefd") != 0){
1353       printf(1, "mkdir irefd failed\n");
1354       exit();
1355     }
1356     if(chdir("irefd") != 0){
1357       printf(1, "chdir irefd failed\n");
1358       exit();
1359     }
1360 
1361     mkdir("");
1362     link("README", "");
1363     fd = open("", O_CREATE);
1364     if(fd >= 0)
1365       close(fd);
1366     fd = open("xx", O_CREATE);
1367     if(fd >= 0)
1368       close(fd);
1369     unlink("xx");
1370   }
1371 
1372   chdir("/");
1373   printf(1, "empty file name OK\n");
1374 }
1375 
1376 // test that fork fails gracefully
1377 // the forktest binary also does this, but it runs out of proc entries first.
1378 // inside the bigger usertests binary, we run out of memory first.
1379 void
1380 forktest(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1381 {
1382   int n, pid;
1383 
1384   printf(1, "fork test\n");
1385 
1386   for(n=0; n<1000; n++){
1387     pid = fork();
1388     if(pid < 0)
1389       break;
1390     if(pid == 0)
1391       exit();
1392   }
1393 
1394   if(n == 1000){
1395     printf(1, "fork claimed to work 1000 times!\n");
1396     exit();
1397   }
1398 
1399   for(; n > 0; n--){
1400     if(wait() < 0){
1401       printf(1, "wait stopped early\n");
1402       exit();
1403     }
1404   }
1405 
1406   if(wait() != -1){
1407     printf(1, "wait got too many\n");
1408     exit();
1409   }
1410 
1411   printf(1, "fork test OK\n");
1412 }
1413 
1414 void
1415 sbrktest(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1416 {
1417   int fds[2], pid, pids[10], ppid;
1418   char *a, *b, *c, *lastaddr, *oldbrk, *p, scratch;
1419   uint amt;
1420 
1421   printf(stdout, "sbrk test\n");
1422   oldbrk = sbrk(0);
1423 
1424   // can one sbrk() less than a page?
1425   a = sbrk(0);
1426   int i;
1427   for(i = 0; i < 5000; i++){
1428     b = sbrk(1);
1429     if(b != a){
1430       printf(stdout, "sbrk test failed %d %x %x\n", i, a, b);
1431       exit();
1432     }
1433     *b = 1;
1434     a = b + 1;
1435   }
1436   pid = fork();
1437   if(pid < 0){
1438     printf(stdout, "sbrk test fork failed\n");
1439     exit();
1440   }
1441   c = sbrk(1);
1442   c = sbrk(1);
1443   if(c != a + 1){
1444     printf(stdout, "sbrk test failed post-fork\n");
1445     exit();
1446   }
1447   if(pid == 0)
1448     exit();
1449   wait();
1450 
1451   // can one grow address space to something big?
1452 #define BIG (100*1024*1024)
1453   a = sbrk(0);
1454   amt = (BIG) - (uint)a;
1455   p = sbrk(amt);
1456   if (p != a) {
1457     printf(stdout, "sbrk test failed to grow big address space; enough phys mem?\n");
1458     exit();
1459   }
1460   lastaddr = (char*) (BIG-1);
1461   *lastaddr = 99;
1462 
1463   // can one de-allocate?
1464   a = sbrk(0);
1465   c = sbrk(-4096);
1466   if(c == (char*)0xffffffff){
1467     printf(stdout, "sbrk could not deallocate\n");
1468     exit();
1469   }
1470   c = sbrk(0);
1471   if(c != a - 4096){
1472     printf(stdout, "sbrk deallocation produced wrong address, a %x c %x\n", a, c);
1473     exit();
1474   }
1475 
1476   // can one re-allocate that page?
1477   a = sbrk(0);
1478   c = sbrk(4096);
1479   if(c != a || sbrk(0) != a + 4096){
1480     printf(stdout, "sbrk re-allocation failed, a %x c %x\n", a, c);
1481     exit();
1482   }
1483   if(*lastaddr == 99){
1484     // should be zero
1485     printf(stdout, "sbrk de-allocation didn't really deallocate\n");
1486     exit();
1487   }
1488 
1489   a = sbrk(0);
1490   c = sbrk(-(sbrk(0) - oldbrk));
1491   if(c != a){
1492     printf(stdout, "sbrk downsize failed, a %x c %x\n", a, c);
1493     exit();
1494   }
1495 
1496   // can we read the kernel's memory?
1497   for(a = (char*)(KERNBASE); a < (char*) (KERNBASE+2000000); a += 50000){
1498     ppid = getpid();
1499     pid = fork();
1500     if(pid < 0){
1501       printf(stdout, "fork failed\n");
1502       exit();
1503     }
1504     if(pid == 0){
1505       printf(stdout, "oops could read %x = %x\n", a, *a);
1506       kill(ppid);
1507       exit();
1508     }
1509     wait();
1510   }
1511 
1512   // if we run the system out of memory, does it clean up the last
1513   // failed allocation?
1514   if(pipe(fds) != 0){
1515     printf(1, "pipe() failed\n");
1516     exit();
1517   }
1518   for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){
1519     if((pids[i] = fork()) == 0){
1520       // allocate a lot of memory
1521       sbrk(BIG - (uint)sbrk(0));
1522       write(fds[1], "x", 1);
1523       // sit around until killed
1524       for(;;) sleep(1000);
1525     }
1526     if(pids[i] != -1)
1527       read(fds[0], &scratch, 1);
1528   }
1529   // if those failed allocations freed up the pages they did allocate,
1530   // we'll be able to allocate here
1531   c = sbrk(4096);
1532   for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){
1533     if(pids[i] == -1)
1534       continue;
1535     kill(pids[i]);
1536     wait();
1537   }
1538   if(c == (char*)0xffffffff){
1539     printf(stdout, "failed sbrk leaked memory\n");
1540     exit();
1541   }
1542 
1543   if(sbrk(0) > oldbrk)
1544     sbrk(-(sbrk(0) - oldbrk));
1545 
1546   printf(stdout, "sbrk test OK\n");
1547 }
1548 
1549 void
1550 validateint(int *p)
     /* [previous][next][first][last][top][bottom][index][help]  */
1551 {
1552   int res;
1553   asm("mov %%esp, %%ebx\n\t"
1554       "mov %3, %%esp\n\t"
1555       "int %2\n\t"
1556       "mov %%ebx, %%esp" :
1557       "=a" (res) :
1558       "a" (SYS_sleep), "n" (T_SYSCALL), "c" (p) :
1559       "ebx");
1560 }
1561 
1562 void
1563 validatetest(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1564 {
1565   int hi, pid;
1566   uint p;
1567 
1568   printf(stdout, "validate test\n");
1569   hi = 1100*1024;
1570 
1571   for(p = 0; p <= (uint)hi; p += 4096){
1572     if((pid = fork()) == 0){
1573       // try to crash the kernel by passing in a badly placed integer
1574       validateint((int*)p);
1575       exit();
1576     }
1577     sleep(0);
1578     sleep(0);
1579     kill(pid);
1580     wait();
1581 
1582     // try to crash the kernel by passing in a bad string pointer
1583     if(link("nosuchfile", (char*)p) != -1){
1584       printf(stdout, "link should not succeed\n");
1585       exit();
1586     }
1587   }
1588 
1589   printf(stdout, "validate ok\n");
1590 }
1591 
1592 // does unintialized data start out zero?
1593 char uninit[10000];
1594 void
1595 bsstest(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1596 {
1597   int i;
1598 
1599   printf(stdout, "bss test\n");
1600   for(i = 0; i < sizeof(uninit); i++){
1601     if(uninit[i] != '\0'){
1602       printf(stdout, "bss test failed\n");
1603       exit();
1604     }
1605   }
1606   printf(stdout, "bss test ok\n");
1607 }
1608 
1609 // does exec return an error if the arguments
1610 // are larger than a page? or does it write
1611 // below the stack and wreck the instructions/data?
1612 void
1613 bigargtest(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
1614 {
1615   int pid, fd;
1616 
1617   unlink("bigarg-ok");
1618   pid = fork();
1619   if(pid == 0){
1620     static char *args[MAXARG];
1621     int i;
1622     for(i = 0; i < MAXARG-1; i++)
1623       args[i] = "bigargs test: failed\n                                                                                                                                                                                                       ";
1624     args[MAXARG-1] = 0;
1625     printf(stdout, "bigarg test\n");
1626     exec("echo", args);
1627     printf(stdout, "bigarg test ok\n");
1628     fd = open("bigarg-ok", O_CREATE);
1629     close(fd);
1630     exit();
1631   } else if(pid < 0){
1632     printf(stdout, "bigargtest: fork failed\n");
1633     exit();
1634   }
1635   wait();
1636   fd = open("bigarg-ok", 0);
1637   if(fd < 0){
1638     printf(stdout, "bigarg test failed!\n");
1639     exit();
1640   }
1641   close(fd);
1642   unlink("bigarg-ok");
1643 }
1644 
1645 // what happens when the file system runs out of blocks?
1646 // answer: balloc panics, so this test is not useful.
1647 void
1648 fsfull()
     /* [previous][next][first][last][top][bottom][index][help]  */
1649 {
1650   int nfiles;
1651   int fsblocks = 0;
1652 
1653   printf(1, "fsfull test\n");
1654 
1655   for(nfiles = 0; ; nfiles++){
1656     char name[64];
1657     name[0] = 'f';
1658     name[1] = '0' + nfiles / 1000;
1659     name[2] = '0' + (nfiles % 1000) / 100;
1660     name[3] = '0' + (nfiles % 100) / 10;
1661     name[4] = '0' + (nfiles % 10);
1662     name[5] = '\0';
1663     printf(1, "writing %s\n", name);
1664     int fd = open(name, O_CREATE|O_RDWR);
1665     if(fd < 0){
1666       printf(1, "open %s failed\n", name);
1667       break;
1668     }
1669     int total = 0;
1670     while(1){
1671       int cc = write(fd, buf, 512);
1672       if(cc < 512)
1673         break;
1674       total += cc;
1675       fsblocks++;
1676     }
1677     printf(1, "wrote %d bytes\n", total);
1678     close(fd);
1679     if(total == 0)
1680       break;
1681   }
1682 
1683   while(nfiles >= 0){
1684     char name[64];
1685     name[0] = 'f';
1686     name[1] = '0' + nfiles / 1000;
1687     name[2] = '0' + (nfiles % 1000) / 100;
1688     name[3] = '0' + (nfiles % 100) / 10;
1689     name[4] = '0' + (nfiles % 10);
1690     name[5] = '\0';
1691     unlink(name);
1692     nfiles--;
1693   }
1694 
1695   printf(1, "fsfull test finished\n");
1696 }
1697 
1698 void
1699 uio()
     /* [previous][next][first][last][top][bottom][index][help]  */
1700 {
1701   #define RTC_ADDR 0x70
1702   #define RTC_DATA 0x71
1703 
1704   ushort port = 0;
1705   uchar val = 0;
1706   int pid;
1707 
1708   printf(1, "uio test\n");
1709   pid = fork();
1710   if(pid == 0){
1711     port = RTC_ADDR;
1712     val = 0x09;  /* year */
1713     /* http://wiki.osdev.org/Inline_Assembly/Examples */
1714     asm volatile("outb %0,%1"::"a"(val), "d" (port));
1715     port = RTC_DATA;
1716     asm volatile("inb %1,%0" : "=a" (val) : "d" (port));
1717     printf(1, "uio: uio succeeded; test FAILED\n");
1718     exit();
1719   } else if(pid < 0){
1720     printf (1, "fork failed\n");
1721     exit();
1722   }
1723   wait();
1724   printf(1, "uio test done\n");
1725 }
1726 
1727 void argptest()
     /* [previous][next][first][last][top][bottom][index][help]  */
1728 {
1729   int fd;
1730   fd = open("init", O_RDONLY);
1731   if (fd < 0) {
1732     printf(2, "open failed\n");
1733     exit();
1734   }
1735   read(fd, sbrk(0) - 1, -1);
1736   close(fd);
1737   printf(1, "arg test passed\n");
1738 }
1739 
1740 unsigned long randstate = 1;
1741 unsigned int
1742 rand()
     /* [previous][next][first][last][top][bottom][index][help]  */
1743 {
1744   randstate = randstate * 1664525 + 1013904223;
1745   return randstate;
1746 }
1747 
1748 int
1749 main(int argc, char *argv[])
     /* [previous][next][first][last][top][bottom][index][help]  */
1750 {
1751   printf(1, "usertests starting\n");
1752 
1753   if(open("usertests.ran", 0) >= 0){
1754     printf(1, "already ran user tests -- rebuild fs.img\n");
1755     exit();
1756   }
1757   close(open("usertests.ran", O_CREATE));
1758 
1759   argptest();
1760   createdelete();
1761   linkunlink();
1762   concreate();
1763   fourfiles();
1764   sharedfd();
1765 
1766   bigargtest();
1767   bigwrite();
1768   bigargtest();
1769   bsstest();
1770   sbrktest();
1771   validatetest();
1772 
1773   opentest();
1774   writetest();
1775   writetest1();
1776   createtest();
1777 
1778   openiputtest();
1779   exitiputtest();
1780   iputtest();
1781 
1782   mem();
1783   pipe1();
1784   preempt();
1785   exitwait();
1786 
1787   rmdot();
1788   fourteen();
1789   bigfile();
1790   subdir();
1791   linktest();
1792   unlinkread();
1793   dirfile();
1794   iref();
1795   forktest();
1796   bigdir(); // slow
1797 
1798   uio();
1799 
1800   exectest();
1801 
1802   exit();
1803 }

/* [previous][next][first][last][top][bottom][index][help]  */