This source file includes following definitions.
- copyin
- copyout
- copyinstr1
- copyinstr2
- copyinstr3
- rwsbrk
- truncate1
- truncate2
- truncate3
- iputtest
- exitiputtest
- openiputtest
- opentest
- writetest
- writebig
- createtest
- dirtest
- exectest
- pipe1
- killstatus
- killzero
- preempt
- exitwait
- reparent
- twochildren
- forkfork
- forkforkfork
- reparent2
- mem
- sharedfd
- fourfiles
- createdelete
- unlinkread
- linktest
- concreate
- linkunlink
- subdir
- bigwrite
- bigfile
- fourteen
- rmdot
- dirfile
- iref
- forktest
- sbrkbasic
- sbrkmuch
- kernmem
- MAXVAplus
- sbrkfail
- sbrkarg
- validatetest
- bsstest
- bigargtest
- fsfull
- argptest
- stacktest
- nowrite
- pgbug
- sbrkbugs
- sbrklast
- sbrk8000
- badarg
- lazy_alloc
- lazy_unmap
- lazy_copy
- lazy_copyinstr
- lazy_sbrk
- partial_write
- unlinkcwd
- bigdir
- manywrites
- badwrite
- execout
- diskfull
- outofinodes
- linkoverflow
- run
- runtests
- countfree
- drivetests
- main
1 #include "kernel/param.h"
2 #include "kernel/types.h"
3 #include "kernel/stat.h"
4 #include "user/user.h"
5 #include "kernel/fs.h"
6 #include "kernel/fcntl.h"
7 #include "kernel/syscall.h"
8 #include "kernel/memlayout.h"
9 #include "kernel/riscv.h"
10
11
12
13
14
15
16
17
18
19
20 #define BUFSZ ((MAXOPBLOCKS + 2) * BSIZE)
21
22 char buf[BUFSZ];
23
24
25
26
27
28
29
30
31
32 void
33 copyin(char *s)
34 {
35 uint64 addrs[] = {0x80000000LL, 0x3fffffe000, 0x3ffffff000, 0x4000000000,
36 0xffffffffffffffff};
37
38 for (int ai = 0; ai < sizeof(addrs) / sizeof(addrs[0]); ai++) {
39 uint64 addr = addrs[ai];
40
41 int fd = open("copyin1", O_CREATE | O_WRONLY);
42 if (fd < 0) {
43 printf("open(copyin1) failed\n");
44 exit(1);
45 }
46 int n = write(fd, (void *)addr, 8192);
47 if (n >= 0) {
48 printf("write(fd, %p, 8192) returned %d, not -1\n", (void *)addr, n);
49 exit(1);
50 }
51 close(fd);
52 unlink("copyin1");
53
54 n = write(1, (char *)addr, 8192);
55 if (n > 0) {
56 printf("write(1, %p, 8192) returned %d, not -1 or 0\n", (void *)addr, n);
57 exit(1);
58 }
59
60 int fds[2];
61 if (pipe(fds) < 0) {
62 printf("pipe() failed\n");
63 exit(1);
64 }
65 n = write(fds[1], (char *)addr, 8192);
66 if (n > 0) {
67 printf("write(pipe, %p, 8192) returned %d, not -1 or 0\n", (void *)addr,
68 n);
69 exit(1);
70 }
71 close(fds[0]);
72 close(fds[1]);
73 }
74 }
75
76
77
78 void
79 copyout(char *s)
80 {
81 uint64 addrs[] = {0LL, 0x80000000LL, 0x3fffffe000,
82 0x3ffffff000, 0x4000000000, 0xffffffffffffffff};
83
84 for (int ai = 0; ai < sizeof(addrs) / sizeof(addrs[0]); ai++) {
85 uint64 addr = addrs[ai];
86
87 int fd = open("README", 0);
88 if (fd < 0) {
89 printf("open(README) failed\n");
90 exit(1);
91 }
92 int n = read(fd, (void *)addr, 8192);
93 if (n > 0) {
94 printf("read(fd, %p, 8192) returned %d, not -1 or 0\n", (void *)addr, n);
95 exit(1);
96 }
97 close(fd);
98
99 int fds[2];
100 if (pipe(fds) < 0) {
101 printf("pipe() failed\n");
102 exit(1);
103 }
104 n = write(fds[1], "x", 1);
105 if (n != 1) {
106 printf("pipe write failed\n");
107 exit(1);
108 }
109 n = read(fds[0], (void *)addr, 8192);
110 if (n > 0) {
111 printf("read(pipe, %p, 8192) returned %d, not -1 or 0\n", (void *)addr,
112 n);
113 exit(1);
114 }
115 close(fds[0]);
116 close(fds[1]);
117 }
118 }
119
120
121 void
122 copyinstr1(char *s)
123 {
124 uint64 addrs[] = {0x80000000LL, 0x3fffffe000, 0x3ffffff000, 0x4000000000,
125 0xffffffffffffffff};
126
127 for (int ai = 0; ai < sizeof(addrs) / sizeof(addrs[0]); ai++) {
128 uint64 addr = addrs[ai];
129
130 int fd = open((char *)addr, O_CREATE | O_WRONLY);
131 if (fd >= 0) {
132 printf("open(%p) returned %d, not -1\n", (void *)addr, fd);
133 exit(1);
134 }
135 }
136 }
137
138
139
140
141 void
142 copyinstr2(char *s)
143 {
144 char b[MAXPATH + 1];
145
146 for (int i = 0; i < MAXPATH; i++)
147 b[i] = 'x';
148 b[MAXPATH] = '\0';
149
150 int ret = unlink(b);
151 if (ret != -1) {
152 printf("unlink(%s) returned %d, not -1\n", b, ret);
153 exit(1);
154 }
155
156 int fd = open(b, O_CREATE | O_WRONLY);
157 if (fd != -1) {
158 printf("open(%s) returned %d, not -1\n", b, fd);
159 exit(1);
160 }
161
162 ret = link(b, b);
163 if (ret != -1) {
164 printf("link(%s, %s) returned %d, not -1\n", b, b, ret);
165 exit(1);
166 }
167
168 char *args[] = {"xx", 0};
169 ret = exec(b, args);
170 if (ret != -1) {
171 printf("exec(%s) returned %d, not -1\n", b, fd);
172 exit(1);
173 }
174
175 int pid = fork();
176 if (pid < 0) {
177 printf("fork failed\n");
178 exit(1);
179 }
180 if (pid == 0) {
181 static char big[PGSIZE + 1];
182 for (int i = 0; i < PGSIZE; i++)
183 big[i] = 'x';
184 big[PGSIZE] = '\0';
185 char *args2[] = {big, big, big, 0};
186 ret = exec("echo", args2);
187 if (ret != -1) {
188 printf("exec(echo, BIG) returned %d, not -1\n", fd);
189 exit(1);
190 }
191 exit(747);
192 }
193
194 int st = 0;
195 wait(&st);
196 if (st != 747) {
197 printf("exec(echo, BIG) succeeded, should have failed\n");
198 exit(1);
199 }
200 }
201
202
203 void
204 copyinstr3(char *s)
205 {
206 sbrk(8192);
207 uint64 top = (uint64)sbrk(0);
208 if ((top % PGSIZE) != 0) {
209 sbrk(PGSIZE - (top % PGSIZE));
210 }
211 top = (uint64)sbrk(0);
212 if (top % PGSIZE) {
213 printf("oops\n");
214 exit(1);
215 }
216
217 char *b = (char *)(top - 1);
218 *b = 'x';
219
220 int ret = unlink(b);
221 if (ret != -1) {
222 printf("unlink(%s) returned %d, not -1\n", b, ret);
223 exit(1);
224 }
225
226 int fd = open(b, O_CREATE | O_WRONLY);
227 if (fd != -1) {
228 printf("open(%s) returned %d, not -1\n", b, fd);
229 exit(1);
230 }
231
232 ret = link(b, b);
233 if (ret != -1) {
234 printf("link(%s, %s) returned %d, not -1\n", b, b, ret);
235 exit(1);
236 }
237
238 char *args[] = {"xx", 0};
239 ret = exec(b, args);
240 if (ret != -1) {
241 printf("exec(%s) returned %d, not -1\n", b, fd);
242 exit(1);
243 }
244 }
245
246
247
248 void
249 rwsbrk(char *s)
250 {
251 int fd, n;
252
253 uint64 a = (uint64)sbrk(8192);
254
255 if (a == (uint64)SBRK_ERROR) {
256 printf("sbrk(rwsbrk) failed\n");
257 exit(1);
258 }
259
260 if (sbrk(-8192) == SBRK_ERROR) {
261 printf("sbrk(rwsbrk) shrink failed\n");
262 exit(1);
263 }
264
265 fd = open("rwsbrk", O_CREATE | O_WRONLY);
266 if (fd < 0) {
267 printf("open(rwsbrk) failed\n");
268 exit(1);
269 }
270 n = write(fd, (void *)(a + PGSIZE), 1024);
271 if (n >= 0) {
272 printf("write(fd, %p, 1024) returned %d, not -1\n", (void *)a + PGSIZE, n);
273 exit(1);
274 }
275 close(fd);
276 unlink("rwsbrk");
277
278 fd = open("README", O_RDONLY);
279 if (fd < 0) {
280 printf("open(README) failed\n");
281 exit(1);
282 }
283 n = read(fd, (void *)(a + PGSIZE), 10);
284 if (n >= 0) {
285 printf("read(fd, %p, 10) returned %d, not -1\n", (void *)a + PGSIZE, n);
286 exit(1);
287 }
288 close(fd);
289
290 exit(0);
291 }
292
293
294 void
295 truncate1(char *s)
296 {
297 char buf[32];
298
299 unlink("truncfile");
300 int fd1 = open("truncfile", O_CREATE | O_WRONLY | O_TRUNC);
301 write(fd1, "abcd", 4);
302 close(fd1);
303
304 int fd2 = open("truncfile", O_RDONLY);
305 int n = read(fd2, buf, sizeof(buf));
306 if (n != 4) {
307 printf("%s: read %d bytes, wanted 4\n", s, n);
308 exit(1);
309 }
310
311 fd1 = open("truncfile", O_WRONLY | O_TRUNC);
312
313 int fd3 = open("truncfile", O_RDONLY);
314 n = read(fd3, buf, sizeof(buf));
315 if (n != 0) {
316 printf("aaa fd3=%d\n", fd3);
317 printf("%s: read %d bytes, wanted 0\n", s, n);
318 exit(1);
319 }
320
321 n = read(fd2, buf, sizeof(buf));
322 if (n != 0) {
323 printf("bbb fd2=%d\n", fd2);
324 printf("%s: read %d bytes, wanted 0\n", s, n);
325 exit(1);
326 }
327
328 write(fd1, "abcdef", 6);
329
330 n = read(fd3, buf, sizeof(buf));
331 if (n != 6) {
332 printf("%s: read %d bytes, wanted 6\n", s, n);
333 exit(1);
334 }
335
336 n = read(fd2, buf, sizeof(buf));
337 if (n != 2) {
338 printf("%s: read %d bytes, wanted 2\n", s, n);
339 exit(1);
340 }
341
342 unlink("truncfile");
343
344 close(fd1);
345 close(fd2);
346 close(fd3);
347 }
348
349
350
351
352
353 void
354 truncate2(char *s)
355 {
356 unlink("truncfile");
357
358 int fd1 = open("truncfile", O_CREATE | O_TRUNC | O_WRONLY);
359 write(fd1, "abcd", 4);
360
361 int fd2 = open("truncfile", O_TRUNC | O_WRONLY);
362
363 int n = write(fd1, "x", 1);
364 if (n != -1) {
365 printf("%s: write returned %d, expected -1\n", s, n);
366 exit(1);
367 }
368
369 unlink("truncfile");
370 close(fd1);
371 close(fd2);
372 }
373
374 void
375 truncate3(char *s)
376 {
377 int pid, xstatus;
378
379 close(open("truncfile", O_CREATE | O_TRUNC | O_WRONLY));
380
381 pid = fork();
382 if (pid < 0) {
383 printf("%s: fork failed\n", s);
384 exit(1);
385 }
386
387 if (pid == 0) {
388 for (int i = 0; i < 100; i++) {
389 char buf[32];
390 int fd = open("truncfile", O_WRONLY);
391 if (fd < 0) {
392 printf("%s: open failed\n", s);
393 exit(1);
394 }
395 int n = write(fd, "1234567890", 10);
396 if (n != 10) {
397 printf("%s: write got %d, expected 10\n", s, n);
398 exit(1);
399 }
400 close(fd);
401 fd = open("truncfile", O_RDONLY);
402 read(fd, buf, sizeof(buf));
403 close(fd);
404 }
405 exit(0);
406 }
407
408 for (int i = 0; i < 150; i++) {
409 int fd = open("truncfile", O_CREATE | O_WRONLY | O_TRUNC);
410 if (fd < 0) {
411 printf("%s: open failed\n", s);
412 exit(1);
413 }
414 int n = write(fd, "xxx", 3);
415 if (n != 3) {
416 printf("%s: write got %d, expected 3\n", s, n);
417 exit(1);
418 }
419 close(fd);
420 }
421
422 wait(&xstatus);
423 unlink("truncfile");
424 exit(xstatus);
425 }
426
427
428 void
429 iputtest(char *s)
430 {
431 if (mkdir("iputdir") < 0) {
432 printf("%s: mkdir failed\n", s);
433 exit(1);
434 }
435 if (chdir("iputdir") < 0) {
436 printf("%s: chdir iputdir failed\n", s);
437 exit(1);
438 }
439 if (unlink("../iputdir") < 0) {
440 printf("%s: unlink ../iputdir failed\n", s);
441 exit(1);
442 }
443 if (chdir("/") < 0) {
444 printf("%s: chdir / failed\n", s);
445 exit(1);
446 }
447 }
448
449
450 void
451 exitiputtest(char *s)
452 {
453 int pid, xstatus;
454
455 pid = fork();
456 if (pid < 0) {
457 printf("%s: fork failed\n", s);
458 exit(1);
459 }
460 if (pid == 0) {
461 if (mkdir("iputdir") < 0) {
462 printf("%s: mkdir failed\n", s);
463 exit(1);
464 }
465 if (chdir("iputdir") < 0) {
466 printf("%s: child chdir failed\n", s);
467 exit(1);
468 }
469 if (unlink("../iputdir") < 0) {
470 printf("%s: unlink ../iputdir failed\n", s);
471 exit(1);
472 }
473 exit(0);
474 }
475 wait(&xstatus);
476 exit(xstatus);
477 }
478
479
480
481
482
483
484
485
486
487
488
489
490 void
491 openiputtest(char *s)
492 {
493 int pid, xstatus;
494
495 if (mkdir("oidir") < 0) {
496 printf("%s: mkdir oidir failed\n", s);
497 exit(1);
498 }
499 pid = fork();
500 if (pid < 0) {
501 printf("%s: fork failed\n", s);
502 exit(1);
503 }
504 if (pid == 0) {
505 int fd = open("oidir", O_RDWR);
506 if (fd >= 0) {
507 printf("%s: open directory for write succeeded\n", s);
508 exit(1);
509 }
510 exit(0);
511 }
512 pause(1);
513 if (unlink("oidir") != 0) {
514 printf("%s: unlink failed\n", s);
515 exit(1);
516 }
517 wait(&xstatus);
518 exit(xstatus);
519 }
520
521
522
523 void
524 opentest(char *s)
525 {
526 int fd;
527
528 fd = open("echo", 0);
529 if (fd < 0) {
530 printf("%s: open echo failed!\n", s);
531 exit(1);
532 }
533 close(fd);
534 fd = open("doesnotexist", 0);
535 if (fd >= 0) {
536 printf("%s: open doesnotexist succeeded!\n", s);
537 exit(1);
538 }
539 }
540
541 void
542 writetest(char *s)
543 {
544 int fd;
545 int i;
546 enum { N = 100, SZ = 10 };
547
548 fd = open("small", O_CREATE | O_RDWR);
549 if (fd < 0) {
550 printf("%s: error: creat small failed!\n", s);
551 exit(1);
552 }
553 for (i = 0; i < N; i++) {
554 if (write(fd, "aaaaaaaaaa", SZ) != SZ) {
555 printf("%s: error: write aa %d new file failed\n", s, i);
556 exit(1);
557 }
558 if (write(fd, "bbbbbbbbbb", SZ) != SZ) {
559 printf("%s: error: write bb %d new file failed\n", s, i);
560 exit(1);
561 }
562 }
563 close(fd);
564 fd = open("small", O_RDONLY);
565 if (fd < 0) {
566 printf("%s: error: open small failed!\n", s);
567 exit(1);
568 }
569 i = read(fd, buf, N * SZ * 2);
570 if (i != N * SZ * 2) {
571 printf("%s: read failed\n", s);
572 exit(1);
573 }
574 close(fd);
575
576 if (unlink("small") < 0) {
577 printf("%s: unlink small failed\n", s);
578 exit(1);
579 }
580 }
581
582 void
583 writebig(char *s)
584 {
585 int i, fd, n;
586
587 fd = open("big", O_CREATE | O_RDWR);
588 if (fd < 0) {
589 printf("%s: error: creat big failed!\n", s);
590 exit(1);
591 }
592
593 for (i = 0; i < MAXFILE; i++) {
594 ((int *)buf)[0] = i;
595 if (write(fd, buf, BSIZE) != BSIZE) {
596 printf("%s: error: write big file failed i=%d\n", s, i);
597 exit(1);
598 }
599 }
600
601 close(fd);
602
603 fd = open("big", O_RDONLY);
604 if (fd < 0) {
605 printf("%s: error: open big failed!\n", s);
606 exit(1);
607 }
608
609 n = 0;
610 for (;;) {
611 i = read(fd, buf, BSIZE);
612 if (i == 0) {
613 if (n != MAXFILE) {
614 printf("%s: read only %d blocks from big", s, n);
615 exit(1);
616 }
617 break;
618 } else if (i != BSIZE) {
619 printf("%s: read failed %d\n", s, i);
620 exit(1);
621 }
622 if (((int *)buf)[0] != n) {
623 printf("%s: read content of block %d is %d\n", s, n, ((int *)buf)[0]);
624 exit(1);
625 }
626 n++;
627 }
628 close(fd);
629 if (unlink("big") < 0) {
630 printf("%s: unlink big failed\n", s);
631 exit(1);
632 }
633 }
634
635
636 void
637 createtest(char *s)
638 {
639 int i, fd;
640 enum { N = 52 };
641
642 char name[3];
643 name[0] = 'a';
644 name[2] = '\0';
645 for (i = 0; i < N; i++) {
646 name[1] = '0' + i;
647 fd = open(name, O_CREATE | O_RDWR);
648 close(fd);
649 }
650 name[0] = 'a';
651 name[2] = '\0';
652 for (i = 0; i < N; i++) {
653 name[1] = '0' + i;
654 unlink(name);
655 }
656 }
657
658 void
659 dirtest(char *s)
660 {
661 if (mkdir("dir0") < 0) {
662 printf("%s: mkdir failed\n", s);
663 exit(1);
664 }
665
666 if (chdir("dir0") < 0) {
667 printf("%s: chdir dir0 failed\n", s);
668 exit(1);
669 }
670
671 if (chdir("..") < 0) {
672 printf("%s: chdir .. failed\n", s);
673 exit(1);
674 }
675
676 if (unlink("dir0") < 0) {
677 printf("%s: unlink dir0 failed\n", s);
678 exit(1);
679 }
680 }
681
682 void
683 exectest(char *s)
684 {
685 int fd, xstatus, pid;
686 char *echoargv[] = {"echo", "OK", 0};
687 char buf[3];
688
689 unlink("echo-ok");
690 pid = fork();
691 if (pid < 0) {
692 printf("%s: fork failed\n", s);
693 exit(1);
694 }
695 if (pid == 0) {
696 int errfd = dup(1);
697 if (errfd < 0) {
698 printf("%s: dup failed\n", s);
699 exit(1);
700 }
701 close(1);
702 fd = open("echo-ok", O_CREATE | O_WRONLY);
703 if (fd < 0) {
704 fprintf(errfd, "%s: create failed\n", s);
705 exit(1);
706 }
707 if (fd != 1) {
708 fprintf(errfd, "%s: wrong fd\n", s);
709 exit(1);
710 }
711 if (exec("echo", echoargv) < 0) {
712 fprintf(errfd, "%s: exec echo failed\n", s);
713 exit(1);
714 }
715
716 }
717 if (wait(&xstatus) != pid) {
718 printf("%s: wait failed!\n", s);
719 }
720 if (xstatus != 0) {
721 printf("%s: nonzero wait status %d\n", s, xstatus);
722 exit(1);
723 }
724
725 fd = open("echo-ok", O_RDONLY);
726 if (fd < 0) {
727 printf("%s: open failed\n", s);
728 exit(1);
729 }
730 if (read(fd, buf, 2) != 2) {
731 printf("%s: read failed\n", s);
732 exit(1);
733 }
734 unlink("echo-ok");
735 if (buf[0] == 'O' && buf[1] == 'K')
736 exit(0);
737 else {
738 printf("%s: wrong output\n", s);
739 exit(1);
740 }
741 }
742
743
744
745 void
746 pipe1(char *s)
747 {
748 int fds[2], pid, xstatus;
749 int seq, i, n, cc, total;
750 enum { N = 5, SZ = 1033 };
751
752 if (pipe(fds) != 0) {
753 printf("%s: pipe() failed\n", s);
754 exit(1);
755 }
756 pid = fork();
757 seq = 0;
758 if (pid == 0) {
759 close(fds[0]);
760 for (n = 0; n < N; n++) {
761 for (i = 0; i < SZ; i++)
762 buf[i] = seq++;
763 if (write(fds[1], buf, SZ) != SZ) {
764 printf("%s: pipe1 oops 1\n", s);
765 exit(1);
766 }
767 }
768 exit(0);
769 } else if (pid > 0) {
770 close(fds[1]);
771 total = 0;
772 cc = 1;
773 while ((n = read(fds[0], buf, cc)) > 0) {
774 for (i = 0; i < n; i++) {
775 if ((buf[i] & 0xff) != (seq++ & 0xff)) {
776 printf("%s: pipe1 oops 2\n", s);
777 return;
778 }
779 }
780 total += n;
781 cc = cc * 2;
782 if (cc > sizeof(buf))
783 cc = sizeof(buf);
784 }
785 if (total != N * SZ) {
786 printf("%s: pipe1 oops 3 total %d\n", s, total);
787 exit(1);
788 }
789 close(fds[0]);
790 wait(&xstatus);
791 exit(xstatus);
792 } else {
793 printf("%s: fork() failed\n", s);
794 exit(1);
795 }
796 }
797
798
799 void
800 killstatus(char *s)
801 {
802 int xst;
803
804 for (int i = 0; i < 100; i++) {
805 int pid1 = fork();
806 if (pid1 < 0) {
807 printf("%s: fork failed\n", s);
808 exit(1);
809 }
810 if (pid1 == 0) {
811 while (1) {
812 getpid();
813 }
814 exit(0);
815 }
816 pause(1);
817 kill(pid1);
818 wait(&xst);
819 if (xst != -1) {
820 printf("%s: status should be -1\n", s);
821 exit(1);
822 }
823 }
824 exit(0);
825 }
826
827
828 void
829 killzero(char *s)
830 {
831 int pid, xst;
832
833 kill(0);
834
835 pid = fork();
836 if (pid < 0) {
837 printf("%s: fork failed\n", s);
838 exit(1);
839 }
840 if (pid == 0) {
841 exit(7);
842 }
843 if (wait(&xst) != pid) {
844 printf("%s: wait wrong pid\n", s);
845 exit(1);
846 }
847 if (xst != 7) {
848 printf("%s: child exited with status %d, expected 7\n", s, xst);
849 exit(1);
850 }
851 exit(0);
852 }
853
854
855 void
856 preempt(char *s)
857 {
858 int pid1, pid2, pid3;
859 int pfds[2];
860
861 pid1 = fork();
862 if (pid1 < 0) {
863 printf("%s: fork failed", s);
864 exit(1);
865 }
866 if (pid1 == 0)
867 for (;;)
868 ;
869
870 pid2 = fork();
871 if (pid2 < 0) {
872 printf("%s: fork failed\n", s);
873 exit(1);
874 }
875 if (pid2 == 0)
876 for (;;)
877 ;
878
879 pipe(pfds);
880 pid3 = fork();
881 if (pid3 < 0) {
882 printf("%s: fork failed\n", s);
883 exit(1);
884 }
885 if (pid3 == 0) {
886 close(pfds[0]);
887 if (write(pfds[1], "x", 1) != 1)
888 printf("%s: preempt write error", s);
889 close(pfds[1]);
890 for (;;)
891 ;
892 }
893
894 close(pfds[1]);
895 if (read(pfds[0], buf, sizeof(buf)) != 1) {
896 printf("%s: preempt read error", s);
897 return;
898 }
899 close(pfds[0]);
900 printf("kill... ");
901 kill(pid1);
902 kill(pid2);
903 kill(pid3);
904 printf("wait... ");
905 wait(0);
906 wait(0);
907 wait(0);
908 }
909
910
911 void
912 exitwait(char *s)
913 {
914 int i, pid;
915
916 for (i = 0; i < 100; i++) {
917 pid = fork();
918 if (pid < 0) {
919 printf("%s: fork failed\n", s);
920 exit(1);
921 }
922 if (pid) {
923 int xstate;
924 if (wait(&xstate) != pid) {
925 printf("%s: wait wrong pid\n", s);
926 exit(1);
927 }
928 if (i != xstate) {
929 printf("%s: wait wrong exit status\n", s);
930 exit(1);
931 }
932 } else {
933 exit(i);
934 }
935 }
936 }
937
938
939
940
941 void
942 reparent(char *s)
943 {
944 int master_pid = getpid();
945 for (int i = 0; i < 200; i++) {
946 int pid = fork();
947 if (pid < 0) {
948 printf("%s: fork failed\n", s);
949 exit(1);
950 }
951 if (pid) {
952 if (wait(0) != pid) {
953 printf("%s: wait wrong pid\n", s);
954 exit(1);
955 }
956 } else {
957 int pid2 = fork();
958 if (pid2 < 0) {
959 kill(master_pid);
960 exit(1);
961 }
962 exit(0);
963 }
964 }
965 exit(0);
966 }
967
968
969 void
970 twochildren(char *s)
971 {
972 for (int i = 0; i < 1000; i++) {
973 int pid1 = fork();
974 if (pid1 < 0) {
975 printf("%s: fork failed\n", s);
976 exit(1);
977 }
978 if (pid1 == 0) {
979 exit(0);
980 } else {
981 int pid2 = fork();
982 if (pid2 < 0) {
983 printf("%s: fork failed\n", s);
984 exit(1);
985 }
986 if (pid2 == 0) {
987 exit(0);
988 } else {
989 wait(0);
990 wait(0);
991 }
992 }
993 }
994 }
995
996
997 void
998 forkfork(char *s)
999 {
1000 enum { N = 2 };
1001
1002 for (int i = 0; i < N; i++) {
1003 int pid = fork();
1004 if (pid < 0) {
1005 printf("%s: fork failed", s);
1006 exit(1);
1007 }
1008 if (pid == 0) {
1009 for (int j = 0; j < 200; j++) {
1010 int pid1 = fork();
1011 if (pid1 < 0) {
1012 exit(1);
1013 }
1014 if (pid1 == 0) {
1015 exit(0);
1016 }
1017 wait(0);
1018 }
1019 exit(0);
1020 }
1021 }
1022
1023 int xstatus;
1024 for (int i = 0; i < N; i++) {
1025 wait(&xstatus);
1026 if (xstatus != 0) {
1027 printf("%s: fork in child failed", s);
1028 exit(1);
1029 }
1030 }
1031 }
1032
1033 void
1034 forkforkfork(char *s)
1035 {
1036 unlink("stopforking");
1037
1038 int pid = fork();
1039 if (pid < 0) {
1040 printf("%s: fork failed", s);
1041 exit(1);
1042 }
1043 if (pid == 0) {
1044 while (1) {
1045 int fd = open("stopforking", 0);
1046 if (fd >= 0) {
1047 exit(0);
1048 }
1049 if (fork() < 0) {
1050 close(open("stopforking", O_CREATE | O_RDWR));
1051 }
1052 }
1053
1054 exit(0);
1055 }
1056
1057 pause(20);
1058 close(open("stopforking", O_CREATE | O_RDWR));
1059 wait(0);
1060 pause(10);
1061 }
1062
1063
1064
1065
1066
1067
1068 void
1069 reparent2(char *s)
1070 {
1071 for (int i = 0; i < 800; i++) {
1072 int pid1 = fork();
1073 if (pid1 < 0) {
1074 printf("fork failed\n");
1075 exit(1);
1076 }
1077 if (pid1 == 0) {
1078 fork();
1079 fork();
1080 exit(0);
1081 }
1082 wait(0);
1083 }
1084
1085 exit(0);
1086 }
1087
1088
1089 void
1090 mem(char *s)
1091 {
1092 void *m1, *m2;
1093 int pid;
1094
1095 if ((pid = fork()) == 0) {
1096 m1 = 0;
1097 while ((m2 = malloc(10001)) != 0) {
1098 *(char **)m2 = m1;
1099 m1 = m2;
1100 }
1101 while (m1) {
1102 m2 = *(char **)m1;
1103 free(m1);
1104 m1 = m2;
1105 }
1106 m1 = malloc(1024 * 20);
1107 if (m1 == 0) {
1108 printf("%s: couldn't allocate mem?!!\n", s);
1109 exit(1);
1110 }
1111 free(m1);
1112 exit(0);
1113 } else {
1114 int xstatus;
1115 wait(&xstatus);
1116 if (xstatus == -1) {
1117
1118
1119 exit(0);
1120 }
1121 exit(xstatus);
1122 }
1123 }
1124
1125
1126
1127
1128
1129 void
1130 sharedfd(char *s)
1131 {
1132 int fd, pid, i, n, nc, np;
1133 enum { N = 1000, SZ = 10 };
1134 char buf[SZ];
1135
1136 unlink("sharedfd");
1137 fd = open("sharedfd", O_CREATE | O_RDWR);
1138 if (fd < 0) {
1139 printf("%s: cannot open sharedfd for writing", s);
1140 exit(1);
1141 }
1142 pid = fork();
1143 memset(buf, pid == 0 ? 'c' : 'p', sizeof(buf));
1144 for (i = 0; i < N; i++) {
1145 if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
1146 printf("%s: write sharedfd failed\n", s);
1147 exit(1);
1148 }
1149 }
1150 if (pid == 0) {
1151 exit(0);
1152 } else {
1153 int xstatus;
1154 wait(&xstatus);
1155 if (xstatus != 0)
1156 exit(xstatus);
1157 }
1158
1159 close(fd);
1160 fd = open("sharedfd", 0);
1161 if (fd < 0) {
1162 printf("%s: cannot open sharedfd for reading\n", s);
1163 exit(1);
1164 }
1165 nc = np = 0;
1166 while ((n = read(fd, buf, sizeof(buf))) > 0) {
1167 for (i = 0; i < sizeof(buf); i++) {
1168 if (buf[i] == 'c')
1169 nc++;
1170 if (buf[i] == 'p')
1171 np++;
1172 }
1173 }
1174 close(fd);
1175 unlink("sharedfd");
1176 if (nc == N * SZ && np == N * SZ) {
1177 exit(0);
1178 } else {
1179 printf("%s: nc/np test fails\n", s);
1180 exit(1);
1181 }
1182 }
1183
1184
1185
1186 void
1187 fourfiles(char *s)
1188 {
1189 int fd, pid, i, j, n, total, pi;
1190 char *names[] = {"f0", "f1", "f2", "f3"};
1191 char *fname;
1192 enum { N = 12, NCHILD = 4, SZ = 500 };
1193
1194 for (pi = 0; pi < NCHILD; pi++) {
1195 fname = names[pi];
1196 unlink(fname);
1197
1198 pid = fork();
1199 if (pid < 0) {
1200 printf("%s: fork failed\n", s);
1201 exit(1);
1202 }
1203
1204 if (pid == 0) {
1205 fd = open(fname, O_CREATE | O_RDWR);
1206 if (fd < 0) {
1207 printf("%s: create failed\n", s);
1208 exit(1);
1209 }
1210
1211 memset(buf, '0' + pi, SZ);
1212 for (i = 0; i < N; i++) {
1213 if ((n = write(fd, buf, SZ)) != SZ) {
1214 printf("write failed %d\n", n);
1215 exit(1);
1216 }
1217 }
1218 exit(0);
1219 }
1220 }
1221
1222 int xstatus;
1223 for (pi = 0; pi < NCHILD; pi++) {
1224 wait(&xstatus);
1225 if (xstatus != 0)
1226 exit(xstatus);
1227 }
1228
1229 for (i = 0; i < NCHILD; i++) {
1230 fname = names[i];
1231 fd = open(fname, 0);
1232 total = 0;
1233 while ((n = read(fd, buf, sizeof(buf))) > 0) {
1234 for (j = 0; j < n; j++) {
1235 if (buf[j] != '0' + i) {
1236 printf("%s: wrong char\n", s);
1237 exit(1);
1238 }
1239 }
1240 total += n;
1241 }
1242 close(fd);
1243 if (total != N * SZ) {
1244 printf("wrong length %d\n", total);
1245 exit(1);
1246 }
1247 unlink(fname);
1248 }
1249 }
1250
1251
1252 void
1253 createdelete(char *s)
1254 {
1255 enum { N = 20, NCHILD = 4 };
1256 int pid, i, fd, pi;
1257 char name[32];
1258
1259 for (pi = 0; pi < NCHILD; pi++) {
1260 pid = fork();
1261 if (pid < 0) {
1262 printf("%s: fork failed\n", s);
1263 exit(1);
1264 }
1265
1266 if (pid == 0) {
1267 name[0] = 'p' + pi;
1268 name[2] = '\0';
1269 for (i = 0; i < N; i++) {
1270 name[1] = '0' + i;
1271 fd = open(name, O_CREATE | O_RDWR);
1272 if (fd < 0) {
1273 printf("%s: create failed\n", s);
1274 exit(1);
1275 }
1276 close(fd);
1277 if (i > 0 && (i % 2) == 0) {
1278 name[1] = '0' + (i / 2);
1279 if (unlink(name) < 0) {
1280 printf("%s: unlink failed\n", s);
1281 exit(1);
1282 }
1283 }
1284 }
1285 exit(0);
1286 }
1287 }
1288
1289 int xstatus;
1290 for (pi = 0; pi < NCHILD; pi++) {
1291 wait(&xstatus);
1292 if (xstatus != 0)
1293 exit(1);
1294 }
1295
1296 name[0] = name[1] = name[2] = 0;
1297 for (i = 0; i < N; i++) {
1298 for (pi = 0; pi < NCHILD; pi++) {
1299 name[0] = 'p' + pi;
1300 name[1] = '0' + i;
1301 fd = open(name, 0);
1302 if ((i == 0 || i >= N / 2) && fd < 0) {
1303 printf("%s: oops createdelete %s didn't exist\n", s, name);
1304 exit(1);
1305 } else if ((i >= 1 && i < N / 2) && fd >= 0) {
1306 printf("%s: oops createdelete %s did exist\n", s, name);
1307 exit(1);
1308 }
1309 if (fd >= 0)
1310 close(fd);
1311 }
1312 }
1313
1314 for (i = 0; i < N; i++) {
1315 for (pi = 0; pi < NCHILD; pi++) {
1316 name[0] = 'p' + pi;
1317 name[1] = '0' + i;
1318 unlink(name);
1319 }
1320 }
1321 }
1322
1323
1324 void
1325 unlinkread(char *s)
1326 {
1327 enum { SZ = 5 };
1328 int fd, fd1;
1329
1330 fd = open("unlinkread", O_CREATE | O_RDWR);
1331 if (fd < 0) {
1332 printf("%s: create unlinkread failed\n", s);
1333 exit(1);
1334 }
1335 write(fd, "hello", SZ);
1336 close(fd);
1337
1338 fd = open("unlinkread", O_RDWR);
1339 if (fd < 0) {
1340 printf("%s: open unlinkread failed\n", s);
1341 exit(1);
1342 }
1343 if (unlink("unlinkread") != 0) {
1344 printf("%s: unlink unlinkread failed\n", s);
1345 exit(1);
1346 }
1347
1348 fd1 = open("unlinkread", O_CREATE | O_RDWR);
1349 write(fd1, "yyy", 3);
1350 close(fd1);
1351
1352 if (read(fd, buf, sizeof(buf)) != SZ) {
1353 printf("%s: unlinkread read failed", s);
1354 exit(1);
1355 }
1356 if (buf[0] != 'h') {
1357 printf("%s: unlinkread wrong data\n", s);
1358 exit(1);
1359 }
1360 if (write(fd, buf, 10) != 10) {
1361 printf("%s: unlinkread write failed\n", s);
1362 exit(1);
1363 }
1364 close(fd);
1365 unlink("unlinkread");
1366 }
1367
1368 void
1369 linktest(char *s)
1370 {
1371 enum { SZ = 5 };
1372 int fd;
1373
1374 unlink("lf1");
1375 unlink("lf2");
1376
1377 fd = open("lf1", O_CREATE | O_RDWR);
1378 if (fd < 0) {
1379 printf("%s: create lf1 failed\n", s);
1380 exit(1);
1381 }
1382 if (write(fd, "hello", SZ) != SZ) {
1383 printf("%s: write lf1 failed\n", s);
1384 exit(1);
1385 }
1386 close(fd);
1387
1388 if (link("lf1", "lf2") < 0) {
1389 printf("%s: link lf1 lf2 failed\n", s);
1390 exit(1);
1391 }
1392 unlink("lf1");
1393
1394 if (open("lf1", 0) >= 0) {
1395 printf("%s: unlinked lf1 but it is still there!\n", s);
1396 exit(1);
1397 }
1398
1399 fd = open("lf2", 0);
1400 if (fd < 0) {
1401 printf("%s: open lf2 failed\n", s);
1402 exit(1);
1403 }
1404 if (read(fd, buf, sizeof(buf)) != SZ) {
1405 printf("%s: read lf2 failed\n", s);
1406 exit(1);
1407 }
1408 close(fd);
1409
1410 if (link("lf2", "lf2") >= 0) {
1411 printf("%s: link lf2 lf2 succeeded! oops\n", s);
1412 exit(1);
1413 }
1414
1415 unlink("lf2");
1416 if (link("lf2", "lf1") >= 0) {
1417 printf("%s: link non-existent succeeded! oops\n", s);
1418 exit(1);
1419 }
1420
1421 if (link(".", "lf1") >= 0) {
1422 printf("%s: link . lf1 succeeded! oops\n", s);
1423 exit(1);
1424 }
1425 }
1426
1427
1428 void
1429 concreate(char *s)
1430 {
1431 enum { N = 40 };
1432 char file[3];
1433 int i, pid, n, fd;
1434 char fa[N];
1435 struct {
1436 ushort inum;
1437 char name[DIRSIZ];
1438 } de;
1439
1440 file[0] = 'C';
1441 file[2] = '\0';
1442 for (i = 0; i < N; i++) {
1443 file[1] = '0' + i;
1444 unlink(file);
1445 pid = fork();
1446 if (pid && (i % 3) == 1) {
1447 link("C0", file);
1448 } else if (pid == 0 && (i % 5) == 1) {
1449 link("C0", file);
1450 } else {
1451 fd = open(file, O_CREATE | O_RDWR);
1452 if (fd < 0) {
1453 printf("concreate create %s failed\n", file);
1454 exit(1);
1455 }
1456 close(fd);
1457 }
1458 if (pid == 0) {
1459 exit(0);
1460 } else {
1461 int xstatus;
1462 wait(&xstatus);
1463 if (xstatus != 0)
1464 exit(1);
1465 }
1466 }
1467
1468 memset(fa, 0, sizeof(fa));
1469 fd = open(".", 0);
1470 n = 0;
1471 while (read(fd, &de, sizeof(de)) > 0) {
1472 if (de.inum == 0)
1473 continue;
1474 if (de.name[0] == 'C' && de.name[2] == '\0') {
1475 i = de.name[1] - '0';
1476 if (i < 0 || i >= sizeof(fa)) {
1477 printf("%s: concreate weird file %s\n", s, de.name);
1478 exit(1);
1479 }
1480 if (fa[i]) {
1481 printf("%s: concreate duplicate file %s\n", s, de.name);
1482 exit(1);
1483 }
1484 fa[i] = 1;
1485 n++;
1486 }
1487 }
1488 close(fd);
1489
1490 if (n != N) {
1491 printf("%s: concreate not enough files in directory listing\n", s);
1492 exit(1);
1493 }
1494
1495 for (i = 0; i < N; i++) {
1496 file[1] = '0' + i;
1497 pid = fork();
1498 if (pid < 0) {
1499 printf("%s: fork failed\n", s);
1500 exit(1);
1501 }
1502 if (((i % 3) == 0 && pid == 0) || ((i % 3) == 1 && pid != 0)) {
1503 close(open(file, 0));
1504 close(open(file, 0));
1505 close(open(file, 0));
1506 close(open(file, 0));
1507 close(open(file, 0));
1508 close(open(file, 0));
1509 } else {
1510 unlink(file);
1511 unlink(file);
1512 unlink(file);
1513 unlink(file);
1514 unlink(file);
1515 unlink(file);
1516 }
1517 if (pid == 0)
1518 exit(0);
1519 else
1520 wait(0);
1521 }
1522 }
1523
1524
1525
1526 void
1527 linkunlink(char *s)
1528 {
1529 int pid, i;
1530
1531 unlink("x");
1532 pid = fork();
1533 if (pid < 0) {
1534 printf("%s: fork failed\n", s);
1535 exit(1);
1536 }
1537
1538 unsigned int x = (pid ? 1 : 97);
1539 for (i = 0; i < 100; i++) {
1540 x = x * 1103515245 + 12345;
1541 if ((x % 3) == 0) {
1542 close(open("x", O_RDWR | O_CREATE));
1543 } else if ((x % 3) == 1) {
1544 link("cat", "x");
1545 } else {
1546 unlink("x");
1547 }
1548 }
1549
1550 if (pid)
1551 wait(0);
1552 else
1553 exit(0);
1554 }
1555
1556 void
1557 subdir(char *s)
1558 {
1559 int fd, cc;
1560
1561 unlink("ff");
1562 if (mkdir("dd") != 0) {
1563 printf("%s: mkdir dd failed\n", s);
1564 exit(1);
1565 }
1566
1567 fd = open("dd/ff", O_CREATE | O_RDWR);
1568 if (fd < 0) {
1569 printf("%s: create dd/ff failed\n", s);
1570 exit(1);
1571 }
1572 write(fd, "ff", 2);
1573 close(fd);
1574
1575 if (unlink("dd") >= 0) {
1576 printf("%s: unlink dd (non-empty dir) succeeded!\n", s);
1577 exit(1);
1578 }
1579
1580 if (mkdir("/dd/dd") != 0) {
1581 printf("%s: subdir mkdir dd/dd failed\n", s);
1582 exit(1);
1583 }
1584
1585 fd = open("dd/dd/ff", O_CREATE | O_RDWR);
1586 if (fd < 0) {
1587 printf("%s: create dd/dd/ff failed\n", s);
1588 exit(1);
1589 }
1590 write(fd, "FF", 2);
1591 close(fd);
1592
1593 fd = open("dd/dd/../ff", 0);
1594 if (fd < 0) {
1595 printf("%s: open dd/dd/../ff failed\n", s);
1596 exit(1);
1597 }
1598 cc = read(fd, buf, sizeof(buf));
1599 if (cc != 2 || buf[0] != 'f') {
1600 printf("%s: dd/dd/../ff wrong content\n", s);
1601 exit(1);
1602 }
1603 close(fd);
1604
1605 if (link("dd/dd/ff", "dd/dd/ffff") != 0) {
1606 printf("%s: link dd/dd/ff dd/dd/ffff failed\n", s);
1607 exit(1);
1608 }
1609
1610 if (unlink("dd/dd/ff") != 0) {
1611 printf("%s: unlink dd/dd/ff failed\n", s);
1612 exit(1);
1613 }
1614 if (open("dd/dd/ff", O_RDONLY) >= 0) {
1615 printf("%s: open (unlinked) dd/dd/ff succeeded\n", s);
1616 exit(1);
1617 }
1618
1619 if (chdir("dd") != 0) {
1620 printf("%s: chdir dd failed\n", s);
1621 exit(1);
1622 }
1623 if (chdir("dd/../../dd") != 0) {
1624 printf("%s: chdir dd/../../dd failed\n", s);
1625 exit(1);
1626 }
1627 if (chdir("dd/../../../dd") != 0) {
1628 printf("%s: chdir dd/../../../dd failed\n", s);
1629 exit(1);
1630 }
1631 if (chdir("./..") != 0) {
1632 printf("%s: chdir ./.. failed\n", s);
1633 exit(1);
1634 }
1635
1636 fd = open("dd/dd/ffff", 0);
1637 if (fd < 0) {
1638 printf("%s: open dd/dd/ffff failed\n", s);
1639 exit(1);
1640 }
1641 if (read(fd, buf, sizeof(buf)) != 2) {
1642 printf("%s: read dd/dd/ffff wrong len\n", s);
1643 exit(1);
1644 }
1645 close(fd);
1646
1647 if (open("dd/dd/ff", O_RDONLY) >= 0) {
1648 printf("%s: open (unlinked) dd/dd/ff succeeded!\n", s);
1649 exit(1);
1650 }
1651
1652 if (open("dd/ff/ff", O_CREATE | O_RDWR) >= 0) {
1653 printf("%s: create dd/ff/ff succeeded!\n", s);
1654 exit(1);
1655 }
1656 if (open("dd/xx/ff", O_CREATE | O_RDWR) >= 0) {
1657 printf("%s: create dd/xx/ff succeeded!\n", s);
1658 exit(1);
1659 }
1660 if (open("dd", O_CREATE) >= 0) {
1661 printf("%s: create dd succeeded!\n", s);
1662 exit(1);
1663 }
1664 if (open("dd", O_RDWR) >= 0) {
1665 printf("%s: open dd rdwr succeeded!\n", s);
1666 exit(1);
1667 }
1668 if (open("dd", O_WRONLY) >= 0) {
1669 printf("%s: open dd wronly succeeded!\n", s);
1670 exit(1);
1671 }
1672 if (link("dd/ff/ff", "dd/dd/xx") == 0) {
1673 printf("%s: link dd/ff/ff dd/dd/xx succeeded!\n", s);
1674 exit(1);
1675 }
1676 if (link("dd/xx/ff", "dd/dd/xx") == 0) {
1677 printf("%s: link dd/xx/ff dd/dd/xx succeeded!\n", s);
1678 exit(1);
1679 }
1680 if (link("dd/ff", "dd/dd/ffff") == 0) {
1681 printf("%s: link dd/ff dd/dd/ffff succeeded!\n", s);
1682 exit(1);
1683 }
1684 if (mkdir("dd/ff/ff") == 0) {
1685 printf("%s: mkdir dd/ff/ff succeeded!\n", s);
1686 exit(1);
1687 }
1688 if (mkdir("dd/xx/ff") == 0) {
1689 printf("%s: mkdir dd/xx/ff succeeded!\n", s);
1690 exit(1);
1691 }
1692 if (mkdir("dd/dd/ffff") == 0) {
1693 printf("%s: mkdir dd/dd/ffff succeeded!\n", s);
1694 exit(1);
1695 }
1696 if (unlink("dd/xx/ff") == 0) {
1697 printf("%s: unlink dd/xx/ff succeeded!\n", s);
1698 exit(1);
1699 }
1700 if (unlink("dd/ff/ff") == 0) {
1701 printf("%s: unlink dd/ff/ff succeeded!\n", s);
1702 exit(1);
1703 }
1704 if (chdir("dd/ff") == 0) {
1705 printf("%s: chdir dd/ff succeeded!\n", s);
1706 exit(1);
1707 }
1708 if (chdir("dd/xx") == 0) {
1709 printf("%s: chdir dd/xx succeeded!\n", s);
1710 exit(1);
1711 }
1712
1713 if (unlink("dd/dd/ffff") != 0) {
1714 printf("%s: unlink dd/dd/ff failed\n", s);
1715 exit(1);
1716 }
1717 if (unlink("dd/ff") != 0) {
1718 printf("%s: unlink dd/ff failed\n", s);
1719 exit(1);
1720 }
1721 if (unlink("dd") == 0) {
1722 printf("%s: unlink non-empty dd succeeded!\n", s);
1723 exit(1);
1724 }
1725 if (unlink("dd/dd") < 0) {
1726 printf("%s: unlink dd/dd failed\n", s);
1727 exit(1);
1728 }
1729 if (unlink("dd") < 0) {
1730 printf("%s: unlink dd failed\n", s);
1731 exit(1);
1732 }
1733 }
1734
1735
1736 void
1737 bigwrite(char *s)
1738 {
1739 int fd, sz;
1740
1741 unlink("bigwrite");
1742 for (sz = 499; sz < (MAXOPBLOCKS + 2) * BSIZE; sz += 471) {
1743 fd = open("bigwrite", O_CREATE | O_RDWR);
1744 if (fd < 0) {
1745 printf("%s: cannot create bigwrite\n", s);
1746 exit(1);
1747 }
1748 int i;
1749 for (i = 0; i < 2; i++) {
1750 int cc = write(fd, buf, sz);
1751 if (cc != sz) {
1752 printf("%s: write(%d) ret %d\n", s, sz, cc);
1753 exit(1);
1754 }
1755 }
1756 close(fd);
1757 unlink("bigwrite");
1758 }
1759 }
1760
1761 void
1762 bigfile(char *s)
1763 {
1764 enum { N = 20, SZ = 600 };
1765 int fd, i, total, cc;
1766
1767 unlink("bigfile.dat");
1768 fd = open("bigfile.dat", O_CREATE | O_RDWR);
1769 if (fd < 0) {
1770 printf("%s: cannot create bigfile", s);
1771 exit(1);
1772 }
1773 for (i = 0; i < N; i++) {
1774 memset(buf, i, SZ);
1775 if (write(fd, buf, SZ) != SZ) {
1776 printf("%s: write bigfile failed\n", s);
1777 exit(1);
1778 }
1779 }
1780 close(fd);
1781
1782 fd = open("bigfile.dat", 0);
1783 if (fd < 0) {
1784 printf("%s: cannot open bigfile\n", s);
1785 exit(1);
1786 }
1787 total = 0;
1788 for (i = 0;; i++) {
1789 cc = read(fd, buf, SZ / 2);
1790 if (cc < 0) {
1791 printf("%s: read bigfile failed\n", s);
1792 exit(1);
1793 }
1794 if (cc == 0)
1795 break;
1796 if (cc != SZ / 2) {
1797 printf("%s: short read bigfile\n", s);
1798 exit(1);
1799 }
1800 if (buf[0] != i / 2 || buf[SZ / 2 - 1] != i / 2) {
1801 printf("%s: read bigfile wrong data\n", s);
1802 exit(1);
1803 }
1804 total += cc;
1805 }
1806 close(fd);
1807 if (total != N * SZ) {
1808 printf("%s: read bigfile wrong total\n", s);
1809 exit(1);
1810 }
1811 unlink("bigfile.dat");
1812 }
1813
1814 void
1815 fourteen(char *s)
1816 {
1817 int fd;
1818
1819
1820
1821 if (mkdir("12345678901234") != 0) {
1822 printf("%s: mkdir 12345678901234 failed\n", s);
1823 exit(1);
1824 }
1825 if (mkdir("12345678901234/123456789012345") != 0) {
1826 printf("%s: mkdir 12345678901234/123456789012345 failed\n", s);
1827 exit(1);
1828 }
1829 fd = open("123456789012345/123456789012345/123456789012345", O_CREATE);
1830 if (fd < 0) {
1831 printf(
1832 "%s: create 123456789012345/123456789012345/123456789012345 failed\n", s);
1833 exit(1);
1834 }
1835 close(fd);
1836 fd = open("12345678901234/12345678901234/12345678901234", 0);
1837 if (fd < 0) {
1838 printf("%s: open 12345678901234/12345678901234/12345678901234 failed\n", s);
1839 exit(1);
1840 }
1841 close(fd);
1842
1843 if (mkdir("12345678901234/12345678901234") == 0) {
1844 printf("%s: mkdir 12345678901234/12345678901234 succeeded!\n", s);
1845 exit(1);
1846 }
1847 if (mkdir("123456789012345/12345678901234") == 0) {
1848 printf("%s: mkdir 12345678901234/123456789012345 succeeded!\n", s);
1849 exit(1);
1850 }
1851
1852
1853 unlink("123456789012345/12345678901234");
1854 unlink("12345678901234/12345678901234");
1855 unlink("12345678901234/12345678901234/12345678901234");
1856 unlink("123456789012345/123456789012345/123456789012345");
1857 unlink("12345678901234/123456789012345");
1858 unlink("12345678901234");
1859 }
1860
1861 void
1862 rmdot(char *s)
1863 {
1864 if (mkdir("dots") != 0) {
1865 printf("%s: mkdir dots failed\n", s);
1866 exit(1);
1867 }
1868 if (chdir("dots") != 0) {
1869 printf("%s: chdir dots failed\n", s);
1870 exit(1);
1871 }
1872 if (unlink(".") == 0) {
1873 printf("%s: rm . worked!\n", s);
1874 exit(1);
1875 }
1876 if (unlink("..") == 0) {
1877 printf("%s: rm .. worked!\n", s);
1878 exit(1);
1879 }
1880 if (chdir("/") != 0) {
1881 printf("%s: chdir / failed\n", s);
1882 exit(1);
1883 }
1884 if (unlink("dots/.") == 0) {
1885 printf("%s: unlink dots/. worked!\n", s);
1886 exit(1);
1887 }
1888 if (unlink("dots/..") == 0) {
1889 printf("%s: unlink dots/.. worked!\n", s);
1890 exit(1);
1891 }
1892 if (unlink("dots") != 0) {
1893 printf("%s: unlink dots failed!\n", s);
1894 exit(1);
1895 }
1896 }
1897
1898 void
1899 dirfile(char *s)
1900 {
1901 int fd;
1902
1903 fd = open("dirfile", O_CREATE);
1904 if (fd < 0) {
1905 printf("%s: create dirfile failed\n", s);
1906 exit(1);
1907 }
1908 close(fd);
1909 if (chdir("dirfile") == 0) {
1910 printf("%s: chdir dirfile succeeded!\n", s);
1911 exit(1);
1912 }
1913 fd = open("dirfile/xx", 0);
1914 if (fd >= 0) {
1915 printf("%s: create dirfile/xx succeeded!\n", s);
1916 exit(1);
1917 }
1918 fd = open("dirfile/xx", O_CREATE);
1919 if (fd >= 0) {
1920 printf("%s: create dirfile/xx succeeded!\n", s);
1921 exit(1);
1922 }
1923 if (mkdir("dirfile/xx") == 0) {
1924 printf("%s: mkdir dirfile/xx succeeded!\n", s);
1925 exit(1);
1926 }
1927 if (unlink("dirfile/xx") == 0) {
1928 printf("%s: unlink dirfile/xx succeeded!\n", s);
1929 exit(1);
1930 }
1931 if (link("README", "dirfile/xx") == 0) {
1932 printf("%s: link to dirfile/xx succeeded!\n", s);
1933 exit(1);
1934 }
1935 if (unlink("dirfile") != 0) {
1936 printf("%s: unlink dirfile failed!\n", s);
1937 exit(1);
1938 }
1939
1940 fd = open(".", O_RDWR);
1941 if (fd >= 0) {
1942 printf("%s: open . for writing succeeded!\n", s);
1943 exit(1);
1944 }
1945 fd = open(".", 0);
1946 if (write(fd, "x", 1) > 0) {
1947 printf("%s: write . succeeded!\n", s);
1948 exit(1);
1949 }
1950 close(fd);
1951 }
1952
1953
1954
1955 void
1956 iref(char *s)
1957 {
1958 int i, fd;
1959
1960 for (i = 0; i < NINODE + 1; i++) {
1961 if (mkdir("irefd") != 0) {
1962 printf("%s: mkdir irefd failed\n", s);
1963 exit(1);
1964 }
1965 if (chdir("irefd") != 0) {
1966 printf("%s: chdir irefd failed\n", s);
1967 exit(1);
1968 }
1969
1970 mkdir("");
1971 link("README", "");
1972 fd = open("", O_CREATE);
1973 if (fd >= 0)
1974 close(fd);
1975 fd = open("xx", O_CREATE);
1976 if (fd >= 0)
1977 close(fd);
1978 unlink("xx");
1979 }
1980
1981
1982 for (i = 0; i < NINODE + 1; i++) {
1983 chdir("..");
1984 unlink("irefd");
1985 }
1986
1987 chdir("/");
1988 }
1989
1990
1991
1992
1993 void
1994 forktest(char *s)
1995 {
1996 enum { N = 1000 };
1997 int n, pid;
1998
1999 for (n = 0; n < N; n++) {
2000 pid = fork();
2001 if (pid < 0)
2002 break;
2003 if (pid == 0)
2004 exit(0);
2005 }
2006
2007 if (n == 0) {
2008 printf("%s: no fork at all!\n", s);
2009 exit(1);
2010 }
2011
2012 if (n == N) {
2013 printf("%s: fork claimed to work 1000 times!\n", s);
2014 exit(1);
2015 }
2016
2017 for (; n > 0; n--) {
2018 if (wait(0) < 0) {
2019 printf("%s: wait stopped early\n", s);
2020 exit(1);
2021 }
2022 }
2023
2024 if (wait(0) != -1) {
2025 printf("%s: wait got too many\n", s);
2026 exit(1);
2027 }
2028 }
2029
2030 void
2031 sbrkbasic(char *s)
2032 {
2033 enum { TOOMUCH = 1024 * 1024 * 1024 };
2034 int i, pid, xstatus;
2035 char *c, *a, *b;
2036
2037
2038 pid = fork();
2039 if (pid < 0) {
2040 printf("fork failed in sbrkbasic\n");
2041 exit(1);
2042 }
2043 if (pid == 0) {
2044 a = sbrk(TOOMUCH);
2045 if (a == (char *)SBRK_ERROR) {
2046
2047 exit(0);
2048 }
2049
2050 for (b = a; b < a + TOOMUCH; b += PGSIZE) {
2051 *b = 99;
2052 }
2053
2054
2055
2056
2057 exit(1);
2058 }
2059
2060 wait(&xstatus);
2061 if (xstatus == 1) {
2062 printf("%s: too much memory allocated!\n", s);
2063 exit(1);
2064 }
2065
2066
2067 a = sbrk(0);
2068 for (i = 0; i < 5000; i++) {
2069 b = sbrk(1);
2070 if (b != a) {
2071 printf("%s: sbrk test failed %d %p %p\n", s, i, a, b);
2072 exit(1);
2073 }
2074 *b = 1;
2075 a = b + 1;
2076 }
2077 pid = fork();
2078 if (pid < 0) {
2079 printf("%s: sbrk test fork failed\n", s);
2080 exit(1);
2081 }
2082 c = sbrk(1);
2083 c = sbrk(1);
2084 if (c != a + 1) {
2085 printf("%s: sbrk test failed post-fork\n", s);
2086 exit(1);
2087 }
2088 if (pid == 0)
2089 exit(0);
2090 wait(&xstatus);
2091 exit(xstatus);
2092 }
2093
2094 void
2095 sbrkmuch(char *s)
2096 {
2097 enum { BIG = 100 * 1024 * 1024 };
2098 char *c, *oldbrk, *a, *lastaddr, *p;
2099 uint64 amt;
2100
2101 oldbrk = sbrk(0);
2102
2103
2104 a = sbrk(0);
2105 amt = BIG - (uint64)a;
2106 p = sbrk(amt);
2107 if (p != a) {
2108 printf("%s: sbrk test failed to grow big address space; enough phys mem?\n",
2109 s);
2110 exit(1);
2111 }
2112
2113 lastaddr = (char *)(BIG - 1);
2114 *lastaddr = 99;
2115
2116
2117 a = sbrk(0);
2118 c = sbrk(-PGSIZE);
2119 if (c == (char *)SBRK_ERROR) {
2120 printf("%s: sbrk could not deallocate\n", s);
2121 exit(1);
2122 }
2123 c = sbrk(0);
2124 if (c != a - PGSIZE) {
2125 printf("%s: sbrk deallocation produced wrong address, a %p c %p\n", s, a,
2126 c);
2127 exit(1);
2128 }
2129
2130
2131 a = sbrk(0);
2132 c = sbrk(PGSIZE);
2133 if (c != a || sbrk(0) != a + PGSIZE) {
2134 printf("%s: sbrk re-allocation failed, a %p c %p\n", s, a, c);
2135 exit(1);
2136 }
2137 if (*lastaddr == 99) {
2138
2139 printf("%s: sbrk de-allocation didn't really deallocate\n", s);
2140 exit(1);
2141 }
2142
2143 a = sbrk(0);
2144 c = sbrk(-(sbrk(0) - oldbrk));
2145 if (c != a) {
2146 printf("%s: sbrk downsize failed, a %p c %p\n", s, a, c);
2147 exit(1);
2148 }
2149 }
2150
2151
2152 void
2153 kernmem(char *s)
2154 {
2155 char *a;
2156 int pid;
2157
2158 for (a = (char *)(KERNBASE); a < (char *)(KERNBASE + 2000000); a += 50000) {
2159 pid = fork();
2160 if (pid < 0) {
2161 printf("%s: fork failed\n", s);
2162 exit(1);
2163 }
2164 if (pid == 0) {
2165 printf("%s: oops could read %p = %x\n", s, a, *a);
2166 exit(1);
2167 }
2168 int xstatus;
2169 wait(&xstatus);
2170 if (xstatus != -1)
2171 exit(1);
2172 }
2173 }
2174
2175
2176 void
2177 MAXVAplus(char *s)
2178 {
2179 volatile uint64 a = MAXVA;
2180 for (; a != 0; a <<= 1) {
2181 int pid;
2182 pid = fork();
2183 if (pid < 0) {
2184 printf("%s: fork failed\n", s);
2185 exit(1);
2186 }
2187 if (pid == 0) {
2188 *(char *)a = 99;
2189 printf("%s: oops wrote %p\n", s, (void *)a);
2190 exit(1);
2191 }
2192 int xstatus;
2193 wait(&xstatus);
2194 if (xstatus != -1)
2195 exit(1);
2196 }
2197 }
2198
2199
2200
2201 void
2202 sbrkfail(char *s)
2203 {
2204 enum { BIG = 100 * 1024 * 1024 };
2205 int i, xstatus;
2206 int fds[2];
2207 char scratch;
2208 char *c, *a;
2209 int pids[10];
2210 int pid;
2211 int failed;
2212
2213 failed = 0;
2214 if (pipe(fds) != 0) {
2215 printf("%s: pipe() failed\n", s);
2216 exit(1);
2217 }
2218 for (i = 0; i < sizeof(pids) / sizeof(pids[0]); i++) {
2219 if ((pids[i] = fork()) == 0) {
2220
2221 if (sbrk(BIG - (uint64)sbrk(0)) == (char *)SBRK_ERROR)
2222 write(fds[1], "0", 1);
2223 else
2224 write(fds[1], "1", 1);
2225
2226 for (;;)
2227 pause(1000);
2228 }
2229 if (pids[i] != -1) {
2230 read(fds[0], &scratch, 1);
2231 if (scratch == '0')
2232 failed = 1;
2233 }
2234 }
2235 if (!failed) {
2236 printf("%s: no allocation failed; allocate more?\n", s);
2237 }
2238
2239
2240
2241 c = sbrk(PGSIZE);
2242 for (i = 0; i < sizeof(pids) / sizeof(pids[0]); i++) {
2243 if (pids[i] == -1)
2244 continue;
2245 kill(pids[i]);
2246 wait(0);
2247 }
2248 if (c == (char *)SBRK_ERROR) {
2249 printf("%s: failed sbrk leaked memory\n", s);
2250 exit(1);
2251 }
2252
2253
2254 pid = fork();
2255 if (pid < 0) {
2256 printf("%s: fork failed\n", s);
2257 exit(1);
2258 }
2259 if (pid == 0) {
2260
2261 a = sbrk(10 * BIG);
2262 if (a == (char *)SBRK_ERROR) {
2263 exit(0);
2264 }
2265 printf("%s: allocate a lot of memory succeeded %d\n", s, 10 * BIG);
2266 exit(1);
2267 }
2268 wait(&xstatus);
2269 if (xstatus != 0)
2270 exit(1);
2271 }
2272
2273
2274 void
2275 sbrkarg(char *s)
2276 {
2277 char *a;
2278 int fd, n;
2279
2280 a = sbrk(PGSIZE);
2281 fd = open("sbrk", O_CREATE | O_WRONLY);
2282 unlink("sbrk");
2283 if (fd < 0) {
2284 printf("%s: open sbrk failed\n", s);
2285 exit(1);
2286 }
2287 if ((n = write(fd, a, PGSIZE)) < 0) {
2288 printf("%s: write sbrk failed\n", s);
2289 exit(1);
2290 }
2291 close(fd);
2292
2293
2294 a = sbrk(PGSIZE);
2295 if (pipe((int *)a) != 0) {
2296 printf("%s: pipe() failed\n", s);
2297 exit(1);
2298 }
2299 }
2300
2301 void
2302 validatetest(char *s)
2303 {
2304 int hi;
2305 uint64 p;
2306
2307 hi = 1100 * 1024;
2308 for (p = 0; p <= (uint)hi; p += PGSIZE) {
2309
2310 if (link("nosuchfile", (char *)p) != -1) {
2311 printf("%s: link should not succeed\n", s);
2312 exit(1);
2313 }
2314 }
2315 }
2316
2317
2318 char uninit[10000];
2319 void
2320 bsstest(char *s)
2321 {
2322 int i;
2323
2324 for (i = 0; i < sizeof(uninit); i++) {
2325 if (uninit[i] != '\0') {
2326 printf("%s: bss test failed\n", s);
2327 exit(1);
2328 }
2329 }
2330 }
2331
2332
2333
2334
2335 void
2336 bigargtest(char *s)
2337 {
2338 int pid, fd, xstatus;
2339
2340 unlink("bigarg-ok");
2341 pid = fork();
2342 if (pid == 0) {
2343 static char *args[MAXARG];
2344 int i;
2345 char big[400];
2346 memset(big, ' ', sizeof(big));
2347 big[sizeof(big) - 1] = '\0';
2348 for (i = 0; i < MAXARG - 1; i++)
2349 args[i] = big;
2350 args[MAXARG - 1] = 0;
2351
2352
2353 exec("echo", args);
2354 fd = open("bigarg-ok", O_CREATE);
2355 close(fd);
2356 exit(0);
2357 } else if (pid < 0) {
2358 printf("%s: bigargtest: fork failed\n", s);
2359 exit(1);
2360 }
2361
2362 wait(&xstatus);
2363 if (xstatus != 0)
2364 exit(xstatus);
2365 fd = open("bigarg-ok", 0);
2366 if (fd < 0) {
2367 printf("%s: bigarg test failed!\n", s);
2368 exit(1);
2369 }
2370 close(fd);
2371 }
2372
2373
2374
2375 void
2376 fsfull()
2377 {
2378 int nfiles;
2379 int fsblocks = 0;
2380
2381 printf("fsfull test\n");
2382
2383 for (nfiles = 0;; nfiles++) {
2384 char name[64];
2385 name[0] = 'f';
2386 name[1] = '0' + nfiles / 1000;
2387 name[2] = '0' + (nfiles % 1000) / 100;
2388 name[3] = '0' + (nfiles % 100) / 10;
2389 name[4] = '0' + (nfiles % 10);
2390 name[5] = '\0';
2391 printf("writing %s\n", name);
2392 int fd = open(name, O_CREATE | O_RDWR);
2393 if (fd < 0) {
2394 printf("open %s failed\n", name);
2395 break;
2396 }
2397 int total = 0;
2398 while (1) {
2399 int cc = write(fd, buf, BSIZE);
2400 if (cc < BSIZE)
2401 break;
2402 total += cc;
2403 fsblocks++;
2404 }
2405 printf("wrote %d bytes\n", total);
2406 close(fd);
2407 if (total == 0)
2408 break;
2409 }
2410
2411 while (nfiles >= 0) {
2412 char name[64];
2413 name[0] = 'f';
2414 name[1] = '0' + nfiles / 1000;
2415 name[2] = '0' + (nfiles % 1000) / 100;
2416 name[3] = '0' + (nfiles % 100) / 10;
2417 name[4] = '0' + (nfiles % 10);
2418 name[5] = '\0';
2419 unlink(name);
2420 nfiles--;
2421 }
2422
2423 printf("fsfull test finished, %d blocks\n", fsblocks);
2424 }
2425
2426 void
2427 argptest(char *s)
2428 {
2429 int fd;
2430 fd = open("init", O_RDONLY);
2431 if (fd < 0) {
2432 printf("%s: open failed\n", s);
2433 exit(1);
2434 }
2435 read(fd, sbrk(0) - 1, -1);
2436 close(fd);
2437 }
2438
2439
2440
2441 void
2442 stacktest(char *s)
2443 {
2444 int pid;
2445 int xstatus;
2446
2447 pid = fork();
2448 if (pid == 0) {
2449 char *sp = (char *)r_sp();
2450 sp -= USERSTACK * PGSIZE;
2451
2452 printf("%s: stacktest: read below stack %d\n", s, *sp);
2453 exit(1);
2454 } else if (pid < 0) {
2455 printf("%s: fork failed\n", s);
2456 exit(1);
2457 }
2458 wait(&xstatus);
2459 if (xstatus == -1)
2460 exit(0);
2461 else
2462 exit(xstatus);
2463 }
2464
2465
2466
2467 void
2468 nowrite(char *s)
2469 {
2470 int pid;
2471 int xstatus;
2472 uint64 addrs[] = {0,
2473 0x80000000LL,
2474 0x3fffffe000,
2475 0x3ffffff000,
2476 0x4000000000,
2477 0xffffffffffffffff};
2478
2479 for (int ai = 0; ai < sizeof(addrs) / sizeof(addrs[0]); ai++) {
2480 pid = fork();
2481 if (pid == 0) {
2482 volatile int *addr = (int *)addrs[ai];
2483 *addr = 10;
2484 printf("%s: write to %p did not fail!\n", s, addr);
2485 exit(0);
2486 } else if (pid < 0) {
2487 printf("%s: fork failed\n", s);
2488 exit(1);
2489 }
2490 wait(&xstatus);
2491 if (xstatus == 0) {
2492
2493 exit(1);
2494 }
2495 }
2496 exit(0);
2497 }
2498
2499
2500
2501
2502 void *big = (void *)0xeaeb0b5b00002f5e;
2503 void
2504 pgbug(char *s)
2505 {
2506 char *argv[1];
2507 argv[0] = 0;
2508 exec(big, argv);
2509 pipe(big);
2510
2511 exit(0);
2512 }
2513
2514
2515
2516
2517 void
2518 sbrkbugs(char *s)
2519 {
2520 int pid = fork();
2521 if (pid < 0) {
2522 printf("fork failed\n");
2523 exit(1);
2524 }
2525 if (pid == 0) {
2526 int sz = (uint64)sbrk(0);
2527
2528
2529
2530 sbrk(-sz);
2531
2532 exit(0);
2533 }
2534 wait(0);
2535
2536 pid = fork();
2537 if (pid < 0) {
2538 printf("fork failed\n");
2539 exit(1);
2540 }
2541 if (pid == 0) {
2542 int sz = (uint64)sbrk(0);
2543
2544
2545
2546 sbrk(-(sz - 3500));
2547 exit(0);
2548 }
2549 wait(0);
2550
2551 pid = fork();
2552 if (pid < 0) {
2553 printf("fork failed\n");
2554 exit(1);
2555 }
2556 if (pid == 0) {
2557
2558 sbrk((10 * PGSIZE + 2048) - (uint64)sbrk(0));
2559
2560
2561
2562
2563 sbrk(-10);
2564
2565 exit(0);
2566 }
2567 wait(0);
2568
2569 exit(0);
2570 }
2571
2572
2573
2574
2575 void
2576 sbrklast(char *s)
2577 {
2578 uint64 top = (uint64)sbrk(0);
2579 if ((top % PGSIZE) != 0)
2580 sbrk(PGSIZE - (top % PGSIZE));
2581 sbrk(PGSIZE);
2582 sbrk(10);
2583 sbrk(-20);
2584 top = (uint64)sbrk(0);
2585 char *p = (char *)(top - 64);
2586 p[0] = 'x';
2587 p[1] = '\0';
2588 int fd = open(p, O_RDWR | O_CREATE);
2589 write(fd, p, 1);
2590 close(fd);
2591 fd = open(p, O_RDWR);
2592 p[0] = '\0';
2593 read(fd, p, 1);
2594 if (p[0] != 'x')
2595 exit(1);
2596 }
2597
2598
2599
2600 void
2601 sbrk8000(char *s)
2602 {
2603 sbrk(0x80000004);
2604 volatile char *top = sbrk(0);
2605 *(top - 1) = *(top - 1) + 1;
2606 }
2607
2608
2609
2610 void
2611 badarg(char *s)
2612 {
2613 for (int i = 0; i < 50000; i++) {
2614 char *argv[2];
2615 argv[0] = (char *)0xffffffff;
2616 argv[1] = 0;
2617 exec("echo", argv);
2618 }
2619
2620 exit(0);
2621 }
2622
2623 #define REGION_SZ (1024 * 1024 * 1024)
2624
2625
2626
2627 void
2628 lazy_alloc(char *s)
2629 {
2630 char *i, *prev_end, *new_end;
2631
2632 prev_end = sbrklazy(REGION_SZ);
2633 if (prev_end == (char *)SBRK_ERROR) {
2634 printf("sbrklazy() failed\n");
2635 exit(1);
2636 }
2637 new_end = prev_end + REGION_SZ;
2638
2639 for (i = prev_end + PGSIZE; i < new_end; i += 64 * PGSIZE)
2640 *(char **)i = i;
2641
2642 for (i = prev_end + PGSIZE; i < new_end; i += 64 * PGSIZE) {
2643 if (*(char **)i != i) {
2644 printf("failed to read value from memory\n");
2645 exit(1);
2646 }
2647 }
2648
2649 exit(0);
2650 }
2651
2652
2653
2654
2655 void
2656 lazy_unmap(char *s)
2657 {
2658 int pid;
2659 char *i, *prev_end, *new_end;
2660
2661 prev_end = sbrklazy(REGION_SZ);
2662 if (prev_end == (char *)SBRK_ERROR) {
2663 printf("sbrklazy() failed\n");
2664 exit(1);
2665 }
2666 new_end = prev_end + REGION_SZ;
2667
2668 for (i = prev_end + PGSIZE; i < new_end; i += PGSIZE * PGSIZE)
2669 *(char **)i = i;
2670
2671 for (i = prev_end + PGSIZE; i < new_end; i += PGSIZE * PGSIZE) {
2672 pid = fork();
2673 if (pid < 0) {
2674 printf("error forking\n");
2675 exit(1);
2676 } else if (pid == 0) {
2677 sbrklazy(-1L * REGION_SZ);
2678 *(char **)i = i;
2679 exit(0);
2680 } else {
2681 int status;
2682 wait(&status);
2683 if (status == 0) {
2684 printf("memory not unmapped\n");
2685 exit(1);
2686 }
2687 }
2688 }
2689
2690 exit(0);
2691 }
2692
2693 void
2694 lazy_copy(char *s)
2695 {
2696
2697 {
2698 char *p = sbrk(0);
2699 sbrklazy(4 * PGSIZE);
2700 open(p + 8192, 0);
2701 }
2702
2703 {
2704 void *xx = sbrk(0);
2705 void *ret = sbrk(-(((uint64)xx) + 1));
2706 if (ret != xx) {
2707 printf("sbrk(sbrk(0)+1) returned %p, not old sz\n", ret);
2708 exit(1);
2709 }
2710 }
2711
2712
2713 unsigned long bad[] = {
2714 0x3fffffc000, 0x3fffffd000, 0x3fffffe000,
2715 0x3ffffff000, 0x4000000000, 0x8000000000,
2716 };
2717 for (int i = 0; i < sizeof(bad) / sizeof(bad[0]); i++) {
2718 int fd = open("README", 0);
2719 if (fd < 0) {
2720 printf("cannot open README\n");
2721 exit(1);
2722 }
2723 if (read(fd, (char *)bad[i], 512) >= 0) {
2724 printf("read succeeded\n");
2725 exit(1);
2726 }
2727 close(fd);
2728 fd = open("junk", O_CREATE | O_RDWR | O_TRUNC);
2729 if (fd < 0) {
2730 printf("cannot open junk\n");
2731 exit(1);
2732 }
2733 if (write(fd, (char *)bad[i], 512) >= 0) {
2734 printf("write succeeded\n");
2735 exit(1);
2736 }
2737 close(fd);
2738 }
2739
2740 exit(0);
2741 }
2742
2743 void
2744 lazy_copyinstr(char *s)
2745 {
2746 char *p = sbrk(0);
2747 sbrk(PGSIZE - ((uint64)p % PGSIZE));
2748
2749 p = sbrk(0);
2750 if ((uint64)p % PGSIZE != 0) {
2751 printf("%s: sbrk did not align\n", s);
2752 exit(1);
2753 }
2754
2755 sbrklazy(2 * PGSIZE);
2756 p[4095] = '/';
2757 int fd = open(&p[4095], O_RDONLY);
2758 if (fd < 0) {
2759 printf("could not open /");
2760 exit(1);
2761 }
2762
2763 struct stat st;
2764 int r = fstat(fd, &st);
2765 if (r < 0) {
2766 printf("could not stat /");
2767 exit(1);
2768 }
2769
2770 if (st.type != T_DIR) {
2771 printf("/ is not T_DIR");
2772 exit(1);
2773 }
2774
2775 close(fd);
2776 }
2777
2778 void
2779 lazy_sbrk(char *s)
2780 {
2781
2782 char *p = sbrk(0);
2783 while ((uint64)p < MAXVA - (1 << 30)) {
2784 p = sbrklazy(1 << 30);
2785 if (p < 0) {
2786 printf("sbrklazy(%d) returned %p\n", 1 << 30, p);
2787 exit(1);
2788 }
2789
2790 p = sbrklazy(0);
2791 }
2792
2793 int n = TRAPFRAME - PGSIZE - (uint64)p;
2794
2795 char *p1 = sbrklazy(n);
2796 if (p1 < 0 || p1 != p) {
2797 printf("sbrklazy(%d) returned %p, not expected %p\n", n, p1, p);
2798 exit(1);
2799 }
2800
2801 p = sbrk(PGSIZE);
2802 if (p < 0 || (uint64)p != TRAPFRAME - PGSIZE) {
2803 printf("sbrk(%d) returned %p, not expected TRAPFRAME-PGSIZE\n", PGSIZE, p);
2804 exit(1);
2805 }
2806
2807 p[0] = 1;
2808 if (p[1] != 0) {
2809 printf("sbrk() returned non-zero-filled memory\n");
2810 exit(1);
2811 }
2812
2813 p = sbrk(1);
2814 if ((uint64)p != -1) {
2815 printf("sbrk(1) returned %p, expected error\n", p);
2816 exit(1);
2817 }
2818
2819 p = sbrklazy(1);
2820 if ((uint64)p != -1) {
2821 printf("sbrklazy(1) returned %p, expected error\n", p);
2822 exit(1);
2823 }
2824
2825 exit(0);
2826 }
2827
2828 void
2829 partial_write(char *s)
2830 {
2831
2832
2833
2834
2835
2836
2837
2838 unlink("testfile");
2839 int fd = open("testfile", O_CREATE | O_RDWR);
2840 if (fd < 0) {
2841 printf("%s: cannot create testfile\n", s);
2842 exit(1);
2843 }
2844
2845 int cc = write(fd, "A", 1);
2846 if (cc != 1) {
2847 printf("%s: could not write A\n", s);
2848 exit(1);
2849 }
2850
2851 close(fd);
2852 fd = open("testfile", O_RDWR);
2853 if (fd < 0) {
2854 printf("%s: cannot re-open testfile\n", s);
2855 exit(1);
2856 }
2857
2858 char *p = sbrk(0);
2859 sbrk(PGSIZE - ((uint64)p % PGSIZE));
2860
2861 p = sbrk(0);
2862 if ((uint64)p % PGSIZE != 0) {
2863 printf("%s: sbrk did not align\n", s);
2864 exit(1);
2865 }
2866
2867 p[-1] = 'X';
2868
2869 cc = write(fd, p - 1, 2);
2870 if (cc != -1) {
2871 printf("%s: write succeeded, should have failed\n", s);
2872 exit(1);
2873 }
2874
2875 close(fd);
2876
2877 fd = open("testfile", O_RDONLY);
2878 if (fd < 0) {
2879 printf("%s: cannot re-open testfile\n", s);
2880 exit(1);
2881 }
2882
2883 char b;
2884 cc = read(fd, &b, 1);
2885 if (cc != 1) {
2886 printf("%s: cannot read testfile\n", s);
2887 exit(1);
2888 }
2889
2890 close(fd);
2891
2892 if (b != 'X') {
2893 printf("%s: read returned %c, expected X\n", s, b);
2894 exit(1);
2895 }
2896
2897 fd = open("bigfile", O_CREATE | O_RDWR);
2898 for (int i = 0; i < 64; i++) {
2899 char buf[1024];
2900 memset(buf, 0, sizeof(buf));
2901 cc = write(fd, buf, sizeof(buf));
2902 if (cc != sizeof(buf)) {
2903 printf("%s: could not write to bigfile\n", s);
2904 exit(-1);
2905 }
2906 }
2907 close(fd);
2908
2909 unlink("bigfile");
2910
2911 fd = open("testfile", O_RDONLY);
2912 if (fd < 0) {
2913 printf("%s: cannot re-open testfile\n", s);
2914 exit(1);
2915 }
2916
2917 cc = read(fd, &b, 1);
2918 if (cc != 1) {
2919 printf("%s: cannot read testfile\n", s);
2920 exit(1);
2921 }
2922
2923 close(fd);
2924
2925 if (b != 'X') {
2926 printf("%s: read returned %c, expected X\n", s, b);
2927 exit(1);
2928 }
2929
2930 unlink("testfile");
2931 }
2932
2933 void
2934 unlinkcwd(char *s)
2935 {
2936 if (mkdir("/a") < 0) {
2937 printf("%s: mkdir /a failed\n", s);
2938 exit(1);
2939 }
2940 if (mkdir("/a/b") < 0) {
2941 printf("%s: mkdir /a/b failed\n", s);
2942 exit(1);
2943 }
2944 if (chdir("/a/b") < 0) {
2945 printf("%s: chdir failed\n", s);
2946 exit(1);
2947 }
2948 if (unlink("/a/b") < 0) {
2949 printf("%s: unlink /a/b failed\n", s);
2950 exit(1);
2951 }
2952 if (unlink("/a") < 0) {
2953 printf("%s: unlink /a failed\n", s);
2954 exit(1);
2955 }
2956 if (open("../", O_RDONLY) > 0) {
2957 printf("%s: open ../ non-existing directory\n", s);
2958 }
2959 if (open("../c", O_CREATE) > 0) {
2960 printf("%s: create ../c non-existing file\n", s);
2961 }
2962 }
2963
2964 struct test {
2965 void (*f)(char *);
2966 char *s;
2967 } quicktests[] = {
2968 {copyin, "copyin"},
2969 {copyout, "copyout"},
2970 {copyinstr1, "copyinstr1"},
2971 {copyinstr2, "copyinstr2"},
2972 {copyinstr3, "copyinstr3"},
2973 {rwsbrk, "rwsbrk"},
2974 {truncate1, "truncate1"},
2975 {truncate2, "truncate2"},
2976 {truncate3, "truncate3"},
2977 {openiputtest, "openiput"},
2978 {exitiputtest, "exitiput"},
2979 {iputtest, "iput"},
2980 {opentest, "opentest"},
2981 {writetest, "writetest"},
2982 {writebig, "writebig"},
2983 {createtest, "createtest"},
2984 {dirtest, "dirtest"},
2985 {exectest, "exectest"},
2986 {pipe1, "pipe1"},
2987 {killstatus, "killstatus"},
2988 {killzero, "killzero"},
2989 {preempt, "preempt"},
2990 {exitwait, "exitwait"},
2991 {reparent, "reparent"},
2992 {twochildren, "twochildren"},
2993 {forkfork, "forkfork"},
2994 {forkforkfork, "forkforkfork"},
2995 {reparent2, "reparent2"},
2996 {mem, "mem"},
2997 {sharedfd, "sharedfd"},
2998 {fourfiles, "fourfiles"},
2999 {createdelete, "createdelete"},
3000 {unlinkread, "unlinkread"},
3001 {linktest, "linktest"},
3002 {concreate, "concreate"},
3003 {linkunlink, "linkunlink"},
3004 {subdir, "subdir"},
3005 {bigwrite, "bigwrite"},
3006 {bigfile, "bigfile"},
3007 {fourteen, "fourteen"},
3008 {rmdot, "rmdot"},
3009 {dirfile, "dirfile"},
3010 {iref, "iref"},
3011 {forktest, "forktest"},
3012 {sbrkbasic, "sbrkbasic"},
3013 {sbrkmuch, "sbrkmuch"},
3014 {kernmem, "kernmem"},
3015 {MAXVAplus, "MAXVAplus"},
3016 {sbrkfail, "sbrkfail"},
3017 {sbrkarg, "sbrkarg"},
3018 {validatetest, "validatetest"},
3019 {bsstest, "bsstest"},
3020 {bigargtest, "bigargtest"},
3021 {argptest, "argptest"},
3022 {stacktest, "stacktest"},
3023 {nowrite, "nowrite"},
3024 {pgbug, "pgbug"},
3025 {sbrkbugs, "sbrkbugs"},
3026 {sbrklast, "sbrklast"},
3027 {sbrk8000, "sbrk8000"},
3028 {badarg, "badarg"},
3029 {lazy_alloc, "lazy_alloc"},
3030 {lazy_unmap, "lazy_unmap"},
3031 {lazy_copy, "lazy_copy"},
3032 {lazy_copyinstr, "lazy_copyinstr"},
3033 {lazy_sbrk, "lazy_sbrk"},
3034 {partial_write, "partial_write"},
3035 {unlinkcwd, "unlinkcwd"},
3036 {0, 0},
3037 };
3038
3039
3040
3041
3042
3043
3044 void
3045 bigdir(char *s)
3046 {
3047 enum { N = 500 };
3048 int i, fd;
3049 char name[10];
3050
3051 unlink("bd");
3052
3053 fd = open("bd", O_CREATE);
3054 if (fd < 0) {
3055 printf("%s: bigdir create failed\n", s);
3056 exit(1);
3057 }
3058 close(fd);
3059
3060 for (i = 0; i < N; i++) {
3061 name[0] = 'x';
3062 name[1] = '0' + (i / 64);
3063 name[2] = '0' + (i % 64);
3064 name[3] = '\0';
3065 if (link("bd", name) != 0) {
3066 printf("%s: bigdir i=%d link(bd, %s) failed\n", s, i, name);
3067 exit(1);
3068 }
3069 }
3070
3071 unlink("bd");
3072 for (i = 0; i < N; i++) {
3073 name[0] = 'x';
3074 name[1] = '0' + (i / 64);
3075 name[2] = '0' + (i % 64);
3076 name[3] = '\0';
3077 if (unlink(name) != 0) {
3078 printf("%s: bigdir unlink failed", s);
3079 exit(1);
3080 }
3081 }
3082 }
3083
3084
3085
3086 void
3087 manywrites(char *s)
3088 {
3089 int nchildren = 4;
3090 int howmany = 30;
3091
3092 for (int ci = 0; ci < nchildren; ci++) {
3093 int pid = fork();
3094 if (pid < 0) {
3095 printf("fork failed\n");
3096 exit(1);
3097 }
3098
3099 if (pid == 0) {
3100 char name[3];
3101 name[0] = 'b';
3102 name[1] = 'a' + ci;
3103 name[2] = '\0';
3104 unlink(name);
3105
3106 for (int iters = 0; iters < howmany; iters++) {
3107 for (int i = 0; i < ci + 1; i++) {
3108 int fd = open(name, O_CREATE | O_RDWR);
3109 if (fd < 0) {
3110 printf("%s: cannot create %s\n", s, name);
3111 exit(1);
3112 }
3113 int sz = sizeof(buf);
3114 int cc = write(fd, buf, sz);
3115 if (cc != sz) {
3116 printf("%s: write(%d) ret %d\n", s, sz, cc);
3117 exit(1);
3118 }
3119 close(fd);
3120 }
3121 unlink(name);
3122 }
3123
3124 unlink(name);
3125 exit(0);
3126 }
3127 }
3128
3129 for (int ci = 0; ci < nchildren; ci++) {
3130 int st = 0;
3131 wait(&st);
3132 if (st != 0)
3133 exit(st);
3134 }
3135 exit(0);
3136 }
3137
3138
3139
3140
3141
3142
3143 void
3144 badwrite(char *s)
3145 {
3146 int assumed_free = 600;
3147
3148 unlink("junk");
3149 for (int i = 0; i < assumed_free; i++) {
3150 int fd = open("junk", O_CREATE | O_WRONLY);
3151 if (fd < 0) {
3152 printf("open junk failed\n");
3153 exit(1);
3154 }
3155 write(fd, (char *)0xffffffffffL, 1);
3156 close(fd);
3157 unlink("junk");
3158 }
3159
3160 int fd = open("junk", O_CREATE | O_WRONLY);
3161 if (fd < 0) {
3162 printf("open junk failed\n");
3163 exit(1);
3164 }
3165 if (write(fd, "x", 1) != 1) {
3166 printf("write failed\n");
3167 exit(1);
3168 }
3169 close(fd);
3170 unlink("junk");
3171
3172 exit(0);
3173 }
3174
3175
3176
3177
3178 void
3179 execout(char *s)
3180 {
3181 for (int avail = 0; avail < 15; avail++) {
3182 int pid = fork();
3183 if (pid < 0) {
3184 printf("fork failed\n");
3185 exit(1);
3186 } else if (pid == 0) {
3187
3188 while (1) {
3189 char *a = sbrk(PGSIZE);
3190 if (a == SBRK_ERROR)
3191 break;
3192 *(a + PGSIZE - 1) = 1;
3193 }
3194
3195
3196
3197 for (int i = 0; i < avail; i++)
3198 sbrk(-PGSIZE);
3199
3200 close(1);
3201 char *args[] = {"echo", "x", 0};
3202 exec("echo", args);
3203 exit(0);
3204 } else {
3205 wait((int *)0);
3206 }
3207 }
3208
3209 exit(0);
3210 }
3211
3212
3213 void
3214 diskfull(char *s)
3215 {
3216 int fi;
3217 int done = 0;
3218
3219 unlink("diskfulldir");
3220
3221 for (fi = 0; done == 0 && '0' + fi < 0177; fi++) {
3222 char name[32];
3223 name[0] = 'b';
3224 name[1] = 'i';
3225 name[2] = 'g';
3226 name[3] = '0' + fi;
3227 name[4] = '\0';
3228 unlink(name);
3229 int fd = open(name, O_CREATE | O_RDWR | O_TRUNC);
3230 if (fd < 0) {
3231
3232 printf("%s: could not create file %s\n", s, name);
3233 done = 1;
3234 break;
3235 }
3236 for (int i = 0; i < MAXFILE; i++) {
3237 char buf[BSIZE];
3238 if (write(fd, buf, BSIZE) != BSIZE) {
3239 done = 1;
3240 close(fd);
3241 break;
3242 }
3243 }
3244 close(fd);
3245 }
3246
3247
3248
3249
3250
3251 int nzz = 128;
3252 for (int i = 0; i < nzz; i++) {
3253 char name[32];
3254 name[0] = 'z';
3255 name[1] = 'z';
3256 name[2] = '0' + (i / 32);
3257 name[3] = '0' + (i % 32);
3258 name[4] = '\0';
3259 unlink(name);
3260 int fd = open(name, O_CREATE | O_RDWR | O_TRUNC);
3261 if (fd < 0)
3262 break;
3263 close(fd);
3264 }
3265
3266
3267 if (mkdir("diskfulldir") == 0)
3268 printf("%s: mkdir(diskfulldir) unexpectedly succeeded!\n", s);
3269
3270 unlink("diskfulldir");
3271
3272 for (int i = 0; i < nzz; i++) {
3273 char name[32];
3274 name[0] = 'z';
3275 name[1] = 'z';
3276 name[2] = '0' + (i / 32);
3277 name[3] = '0' + (i % 32);
3278 name[4] = '\0';
3279 unlink(name);
3280 }
3281
3282 for (int i = 0; '0' + i < 0177; i++) {
3283 char name[32];
3284 name[0] = 'b';
3285 name[1] = 'i';
3286 name[2] = 'g';
3287 name[3] = '0' + i;
3288 name[4] = '\0';
3289 unlink(name);
3290 }
3291 }
3292
3293 void
3294 outofinodes(char *s)
3295 {
3296 int nzz = 32 * 32;
3297 for (int i = 0; i < nzz; i++) {
3298 char name[32];
3299 name[0] = 'z';
3300 name[1] = 'z';
3301 name[2] = '0' + (i / 32);
3302 name[3] = '0' + (i % 32);
3303 name[4] = '\0';
3304 unlink(name);
3305 int fd = open(name, O_CREATE | O_RDWR | O_TRUNC);
3306 if (fd < 0) {
3307
3308 break;
3309 }
3310 close(fd);
3311 }
3312
3313 for (int i = 0; i < nzz; i++) {
3314 char name[32];
3315 name[0] = 'z';
3316 name[1] = 'z';
3317 name[2] = '0' + (i / 32);
3318 name[3] = '0' + (i % 32);
3319 name[4] = '\0';
3320 unlink(name);
3321 }
3322 }
3323
3324 void
3325 linkoverflow(char *s)
3326 {
3327 enum { TARGET = 32768 };
3328 enum { DIRS = 64 };
3329 struct stat st;
3330 int i;
3331
3332 unlink("/lof");
3333 int fd = open("/lof", O_CREATE | O_RDWR);
3334 if (fd < 0) {
3335 printf("%s: cannot create /lof\n", s);
3336 exit(1);
3337 }
3338 close(fd);
3339
3340 for (i = 0; i < TARGET; i++) {
3341 int d = i % DIRS;
3342 int f = i / DIRS;
3343
3344 char pn[16];
3345 pn[0] = '/';
3346 pn[1] = 'd';
3347 pn[2] = '_';
3348 pn[3] = 'a' + (d / 16);
3349 pn[4] = 'a' + (d % 16);
3350 pn[5] = '\0';
3351 if (f == 0 && mkdir(pn) < 0) {
3352 printf("%s: mkdir(%s) failed\n", s, pn);
3353 exit(1);
3354 }
3355
3356 pn[5] = '/';
3357 pn[6] = 'l';
3358 pn[7] = 'a' + (f / 256);
3359 pn[8] = 'a' + ((f / 16) % 16);
3360 pn[9] = 'a' + (f % 16);
3361 pn[10] = '\0';
3362
3363 if (link("/lof", pn) < 0) {
3364 if (stat("/lof", &st) < 0) {
3365 printf("%s: stat(/lof) failed\n", s);
3366 exit(1);
3367 }
3368 if (st.nlink >= 32767) {
3369
3370 break;
3371 }
3372 printf("%s: link failed after %d links (nlink=%d)\n", s, i, st.nlink);
3373 exit(1);
3374 }
3375
3376 if (i % 100 == 0) {
3377 printf("%s: i=%d, pn=%s\n", s, i, pn);
3378 }
3379 }
3380
3381 if (stat("/lof", &st) < 0) {
3382 printf("%s: stat(/lof) failed\n", s);
3383 exit(1);
3384 }
3385
3386 unlink("/lof");
3387
3388 if (st.nlink < 0) {
3389 printf("%s: negative link count: %d\n", s, st.nlink);
3390 exit(1);
3391 }
3392 }
3393
3394 struct test slowtests[] = {
3395 {bigdir, "bigdir"},
3396 {manywrites, "manywrites"},
3397 {badwrite, "badwrite"},
3398 {execout, "execout"},
3399 {diskfull, "diskfull"},
3400 {outofinodes, "outofinodes"},
3401
3402
3403 {0, 0},
3404 };
3405
3406
3407
3408
3409
3410
3411
3412 int
3413 run(void f(char *), char *s)
3414 {
3415 int pid;
3416 int xstatus;
3417
3418 printf("test %s: ", s);
3419 if ((pid = fork()) < 0) {
3420 printf("runtest: fork error\n");
3421 exit(1);
3422 }
3423 if (pid == 0) {
3424 f(s);
3425 exit(0);
3426 } else {
3427 wait(&xstatus);
3428 if (xstatus != 0)
3429 printf("FAILED\n");
3430 else
3431 printf("OK\n");
3432 return xstatus == 0;
3433 }
3434 }
3435
3436 int
3437 runtests(struct test *tests, char *justone, int continuous)
3438 {
3439 int ntests = 0;
3440 for (struct test *t = tests; t->s != 0; t++) {
3441 if ((justone == 0) || strcmp(t->s, justone) == 0) {
3442 ntests++;
3443 if (!run(t->f, t->s)) {
3444 if (continuous != 2) {
3445 printf("SOME TESTS FAILED\n");
3446 return -1;
3447 }
3448 }
3449 }
3450 }
3451 return ntests;
3452 }
3453
3454
3455 int
3456 countfree()
3457 {
3458 int n = 0;
3459 uint64 sz0 = (uint64)sbrk(0);
3460 while (1) {
3461 char *a = sbrk(PGSIZE);
3462 if (a == SBRK_ERROR) {
3463 break;
3464 }
3465 n += 1;
3466 }
3467 sbrk(-((uint64)sbrk(0) - sz0));
3468 return n;
3469 }
3470
3471 int
3472 drivetests(int quick, int continuous, char *justone)
3473 {
3474 do {
3475 printf("usertests starting\n");
3476 int free0 = countfree();
3477 int free1 = 0;
3478 int ntests = 0;
3479 int n;
3480 n = runtests(quicktests, justone, continuous);
3481 if (n < 0) {
3482 if (continuous != 2) {
3483 return 1;
3484 }
3485 } else {
3486 ntests += n;
3487 }
3488 if (!quick) {
3489 if (justone == 0)
3490 printf("usertests slow tests starting\n");
3491 n = runtests(slowtests, justone, continuous);
3492 if (n < 0) {
3493 if (continuous != 2) {
3494 return 1;
3495 }
3496 } else {
3497 ntests += n;
3498 }
3499 }
3500 if ((free1 = countfree()) < free0) {
3501 printf("FAILED -- lost some free pages %d (out of %d)\n", free1, free0);
3502 if (continuous != 2) {
3503 return 1;
3504 }
3505 }
3506 if (justone != 0 && ntests == 0) {
3507 printf("NO TESTS EXECUTED\n");
3508 return 1;
3509 }
3510 } while (continuous);
3511 return 0;
3512 }
3513
3514 int
3515 main(int argc, char *argv[])
3516 {
3517 int continuous = 0;
3518 int quick = 0;
3519 char *justone = 0;
3520
3521 if (argc == 2 && strcmp(argv[1], "-q") == 0) {
3522 quick = 1;
3523 } else if (argc == 2 && strcmp(argv[1], "-c") == 0) {
3524 continuous = 1;
3525 } else if (argc == 2 && strcmp(argv[1], "-C") == 0) {
3526 continuous = 2;
3527 } else if (argc == 2 && argv[1][0] != '-') {
3528 justone = argv[1];
3529 } else if (argc > 1) {
3530 printf("Usage: usertests [-c] [-C] [-q] [testname]\n");
3531 exit(1);
3532 }
3533 if (drivetests(quick, continuous, justone)) {
3534 exit(1);
3535 }
3536 printf("ALL TESTS PASSED\n");
3537 exit(0);
3538 }