root/usertests.c
/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- iputtest
 - exitiputtest
 - openiputtest
 - opentest
 - writetest
 - writetest1
 - createtest
 - dirtest
 - exectest
 - pipe1
 - preempt
 - exitwait
 - mem
 - sharedfd
 - fourfiles
 - createdelete
 - unlinkread
 - linktest
 - concreate
 - linkunlink
 - bigdir
 - subdir
 - bigwrite
 - bigfile
 - fourteen
 - rmdot
 - dirfile
 - iref
 - forktest
 - sbrktest
 - validateint
 - validatetest
 - bsstest
 - bigargtest
 - fsfull
 - rand
 - 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)
  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)
  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)
  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)
 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)
 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)
 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)
 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)
 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)
 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)
 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)
 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)
 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)
 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)
 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)
 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)
 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)
 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)
 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)
 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()
 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)
 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)
 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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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()
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 unsigned long randstate = 1;
1699 unsigned int
1700 rand()
1701 {
1702   randstate = randstate * 1664525 + 1013904223;
1703   return randstate;
1704 }
1705 
1706 int
1707 main(int argc, char *argv[])
1708 {
1709   printf(1, "usertests starting\n");
1710 
1711   if(open("usertests.ran", 0) >= 0){
1712     printf(1, "already ran user tests -- rebuild fs.img\n");
1713     exit();
1714   }
1715   close(open("usertests.ran", O_CREATE));
1716 
1717   createdelete();
1718   linkunlink();
1719   concreate();
1720   fourfiles();
1721   sharedfd();
1722 
1723   bigargtest();
1724   bigwrite();
1725   bigargtest();
1726   bsstest();
1727   sbrktest();
1728   validatetest();
1729 
1730   opentest();
1731   writetest();
1732   writetest1();
1733   createtest();
1734 
1735   openiputtest();
1736   exitiputtest();
1737   iputtest();
1738 
1739   mem();
1740   pipe1();
1741   preempt();
1742   exitwait();
1743 
1744   rmdot();
1745   fourteen();
1746   bigfile();
1747   subdir();
1748   linktest();
1749   unlinkread();
1750   dirfile();
1751   iref();
1752   forktest();
1753   bigdir(); // slow
1754   exectest();
1755 
1756   exit();
1757 }