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