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