xref: /xv6-public/usertests.c (revision 907f23a5)
15e083578SRobert Morris #include "param.h"
28787cd01Skaashoek #include "types.h"
38787cd01Skaashoek #include "stat.h"
49b37d1bfSrsc #include "user.h"
5a64cd813Skaashoek #include "fs.h"
643572072Srtm #include "fcntl.h"
7b1d41d67SAustin Clements #include "syscall.h"
8b1d41d67SAustin Clements #include "traps.h"
964797663SFrans Kaashoek #include "memlayout.h"
109b37d1bfSrsc 
112e590463SRobert Morris char buf[8192];
12a64cd813Skaashoek char name[3];
1334295f46Srsc char *echoargv[] = { "echo", "ALL", "TESTS", "PASSED", 0 };
14a64cd813Skaashoek int stdout = 1;
15a64cd813Skaashoek 
162c565472SRobert Morris // does chdir() call iput(p->cwd) in a transaction?
172c565472SRobert Morris void
iputtest(void)182c565472SRobert Morris iputtest(void)
192c565472SRobert Morris {
202c565472SRobert Morris   printf(stdout, "iput test\n");
212c565472SRobert Morris 
222c565472SRobert Morris   if(mkdir("iputdir") < 0){
232c565472SRobert Morris     printf(stdout, "mkdir failed\n");
242c565472SRobert Morris     exit();
252c565472SRobert Morris   }
262c565472SRobert Morris   if(chdir("iputdir") < 0){
272c565472SRobert Morris     printf(stdout, "chdir iputdir failed\n");
282c565472SRobert Morris     exit();
292c565472SRobert Morris   }
302c565472SRobert Morris   if(unlink("../iputdir") < 0){
312c565472SRobert Morris     printf(stdout, "unlink ../iputdir failed\n");
322c565472SRobert Morris     exit();
332c565472SRobert Morris   }
342c565472SRobert Morris   if(chdir("/") < 0){
352c565472SRobert Morris     printf(stdout, "chdir / failed\n");
362c565472SRobert Morris     exit();
372c565472SRobert Morris   }
382c565472SRobert Morris   printf(stdout, "iput test ok\n");
392c565472SRobert Morris }
402c565472SRobert Morris 
412c565472SRobert Morris // does exit() call iput(p->cwd) in a transaction?
422c565472SRobert Morris void
exitiputtest(void)432c565472SRobert Morris exitiputtest(void)
442c565472SRobert Morris {
452c565472SRobert Morris   int pid;
462c565472SRobert Morris 
472c565472SRobert Morris   printf(stdout, "exitiput test\n");
482c565472SRobert Morris 
492c565472SRobert Morris   pid = fork();
502c565472SRobert Morris   if(pid < 0){
512c565472SRobert Morris     printf(stdout, "fork failed\n");
522c565472SRobert Morris     exit();
532c565472SRobert Morris   }
542c565472SRobert Morris   if(pid == 0){
552c565472SRobert Morris     if(mkdir("iputdir") < 0){
562c565472SRobert Morris       printf(stdout, "mkdir failed\n");
572c565472SRobert Morris       exit();
582c565472SRobert Morris     }
592c565472SRobert Morris     if(chdir("iputdir") < 0){
602c565472SRobert Morris       printf(stdout, "child chdir failed\n");
612c565472SRobert Morris       exit();
622c565472SRobert Morris     }
632c565472SRobert Morris     if(unlink("../iputdir") < 0){
642c565472SRobert Morris       printf(stdout, "unlink ../iputdir failed\n");
652c565472SRobert Morris       exit();
662c565472SRobert Morris     }
672c565472SRobert Morris     exit();
682c565472SRobert Morris   }
692c565472SRobert Morris   wait();
702c565472SRobert Morris   printf(stdout, "exitiput test ok\n");
712c565472SRobert Morris }
722c565472SRobert Morris 
732c565472SRobert Morris // does the error path in open() for attempt to write a
742c565472SRobert Morris // directory call iput() in a transaction?
752c565472SRobert Morris // needs a hacked kernel that pauses just after the namei()
762c565472SRobert Morris // call in sys_open():
772c565472SRobert Morris //    if((ip = namei(path)) == 0)
782c565472SRobert Morris //      return -1;
792c565472SRobert Morris //    {
802c565472SRobert Morris //      int i;
812c565472SRobert Morris //      for(i = 0; i < 10000; i++)
822c565472SRobert Morris //        yield();
832c565472SRobert Morris //    }
842c565472SRobert Morris void
openiputtest(void)852c565472SRobert Morris openiputtest(void)
862c565472SRobert Morris {
872c565472SRobert Morris   int pid;
882c565472SRobert Morris 
892c565472SRobert Morris   printf(stdout, "openiput test\n");
902c565472SRobert Morris   if(mkdir("oidir") < 0){
912c565472SRobert Morris     printf(stdout, "mkdir oidir failed\n");
922c565472SRobert Morris     exit();
932c565472SRobert Morris   }
942c565472SRobert Morris   pid = fork();
952c565472SRobert Morris   if(pid < 0){
962c565472SRobert Morris     printf(stdout, "fork failed\n");
972c565472SRobert Morris     exit();
982c565472SRobert Morris   }
992c565472SRobert Morris   if(pid == 0){
1002c565472SRobert Morris     int fd = open("oidir", O_RDWR);
1012c565472SRobert Morris     if(fd >= 0){
1022c565472SRobert Morris       printf(stdout, "open directory for write succeeded\n");
1032c565472SRobert Morris       exit();
1042c565472SRobert Morris     }
1052c565472SRobert Morris     exit();
1062c565472SRobert Morris   }
1072c565472SRobert Morris   sleep(1);
1082c565472SRobert Morris   if(unlink("oidir") != 0){
1092c565472SRobert Morris     printf(stdout, "unlink failed\n");
1102c565472SRobert Morris     exit();
1112c565472SRobert Morris   }
1122c565472SRobert Morris   wait();
1132c565472SRobert Morris   printf(stdout, "openiput test ok\n");
1142c565472SRobert Morris }
1152c565472SRobert Morris 
116a64cd813Skaashoek // simple file system tests
117a64cd813Skaashoek 
118a64cd813Skaashoek void
opentest(void)119a64cd813Skaashoek opentest(void)
120a64cd813Skaashoek {
121a64cd813Skaashoek   int fd;
122a64cd813Skaashoek 
123a64cd813Skaashoek   printf(stdout, "open test\n");
124a64cd813Skaashoek   fd = open("echo", 0);
125a64cd813Skaashoek   if(fd < 0){
126a64cd813Skaashoek     printf(stdout, "open echo failed!\n");
127a64cd813Skaashoek     exit();
128a64cd813Skaashoek   }
129a64cd813Skaashoek   close(fd);
130a64cd813Skaashoek   fd = open("doesnotexist", 0);
131a64cd813Skaashoek   if(fd >= 0){
132a64cd813Skaashoek     printf(stdout, "open doesnotexist succeeded!\n");
133a64cd813Skaashoek     exit();
134a64cd813Skaashoek   }
135a64cd813Skaashoek   printf(stdout, "open test ok\n");
136a64cd813Skaashoek }
137a64cd813Skaashoek 
138a64cd813Skaashoek void
writetest(void)139a64cd813Skaashoek writetest(void)
140a64cd813Skaashoek {
141a64cd813Skaashoek   int fd;
142a64cd813Skaashoek   int i;
143a64cd813Skaashoek 
144a64cd813Skaashoek   printf(stdout, "small file test\n");
145a64cd813Skaashoek   fd = open("small", O_CREATE|O_RDWR);
146a64cd813Skaashoek   if(fd >= 0){
147a64cd813Skaashoek     printf(stdout, "creat small succeeded; ok\n");
148a64cd813Skaashoek   } else {
149a64cd813Skaashoek     printf(stdout, "error: creat small failed!\n");
150a64cd813Skaashoek     exit();
151a64cd813Skaashoek   }
152a64cd813Skaashoek   for(i = 0; i < 100; i++){
153a64cd813Skaashoek     if(write(fd, "aaaaaaaaaa", 10) != 10){
154a64cd813Skaashoek       printf(stdout, "error: write aa %d new file failed\n", i);
155a64cd813Skaashoek       exit();
156a64cd813Skaashoek     }
157a64cd813Skaashoek     if(write(fd, "bbbbbbbbbb", 10) != 10){
158a64cd813Skaashoek       printf(stdout, "error: write bb %d new file failed\n", i);
159a64cd813Skaashoek       exit();
160a64cd813Skaashoek     }
161a64cd813Skaashoek   }
162a64cd813Skaashoek   printf(stdout, "writes ok\n");
163a64cd813Skaashoek   close(fd);
164a64cd813Skaashoek   fd = open("small", O_RDONLY);
165a64cd813Skaashoek   if(fd >= 0){
166a64cd813Skaashoek     printf(stdout, "open small succeeded ok\n");
167a64cd813Skaashoek   } else {
168a64cd813Skaashoek     printf(stdout, "error: open small failed!\n");
169a64cd813Skaashoek     exit();
170a64cd813Skaashoek   }
171a64cd813Skaashoek   i = read(fd, buf, 2000);
172a64cd813Skaashoek   if(i == 2000){
173a64cd813Skaashoek     printf(stdout, "read succeeded ok\n");
174a64cd813Skaashoek   } else {
175a64cd813Skaashoek     printf(stdout, "read failed\n");
176a64cd813Skaashoek     exit();
177a64cd813Skaashoek   }
178a64cd813Skaashoek   close(fd);
179a64cd813Skaashoek 
180a64cd813Skaashoek   if(unlink("small") < 0){
181a64cd813Skaashoek     printf(stdout, "unlink small failed\n");
182a64cd813Skaashoek     exit();
183a64cd813Skaashoek   }
184a64cd813Skaashoek   printf(stdout, "small file test ok\n");
185a64cd813Skaashoek }
186a64cd813Skaashoek 
187a64cd813Skaashoek void
writetest1(void)188a64cd813Skaashoek writetest1(void)
189a64cd813Skaashoek {
190a64cd813Skaashoek   int i, fd, n;
191a64cd813Skaashoek 
192a64cd813Skaashoek   printf(stdout, "big files test\n");
193a64cd813Skaashoek 
194a64cd813Skaashoek   fd = open("big", O_CREATE|O_RDWR);
195a64cd813Skaashoek   if(fd < 0){
196a64cd813Skaashoek     printf(stdout, "error: creat big failed!\n");
197a64cd813Skaashoek     exit();
198a64cd813Skaashoek   }
199a64cd813Skaashoek 
200a64cd813Skaashoek   for(i = 0; i < MAXFILE; i++){
201a64cd813Skaashoek     ((int*)buf)[0] = i;
202a64cd813Skaashoek     if(write(fd, buf, 512) != 512){
203a64cd813Skaashoek       printf(stdout, "error: write big file failed\n", i);
204a64cd813Skaashoek       exit();
205a64cd813Skaashoek     }
206a64cd813Skaashoek   }
207a64cd813Skaashoek 
208a64cd813Skaashoek   close(fd);
209a64cd813Skaashoek 
210a64cd813Skaashoek   fd = open("big", O_RDONLY);
211a64cd813Skaashoek   if(fd < 0){
212a64cd813Skaashoek     printf(stdout, "error: open big failed!\n");
213a64cd813Skaashoek     exit();
214a64cd813Skaashoek   }
215a64cd813Skaashoek 
216a64cd813Skaashoek   n = 0;
217a64cd813Skaashoek   for(;;){
218a64cd813Skaashoek     i = read(fd, buf, 512);
219a64cd813Skaashoek     if(i == 0){
220a64cd813Skaashoek       if(n == MAXFILE - 1){
221a64cd813Skaashoek         printf(stdout, "read only %d blocks from big", n);
222a64cd813Skaashoek         exit();
223a64cd813Skaashoek       }
224a64cd813Skaashoek       break;
225a64cd813Skaashoek     } else if(i != 512){
226a64cd813Skaashoek       printf(stdout, "read failed %d\n", i);
227a64cd813Skaashoek       exit();
228a64cd813Skaashoek     }
229a64cd813Skaashoek     if(((int*)buf)[0] != n){
230a64cd813Skaashoek       printf(stdout, "read content of block %d is %d\n",
231a64cd813Skaashoek              n, ((int*)buf)[0]);
232a64cd813Skaashoek       exit();
233a64cd813Skaashoek     }
234a64cd813Skaashoek     n++;
235a64cd813Skaashoek   }
236a64cd813Skaashoek   close(fd);
237a64cd813Skaashoek   if(unlink("big") < 0){
238a64cd813Skaashoek     printf(stdout, "unlink big failed\n");
239a64cd813Skaashoek     exit();
240a64cd813Skaashoek   }
241a64cd813Skaashoek   printf(stdout, "big files ok\n");
242a64cd813Skaashoek }
243a64cd813Skaashoek 
244a64cd813Skaashoek void
createtest(void)245a64cd813Skaashoek createtest(void)
246a64cd813Skaashoek {
247a64cd813Skaashoek   int i, fd;
248a64cd813Skaashoek 
249a64cd813Skaashoek   printf(stdout, "many creates, followed by unlink test\n");
250a64cd813Skaashoek 
251a64cd813Skaashoek   name[0] = 'a';
252a64cd813Skaashoek   name[2] = '\0';
253a64cd813Skaashoek   for(i = 0; i < 52; i++){
254a64cd813Skaashoek     name[1] = '0' + i;
255a64cd813Skaashoek     fd = open(name, O_CREATE|O_RDWR);
256a64cd813Skaashoek     close(fd);
257a64cd813Skaashoek   }
258a64cd813Skaashoek   name[0] = 'a';
259a64cd813Skaashoek   name[2] = '\0';
260a64cd813Skaashoek   for(i = 0; i < 52; i++){
261a64cd813Skaashoek     name[1] = '0' + i;
262a64cd813Skaashoek     unlink(name);
263a64cd813Skaashoek   }
264a64cd813Skaashoek   printf(stdout, "many creates, followed by unlink; ok\n");
265a64cd813Skaashoek }
266a64cd813Skaashoek 
dirtest(void)267a64cd813Skaashoek void dirtest(void)
268a64cd813Skaashoek {
269a64cd813Skaashoek   printf(stdout, "mkdir test\n");
270a64cd813Skaashoek 
271a64cd813Skaashoek   if(mkdir("dir0") < 0){
272a64cd813Skaashoek     printf(stdout, "mkdir failed\n");
273a64cd813Skaashoek     exit();
274a64cd813Skaashoek   }
275a64cd813Skaashoek 
276a64cd813Skaashoek   if(chdir("dir0") < 0){
277a64cd813Skaashoek     printf(stdout, "chdir dir0 failed\n");
278a64cd813Skaashoek     exit();
279a64cd813Skaashoek   }
280a64cd813Skaashoek 
281a64cd813Skaashoek   if(chdir("..") < 0){
282a64cd813Skaashoek     printf(stdout, "chdir .. failed\n");
283a64cd813Skaashoek     exit();
284a64cd813Skaashoek   }
285a64cd813Skaashoek 
286a64cd813Skaashoek   if(unlink("dir0") < 0){
287a64cd813Skaashoek     printf(stdout, "unlink dir0 failed\n");
288a64cd813Skaashoek     exit();
289a64cd813Skaashoek   }
2902c565472SRobert Morris   printf(stdout, "mkdir test ok\n");
291a64cd813Skaashoek }
292a64cd813Skaashoek 
293a64cd813Skaashoek void
exectest(void)294a64cd813Skaashoek exectest(void)
295a64cd813Skaashoek {
296a64cd813Skaashoek   printf(stdout, "exec test\n");
29734295f46Srsc   if(exec("echo", echoargv) < 0){
298a64cd813Skaashoek     printf(stdout, "exec echo failed\n");
299a64cd813Skaashoek     exit();
300a64cd813Skaashoek   }
301a64cd813Skaashoek }
302c41f1de5Srtm 
303b548df15Srtm // simple fork and pipe read/write
304b548df15Srtm 
305c41f1de5Srtm void
pipe1(void)306c54c7926Srsc pipe1(void)
307c41f1de5Srtm {
308c41f1de5Srtm   int fds[2], pid;
309dca5b5caSrsc   int seq, i, n, cc, total;
310c41f1de5Srtm 
311dfcc5b99Srtm   if(pipe(fds) != 0){
312a64cd813Skaashoek     printf(1, "pipe() failed\n");
313dfcc5b99Srtm     exit();
314dfcc5b99Srtm   }
3158b4e2a08Srtm   pid = fork();
316dca5b5caSrsc   seq = 0;
317c41f1de5Srtm   if(pid == 0){
3188b4e2a08Srtm     close(fds[0]);
3198b4e2a08Srtm     for(n = 0; n < 5; n++){
3208b4e2a08Srtm       for(i = 0; i < 1033; i++)
3218b4e2a08Srtm         buf[i] = seq++;
3228b4e2a08Srtm       if(write(fds[1], buf, 1033) != 1033){
32343572072Srtm         printf(1, "pipe1 oops 1\n");
3249b37d1bfSrsc         exit();
3258b4e2a08Srtm       }
3268b4e2a08Srtm     }
3279b37d1bfSrsc     exit();
328dfcc5b99Srtm   } else if(pid > 0){
3298b4e2a08Srtm     close(fds[1]);
3308b4e2a08Srtm     total = 0;
3318b4e2a08Srtm     cc = 1;
332c54c7926Srsc     while((n = read(fds[0], buf, cc)) > 0){
3338b4e2a08Srtm       for(i = 0; i < n; i++){
3348b4e2a08Srtm         if((buf[i] & 0xff) != (seq++ & 0xff)){
33543572072Srtm           printf(1, "pipe1 oops 2\n");
336c41f1de5Srtm           return;
337c41f1de5Srtm         }
338c41f1de5Srtm       }
3398b4e2a08Srtm       total += n;
3408b4e2a08Srtm       cc = cc * 2;
3418b4e2a08Srtm       if(cc > sizeof(buf))
3428b4e2a08Srtm         cc = sizeof(buf);
3438b4e2a08Srtm     }
3445e083578SRobert Morris     if(total != 5 * 1033){
345dfcc5b99Srtm       printf(1, "pipe1 oops 3 total %d\n", total);
3465e083578SRobert Morris       exit();
3475e083578SRobert Morris     }
3488b4e2a08Srtm     close(fds[0]);
34946bbd72fSrtm     wait();
350dfcc5b99Srtm   } else {
351a64cd813Skaashoek     printf(1, "fork() failed\n");
352dfcc5b99Srtm     exit();
3538b4e2a08Srtm   }
354a64cd813Skaashoek   printf(1, "pipe1 ok\n");
355c41f1de5Srtm }
356c41f1de5Srtm 
357b548df15Srtm // meant to be run w/ at most two CPUs
358b548df15Srtm void
preempt(void)359c54c7926Srsc preempt(void)
360b548df15Srtm {
361b548df15Srtm   int pid1, pid2, pid3;
362b548df15Srtm   int pfds[2];
363b548df15Srtm 
36456c1a151Srsc   printf(1, "preempt: ");
365b548df15Srtm   pid1 = fork();
366b548df15Srtm   if(pid1 == 0)
367c54c7926Srsc     for(;;)
368b548df15Srtm       ;
369b548df15Srtm 
370b548df15Srtm   pid2 = fork();
371b548df15Srtm   if(pid2 == 0)
372c54c7926Srsc     for(;;)
373b548df15Srtm       ;
374b548df15Srtm 
375b548df15Srtm   pipe(pfds);
376b548df15Srtm   pid3 = fork();
377b548df15Srtm   if(pid3 == 0){
378b548df15Srtm     close(pfds[0]);
379b548df15Srtm     if(write(pfds[1], "x", 1) != 1)
38043572072Srtm       printf(1, "preempt write error");
381b548df15Srtm     close(pfds[1]);
382c54c7926Srsc     for(;;)
383b548df15Srtm       ;
384b548df15Srtm   }
385b548df15Srtm 
386b548df15Srtm   close(pfds[1]);
387b548df15Srtm   if(read(pfds[0], buf, sizeof(buf)) != 1){
38843572072Srtm     printf(1, "preempt read error");
389b548df15Srtm     return;
390b548df15Srtm   }
391b548df15Srtm   close(pfds[0]);
39256c1a151Srsc   printf(1, "kill... ");
393b548df15Srtm   kill(pid1);
394b548df15Srtm   kill(pid2);
395b548df15Srtm   kill(pid3);
39656c1a151Srsc   printf(1, "wait... ");
397b548df15Srtm   wait();
398b548df15Srtm   wait();
399b548df15Srtm   wait();
400a64cd813Skaashoek   printf(1, "preempt ok\n");
401b548df15Srtm }
402b548df15Srtm 
40346bbd72fSrtm // try to find any races between exit and wait
40446bbd72fSrtm void
exitwait(void)405c54c7926Srsc exitwait(void)
40646bbd72fSrtm {
40746bbd72fSrtm   int i, pid;
40846bbd72fSrtm 
40946bbd72fSrtm   for(i = 0; i < 100; i++){
41046bbd72fSrtm     pid = fork();
41146bbd72fSrtm     if(pid < 0){
41243572072Srtm       printf(1, "fork failed\n");
41346bbd72fSrtm       return;
41446bbd72fSrtm     }
41546bbd72fSrtm     if(pid){
41646bbd72fSrtm       if(wait() != pid){
41743572072Srtm         printf(1, "wait wrong pid\n");
41846bbd72fSrtm         return;
41946bbd72fSrtm       }
42046bbd72fSrtm     } else {
4219b37d1bfSrsc       exit();
42246bbd72fSrtm     }
42346bbd72fSrtm   }
424a64cd813Skaashoek   printf(1, "exitwait ok\n");
42546bbd72fSrtm }
42646bbd72fSrtm 
42781d52199Skaashoek void
mem(void)42881d52199Skaashoek mem(void)
42981d52199Skaashoek {
43081d52199Skaashoek   void *m1, *m2;
431789b508dSRobert Morris   int pid, ppid;
43281d52199Skaashoek 
433dd645ef1SAustin Clements   printf(1, "mem test\n");
434789b508dSRobert Morris   ppid = getpid();
435dfcc5b99Srtm   if((pid = fork()) == 0){
43681d52199Skaashoek     m1 = 0;
437dfcc5b99Srtm     while((m2 = malloc(10001)) != 0){
43881d52199Skaashoek       *(char**)m2 = m1;
43981d52199Skaashoek       m1 = m2;
44081d52199Skaashoek     }
44181d52199Skaashoek     while(m1){
44281d52199Skaashoek       m2 = *(char**)m1;
44381d52199Skaashoek       free(m1);
44481d52199Skaashoek       m1 = m2;
44581d52199Skaashoek     }
44681d52199Skaashoek     m1 = malloc(1024*20);
44781d52199Skaashoek     if(m1 == 0){
448a64cd813Skaashoek       printf(1, "couldn't allocate mem?!!\n");
449789b508dSRobert Morris       kill(ppid);
45081d52199Skaashoek       exit();
45181d52199Skaashoek     }
45281d52199Skaashoek     free(m1);
4533b95801aSrtm     printf(1, "mem ok\n");
454dfcc5b99Srtm     exit();
455dfcc5b99Srtm   } else {
456dfcc5b99Srtm     wait();
457dfcc5b99Srtm   }
45881d52199Skaashoek }
45981d52199Skaashoek 
460a64cd813Skaashoek // More file system tests
461a64cd813Skaashoek 
462a64cd813Skaashoek // two processes write to the same file descriptor
463a64cd813Skaashoek // is the offset shared? does inode locking work?
464a64cd813Skaashoek void
sharedfd(void)465c664dd5dSrsc sharedfd(void)
466a64cd813Skaashoek {
467a64cd813Skaashoek   int fd, pid, i, n, nc, np;
468a64cd813Skaashoek   char buf[10];
469a64cd813Skaashoek 
4705053dd6aSRobert Morris   printf(1, "sharedfd test\n");
4715053dd6aSRobert Morris 
472a64cd813Skaashoek   unlink("sharedfd");
473a64cd813Skaashoek   fd = open("sharedfd", O_CREATE|O_RDWR);
474a64cd813Skaashoek   if(fd < 0){
475a64cd813Skaashoek     printf(1, "fstests: cannot open sharedfd for writing");
476a64cd813Skaashoek     return;
477a64cd813Skaashoek   }
478a64cd813Skaashoek   pid = fork();
479a64cd813Skaashoek   memset(buf, pid==0?'c':'p', sizeof(buf));
480f3c393baSrsc   for(i = 0; i < 1000; i++){
481a64cd813Skaashoek     if(write(fd, buf, sizeof(buf)) != sizeof(buf)){
482a64cd813Skaashoek       printf(1, "fstests: write sharedfd failed\n");
483a64cd813Skaashoek       break;
484a64cd813Skaashoek     }
485a64cd813Skaashoek   }
486a64cd813Skaashoek   if(pid == 0)
487a64cd813Skaashoek     exit();
488a64cd813Skaashoek   else
489a64cd813Skaashoek     wait();
490a64cd813Skaashoek   close(fd);
491a64cd813Skaashoek   fd = open("sharedfd", 0);
492a64cd813Skaashoek   if(fd < 0){
493a64cd813Skaashoek     printf(1, "fstests: cannot open sharedfd for reading\n");
494a64cd813Skaashoek     return;
495a64cd813Skaashoek   }
496a64cd813Skaashoek   nc = np = 0;
497a64cd813Skaashoek   while((n = read(fd, buf, sizeof(buf))) > 0){
498a64cd813Skaashoek     for(i = 0; i < sizeof(buf); i++){
499a64cd813Skaashoek       if(buf[i] == 'c')
500a64cd813Skaashoek         nc++;
501a64cd813Skaashoek       if(buf[i] == 'p')
502a64cd813Skaashoek         np++;
503a64cd813Skaashoek     }
504a64cd813Skaashoek   }
505a64cd813Skaashoek   close(fd);
506a64cd813Skaashoek   unlink("sharedfd");
5075e083578SRobert Morris   if(nc == 10000 && np == 10000){
508a64cd813Skaashoek     printf(1, "sharedfd ok\n");
5095e083578SRobert Morris   } else {
510a64cd813Skaashoek     printf(1, "sharedfd oops %d %d\n", nc, np);
5115e083578SRobert Morris     exit();
5125e083578SRobert Morris   }
513a64cd813Skaashoek }
514a64cd813Skaashoek 
51548aa9174SRobert Morris // four processes write different files at the same
516a64cd813Skaashoek // time, to test block allocation.
517a64cd813Skaashoek void
fourfiles(void)51848aa9174SRobert Morris fourfiles(void)
519a64cd813Skaashoek {
52048aa9174SRobert Morris   int fd, pid, i, j, n, total, pi;
52148aa9174SRobert Morris   char *names[] = { "f0", "f1", "f2", "f3" };
522a64cd813Skaashoek   char *fname;
523a64cd813Skaashoek 
52448aa9174SRobert Morris   printf(1, "fourfiles test\n");
525a64cd813Skaashoek 
52648aa9174SRobert Morris   for(pi = 0; pi < 4; pi++){
52748aa9174SRobert Morris     fname = names[pi];
52848aa9174SRobert Morris     unlink(fname);
529a64cd813Skaashoek 
530a64cd813Skaashoek     pid = fork();
531a64cd813Skaashoek     if(pid < 0){
532a64cd813Skaashoek       printf(1, "fork failed\n");
5335e083578SRobert Morris       exit();
534a64cd813Skaashoek     }
535a64cd813Skaashoek 
53648aa9174SRobert Morris     if(pid == 0){
537a64cd813Skaashoek       fd = open(fname, O_CREATE | O_RDWR);
538a64cd813Skaashoek       if(fd < 0){
539a64cd813Skaashoek         printf(1, "create failed\n");
540a64cd813Skaashoek         exit();
541a64cd813Skaashoek       }
542a64cd813Skaashoek 
54348aa9174SRobert Morris       memset(buf, '0'+pi, 512);
544a64cd813Skaashoek       for(i = 0; i < 12; i++){
545a64cd813Skaashoek         if((n = write(fd, buf, 500)) != 500){
546a64cd813Skaashoek           printf(1, "write failed %d\n", n);
547a64cd813Skaashoek           exit();
548a64cd813Skaashoek         }
549a64cd813Skaashoek       }
550a64cd813Skaashoek       exit();
55148aa9174SRobert Morris     }
55248aa9174SRobert Morris   }
55348aa9174SRobert Morris 
55448aa9174SRobert Morris   for(pi = 0; pi < 4; pi++){
55548aa9174SRobert Morris     wait();
55648aa9174SRobert Morris   }
557a64cd813Skaashoek 
558a64cd813Skaashoek   for(i = 0; i < 2; i++){
55948aa9174SRobert Morris     fname = names[i];
56048aa9174SRobert Morris     fd = open(fname, 0);
561a64cd813Skaashoek     total = 0;
562a64cd813Skaashoek     while((n = read(fd, buf, sizeof(buf))) > 0){
563a64cd813Skaashoek       for(j = 0; j < n; j++){
56448aa9174SRobert Morris         if(buf[j] != '0'+i){
565a64cd813Skaashoek           printf(1, "wrong char\n");
566a64cd813Skaashoek           exit();
567a64cd813Skaashoek         }
568a64cd813Skaashoek       }
569a64cd813Skaashoek       total += n;
570a64cd813Skaashoek     }
571a64cd813Skaashoek     close(fd);
572a64cd813Skaashoek     if(total != 12*500){
573a64cd813Skaashoek       printf(1, "wrong length %d\n", total);
574a64cd813Skaashoek       exit();
575a64cd813Skaashoek     }
57648aa9174SRobert Morris     unlink(fname);
577a64cd813Skaashoek   }
578a64cd813Skaashoek 
57948aa9174SRobert Morris   printf(1, "fourfiles ok\n");
580a64cd813Skaashoek }
581a64cd813Skaashoek 
58248aa9174SRobert Morris // four processes create and delete different files in same directory
583a64cd813Skaashoek void
createdelete(void)584c664dd5dSrsc createdelete(void)
585a64cd813Skaashoek {
586dca5b5caSrsc   enum { N = 20 };
58748aa9174SRobert Morris   int pid, i, fd, pi;
588a64cd813Skaashoek   char name[32];
589a64cd813Skaashoek 
590a64cd813Skaashoek   printf(1, "createdelete test\n");
59148aa9174SRobert Morris 
59248aa9174SRobert Morris   for(pi = 0; pi < 4; pi++){
593a64cd813Skaashoek     pid = fork();
594a64cd813Skaashoek     if(pid < 0){
595a64cd813Skaashoek       printf(1, "fork failed\n");
596a64cd813Skaashoek       exit();
597a64cd813Skaashoek     }
598a64cd813Skaashoek 
59948aa9174SRobert Morris     if(pid == 0){
60048aa9174SRobert Morris       name[0] = 'p' + pi;
601a64cd813Skaashoek       name[2] = '\0';
602dca5b5caSrsc       for(i = 0; i < N; i++){
603a64cd813Skaashoek         name[1] = '0' + i;
604a64cd813Skaashoek         fd = open(name, O_CREATE | O_RDWR);
605a64cd813Skaashoek         if(fd < 0){
606a64cd813Skaashoek           printf(1, "create failed\n");
607a64cd813Skaashoek           exit();
608a64cd813Skaashoek         }
609a64cd813Skaashoek         close(fd);
610a64cd813Skaashoek         if(i > 0 && (i % 2 ) == 0){
611a64cd813Skaashoek           name[1] = '0' + (i / 2);
612a64cd813Skaashoek           if(unlink(name) < 0){
613a64cd813Skaashoek             printf(1, "unlink failed\n");
614a64cd813Skaashoek             exit();
615a64cd813Skaashoek           }
616a64cd813Skaashoek         }
617a64cd813Skaashoek       }
618a64cd813Skaashoek       exit();
61948aa9174SRobert Morris     }
62048aa9174SRobert Morris   }
62148aa9174SRobert Morris 
62248aa9174SRobert Morris   for(pi = 0; pi < 4; pi++){
6232d61a40bSrsc     wait();
624a64cd813Skaashoek   }
625a64cd813Skaashoek 
62648aa9174SRobert Morris   name[0] = name[1] = name[2] = 0;
62748aa9174SRobert Morris   for(i = 0; i < N; i++){
62848aa9174SRobert Morris     for(pi = 0; pi < 4; pi++){
62948aa9174SRobert Morris       name[0] = 'p' + pi;
630a64cd813Skaashoek       name[1] = '0' + i;
631a64cd813Skaashoek       fd = open(name, 0);
632dca5b5caSrsc       if((i == 0 || i >= N/2) && fd < 0){
633a64cd813Skaashoek         printf(1, "oops createdelete %s didn't exist\n", name);
634a64cd813Skaashoek         exit();
635dca5b5caSrsc       } else if((i >= 1 && i < N/2) && fd >= 0){
636a64cd813Skaashoek         printf(1, "oops createdelete %s did exist\n", name);
637a64cd813Skaashoek         exit();
638a64cd813Skaashoek       }
639a64cd813Skaashoek       if(fd >= 0)
640a64cd813Skaashoek         close(fd);
641a64cd813Skaashoek     }
64248aa9174SRobert Morris   }
643a64cd813Skaashoek 
644dca5b5caSrsc   for(i = 0; i < N; i++){
64548aa9174SRobert Morris     for(pi = 0; pi < 4; pi++){
64648aa9174SRobert Morris       name[0] = 'p' + i;
647a64cd813Skaashoek       name[1] = '0' + i;
648a64cd813Skaashoek       unlink(name);
64948aa9174SRobert Morris     }
650a64cd813Skaashoek   }
651a64cd813Skaashoek 
652a64cd813Skaashoek   printf(1, "createdelete ok\n");
653a64cd813Skaashoek }
654a64cd813Skaashoek 
655a64cd813Skaashoek // can I unlink a file and still read it?
656a64cd813Skaashoek void
unlinkread(void)657c664dd5dSrsc unlinkread(void)
658a64cd813Skaashoek {
659a64cd813Skaashoek   int fd, fd1;
660a64cd813Skaashoek 
661a64cd813Skaashoek   printf(1, "unlinkread test\n");
662a64cd813Skaashoek   fd = open("unlinkread", O_CREATE | O_RDWR);
663a64cd813Skaashoek   if(fd < 0){
664a64cd813Skaashoek     printf(1, "create unlinkread failed\n");
665a64cd813Skaashoek     exit();
666a64cd813Skaashoek   }
667a64cd813Skaashoek   write(fd, "hello", 5);
668a64cd813Skaashoek   close(fd);
669a64cd813Skaashoek 
670a64cd813Skaashoek   fd = open("unlinkread", O_RDWR);
671a64cd813Skaashoek   if(fd < 0){
672a64cd813Skaashoek     printf(1, "open unlinkread failed\n");
673a64cd813Skaashoek     exit();
674a64cd813Skaashoek   }
675a64cd813Skaashoek   if(unlink("unlinkread") != 0){
676a64cd813Skaashoek     printf(1, "unlink unlinkread failed\n");
677a64cd813Skaashoek     exit();
678a64cd813Skaashoek   }
679a64cd813Skaashoek 
680a64cd813Skaashoek   fd1 = open("unlinkread", O_CREATE | O_RDWR);
681a64cd813Skaashoek   write(fd1, "yyy", 3);
682a64cd813Skaashoek   close(fd1);
683a64cd813Skaashoek 
684a64cd813Skaashoek   if(read(fd, buf, sizeof(buf)) != 5){
685a64cd813Skaashoek     printf(1, "unlinkread read failed");
686a64cd813Skaashoek     exit();
687a64cd813Skaashoek   }
688a64cd813Skaashoek   if(buf[0] != 'h'){
689a64cd813Skaashoek     printf(1, "unlinkread wrong data\n");
690a64cd813Skaashoek     exit();
691a64cd813Skaashoek   }
692a64cd813Skaashoek   if(write(fd, buf, 10) != 10){
693a64cd813Skaashoek     printf(1, "unlinkread write failed\n");
694a64cd813Skaashoek     exit();
695a64cd813Skaashoek   }
696a64cd813Skaashoek   close(fd);
697a64cd813Skaashoek   unlink("unlinkread");
698a64cd813Skaashoek   printf(1, "unlinkread ok\n");
699a64cd813Skaashoek }
700a64cd813Skaashoek 
701a64cd813Skaashoek void
linktest(void)702c664dd5dSrsc linktest(void)
703a64cd813Skaashoek {
704a64cd813Skaashoek   int fd;
705a64cd813Skaashoek 
706a64cd813Skaashoek   printf(1, "linktest\n");
707a64cd813Skaashoek 
708a64cd813Skaashoek   unlink("lf1");
709a64cd813Skaashoek   unlink("lf2");
710a64cd813Skaashoek 
711a64cd813Skaashoek   fd = open("lf1", O_CREATE|O_RDWR);
712a64cd813Skaashoek   if(fd < 0){
713a64cd813Skaashoek     printf(1, "create lf1 failed\n");
714a64cd813Skaashoek     exit();
715a64cd813Skaashoek   }
716a64cd813Skaashoek   if(write(fd, "hello", 5) != 5){
717a64cd813Skaashoek     printf(1, "write lf1 failed\n");
718a64cd813Skaashoek     exit();
719a64cd813Skaashoek   }
720a64cd813Skaashoek   close(fd);
721a64cd813Skaashoek 
722a64cd813Skaashoek   if(link("lf1", "lf2") < 0){
723a64cd813Skaashoek     printf(1, "link lf1 lf2 failed\n");
724a64cd813Skaashoek     exit();
725a64cd813Skaashoek   }
726a64cd813Skaashoek   unlink("lf1");
727a64cd813Skaashoek 
728a64cd813Skaashoek   if(open("lf1", 0) >= 0){
729a64cd813Skaashoek     printf(1, "unlinked lf1 but it is still there!\n");
730a64cd813Skaashoek     exit();
731a64cd813Skaashoek   }
732a64cd813Skaashoek 
733a64cd813Skaashoek   fd = open("lf2", 0);
734a64cd813Skaashoek   if(fd < 0){
735a64cd813Skaashoek     printf(1, "open lf2 failed\n");
736a64cd813Skaashoek     exit();
737a64cd813Skaashoek   }
738a64cd813Skaashoek   if(read(fd, buf, sizeof(buf)) != 5){
739a64cd813Skaashoek     printf(1, "read lf2 failed\n");
740a64cd813Skaashoek     exit();
741a64cd813Skaashoek   }
742a64cd813Skaashoek   close(fd);
743a64cd813Skaashoek 
744a64cd813Skaashoek   if(link("lf2", "lf2") >= 0){
745a64cd813Skaashoek     printf(1, "link lf2 lf2 succeeded! oops\n");
746a64cd813Skaashoek     exit();
747a64cd813Skaashoek   }
748a64cd813Skaashoek 
749a64cd813Skaashoek   unlink("lf2");
750a64cd813Skaashoek   if(link("lf2", "lf1") >= 0){
751a64cd813Skaashoek     printf(1, "link non-existant succeeded! oops\n");
752a64cd813Skaashoek     exit();
753a64cd813Skaashoek   }
754a64cd813Skaashoek 
755a64cd813Skaashoek   if(link(".", "lf1") >= 0){
756a64cd813Skaashoek     printf(1, "link . lf1 succeeded! oops\n");
757a64cd813Skaashoek     exit();
758a64cd813Skaashoek   }
759a64cd813Skaashoek 
760a64cd813Skaashoek   printf(1, "linktest ok\n");
761a64cd813Skaashoek }
762a64cd813Skaashoek 
7635053dd6aSRobert Morris // test concurrent create/link/unlink of the same file
764a64cd813Skaashoek void
concreate(void)765c664dd5dSrsc concreate(void)
766a64cd813Skaashoek {
767a64cd813Skaashoek   char file[3];
768a64cd813Skaashoek   int i, pid, n, fd;
769a64cd813Skaashoek   char fa[40];
770a64cd813Skaashoek   struct {
771115e1774Srsc     ushort inum;
772a64cd813Skaashoek     char name[14];
773a64cd813Skaashoek   } de;
774a64cd813Skaashoek 
775a64cd813Skaashoek   printf(1, "concreate test\n");
776a64cd813Skaashoek   file[0] = 'C';
777a64cd813Skaashoek   file[2] = '\0';
778a64cd813Skaashoek   for(i = 0; i < 40; i++){
779a64cd813Skaashoek     file[1] = '0' + i;
780a64cd813Skaashoek     unlink(file);
781a64cd813Skaashoek     pid = fork();
782a64cd813Skaashoek     if(pid && (i % 3) == 1){
783a64cd813Skaashoek       link("C0", file);
784a64cd813Skaashoek     } else if(pid == 0 && (i % 5) == 1){
785a64cd813Skaashoek       link("C0", file);
786a64cd813Skaashoek     } else {
787a64cd813Skaashoek       fd = open(file, O_CREATE | O_RDWR);
788a64cd813Skaashoek       if(fd < 0){
789a64cd813Skaashoek         printf(1, "concreate create %s failed\n", file);
790a64cd813Skaashoek         exit();
791a64cd813Skaashoek       }
792a64cd813Skaashoek       close(fd);
793a64cd813Skaashoek     }
794a64cd813Skaashoek     if(pid == 0)
795a64cd813Skaashoek       exit();
796a64cd813Skaashoek     else
797a64cd813Skaashoek       wait();
798a64cd813Skaashoek   }
799a64cd813Skaashoek 
800a64cd813Skaashoek   memset(fa, 0, sizeof(fa));
801a64cd813Skaashoek   fd = open(".", 0);
802a64cd813Skaashoek   n = 0;
803a64cd813Skaashoek   while(read(fd, &de, sizeof(de)) > 0){
804a64cd813Skaashoek     if(de.inum == 0)
805a64cd813Skaashoek       continue;
806a64cd813Skaashoek     if(de.name[0] == 'C' && de.name[2] == '\0'){
807a64cd813Skaashoek       i = de.name[1] - '0';
808a64cd813Skaashoek       if(i < 0 || i >= sizeof(fa)){
809a64cd813Skaashoek         printf(1, "concreate weird file %s\n", de.name);
810a64cd813Skaashoek         exit();
811a64cd813Skaashoek       }
812a64cd813Skaashoek       if(fa[i]){
813a64cd813Skaashoek         printf(1, "concreate duplicate file %s\n", de.name);
814a64cd813Skaashoek         exit();
815a64cd813Skaashoek       }
816a64cd813Skaashoek       fa[i] = 1;
817a64cd813Skaashoek       n++;
818a64cd813Skaashoek     }
819a64cd813Skaashoek   }
820a64cd813Skaashoek   close(fd);
821a64cd813Skaashoek 
822a64cd813Skaashoek   if(n != 40){
823a64cd813Skaashoek     printf(1, "concreate not enough files in directory listing\n");
824a64cd813Skaashoek     exit();
825a64cd813Skaashoek   }
826a64cd813Skaashoek 
827a64cd813Skaashoek   for(i = 0; i < 40; i++){
828a64cd813Skaashoek     file[1] = '0' + i;
8293d5f21eeSrtm     pid = fork();
8303d5f21eeSrtm     if(pid < 0){
8313d5f21eeSrtm       printf(1, "fork failed\n");
8323d5f21eeSrtm       exit();
8333d5f21eeSrtm     }
8343d5f21eeSrtm     if(((i % 3) == 0 && pid == 0) ||
8353d5f21eeSrtm        ((i % 3) == 1 && pid != 0)){
8365053dd6aSRobert Morris       close(open(file, 0));
8375053dd6aSRobert Morris       close(open(file, 0));
8385053dd6aSRobert Morris       close(open(file, 0));
8395053dd6aSRobert Morris       close(open(file, 0));
8403d5f21eeSrtm     } else {
841a64cd813Skaashoek       unlink(file);
8425053dd6aSRobert Morris       unlink(file);
8435053dd6aSRobert Morris       unlink(file);
8445053dd6aSRobert Morris       unlink(file);
845a64cd813Skaashoek     }
8463d5f21eeSrtm     if(pid == 0)
8473d5f21eeSrtm       exit();
8483d5f21eeSrtm     else
8493d5f21eeSrtm       wait();
8503d5f21eeSrtm   }
851a64cd813Skaashoek 
852a64cd813Skaashoek   printf(1, "concreate ok\n");
853a64cd813Skaashoek }
854a64cd813Skaashoek 
8555053dd6aSRobert Morris // another concurrent link/unlink/create test,
8565053dd6aSRobert Morris // to look for deadlocks.
8575053dd6aSRobert Morris void
linkunlink()8585053dd6aSRobert Morris linkunlink()
8595053dd6aSRobert Morris {
8605053dd6aSRobert Morris   int pid, i;
8615053dd6aSRobert Morris 
8625053dd6aSRobert Morris   printf(1, "linkunlink test\n");
8635053dd6aSRobert Morris 
8645053dd6aSRobert Morris   unlink("x");
8655053dd6aSRobert Morris   pid = fork();
8665053dd6aSRobert Morris   if(pid < 0){
8675053dd6aSRobert Morris     printf(1, "fork failed\n");
8685053dd6aSRobert Morris     exit();
8695053dd6aSRobert Morris   }
8705053dd6aSRobert Morris 
8715053dd6aSRobert Morris   unsigned int x = (pid ? 1 : 97);
8725053dd6aSRobert Morris   for(i = 0; i < 100; i++){
8735053dd6aSRobert Morris     x = x * 1103515245 + 12345;
8745053dd6aSRobert Morris     if((x % 3) == 0){
8755053dd6aSRobert Morris       close(open("x", O_RDWR | O_CREATE));
8765053dd6aSRobert Morris     } else if((x % 3) == 1){
8775053dd6aSRobert Morris       link("cat", "x");
8785053dd6aSRobert Morris     } else {
8795053dd6aSRobert Morris       unlink("x");
8805053dd6aSRobert Morris     }
8815053dd6aSRobert Morris   }
8825053dd6aSRobert Morris 
8835053dd6aSRobert Morris   if(pid)
8845053dd6aSRobert Morris     wait();
8855053dd6aSRobert Morris   else
8865053dd6aSRobert Morris     exit();
8875053dd6aSRobert Morris 
8885053dd6aSRobert Morris   printf(1, "linkunlink ok\n");
8895053dd6aSRobert Morris }
8905053dd6aSRobert Morris 
891a64cd813Skaashoek // directory that uses indirect blocks
892a64cd813Skaashoek void
bigdir(void)893c664dd5dSrsc bigdir(void)
894a64cd813Skaashoek {
895a64cd813Skaashoek   int i, fd;
896a64cd813Skaashoek   char name[10];
897a64cd813Skaashoek 
898a64cd813Skaashoek   printf(1, "bigdir test\n");
899a64cd813Skaashoek   unlink("bd");
900a64cd813Skaashoek 
901a64cd813Skaashoek   fd = open("bd", O_CREATE);
902a64cd813Skaashoek   if(fd < 0){
903a64cd813Skaashoek     printf(1, "bigdir create failed\n");
904a64cd813Skaashoek     exit();
905a64cd813Skaashoek   }
906a64cd813Skaashoek   close(fd);
907a64cd813Skaashoek 
908a64cd813Skaashoek   for(i = 0; i < 500; i++){
909a64cd813Skaashoek     name[0] = 'x';
910a64cd813Skaashoek     name[1] = '0' + (i / 64);
911a64cd813Skaashoek     name[2] = '0' + (i % 64);
912a64cd813Skaashoek     name[3] = '\0';
913a64cd813Skaashoek     if(link("bd", name) != 0){
914a64cd813Skaashoek       printf(1, "bigdir link failed\n");
915a64cd813Skaashoek       exit();
916a64cd813Skaashoek     }
917a64cd813Skaashoek   }
918a64cd813Skaashoek 
919a64cd813Skaashoek   unlink("bd");
920a64cd813Skaashoek   for(i = 0; i < 500; i++){
921a64cd813Skaashoek     name[0] = 'x';
922a64cd813Skaashoek     name[1] = '0' + (i / 64);
923a64cd813Skaashoek     name[2] = '0' + (i % 64);
924a64cd813Skaashoek     name[3] = '\0';
925a64cd813Skaashoek     if(unlink(name) != 0){
926a64cd813Skaashoek       printf(1, "bigdir unlink failed");
927a64cd813Skaashoek       exit();
928a64cd813Skaashoek     }
929a64cd813Skaashoek   }
930a64cd813Skaashoek 
931a64cd813Skaashoek   printf(1, "bigdir ok\n");
932a64cd813Skaashoek }
933a64cd813Skaashoek 
934a64cd813Skaashoek void
subdir(void)935c664dd5dSrsc subdir(void)
936a64cd813Skaashoek {
937a64cd813Skaashoek   int fd, cc;
938a64cd813Skaashoek 
939a64cd813Skaashoek   printf(1, "subdir test\n");
940a64cd813Skaashoek 
941a64cd813Skaashoek   unlink("ff");
942a64cd813Skaashoek   if(mkdir("dd") != 0){
943a64cd813Skaashoek     printf(1, "subdir mkdir dd failed\n");
944a64cd813Skaashoek     exit();
945a64cd813Skaashoek   }
946a64cd813Skaashoek 
947a64cd813Skaashoek   fd = open("dd/ff", O_CREATE | O_RDWR);
948a64cd813Skaashoek   if(fd < 0){
949a64cd813Skaashoek     printf(1, "create dd/ff failed\n");
950a64cd813Skaashoek     exit();
951a64cd813Skaashoek   }
952a64cd813Skaashoek   write(fd, "ff", 2);
953a64cd813Skaashoek   close(fd);
954a64cd813Skaashoek 
955c88bf235Srsc   if(unlink("dd") >= 0){
956c88bf235Srsc     printf(1, "unlink dd (non-empty dir) succeeded!\n");
957c88bf235Srsc     exit();
958c88bf235Srsc   }
959c88bf235Srsc 
960a64cd813Skaashoek   if(mkdir("/dd/dd") != 0){
961a64cd813Skaashoek     printf(1, "subdir mkdir dd/dd failed\n");
962a64cd813Skaashoek     exit();
963a64cd813Skaashoek   }
964a64cd813Skaashoek 
965a64cd813Skaashoek   fd = open("dd/dd/ff", O_CREATE | O_RDWR);
966a64cd813Skaashoek   if(fd < 0){
967a64cd813Skaashoek     printf(1, "create dd/dd/ff failed\n");
968a64cd813Skaashoek     exit();
969a64cd813Skaashoek   }
970a64cd813Skaashoek   write(fd, "FF", 2);
971a64cd813Skaashoek   close(fd);
972a64cd813Skaashoek 
973a64cd813Skaashoek   fd = open("dd/dd/../ff", 0);
974a64cd813Skaashoek   if(fd < 0){
975a64cd813Skaashoek     printf(1, "open dd/dd/../ff failed\n");
976a64cd813Skaashoek     exit();
977a64cd813Skaashoek   }
978a64cd813Skaashoek   cc = read(fd, buf, sizeof(buf));
979a64cd813Skaashoek   if(cc != 2 || buf[0] != 'f'){
980a64cd813Skaashoek     printf(1, "dd/dd/../ff wrong content\n");
981a64cd813Skaashoek     exit();
982a64cd813Skaashoek   }
983a64cd813Skaashoek   close(fd);
984a64cd813Skaashoek 
985a64cd813Skaashoek   if(link("dd/dd/ff", "dd/dd/ffff") != 0){
986a64cd813Skaashoek     printf(1, "link dd/dd/ff dd/dd/ffff failed\n");
987a64cd813Skaashoek     exit();
988a64cd813Skaashoek   }
989a64cd813Skaashoek 
990a64cd813Skaashoek   if(unlink("dd/dd/ff") != 0){
991a64cd813Skaashoek     printf(1, "unlink dd/dd/ff failed\n");
992a64cd813Skaashoek     exit();
993a64cd813Skaashoek   }
994c88bf235Srsc   if(open("dd/dd/ff", O_RDONLY) >= 0){
995c88bf235Srsc     printf(1, "open (unlinked) dd/dd/ff succeeded\n");
996c88bf235Srsc     exit();
997c88bf235Srsc   }
998a64cd813Skaashoek 
999a64cd813Skaashoek   if(chdir("dd") != 0){
1000a64cd813Skaashoek     printf(1, "chdir dd failed\n");
1001a64cd813Skaashoek     exit();
1002a64cd813Skaashoek   }
1003a64cd813Skaashoek   if(chdir("dd/../../dd") != 0){
1004a64cd813Skaashoek     printf(1, "chdir dd/../../dd failed\n");
1005a64cd813Skaashoek     exit();
1006a64cd813Skaashoek   }
1007c88bf235Srsc   if(chdir("dd/../../../dd") != 0){
1008c88bf235Srsc     printf(1, "chdir dd/../../dd failed\n");
1009c88bf235Srsc     exit();
1010c88bf235Srsc   }
1011a64cd813Skaashoek   if(chdir("./..") != 0){
1012a64cd813Skaashoek     printf(1, "chdir ./.. failed\n");
1013a64cd813Skaashoek     exit();
1014a64cd813Skaashoek   }
1015a64cd813Skaashoek 
1016a64cd813Skaashoek   fd = open("dd/dd/ffff", 0);
1017a64cd813Skaashoek   if(fd < 0){
1018a64cd813Skaashoek     printf(1, "open dd/dd/ffff failed\n");
1019a64cd813Skaashoek     exit();
1020a64cd813Skaashoek   }
1021a64cd813Skaashoek   if(read(fd, buf, sizeof(buf)) != 2){
1022a64cd813Skaashoek     printf(1, "read dd/dd/ffff wrong len\n");
1023a64cd813Skaashoek     exit();
1024a64cd813Skaashoek   }
1025a64cd813Skaashoek   close(fd);
1026a64cd813Skaashoek 
1027c88bf235Srsc   if(open("dd/dd/ff", O_RDONLY) >= 0){
1028c88bf235Srsc     printf(1, "open (unlinked) dd/dd/ff succeeded!\n");
1029a64cd813Skaashoek     exit();
1030a64cd813Skaashoek   }
1031a64cd813Skaashoek 
1032a64cd813Skaashoek   if(open("dd/ff/ff", O_CREATE|O_RDWR) >= 0){
1033a64cd813Skaashoek     printf(1, "create dd/ff/ff succeeded!\n");
1034a64cd813Skaashoek     exit();
1035a64cd813Skaashoek   }
1036a64cd813Skaashoek   if(open("dd/xx/ff", O_CREATE|O_RDWR) >= 0){
1037a64cd813Skaashoek     printf(1, "create dd/xx/ff succeeded!\n");
1038a64cd813Skaashoek     exit();
1039a64cd813Skaashoek   }
1040a64cd813Skaashoek   if(open("dd", O_CREATE) >= 0){
1041a64cd813Skaashoek     printf(1, "create dd succeeded!\n");
1042a64cd813Skaashoek     exit();
1043a64cd813Skaashoek   }
1044a64cd813Skaashoek   if(open("dd", O_RDWR) >= 0){
1045a64cd813Skaashoek     printf(1, "open dd rdwr succeeded!\n");
1046a64cd813Skaashoek     exit();
1047a64cd813Skaashoek   }
1048a64cd813Skaashoek   if(open("dd", O_WRONLY) >= 0){
1049a64cd813Skaashoek     printf(1, "open dd wronly succeeded!\n");
1050a64cd813Skaashoek     exit();
1051a64cd813Skaashoek   }
1052a64cd813Skaashoek   if(link("dd/ff/ff", "dd/dd/xx") == 0){
1053a64cd813Skaashoek     printf(1, "link dd/ff/ff dd/dd/xx succeeded!\n");
1054a64cd813Skaashoek     exit();
1055a64cd813Skaashoek   }
1056a64cd813Skaashoek   if(link("dd/xx/ff", "dd/dd/xx") == 0){
1057a64cd813Skaashoek     printf(1, "link dd/xx/ff dd/dd/xx succeeded!\n");
1058a64cd813Skaashoek     exit();
1059a64cd813Skaashoek   }
1060a64cd813Skaashoek   if(link("dd/ff", "dd/dd/ffff") == 0){
1061a64cd813Skaashoek     printf(1, "link dd/ff dd/dd/ffff succeeded!\n");
1062a64cd813Skaashoek     exit();
1063a64cd813Skaashoek   }
1064a64cd813Skaashoek   if(mkdir("dd/ff/ff") == 0){
1065a64cd813Skaashoek     printf(1, "mkdir dd/ff/ff succeeded!\n");
1066a64cd813Skaashoek     exit();
1067a64cd813Skaashoek   }
1068a64cd813Skaashoek   if(mkdir("dd/xx/ff") == 0){
1069a64cd813Skaashoek     printf(1, "mkdir dd/xx/ff succeeded!\n");
1070a64cd813Skaashoek     exit();
1071a64cd813Skaashoek   }
1072a64cd813Skaashoek   if(mkdir("dd/dd/ffff") == 0){
1073a64cd813Skaashoek     printf(1, "mkdir dd/dd/ffff succeeded!\n");
1074a64cd813Skaashoek     exit();
1075a64cd813Skaashoek   }
1076a64cd813Skaashoek   if(unlink("dd/xx/ff") == 0){
1077a64cd813Skaashoek     printf(1, "unlink dd/xx/ff succeeded!\n");
1078a64cd813Skaashoek     exit();
1079a64cd813Skaashoek   }
1080a64cd813Skaashoek   if(unlink("dd/ff/ff") == 0){
1081a64cd813Skaashoek     printf(1, "unlink dd/ff/ff succeeded!\n");
1082a64cd813Skaashoek     exit();
1083a64cd813Skaashoek   }
1084a64cd813Skaashoek   if(chdir("dd/ff") == 0){
1085a64cd813Skaashoek     printf(1, "chdir dd/ff succeeded!\n");
1086a64cd813Skaashoek     exit();
1087a64cd813Skaashoek   }
1088a64cd813Skaashoek   if(chdir("dd/xx") == 0){
1089a64cd813Skaashoek     printf(1, "chdir dd/xx succeeded!\n");
1090a64cd813Skaashoek     exit();
1091a64cd813Skaashoek   }
1092a64cd813Skaashoek 
1093a64cd813Skaashoek   if(unlink("dd/dd/ffff") != 0){
1094a64cd813Skaashoek     printf(1, "unlink dd/dd/ff failed\n");
1095a64cd813Skaashoek     exit();
1096a64cd813Skaashoek   }
1097a64cd813Skaashoek   if(unlink("dd/ff") != 0){
1098a64cd813Skaashoek     printf(1, "unlink dd/ff failed\n");
1099a64cd813Skaashoek     exit();
1100a64cd813Skaashoek   }
1101c88bf235Srsc   if(unlink("dd") == 0){
1102c88bf235Srsc     printf(1, "unlink non-empty dd succeeded!\n");
1103c88bf235Srsc     exit();
1104c88bf235Srsc   }
1105c88bf235Srsc   if(unlink("dd/dd") < 0){
1106c88bf235Srsc     printf(1, "unlink dd/dd failed\n");
1107c88bf235Srsc     exit();
1108c88bf235Srsc   }
1109c88bf235Srsc   if(unlink("dd") < 0){
1110c88bf235Srsc     printf(1, "unlink dd failed\n");
1111c88bf235Srsc     exit();
1112c88bf235Srsc   }
1113a64cd813Skaashoek 
1114a64cd813Skaashoek   printf(1, "subdir ok\n");
1115a64cd813Skaashoek }
1116a64cd813Skaashoek 
11172e590463SRobert Morris // test writes that are larger than the log.
11182e590463SRobert Morris void
bigwrite(void)11192e590463SRobert Morris bigwrite(void)
11202e590463SRobert Morris {
11212e590463SRobert Morris   int fd, sz;
11222e590463SRobert Morris 
11232e590463SRobert Morris   printf(1, "bigwrite test\n");
11242e590463SRobert Morris 
11252e590463SRobert Morris   unlink("bigwrite");
11262e590463SRobert Morris   for(sz = 499; sz < 12*512; sz += 471){
11272e590463SRobert Morris     fd = open("bigwrite", O_CREATE | O_RDWR);
11282e590463SRobert Morris     if(fd < 0){
11292e590463SRobert Morris       printf(1, "cannot create bigwrite\n");
11302e590463SRobert Morris       exit();
11312e590463SRobert Morris     }
11322e590463SRobert Morris     int i;
11332e590463SRobert Morris     for(i = 0; i < 2; i++){
11342e590463SRobert Morris       int cc = write(fd, buf, sz);
11352e590463SRobert Morris       if(cc != sz){
11362e590463SRobert Morris         printf(1, "write(%d) ret %d\n", sz, cc);
11372e590463SRobert Morris         exit();
11382e590463SRobert Morris       }
11392e590463SRobert Morris     }
11402e590463SRobert Morris     close(fd);
11412e590463SRobert Morris     unlink("bigwrite");
11422e590463SRobert Morris   }
11432e590463SRobert Morris 
11442e590463SRobert Morris   printf(1, "bigwrite ok\n");
11452e590463SRobert Morris }
11462e590463SRobert Morris 
1147a64cd813Skaashoek void
bigfile(void)1148c664dd5dSrsc bigfile(void)
1149a64cd813Skaashoek {
1150a64cd813Skaashoek   int fd, i, total, cc;
1151a64cd813Skaashoek 
1152a64cd813Skaashoek   printf(1, "bigfile test\n");
1153a64cd813Skaashoek 
1154a64cd813Skaashoek   unlink("bigfile");
1155a64cd813Skaashoek   fd = open("bigfile", O_CREATE | O_RDWR);
1156a64cd813Skaashoek   if(fd < 0){
1157a64cd813Skaashoek     printf(1, "cannot create bigfile");
1158a64cd813Skaashoek     exit();
1159a64cd813Skaashoek   }
1160a64cd813Skaashoek   for(i = 0; i < 20; i++){
1161a64cd813Skaashoek     memset(buf, i, 600);
1162a64cd813Skaashoek     if(write(fd, buf, 600) != 600){
1163a64cd813Skaashoek       printf(1, "write bigfile failed\n");
1164a64cd813Skaashoek       exit();
1165a64cd813Skaashoek     }
1166a64cd813Skaashoek   }
1167a64cd813Skaashoek   close(fd);
1168a64cd813Skaashoek 
1169a64cd813Skaashoek   fd = open("bigfile", 0);
1170a64cd813Skaashoek   if(fd < 0){
1171a64cd813Skaashoek     printf(1, "cannot open bigfile\n");
1172a64cd813Skaashoek     exit();
1173a64cd813Skaashoek   }
1174a64cd813Skaashoek   total = 0;
1175a64cd813Skaashoek   for(i = 0; ; i++){
1176a64cd813Skaashoek     cc = read(fd, buf, 300);
1177a64cd813Skaashoek     if(cc < 0){
1178a64cd813Skaashoek       printf(1, "read bigfile failed\n");
1179a64cd813Skaashoek       exit();
1180a64cd813Skaashoek     }
1181a64cd813Skaashoek     if(cc == 0)
1182a64cd813Skaashoek       break;
1183a64cd813Skaashoek     if(cc != 300){
1184a64cd813Skaashoek       printf(1, "short read bigfile\n");
1185a64cd813Skaashoek       exit();
1186a64cd813Skaashoek     }
1187a64cd813Skaashoek     if(buf[0] != i/2 || buf[299] != i/2){
1188a64cd813Skaashoek       printf(1, "read bigfile wrong data\n");
1189a64cd813Skaashoek       exit();
1190a64cd813Skaashoek     }
1191a64cd813Skaashoek     total += cc;
1192a64cd813Skaashoek   }
1193a64cd813Skaashoek   close(fd);
1194a64cd813Skaashoek   if(total != 20*600){
1195a64cd813Skaashoek     printf(1, "read bigfile wrong total\n");
1196a64cd813Skaashoek     exit();
1197a64cd813Skaashoek   }
1198a64cd813Skaashoek   unlink("bigfile");
1199a64cd813Skaashoek 
1200a64cd813Skaashoek   printf(1, "bigfile test ok\n");
1201a64cd813Skaashoek }
1202a64cd813Skaashoek 
1203a64cd813Skaashoek void
fourteen(void)1204c664dd5dSrsc fourteen(void)
1205a64cd813Skaashoek {
1206a64cd813Skaashoek   int fd;
1207a64cd813Skaashoek 
12085e03dd86Srsc   // DIRSIZ is 14.
1209a64cd813Skaashoek   printf(1, "fourteen test\n");
1210a64cd813Skaashoek 
1211a64cd813Skaashoek   if(mkdir("12345678901234") != 0){
1212a64cd813Skaashoek     printf(1, "mkdir 12345678901234 failed\n");
1213a64cd813Skaashoek     exit();
1214a64cd813Skaashoek   }
1215a64cd813Skaashoek   if(mkdir("12345678901234/123456789012345") != 0){
1216a64cd813Skaashoek     printf(1, "mkdir 12345678901234/123456789012345 failed\n");
1217a64cd813Skaashoek     exit();
1218a64cd813Skaashoek   }
1219a64cd813Skaashoek   fd = open("123456789012345/123456789012345/123456789012345", O_CREATE);
1220a64cd813Skaashoek   if(fd < 0){
1221a64cd813Skaashoek     printf(1, "create 123456789012345/123456789012345/123456789012345 failed\n");
1222a64cd813Skaashoek     exit();
1223a64cd813Skaashoek   }
1224a64cd813Skaashoek   close(fd);
1225a64cd813Skaashoek   fd = open("12345678901234/12345678901234/12345678901234", 0);
1226a64cd813Skaashoek   if(fd < 0){
1227a64cd813Skaashoek     printf(1, "open 12345678901234/12345678901234/12345678901234 failed\n");
1228a64cd813Skaashoek     exit();
1229a64cd813Skaashoek   }
1230a64cd813Skaashoek   close(fd);
12316c8acf9eSrsc 
1232a64cd813Skaashoek   if(mkdir("12345678901234/12345678901234") == 0){
1233a64cd813Skaashoek     printf(1, "mkdir 12345678901234/12345678901234 succeeded!\n");
1234a64cd813Skaashoek     exit();
1235a64cd813Skaashoek   }
1236a64cd813Skaashoek   if(mkdir("123456789012345/12345678901234") == 0){
1237a64cd813Skaashoek     printf(1, "mkdir 12345678901234/123456789012345 succeeded!\n");
1238a64cd813Skaashoek     exit();
1239a64cd813Skaashoek   }
1240a64cd813Skaashoek 
1241a64cd813Skaashoek   printf(1, "fourteen ok\n");
1242a64cd813Skaashoek }
1243a64cd813Skaashoek 
12445e03dd86Srsc void
rmdot(void)12455e03dd86Srsc rmdot(void)
12465e03dd86Srsc {
12475e03dd86Srsc   printf(1, "rmdot test\n");
12485e03dd86Srsc   if(mkdir("dots") != 0){
12495e03dd86Srsc     printf(1, "mkdir dots failed\n");
12505e03dd86Srsc     exit();
12515e03dd86Srsc   }
12525e03dd86Srsc   if(chdir("dots") != 0){
12535e03dd86Srsc     printf(1, "chdir dots failed\n");
12545e03dd86Srsc     exit();
12555e03dd86Srsc   }
12565e03dd86Srsc   if(unlink(".") == 0){
12575e03dd86Srsc     printf(1, "rm . worked!\n");
12585e03dd86Srsc     exit();
12595e03dd86Srsc   }
12605e03dd86Srsc   if(unlink("..") == 0){
12615e03dd86Srsc     printf(1, "rm .. worked!\n");
12625e03dd86Srsc     exit();
12635e03dd86Srsc   }
12645e03dd86Srsc   if(chdir("/") != 0){
12655e03dd86Srsc     printf(1, "chdir / failed\n");
12665e03dd86Srsc     exit();
12675e03dd86Srsc   }
12685e03dd86Srsc   if(unlink("dots/.") == 0){
12695e03dd86Srsc     printf(1, "unlink dots/. worked!\n");
12705e03dd86Srsc     exit();
12715e03dd86Srsc   }
12725e03dd86Srsc   if(unlink("dots/..") == 0){
12735e03dd86Srsc     printf(1, "unlink dots/.. worked!\n");
12745e03dd86Srsc     exit();
12755e03dd86Srsc   }
12765e03dd86Srsc   if(unlink("dots") != 0){
12775e03dd86Srsc     printf(1, "unlink dots failed!\n");
12785e03dd86Srsc     exit();
12795e03dd86Srsc   }
12805e03dd86Srsc   printf(1, "rmdot ok\n");
12815e03dd86Srsc }
12825e03dd86Srsc 
128320365348Srtm void
dirfile(void)128420365348Srtm dirfile(void)
128520365348Srtm {
128620365348Srtm   int fd;
128720365348Srtm 
128820365348Srtm   printf(1, "dir vs file\n");
128920365348Srtm 
129020365348Srtm   fd = open("dirfile", O_CREATE);
129120365348Srtm   if(fd < 0){
129220365348Srtm     printf(1, "create dirfile failed\n");
129320365348Srtm     exit();
129420365348Srtm   }
129520365348Srtm   close(fd);
129620365348Srtm   if(chdir("dirfile") == 0){
129720365348Srtm     printf(1, "chdir dirfile succeeded!\n");
129820365348Srtm     exit();
129920365348Srtm   }
130020365348Srtm   fd = open("dirfile/xx", 0);
130120365348Srtm   if(fd >= 0){
130220365348Srtm     printf(1, "create dirfile/xx succeeded!\n");
130320365348Srtm     exit();
130420365348Srtm   }
130520365348Srtm   fd = open("dirfile/xx", O_CREATE);
130620365348Srtm   if(fd >= 0){
130720365348Srtm     printf(1, "create dirfile/xx succeeded!\n");
130820365348Srtm     exit();
130920365348Srtm   }
131020365348Srtm   if(mkdir("dirfile/xx") == 0){
131120365348Srtm     printf(1, "mkdir dirfile/xx succeeded!\n");
131220365348Srtm     exit();
131320365348Srtm   }
131420365348Srtm   if(unlink("dirfile/xx") == 0){
131520365348Srtm     printf(1, "unlink dirfile/xx succeeded!\n");
131620365348Srtm     exit();
131720365348Srtm   }
131820365348Srtm   if(link("README", "dirfile/xx") == 0){
131920365348Srtm     printf(1, "link to dirfile/xx succeeded!\n");
132020365348Srtm     exit();
132120365348Srtm   }
132220365348Srtm   if(unlink("dirfile") != 0){
132320365348Srtm     printf(1, "unlink dirfile failed!\n");
132420365348Srtm     exit();
132520365348Srtm   }
132620365348Srtm 
132720365348Srtm   fd = open(".", O_RDWR);
132820365348Srtm   if(fd >= 0){
132920365348Srtm     printf(1, "open . for writing succeeded!\n");
133020365348Srtm     exit();
133120365348Srtm   }
133220365348Srtm   fd = open(".", 0);
133320365348Srtm   if(write(fd, "x", 1) > 0){
133420365348Srtm     printf(1, "write . succeeded!\n");
133520365348Srtm     exit();
133620365348Srtm   }
133720365348Srtm   close(fd);
133820365348Srtm 
133920365348Srtm   printf(1, "dir vs file OK\n");
134020365348Srtm }
134120365348Srtm 
134220365348Srtm // test that iput() is called at the end of _namei()
134320365348Srtm void
iref(void)134420365348Srtm iref(void)
134520365348Srtm {
134620365348Srtm   int i, fd;
134720365348Srtm 
134820365348Srtm   printf(1, "empty file name\n");
134920365348Srtm 
135020365348Srtm   // the 50 is NINODE
135120365348Srtm   for(i = 0; i < 50 + 1; i++){
135220365348Srtm     if(mkdir("irefd") != 0){
135320365348Srtm       printf(1, "mkdir irefd failed\n");
135420365348Srtm       exit();
135520365348Srtm     }
135620365348Srtm     if(chdir("irefd") != 0){
135720365348Srtm       printf(1, "chdir irefd failed\n");
135820365348Srtm       exit();
135920365348Srtm     }
136020365348Srtm 
136120365348Srtm     mkdir("");
136220365348Srtm     link("README", "");
136320365348Srtm     fd = open("", O_CREATE);
136420365348Srtm     if(fd >= 0)
136520365348Srtm       close(fd);
136620365348Srtm     fd = open("xx", O_CREATE);
136720365348Srtm     if(fd >= 0)
136820365348Srtm       close(fd);
136920365348Srtm     unlink("xx");
137020365348Srtm   }
137120365348Srtm 
137220365348Srtm   chdir("/");
137320365348Srtm   printf(1, "empty file name OK\n");
137420365348Srtm }
137520365348Srtm 
1376e0e7d07eSrsc // test that fork fails gracefully
1377e0e7d07eSrsc // the forktest binary also does this, but it runs out of proc entries first.
1378e0e7d07eSrsc // inside the bigger usertests binary, we run out of memory first.
1379e0e7d07eSrsc void
forktest(void)1380e0e7d07eSrsc forktest(void)
1381e0e7d07eSrsc {
1382e0e7d07eSrsc   int n, pid;
1383e0e7d07eSrsc 
1384e0e7d07eSrsc   printf(1, "fork test\n");
1385e0e7d07eSrsc 
1386e0e7d07eSrsc   for(n=0; n<1000; n++){
1387e0e7d07eSrsc     pid = fork();
1388e0e7d07eSrsc     if(pid < 0)
1389e0e7d07eSrsc       break;
1390e0e7d07eSrsc     if(pid == 0)
1391e0e7d07eSrsc       exit();
1392e0e7d07eSrsc   }
1393e0e7d07eSrsc 
1394e0e7d07eSrsc   if(n == 1000){
1395e0e7d07eSrsc     printf(1, "fork claimed to work 1000 times!\n");
1396e0e7d07eSrsc     exit();
1397e0e7d07eSrsc   }
1398e0e7d07eSrsc 
1399e0e7d07eSrsc   for(; n > 0; n--){
1400e0e7d07eSrsc     if(wait() < 0){
1401e0e7d07eSrsc       printf(1, "wait stopped early\n");
1402e0e7d07eSrsc       exit();
1403e0e7d07eSrsc     }
1404e0e7d07eSrsc   }
1405e0e7d07eSrsc 
1406e0e7d07eSrsc   if(wait() != -1){
1407e0e7d07eSrsc     printf(1, "wait got too many\n");
1408e0e7d07eSrsc     exit();
1409e0e7d07eSrsc   }
1410e0e7d07eSrsc 
1411e0e7d07eSrsc   printf(1, "fork test OK\n");
1412e0e7d07eSrsc }
1413e0e7d07eSrsc 
1414eb18645fSRobert Morris void
sbrktest(void)1415eb18645fSRobert Morris sbrktest(void)
1416eb18645fSRobert Morris {
141711b7438bSFrans Kaashoek   int fds[2], pid, pids[10], ppid;
14181a81e38bSRuss Cox   char *a, *b, *c, *lastaddr, *oldbrk, *p, scratch;
14191a81e38bSRuss Cox   uint amt;
142083d2db91SRobert Morris 
1421eb18645fSRobert Morris   printf(stdout, "sbrk test\n");
14221a81e38bSRuss Cox   oldbrk = sbrk(0);
142383d2db91SRobert Morris 
142483d2db91SRobert Morris   // can one sbrk() less than a page?
14251a81e38bSRuss Cox   a = sbrk(0);
1426eb18645fSRobert Morris   int i;
1427eb18645fSRobert Morris   for(i = 0; i < 5000; i++){
14281a81e38bSRuss Cox     b = sbrk(1);
1429eb18645fSRobert Morris     if(b != a){
1430eb18645fSRobert Morris       printf(stdout, "sbrk test failed %d %x %x\n", i, a, b);
1431eb18645fSRobert Morris       exit();
1432eb18645fSRobert Morris     }
1433eb18645fSRobert Morris     *b = 1;
1434eb18645fSRobert Morris     a = b + 1;
1435eb18645fSRobert Morris   }
143683d2db91SRobert Morris   pid = fork();
1437eb18645fSRobert Morris   if(pid < 0){
1438eb18645fSRobert Morris     printf(stdout, "sbrk test fork failed\n");
1439eb18645fSRobert Morris     exit();
1440eb18645fSRobert Morris   }
14411a81e38bSRuss Cox   c = sbrk(1);
1442eb18645fSRobert Morris   c = sbrk(1);
1443eb18645fSRobert Morris   if(c != a + 1){
1444eb18645fSRobert Morris     printf(stdout, "sbrk test failed post-fork\n");
1445eb18645fSRobert Morris     exit();
1446eb18645fSRobert Morris   }
1447eb18645fSRobert Morris   if(pid == 0)
1448eb18645fSRobert Morris     exit();
1449eb18645fSRobert Morris   wait();
145083d2db91SRobert Morris 
145164797663SFrans Kaashoek   // can one grow address space to something big?
145264797663SFrans Kaashoek #define BIG (100*1024*1024)
145383d2db91SRobert Morris   a = sbrk(0);
145464797663SFrans Kaashoek   amt = (BIG) - (uint)a;
14551a81e38bSRuss Cox   p = sbrk(amt);
145683d2db91SRobert Morris   if (p != a) {
145764797663SFrans Kaashoek     printf(stdout, "sbrk test failed to grow big address space; enough phys mem?\n");
145883d2db91SRobert Morris     exit();
145983d2db91SRobert Morris   }
146064797663SFrans Kaashoek   lastaddr = (char*) (BIG-1);
146183d2db91SRobert Morris   *lastaddr = 99;
146283d2db91SRobert Morris 
146383d2db91SRobert Morris   // can one de-allocate?
146483d2db91SRobert Morris   a = sbrk(0);
146583d2db91SRobert Morris   c = sbrk(-4096);
146683d2db91SRobert Morris   if(c == (char*)0xffffffff){
146783d2db91SRobert Morris     printf(stdout, "sbrk could not deallocate\n");
146883d2db91SRobert Morris     exit();
146983d2db91SRobert Morris   }
147083d2db91SRobert Morris   c = sbrk(0);
147183d2db91SRobert Morris   if(c != a - 4096){
147283d2db91SRobert Morris     printf(stdout, "sbrk deallocation produced wrong address, a %x c %x\n", a, c);
147383d2db91SRobert Morris     exit();
147483d2db91SRobert Morris   }
147583d2db91SRobert Morris 
147683d2db91SRobert Morris   // can one re-allocate that page?
147783d2db91SRobert Morris   a = sbrk(0);
147883d2db91SRobert Morris   c = sbrk(4096);
147983d2db91SRobert Morris   if(c != a || sbrk(0) != a + 4096){
148083d2db91SRobert Morris     printf(stdout, "sbrk re-allocation failed, a %x c %x\n", a, c);
148183d2db91SRobert Morris     exit();
148283d2db91SRobert Morris   }
148383d2db91SRobert Morris   if(*lastaddr == 99){
148483d2db91SRobert Morris     // should be zero
148583d2db91SRobert Morris     printf(stdout, "sbrk de-allocation didn't really deallocate\n");
148683d2db91SRobert Morris     exit();
148783d2db91SRobert Morris   }
148883d2db91SRobert Morris 
148911b7438bSFrans Kaashoek   a = sbrk(0);
149011b7438bSFrans Kaashoek   c = sbrk(-(sbrk(0) - oldbrk));
149111b7438bSFrans Kaashoek   if(c != a){
149211b7438bSFrans Kaashoek     printf(stdout, "sbrk downsize failed, a %x c %x\n", a, c);
149311b7438bSFrans Kaashoek     exit();
149411b7438bSFrans Kaashoek   }
149511b7438bSFrans Kaashoek 
1496789b508dSRobert Morris   // can we read the kernel's memory?
149764797663SFrans Kaashoek   for(a = (char*)(KERNBASE); a < (char*) (KERNBASE+2000000); a += 50000){
14981a81e38bSRuss Cox     ppid = getpid();
14991a81e38bSRuss Cox     pid = fork();
1500789b508dSRobert Morris     if(pid < 0){
1501789b508dSRobert Morris       printf(stdout, "fork failed\n");
1502789b508dSRobert Morris       exit();
1503789b508dSRobert Morris     }
1504789b508dSRobert Morris     if(pid == 0){
1505789b508dSRobert Morris       printf(stdout, "oops could read %x = %x\n", a, *a);
1506789b508dSRobert Morris       kill(ppid);
1507789b508dSRobert Morris       exit();
1508789b508dSRobert Morris     }
1509789b508dSRobert Morris     wait();
1510789b508dSRobert Morris   }
1511789b508dSRobert Morris 
1512dd645ef1SAustin Clements   // if we run the system out of memory, does it clean up the last
1513dd645ef1SAustin Clements   // failed allocation?
1514dd645ef1SAustin Clements   if(pipe(fds) != 0){
1515dd645ef1SAustin Clements     printf(1, "pipe() failed\n");
1516dd645ef1SAustin Clements     exit();
1517dd645ef1SAustin Clements   }
1518dd645ef1SAustin Clements   for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){
1519dd645ef1SAustin Clements     if((pids[i] = fork()) == 0){
152011b7438bSFrans Kaashoek       // allocate a lot of memory
152111b7438bSFrans Kaashoek       sbrk(BIG - (uint)sbrk(0));
1522dd645ef1SAustin Clements       write(fds[1], "x", 1);
1523dd645ef1SAustin Clements       // sit around until killed
1524b0751a3eSAustin Clements       for(;;) sleep(1000);
1525dd645ef1SAustin Clements     }
1526dd645ef1SAustin Clements     if(pids[i] != -1)
1527dd645ef1SAustin Clements       read(fds[0], &scratch, 1);
1528dd645ef1SAustin Clements   }
1529dd645ef1SAustin Clements   // if those failed allocations freed up the pages they did allocate,
1530dd645ef1SAustin Clements   // we'll be able to allocate here
1531dd645ef1SAustin Clements   c = sbrk(4096);
1532dd645ef1SAustin Clements   for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){
1533dd645ef1SAustin Clements     if(pids[i] == -1)
1534dd645ef1SAustin Clements       continue;
1535dd645ef1SAustin Clements     kill(pids[i]);
1536dd645ef1SAustin Clements     wait();
1537dd645ef1SAustin Clements   }
1538dd645ef1SAustin Clements   if(c == (char*)0xffffffff){
1539dd645ef1SAustin Clements     printf(stdout, "failed sbrk leaked memory\n");
1540dd645ef1SAustin Clements     exit();
1541dd645ef1SAustin Clements   }
1542dd645ef1SAustin Clements 
1543789b508dSRobert Morris   if(sbrk(0) > oldbrk)
1544789b508dSRobert Morris     sbrk(-(sbrk(0) - oldbrk));
1545789b508dSRobert Morris 
1546eb18645fSRobert Morris   printf(stdout, "sbrk test OK\n");
1547eb18645fSRobert Morris }
1548eb18645fSRobert Morris 
1549c4cc10daSRobert Morris void
validateint(int * p)1550b1d41d67SAustin Clements validateint(int *p)
1551c4cc10daSRobert Morris {
1552b1d41d67SAustin Clements   int res;
1553b1d41d67SAustin Clements   asm("mov %%esp, %%ebx\n\t"
1554b1d41d67SAustin Clements       "mov %3, %%esp\n\t"
1555b1d41d67SAustin Clements       "int %2\n\t"
1556b1d41d67SAustin Clements       "mov %%ebx, %%esp" :
1557b1d41d67SAustin Clements       "=a" (res) :
1558b1d41d67SAustin Clements       "a" (SYS_sleep), "n" (T_SYSCALL), "c" (p) :
1559b1d41d67SAustin Clements       "ebx");
1560b1d41d67SAustin Clements }
1561b1d41d67SAustin Clements 
1562b1d41d67SAustin Clements void
validatetest(void)1563b1d41d67SAustin Clements validatetest(void)
1564b1d41d67SAustin Clements {
15651a81e38bSRuss Cox   int hi, pid;
15661a81e38bSRuss Cox   uint p;
1567b1d41d67SAustin Clements 
1568b1d41d67SAustin Clements   printf(stdout, "validate test\n");
15691a81e38bSRuss Cox   hi = 1100*1024;
1570b1d41d67SAustin Clements 
1571b1d41d67SAustin Clements   for(p = 0; p <= (uint)hi; p += 4096){
1572b1d41d67SAustin Clements     if((pid = fork()) == 0){
1573b1d41d67SAustin Clements       // try to crash the kernel by passing in a badly placed integer
1574b1d41d67SAustin Clements       validateint((int*)p);
1575c4cc10daSRobert Morris       exit();
1576c4cc10daSRobert Morris     }
1577b1d41d67SAustin Clements     sleep(0);
1578b1d41d67SAustin Clements     sleep(0);
1579b1d41d67SAustin Clements     kill(pid);
1580c4cc10daSRobert Morris     wait();
1581b1d41d67SAustin Clements 
1582b1d41d67SAustin Clements     // try to crash the kernel by passing in a bad string pointer
1583b1d41d67SAustin Clements     if(link("nosuchfile", (char*)p) != -1){
1584b1d41d67SAustin Clements       printf(stdout, "link should not succeed\n");
1585b1d41d67SAustin Clements       exit();
1586b1d41d67SAustin Clements     }
1587b1d41d67SAustin Clements   }
1588b1d41d67SAustin Clements 
1589b1d41d67SAustin Clements   printf(stdout, "validate ok\n");
1590c4cc10daSRobert Morris }
1591c4cc10daSRobert Morris 
1592a9183883SRobert Morris // does unintialized data start out zero?
159305d66b06SRobert Morris char uninit[10000];
159405d66b06SRobert Morris void
bsstest(void)159505d66b06SRobert Morris bsstest(void)
159605d66b06SRobert Morris {
159705d66b06SRobert Morris   int i;
15981a81e38bSRuss Cox 
159905d66b06SRobert Morris   printf(stdout, "bss test\n");
160005d66b06SRobert Morris   for(i = 0; i < sizeof(uninit); i++){
160105d66b06SRobert Morris     if(uninit[i] != '\0'){
160205d66b06SRobert Morris       printf(stdout, "bss test failed\n");
160305d66b06SRobert Morris       exit();
160405d66b06SRobert Morris     }
160505d66b06SRobert Morris   }
160605d66b06SRobert Morris   printf(stdout, "bss test ok\n");
160705d66b06SRobert Morris }
160805d66b06SRobert Morris 
16095a236924SRobert Morris // does exec return an error if the arguments
16105a236924SRobert Morris // are larger than a page? or does it write
16115a236924SRobert Morris // below the stack and wreck the instructions/data?
1612a9183883SRobert Morris void
bigargtest(void)1613a9183883SRobert Morris bigargtest(void)
1614a9183883SRobert Morris {
1615d73dd097SAustin Clements   int pid, fd;
1616a9183883SRobert Morris 
16175a236924SRobert Morris   unlink("bigarg-ok");
1618a9183883SRobert Morris   pid = fork();
1619a9183883SRobert Morris   if(pid == 0){
16205a236924SRobert Morris     static char *args[MAXARG];
1621a9183883SRobert Morris     int i;
16225a236924SRobert Morris     for(i = 0; i < MAXARG-1; i++)
16234655d42eSRobert Morris       args[i] = "bigargs test: failed\n                                                                                                                                                                                                       ";
16245a236924SRobert Morris     args[MAXARG-1] = 0;
1625371ab7faSRobert Morris     printf(stdout, "bigarg test\n");
1626a9183883SRobert Morris     exec("echo", args);
1627a9183883SRobert Morris     printf(stdout, "bigarg test ok\n");
16285a236924SRobert Morris     fd = open("bigarg-ok", O_CREATE);
16295a236924SRobert Morris     close(fd);
1630a9183883SRobert Morris     exit();
1631a9183883SRobert Morris   } else if(pid < 0){
1632a9183883SRobert Morris     printf(stdout, "bigargtest: fork failed\n");
1633a9183883SRobert Morris     exit();
1634a9183883SRobert Morris   }
1635a9183883SRobert Morris   wait();
16365a236924SRobert Morris   fd = open("bigarg-ok", 0);
16375a236924SRobert Morris   if(fd < 0){
16385a236924SRobert Morris     printf(stdout, "bigarg test failed!\n");
16395a236924SRobert Morris     exit();
16405a236924SRobert Morris   }
16415a236924SRobert Morris   close(fd);
16425a236924SRobert Morris   unlink("bigarg-ok");
1643a9183883SRobert Morris }
1644a9183883SRobert Morris 
1645327cc21fSRobert Morris // what happens when the file system runs out of blocks?
1646327cc21fSRobert Morris // answer: balloc panics, so this test is not useful.
1647327cc21fSRobert Morris void
fsfull()1648327cc21fSRobert Morris fsfull()
1649327cc21fSRobert Morris {
1650327cc21fSRobert Morris   int nfiles;
1651327cc21fSRobert Morris   int fsblocks = 0;
1652327cc21fSRobert Morris 
1653327cc21fSRobert Morris   printf(1, "fsfull test\n");
1654327cc21fSRobert Morris 
1655327cc21fSRobert Morris   for(nfiles = 0; ; nfiles++){
1656327cc21fSRobert Morris     char name[64];
1657327cc21fSRobert Morris     name[0] = 'f';
1658327cc21fSRobert Morris     name[1] = '0' + nfiles / 1000;
1659327cc21fSRobert Morris     name[2] = '0' + (nfiles % 1000) / 100;
1660327cc21fSRobert Morris     name[3] = '0' + (nfiles % 100) / 10;
1661327cc21fSRobert Morris     name[4] = '0' + (nfiles % 10);
1662327cc21fSRobert Morris     name[5] = '\0';
1663327cc21fSRobert Morris     printf(1, "writing %s\n", name);
1664327cc21fSRobert Morris     int fd = open(name, O_CREATE|O_RDWR);
1665327cc21fSRobert Morris     if(fd < 0){
1666327cc21fSRobert Morris       printf(1, "open %s failed\n", name);
1667327cc21fSRobert Morris       break;
1668327cc21fSRobert Morris     }
1669327cc21fSRobert Morris     int total = 0;
1670327cc21fSRobert Morris     while(1){
1671327cc21fSRobert Morris       int cc = write(fd, buf, 512);
1672327cc21fSRobert Morris       if(cc < 512)
1673327cc21fSRobert Morris         break;
1674327cc21fSRobert Morris       total += cc;
1675327cc21fSRobert Morris       fsblocks++;
1676327cc21fSRobert Morris     }
1677327cc21fSRobert Morris     printf(1, "wrote %d bytes\n", total);
1678327cc21fSRobert Morris     close(fd);
1679327cc21fSRobert Morris     if(total == 0)
1680327cc21fSRobert Morris       break;
1681327cc21fSRobert Morris   }
1682327cc21fSRobert Morris 
1683327cc21fSRobert Morris   while(nfiles >= 0){
1684327cc21fSRobert Morris     char name[64];
1685327cc21fSRobert Morris     name[0] = 'f';
1686327cc21fSRobert Morris     name[1] = '0' + nfiles / 1000;
1687327cc21fSRobert Morris     name[2] = '0' + (nfiles % 1000) / 100;
1688327cc21fSRobert Morris     name[3] = '0' + (nfiles % 100) / 10;
1689327cc21fSRobert Morris     name[4] = '0' + (nfiles % 10);
1690327cc21fSRobert Morris     name[5] = '\0';
1691327cc21fSRobert Morris     unlink(name);
1692327cc21fSRobert Morris     nfiles--;
1693327cc21fSRobert Morris   }
1694327cc21fSRobert Morris 
1695327cc21fSRobert Morris   printf(1, "fsfull test finished\n");
1696327cc21fSRobert Morris }
1697327cc21fSRobert Morris 
1698aff0c8d5SFrans Kaashoek void
uio()1699aff0c8d5SFrans Kaashoek uio()
1700aff0c8d5SFrans Kaashoek {
1701aff0c8d5SFrans Kaashoek   #define RTC_ADDR 0x70
1702aff0c8d5SFrans Kaashoek   #define RTC_DATA 0x71
1703aff0c8d5SFrans Kaashoek 
1704aff0c8d5SFrans Kaashoek   ushort port = 0;
1705aff0c8d5SFrans Kaashoek   uchar val = 0;
1706aff0c8d5SFrans Kaashoek   int pid;
1707aff0c8d5SFrans Kaashoek 
1708aff0c8d5SFrans Kaashoek   printf(1, "uio test\n");
1709aff0c8d5SFrans Kaashoek   pid = fork();
1710aff0c8d5SFrans Kaashoek   if(pid == 0){
1711aff0c8d5SFrans Kaashoek     port = RTC_ADDR;
1712aff0c8d5SFrans Kaashoek     val = 0x09;  /* year */
1713aff0c8d5SFrans Kaashoek     /* http://wiki.osdev.org/Inline_Assembly/Examples */
1714aff0c8d5SFrans Kaashoek     asm volatile("outb %0,%1"::"a"(val), "d" (port));
1715aff0c8d5SFrans Kaashoek     port = RTC_DATA;
1716aff0c8d5SFrans Kaashoek     asm volatile("inb %1,%0" : "=a" (val) : "d" (port));
1717aff0c8d5SFrans Kaashoek     printf(1, "uio: uio succeeded; test FAILED\n");
1718aff0c8d5SFrans Kaashoek     exit();
1719aff0c8d5SFrans Kaashoek   } else if(pid < 0){
1720aff0c8d5SFrans Kaashoek     printf (1, "fork failed\n");
1721aff0c8d5SFrans Kaashoek     exit();
1722aff0c8d5SFrans Kaashoek   }
1723aff0c8d5SFrans Kaashoek   wait();
1724aff0c8d5SFrans Kaashoek   printf(1, "uio test done\n");
1725aff0c8d5SFrans Kaashoek }
1726aff0c8d5SFrans Kaashoek 
argptest()1727*907f23a5SFrans Kaashoek void argptest()
1728*907f23a5SFrans Kaashoek {
1729*907f23a5SFrans Kaashoek   int fd;
1730*907f23a5SFrans Kaashoek   fd = open("init", O_RDONLY);
1731*907f23a5SFrans Kaashoek   if (fd < 0) {
1732*907f23a5SFrans Kaashoek     printf(2, "open failed\n");
1733*907f23a5SFrans Kaashoek     exit();
1734*907f23a5SFrans Kaashoek   }
1735*907f23a5SFrans Kaashoek   read(fd, sbrk(0) - 1, -1);
1736*907f23a5SFrans Kaashoek   close(fd);
1737*907f23a5SFrans Kaashoek   printf(1, "arg test passed\n");
1738*907f23a5SFrans Kaashoek }
1739*907f23a5SFrans Kaashoek 
17405e083578SRobert Morris unsigned long randstate = 1;
17415e083578SRobert Morris unsigned int
rand()17425e083578SRobert Morris rand()
17435e083578SRobert Morris {
17445e083578SRobert Morris   randstate = randstate * 1664525 + 1013904223;
17455e083578SRobert Morris   return randstate;
17465e083578SRobert Morris }
17475e083578SRobert Morris 
17489b37d1bfSrsc int
main(int argc,char * argv[])17498455980bSrtm main(int argc, char *argv[])
1750c41f1de5Srtm {
1751a64cd813Skaashoek   printf(1, "usertests starting\n");
1752a64cd813Skaashoek 
1753f3c393baSrsc   if(open("usertests.ran", 0) >= 0){
1754f3c393baSrsc     printf(1, "already ran user tests -- rebuild fs.img\n");
1755f3c393baSrsc     exit();
1756f3c393baSrsc   }
1757f3c393baSrsc   close(open("usertests.ran", O_CREATE));
1758f3c393baSrsc 
1759*907f23a5SFrans Kaashoek   argptest();
176048aa9174SRobert Morris   createdelete();
176148aa9174SRobert Morris   linkunlink();
176248aa9174SRobert Morris   concreate();
176348aa9174SRobert Morris   fourfiles();
176448aa9174SRobert Morris   sharedfd();
176548aa9174SRobert Morris 
17665a236924SRobert Morris   bigargtest();
17672e590463SRobert Morris   bigwrite();
17684655d42eSRobert Morris   bigargtest();
176905d66b06SRobert Morris   bsstest();
1770eb18645fSRobert Morris   sbrktest();
1771b1d41d67SAustin Clements   validatetest();
1772eb18645fSRobert Morris 
1773a64cd813Skaashoek   opentest();
1774a64cd813Skaashoek   writetest();
1775a64cd813Skaashoek   writetest1();
1776a64cd813Skaashoek   createtest();
1777c41f1de5Srtm 
17782c565472SRobert Morris   openiputtest();
17792c565472SRobert Morris   exitiputtest();
17802c565472SRobert Morris   iputtest();
17812c565472SRobert Morris 
178281d52199Skaashoek   mem();
17833b95801aSrtm   pipe1();
17843b95801aSrtm   preempt();
17853b95801aSrtm   exitwait();
178646bbd72fSrtm 
17875e03dd86Srsc   rmdot();
1788a64cd813Skaashoek   fourteen();
1789a64cd813Skaashoek   bigfile();
1790a64cd813Skaashoek   subdir();
1791a64cd813Skaashoek   linktest();
1792a64cd813Skaashoek   unlinkread();
179320365348Srtm   dirfile();
179420365348Srtm   iref();
1795e0e7d07eSrsc   forktest();
1796d5225710Srsc   bigdir(); // slow
1797aff0c8d5SFrans Kaashoek 
1798aff0c8d5SFrans Kaashoek   uio();
1799aff0c8d5SFrans Kaashoek 
1800a64cd813Skaashoek   exectest();
1801a64cd813Skaashoek 
180243572072Srtm   exit();
1803c41f1de5Srtm }
1804