diff --git a/Makefile b/Makefile index f72d196..1e1a0a8 100644 --- a/Makefile +++ b/Makefile @@ -84,18 +84,10 @@ vectors.S : vectors.pl ULIB = ulib.o usys.o printf.o umalloc.o -user1 : user1.o $(ULIB) - $(LD) -N -e main -Ttext 0 -o user1 user1.o $(ULIB) - $(OBJDUMP) -S user1 > user1.asm - usertests : usertests.o $(ULIB) $(LD) -N -e main -Ttext 0 -o usertests usertests.o $(ULIB) $(OBJDUMP) -S usertests > usertests.asm -fstests : fstests.o $(ULIB) - $(LD) -N -e main -Ttext 0 -o fstests fstests.o $(ULIB) - $(OBJDUMP) -S fstests > fstests.asm - _echo : echo.o $(ULIB) $(LD) -N -e main -Ttext 0 -o _echo echo.o $(ULIB) $(OBJDUMP) -S _echo > echo.asm @@ -104,10 +96,6 @@ _cat : cat.o $(ULIB) $(LD) -N -e main -Ttext 0 -o _cat cat.o $(ULIB) $(OBJDUMP) -S _cat > cat.asm -userfs : userfs.o $(ULIB) - $(LD) -N -e main -Ttext 0 -o userfs userfs.o $(ULIB) - $(OBJDUMP) -S userfs > userfs.asm - _init : init.o $(ULIB) $(LD) -N -e main -Ttext 0 -o _init init.o $(ULIB) $(OBJDUMP) -S _init > init.asm @@ -131,8 +119,8 @@ _rm : rm.o $(ULIB) mkfs : mkfs.c fs.h cc -o mkfs mkfs.c -fs.img : mkfs userfs usertests _echo _cat README _init _sh _ls _mkdir _rm fstests - ./mkfs fs.img userfs usertests _echo _cat README _init _sh _ls _mkdir _rm fstests +fs.img : mkfs usertests _echo _cat README _init _sh _ls _mkdir _rm fstests + ./mkfs fs.img usertests _echo _cat README _init _sh _ls _mkdir _rm fstests -include *.d @@ -140,5 +128,5 @@ clean : /bin/rm -f rm rm -f *.ps *.tex *.dvi *.idx *.aux *.log *.ind *.ilg \ *.o *.d *.asm vectors.S parport.out \ - bootblock kernel xv6.img user1 userfs usertests \ - fs.img mkfs echo init fstests + bootblock kernel xv6.img usertests \ + fs.img mkfs echo init diff --git a/fstests.c b/fstests.c deleted file mode 100644 index 4956437..0000000 --- a/fstests.c +++ /dev/null @@ -1,685 +0,0 @@ -#include "types.h" -#include "stat.h" -#include "user.h" -#include "fcntl.h" - -char buf[512]; - -// two processes write to the same file descriptor -// is the offset shared? does inode locking work? -void -sharedfd() -{ - int fd, pid, i, n, nc, np; - char buf[10]; - - unlink("sharedfd"); - fd = open("sharedfd", O_CREATE|O_RDWR); - if(fd < 0){ - printf(1, "fstests: cannot open sharedfd for writing"); - return; - } - pid = fork(); - memset(buf, pid==0?'c':'p', sizeof(buf)); - for(i = 0; i < 100; i++){ - if(write(fd, buf, sizeof(buf)) != sizeof(buf)){ - printf(1, "fstests: write sharedfd failed\n"); - break; - } - } - if(pid == 0) - exit(); - else - wait(); - close(fd); - fd = open("sharedfd", 0); - if(fd < 0){ - printf(1, "fstests: cannot open sharedfd for reading\n"); - return; - } - nc = np = 0; - while((n = read(fd, buf, sizeof(buf))) > 0){ - for(i = 0; i < sizeof(buf); i++){ - if(buf[i] == 'c') - nc++; - if(buf[i] == 'p') - np++; - } - } - close(fd); - unlink("sharedfd"); - if(nc == 1000 && np == 1000) - printf(1, "sharedfd ok\n"); - else - printf(1, "sharedfd oops %d %d\n", nc, np); -} - -// two processes write two different files at the same -// time, to test block allocation. -void -twofiles() -{ - int fd, pid, i, j, n, total; - char *fname; - - unlink("f1"); - unlink("f2"); - - pid = fork(); - if(pid < 0){ - puts("fork failed\n"); - return; - } - - fname = pid ? "f1" : "f2"; - fd = open(fname, O_CREATE | O_RDWR); - if(fd < 0){ - puts("create failed\n"); - exit(); - } - - memset(buf, pid?'p':'c', 512); - for(i = 0; i < 12; i++){ - if((n = write(fd, buf, 500)) != 500){ - printf(1, "write failed %d\n", n); - exit(); - } - } - close(fd); - if(pid) - wait(); - else - exit(); - - for(i = 0; i < 2; i++){ - fd = open(i?"f1":"f2", 0); - total = 0; - while((n = read(fd, buf, sizeof(buf))) > 0){ - for(j = 0; j < n; j++){ - if(buf[j] != (i?'p':'c')){ - puts("wrong char\n"); - exit(); - } - } - total += n; - } - close(fd); - if(total != 12*500){ - printf(1, "wrong length %d\n", total); - exit(); - } - } - - unlink("f1"); - unlink("f2"); - - puts("twofiles ok\n"); -} - -// two processes create and delete files in same directory -void -createdelete() -{ - int pid, i, fd; - int n = 20; - char name[32]; - - pid = fork(); - if(pid < 0){ - puts("fork failed\n"); - exit(); - } - - name[0] = pid ? 'p' : 'c'; - name[2] = '\0'; - for(i = 0; i < n; i++){ - name[1] = '0' + i; - fd = open(name, O_CREATE | O_RDWR); - if(fd < 0){ - puts("create failed\n"); - exit(); - } - close(fd); - if(i > 0 && (i % 2 ) == 0){ - name[1] = '0' + (i / 2); - if(unlink(name) < 0){ - puts("unlink failed\n"); - exit(); - } - } - } - - if(pid) - exit(); - else - exit(); - - for(i = 0; i < n; i++){ - name[0] = 'p'; - name[1] = '0' + i; - fd = open(name, 0); - if((i == 0 || i >= n/2) && fd < 0){ - printf(1, "oops createdelete %s didn't exist\n", name); - exit(); - } else if((i >= 1 && i < n/2) && fd >= 0){ - printf(1, "oops createdelete %s did exist\n", name); - exit(); - } - if(fd >= 0) - close(fd); - - name[0] = 'c'; - name[1] = '0' + i; - fd = open(name, 0); - if((i == 0 || i >= n/2) && fd < 0){ - printf(1, "oops createdelete %s didn't exist\n", name); - exit(); - } else if((i >= 1 && i < n/2) && fd >= 0){ - printf(1, "oops createdelete %s did exist\n", name); - exit(); - } - if(fd >= 0) - close(fd); - } - - for(i = 0; i < n; i++){ - name[0] = 'p'; - name[1] = '0' + i; - unlink(name); - name[0] = 'c'; - unlink(name); - } - - printf(1, "createdelete ok\n"); -} - -// can I unlink a file and still read it? -void -unlinkread() -{ - int fd, fd1; - - fd = open("unlinkread", O_CREATE | O_RDWR); - if(fd < 0){ - puts("create unlinkread failed\n"); - exit(); - } - write(fd, "hello", 5); - close(fd); - - fd = open("unlinkread", O_RDWR); - if(fd < 0){ - puts("open unlinkread failed\n"); - exit(); - } - if(unlink("unlinkread") != 0){ - puts("unlink unlinkread failed\n"); - exit(); - } - - fd1 = open("unlinkread", O_CREATE | O_RDWR); - write(fd1, "yyy", 3); - close(fd1); - - if(read(fd, buf, sizeof(buf)) != 5){ - puts("unlinkread read failed"); - exit(); - } - if(buf[0] != 'h'){ - puts("unlinkread wrong data\n"); - exit(); - } - if(write(fd, buf, 10) != 10){ - puts("unlinkread write failed\n"); - exit(); - } - close(fd); - unlink("unlinkread"); - puts("unlinkread ok\n"); -} - -void -linktest() -{ - int fd; - - unlink("lf1"); - unlink("lf2"); - - fd = open("lf1", O_CREATE|O_RDWR); - if(fd < 0){ - puts("create lf1 failed\n"); - exit(); - } - if(write(fd, "hello", 5) != 5){ - puts("write lf1 failed\n"); - exit(); - } - close(fd); - - if(link("lf1", "lf2") < 0){ - puts("link lf1 lf2 failed\n"); - exit(); - } - unlink("lf1"); - - if(open("lf1", 0) >= 0){ - puts("unlinked lf1 but it is still there!\n"); - exit(); - } - - fd = open("lf2", 0); - if(fd < 0){ - puts("open lf2 failed\n"); - exit(); - } - if(read(fd, buf, sizeof(buf)) != 5){ - puts("read lf2 failed\n"); - exit(); - } - close(fd); - - if(link("lf2", "lf2") >= 0){ - puts("link lf2 lf2 succeeded! oops\n"); - exit(); - } - - unlink("lf2"); - if(link("lf2", "lf1") >= 0){ - puts("link non-existant succeeded! oops\n"); - exit(); - } - - if(link(".", "lf1") >= 0){ - puts("link . lf1 succeeded! oops\n"); - exit(); - } - - puts("linktest ok\n"); -} - -// test concurrent create of the same file -void -concreate() -{ - char file[3]; - int i, pid, n, fd; - char fa[40]; - struct { - unsigned short inum; - char name[14]; - } de; - - file[0] = 'C'; - file[2] = '\0'; - for(i = 0; i < 40; i++){ - file[1] = '0' + i; - unlink(file); - pid = fork(); - if(pid && (i % 3) == 1){ - link("C0", file); - } else if(pid == 0 && (i % 5) == 1){ - link("C0", file); - } else { - fd = open(file, O_CREATE | O_RDWR); - if(fd < 0){ - printf(1, "concreate create %s failed\n", file); - exit(); - } - close(fd); - } - if(pid == 0) - exit(); - else - wait(); - } - - memset(fa, 0, sizeof(fa)); - fd = open(".", 0); - n = 0; - while(read(fd, &de, sizeof(de)) > 0){ - if(de.inum == 0) - continue; - if(de.name[0] == 'C' && de.name[2] == '\0'){ - i = de.name[1] - '0'; - if(i < 0 || i >= sizeof(fa)){ - printf(1, "concreate weird file %s\n", de.name); - exit(); - } - if(fa[i]){ - printf(1, "concreate duplicate file %s\n", de.name); - exit(); - } - fa[i] = 1; - n++; - } - } - close(fd); - - if(n != 40){ - puts("concreate not enough files in directory listing\n"); - exit(); - } - - for(i = 0; i < 40; i++){ - file[1] = '0' + i; - unlink(file); - } - - puts("concreate ok\n"); -} - -// directory that uses indirect blocks -void -bigdir() -{ - int i, fd; - char name[10]; - - unlink("bd"); - - fd = open("bd", O_CREATE); - if(fd < 0){ - puts("bigdir create failed\n"); - exit(); - } - close(fd); - - for(i = 0; i < 500; i++){ - name[0] = 'x'; - name[1] = '0' + (i / 64); - name[2] = '0' + (i % 64); - name[3] = '\0'; - if(link("bd", name) != 0){ - puts("bigdir link failed\n"); - exit(); - } - puts("c"); - } - - unlink("bd"); - for(i = 0; i < 500; i++){ - name[0] = 'x'; - name[1] = '0' + (i / 64); - name[2] = '0' + (i % 64); - name[3] = '\0'; - if(unlink(name) != 0){ - puts("bigdir unlink failed"); - exit(); - } - puts("d"); - } - - puts("bigdir ok\n"); -} - -void -subdir() -{ - int fd, cc; - - unlink("ff"); - if(mkdir("dd") != 0){ - puts("subdir mkdir dd failed\n"); - exit(); - } - - fd = open("dd/ff", O_CREATE | O_RDWR); - if(fd < 0){ - puts("create dd/ff failed\n"); - exit(); - } - write(fd, "ff", 2); - close(fd); - - if(mkdir("/dd/dd") != 0){ - puts("subdir mkdir dd/dd failed\n"); - exit(); - } - - fd = open("dd/dd/ff", O_CREATE | O_RDWR); - if(fd < 0){ - puts("create dd/dd/ff failed\n"); - exit(); - } - write(fd, "FF", 2); - close(fd); - - fd = open("dd/dd/../ff", 0); - if(fd < 0){ - puts("open dd/dd/../ff failed\n"); - exit(); - } - cc = read(fd, buf, sizeof(buf)); - if(cc != 2 || buf[0] != 'f'){ - puts("dd/dd/../ff wrong content\n"); - exit(); - } - close(fd); - - if(link("dd/dd/ff", "dd/dd/ffff") != 0){ - puts("link dd/dd/ff dd/dd/ffff failed\n"); - exit(); - } - - if(unlink("dd/dd/ff") != 0){ - puts("unlink dd/dd/ff failed\n"); - exit(); - } - - if(chdir("dd") != 0){ - puts("chdir dd failed\n"); - exit(); - } - if(chdir("dd/../../dd") != 0){ - puts("chdir dd/../../dd failed\n"); - exit(); - } - if(chdir("./..") != 0){ - puts("chdir ./.. failed\n"); - exit(); - } - - fd = open("dd/dd/ffff", 0); - if(fd < 0){ - puts("open dd/dd/ffff failed\n"); - exit(); - } - if(read(fd, buf, sizeof(buf)) != 2){ - puts("read dd/dd/ffff wrong len\n"); - exit(); - } - close(fd); - - if(open("dd/dd/ff", 0) >= 0){ - puts("open dd/dd/ff succeeded!\n"); - exit(); - } - - if(open("dd/ff/ff", O_CREATE|O_RDWR) >= 0){ - puts("create dd/ff/ff succeeded!\n"); - exit(); - } - if(open("dd/xx/ff", O_CREATE|O_RDWR) >= 0){ - puts("create dd/xx/ff succeeded!\n"); - exit(); - } - if(open("dd", O_CREATE) >= 0){ - puts("create dd succeeded!\n"); - exit(); - } - if(open("dd", O_RDWR) >= 0){ - puts("open dd rdwr succeeded!\n"); - exit(); - } - if(open("dd", O_WRONLY) >= 0){ - puts("open dd wronly succeeded!\n"); - exit(); - } - if(link("dd/ff/ff", "dd/dd/xx") == 0){ - puts("link dd/ff/ff dd/dd/xx succeeded!\n"); - exit(); - } - if(link("dd/xx/ff", "dd/dd/xx") == 0){ - puts("link dd/xx/ff dd/dd/xx succeeded!\n"); - exit(); - } - if(link("dd/ff", "dd/dd/ffff") == 0){ - puts("link dd/ff dd/dd/ffff succeeded!\n"); - exit(); - } - if(mkdir("dd/ff/ff") == 0){ - puts("mkdir dd/ff/ff succeeded!\n"); - exit(); - } - if(mkdir("dd/xx/ff") == 0){ - puts("mkdir dd/xx/ff succeeded!\n"); - exit(); - } - if(mkdir("dd/dd/ffff") == 0){ - puts("mkdir dd/dd/ffff succeeded!\n"); - exit(); - } - if(unlink("dd/xx/ff") == 0){ - puts("unlink dd/xx/ff succeeded!\n"); - exit(); - } - if(unlink("dd/ff/ff") == 0){ - puts("unlink dd/ff/ff succeeded!\n"); - exit(); - } - if(chdir("dd/ff") == 0){ - puts("chdir dd/ff succeeded!\n"); - exit(); - } - if(chdir("dd/xx") == 0){ - puts("chdir dd/xx succeeded!\n"); - exit(); - } - - if(unlink("dd/dd/ffff") != 0){ - puts("unlink dd/dd/ff failed\n"); - exit(); - } - if(unlink("dd/ff") != 0){ - puts("unlink dd/ff failed\n"); - exit(); - } - - // unlink dd/dd - // unlink dd - - puts("subdir ok\n"); -} - -void -bigfile() -{ - int fd, i, total, cc; - - unlink("bigfile"); - fd = open("bigfile", O_CREATE | O_RDWR); - if(fd < 0){ - puts("cannot create bigfile"); - exit(); - } - for(i = 0; i < 20; i++){ - memset(buf, i, 600); - if(write(fd, buf, 600) != 600){ - puts("write bigfile failed\n"); - exit(); - } - } - close(fd); - - fd = open("bigfile", 0); - if(fd < 0){ - puts("cannot open bigfile\n"); - exit(); - } - total = 0; - for(i = 0; ; i++){ - cc = read(fd, buf, 300); - if(cc < 0){ - puts("read bigfile failed\n"); - exit(); - } - if(cc == 0) - break; - if(cc != 300){ - puts("short read bigfile\n"); - exit(); - } - if(buf[0] != i/2 || buf[299] != i/2){ - puts("read bigfile wrong data\n"); - exit(); - } - total += cc; - } - close(fd); - if(total != 20*600){ - puts("read bigfile wrong total\n"); - exit(); - } - unlink("bigfile"); - - puts("bigfile ok\n"); -} - -void -fourteen() -{ - int fd; - - if(mkdir("12345678901234") != 0){ - puts("mkdir 12345678901234 failed\n"); - exit(); - } - if(mkdir("12345678901234/123456789012345") != 0){ - puts("mkdir 12345678901234/123456789012345 failed\n"); - exit(); - } - fd = open("123456789012345/123456789012345/123456789012345", O_CREATE); - if(fd < 0){ - puts("create 123456789012345/123456789012345/123456789012345 failed\n"); - exit(); - } - close(fd); - fd = open("12345678901234/12345678901234/12345678901234", 0); - if(fd < 0){ - puts("open 12345678901234/12345678901234/12345678901234 failed\n"); - exit(); - } - close(fd); - - if(mkdir("12345678901234/12345678901234") == 0){ - puts("mkdir 12345678901234/12345678901234 succeeded!\n"); - exit(); - } - if(mkdir("123456789012345/12345678901234") == 0){ - puts("mkdir 12345678901234/123456789012345 succeeded!\n"); - exit(); - } - - puts("fourteen ok\n"); -} - -int -main(int argc, char *argv[]) -{ - puts("fstests starting\n"); - - fourteen(); - bigfile(); - subdir(); - // bigdir(); // slow - concreate(); - linktest(); - unlinkread(); - createdelete(); - twofiles(); - sharedfd(); - - puts("fstests finished\n"); - exit(); -} diff --git a/user1.c b/user1.c deleted file mode 100644 index 267320e..0000000 --- a/user1.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "user.h" - -char buf[32]; - -int -main(void) -{ - int pid, fds[2], n; - - pipe(fds); - pid = fork(); - if(pid > 0){ - write(fds[1], "xyz", 4); - puts("w"); - } else { - n = read(fds[0], buf, sizeof(buf)); - puts("r: "); - puts(buf); - puts("\n"); - } - for(;;); -} diff --git a/userfs.c b/userfs.c deleted file mode 100644 index b409f1e..0000000 --- a/userfs.c +++ /dev/null @@ -1,210 +0,0 @@ -#include "types.h" -#include "stat.h" -#include "user.h" -#include "fs.h" -#include "fcntl.h" - -// simple file system tests - -char buf[2000]; -char name[3]; -char *echo_args[] = { "echo", "hello", "goodbye", 0 }; -char *cat_args[] = { "cat", "readme", 0 }; -int stdout = 1; - -void -opentest(void) -{ - int fd; - - fd = open("echo", 0); - if(fd >= 0){ - printf(stdout, "open echo ok\n"); - close(fd); - } else { - printf(stdout, "open echo failed!\n"); - exit(); - } - fd = open("doesnotexist", 0); - if(fd >= 0){ - printf(stdout, "open doesnotexist succeeded!\n"); - exit(); - } else { - printf(stdout, "open doesnotexist failed\n"); - } -} - -void -writetest(void) -{ - int fd; - int i; - - fd = open("small", O_CREATE|O_RDWR); - if(fd >= 0){ - printf(stdout, "creat small succeeded\n"); - } else { - printf(stdout, "error: creat small failed!\n"); - exit(); - } - for(i = 0; i < 100; i++) { - if(write(fd, "aaaaaaaaaa", 10) != 10) { - printf(stdout, "error: write aa %d new file failed\n", i); - exit(); - } - if(write(fd, "bbbbbbbbbb", 10) != 10) { - printf(stdout, "error: write bb %d new file failed\n", i); - exit(); - } - } - printf(stdout, "writes done\n"); - close(fd); - fd = open("small", O_RDONLY); - if(fd >= 0){ - printf(stdout, "open small succeeded\n"); - } else { - printf(stdout, "error: open small failed!\n"); - exit(); - } - i = read(fd, buf, 2000); - if(i == 2000) { - printf(stdout, "read succeeded\n"); - } else { - printf(stdout, "read failed\n"); - exit(); - } - close(fd); - - if(unlink("small") < 0) { - printf(stdout, "unlink small failed\n"); - exit(); - } -} - -void -writetest1(void) -{ - int i, fd, n; - - printf(stdout, "big files\n"); - - fd = open("big", O_CREATE|O_RDWR); - if(fd < 0){ - printf(stdout, "error: creat big failed!\n"); - exit(); - } - - for(i = 0; i < MAXFILE; i++) { - ((int*) buf)[0] = i; - if(write(fd, buf, 512) != 512) { - printf(stdout, "error: write big file failed\n", i); - exit(); - } - } - - close(fd); - - fd = open("big", O_RDONLY); - if(fd < 0){ - printf(stdout, "error: open big failed!\n"); - exit(); - } - - n = 0; - for(;;) { - i = read(fd, buf, 512); - if(i == 0) { - if(n == MAXFILE - 1) { - printf(stdout, "read only %d blocks from big", n); - exit(); - } - break; - } else if(i != 512) { - printf(stdout, "read failed %d\n", i); - exit(); - } - if(((int*)buf)[0] != n) { - printf(stdout, "read content of block %d is %d\n", - n, ((int*)buf)[0]); - exit(); - } - n++; - } - close(fd); - if(unlink("big") < 0) { - printf(stdout, "unlink big failed\n"); - exit(); - } -} - -void -createtest(void) -{ - int i, fd; - - printf(stdout, "many creates, followed by unlink\n"); - - name[0] = 'a'; - name[2] = '\0'; - for(i = 0; i < 52; i++) { - name[1] = '0' + i; - fd = open(name, O_CREATE|O_RDWR); - close(fd); - } - name[0] = 'a'; - name[2] = '\0'; - for(i = 0; i < 52; i++) { - name[1] = '0' + i; - unlink(name); - } -} - -void dirtest(void) -{ - printf(stdout, "mkdir\n"); - - if(mkdir("dir0") < 0) { - printf(stdout, "mkdir failed\n"); - exit(); - } - - if(chdir("dir0") < 0) { - printf(stdout, "chdir dir0 failed\n"); - exit(); - } - - if(chdir("..") < 0) { - printf(stdout, "chdir .. failed\n"); - exit(); - } - - if(unlink("dir0") < 0) { - printf(stdout, "unlink dir0 failed\n"); - exit(); - } -} - -void -exectest(void) -{ - if(exec("echo", echo_args) < 0) { - printf(stdout, "exec echo failed\n"); - exit(); - } - if(exec("cat", cat_args) < 0) { - printf(stdout, "exec cat failed\n"); - exit(); - } -} - -int -main(void) -{ - printf(stdout, "userfs is running\n"); - opentest(); - writetest(); - writetest1(); - createtest(); - exectest(); - return 0; -} diff --git a/usertests.c b/usertests.c index 0b003bd..f8a3efe 100644 --- a/usertests.c +++ b/usertests.c @@ -1,9 +1,201 @@ #include "types.h" #include "stat.h" #include "user.h" +#include "fs.h" #include "fcntl.h" char buf[2048]; +char name[3]; +char *echo_args[] = { "echo", "hello", "goodbye", 0 }; +char *cat_args[] = { "cat", "README", 0 }; +int stdout = 1; + +// simple file system tests + +void +opentest(void) +{ + int fd; + + printf(stdout, "open test\n"); + fd = open("echo", 0); + if(fd < 0){ + printf(stdout, "open echo failed!\n"); + exit(); + } + close(fd); + fd = open("doesnotexist", 0); + if(fd >= 0){ + printf(stdout, "open doesnotexist succeeded!\n"); + exit(); + } + printf(stdout, "open test ok\n"); +} + +void +writetest(void) +{ + int fd; + int i; + + printf(stdout, "small file test\n"); + fd = open("small", O_CREATE|O_RDWR); + if(fd >= 0){ + printf(stdout, "creat small succeeded; ok\n"); + } else { + printf(stdout, "error: creat small failed!\n"); + exit(); + } + for(i = 0; i < 100; i++) { + if(write(fd, "aaaaaaaaaa", 10) != 10) { + printf(stdout, "error: write aa %d new file failed\n", i); + exit(); + } + if(write(fd, "bbbbbbbbbb", 10) != 10) { + printf(stdout, "error: write bb %d new file failed\n", i); + exit(); + } + } + printf(stdout, "writes ok\n"); + close(fd); + fd = open("small", O_RDONLY); + if(fd >= 0){ + printf(stdout, "open small succeeded ok\n"); + } else { + printf(stdout, "error: open small failed!\n"); + exit(); + } + i = read(fd, buf, 2000); + if(i == 2000) { + printf(stdout, "read succeeded ok\n"); + } else { + printf(stdout, "read failed\n"); + exit(); + } + close(fd); + + if(unlink("small") < 0) { + printf(stdout, "unlink small failed\n"); + exit(); + } + printf(stdout, "small file test ok\n"); +} + +void +writetest1(void) +{ + int i, fd, n; + + printf(stdout, "big files test\n"); + + fd = open("big", O_CREATE|O_RDWR); + if(fd < 0){ + printf(stdout, "error: creat big failed!\n"); + exit(); + } + + for(i = 0; i < MAXFILE; i++) { + ((int*) buf)[0] = i; + if(write(fd, buf, 512) != 512) { + printf(stdout, "error: write big file failed\n", i); + exit(); + } + } + + close(fd); + + fd = open("big", O_RDONLY); + if(fd < 0){ + printf(stdout, "error: open big failed!\n"); + exit(); + } + + n = 0; + for(;;) { + i = read(fd, buf, 512); + if(i == 0) { + if(n == MAXFILE - 1) { + printf(stdout, "read only %d blocks from big", n); + exit(); + } + break; + } else if(i != 512) { + printf(stdout, "read failed %d\n", i); + exit(); + } + if(((int*)buf)[0] != n) { + printf(stdout, "read content of block %d is %d\n", + n, ((int*)buf)[0]); + exit(); + } + n++; + } + close(fd); + if(unlink("big") < 0) { + printf(stdout, "unlink big failed\n"); + exit(); + } + printf(stdout, "big files ok\n"); +} + +void +createtest(void) +{ + int i, fd; + + printf(stdout, "many creates, followed by unlink test\n"); + + name[0] = 'a'; + name[2] = '\0'; + for(i = 0; i < 52; i++) { + name[1] = '0' + i; + fd = open(name, O_CREATE|O_RDWR); + close(fd); + } + name[0] = 'a'; + name[2] = '\0'; + for(i = 0; i < 52; i++) { + name[1] = '0' + i; + unlink(name); + } + printf(stdout, "many creates, followed by unlink; ok\n"); +} + +void dirtest(void) +{ + printf(stdout, "mkdir test\n"); + + if(mkdir("dir0") < 0) { + printf(stdout, "mkdir failed\n"); + exit(); + } + + if(chdir("dir0") < 0) { + printf(stdout, "chdir dir0 failed\n"); + exit(); + } + + if(chdir("..") < 0) { + printf(stdout, "chdir .. failed\n"); + exit(); + } + + if(unlink("dir0") < 0) { + printf(stdout, "unlink dir0 failed\n"); + exit(); + } + printf(stdout, "mkdir test\n"); +} + +void +exectest(void) +{ + printf(stdout, "exec test\n"); + if(exec("echo", echo_args) < 0) { + printf(stdout, "exec echo failed\n"); + exit(); + } +} // simple fork and pipe read/write @@ -14,7 +206,7 @@ pipe1(void) int seq = 0, i, n, cc, total; if(pipe(fds) != 0){ - puts("pipe() failed\n"); + printf(1, "pipe() failed\n"); exit(); } pid = fork(); @@ -50,10 +242,10 @@ pipe1(void) close(fds[0]); wait(); } else { - puts("fork() failed\n"); + printf(1, "fork() failed\n"); exit(); } - puts("pipe1 ok\n"); + printf(1, "pipe1 ok\n"); } // meant to be run w/ at most two CPUs @@ -96,7 +288,7 @@ preempt(void) wait(); wait(); wait(); - puts("preempt ok\n"); + printf(1, "preempt ok\n"); } // try to find any races between exit and wait @@ -120,7 +312,7 @@ exitwait(void) exit(); } } - puts("exitwait ok\n"); + printf(1, "exitwait ok\n"); } void @@ -142,7 +334,7 @@ mem(void) } m1 = malloc(1024*20); if(m1 == 0) { - puts("couldn't allocate mem?!!\n"); + printf(1, "couldn't allocate mem?!!\n"); exit(); } free(m1); @@ -153,16 +345,706 @@ mem(void) } } +// More file system tests + +// two processes write to the same file descriptor +// is the offset shared? does inode locking work? +void +sharedfd() +{ + int fd, pid, i, n, nc, np; + char buf[10]; + + unlink("sharedfd"); + fd = open("sharedfd", O_CREATE|O_RDWR); + if(fd < 0){ + printf(1, "fstests: cannot open sharedfd for writing"); + return; + } + pid = fork(); + memset(buf, pid==0?'c':'p', sizeof(buf)); + for(i = 0; i < 100; i++){ + if(write(fd, buf, sizeof(buf)) != sizeof(buf)){ + printf(1, "fstests: write sharedfd failed\n"); + break; + } + } + if(pid == 0) + exit(); + else + wait(); + close(fd); + fd = open("sharedfd", 0); + if(fd < 0){ + printf(1, "fstests: cannot open sharedfd for reading\n"); + return; + } + nc = np = 0; + while((n = read(fd, buf, sizeof(buf))) > 0){ + for(i = 0; i < sizeof(buf); i++){ + if(buf[i] == 'c') + nc++; + if(buf[i] == 'p') + np++; + } + } + close(fd); + unlink("sharedfd"); + if(nc == 1000 && np == 1000) + printf(1, "sharedfd ok\n"); + else + printf(1, "sharedfd oops %d %d\n", nc, np); +} + +// two processes write two different files at the same +// time, to test block allocation. +void +twofiles() +{ + int fd, pid, i, j, n, total; + char *fname; + + printf(1, "twofiles test\n"); + + unlink("f1"); + unlink("f2"); + + pid = fork(); + if(pid < 0){ + printf(1, "fork failed\n"); + return; + } + + fname = pid ? "f1" : "f2"; + fd = open(fname, O_CREATE | O_RDWR); + if(fd < 0){ + printf(1, "create failed\n"); + exit(); + } + + memset(buf, pid?'p':'c', 512); + for(i = 0; i < 12; i++){ + if((n = write(fd, buf, 500)) != 500){ + printf(1, "write failed %d\n", n); + exit(); + } + } + close(fd); + if(pid) + wait(); + else + exit(); + + for(i = 0; i < 2; i++){ + fd = open(i?"f1":"f2", 0); + total = 0; + while((n = read(fd, buf, sizeof(buf))) > 0){ + for(j = 0; j < n; j++){ + if(buf[j] != (i?'p':'c')){ + printf(1, "wrong char\n"); + exit(); + } + } + total += n; + } + close(fd); + if(total != 12*500){ + printf(1, "wrong length %d\n", total); + exit(); + } + } + + unlink("f1"); + unlink("f2"); + + printf(1, "twofiles ok\n"); +} + +// two processes create and delete files in same directory +void +createdelete() +{ + int pid, i, fd; + int n = 20; + char name[32]; + + printf(1, "createdelete test\n"); + pid = fork(); + if(pid < 0){ + printf(1, "fork failed\n"); + exit(); + } + + name[0] = pid ? 'p' : 'c'; + name[2] = '\0'; + for(i = 0; i < n; i++){ + name[1] = '0' + i; + fd = open(name, O_CREATE | O_RDWR); + if(fd < 0){ + printf(1, "create failed\n"); + exit(); + } + close(fd); + if(i > 0 && (i % 2 ) == 0){ + name[1] = '0' + (i / 2); + if(unlink(name) < 0){ + printf(1, "unlink failed\n"); + exit(); + } + } + } + + if(pid==0) + exit(); + // else + //exit(); + + for(i = 0; i < n; i++){ + name[0] = 'p'; + name[1] = '0' + i; + fd = open(name, 0); + if((i == 0 || i >= n/2) && fd < 0){ + printf(1, "oops createdelete %s didn't exist\n", name); + exit(); + } else if((i >= 1 && i < n/2) && fd >= 0){ + printf(1, "oops createdelete %s did exist\n", name); + exit(); + } + if(fd >= 0) + close(fd); + + name[0] = 'c'; + name[1] = '0' + i; + fd = open(name, 0); + if((i == 0 || i >= n/2) && fd < 0){ + printf(1, "oops createdelete %s didn't exist\n", name); + exit(); + } else if((i >= 1 && i < n/2) && fd >= 0){ + printf(1, "oops createdelete %s did exist\n", name); + exit(); + } + if(fd >= 0) + close(fd); + } + + for(i = 0; i < n; i++){ + name[0] = 'p'; + name[1] = '0' + i; + unlink(name); + name[0] = 'c'; + unlink(name); + } + + printf(1, "createdelete ok\n"); +} + +// can I unlink a file and still read it? +void +unlinkread() +{ + int fd, fd1; + + printf(1, "unlinkread test\n"); + fd = open("unlinkread", O_CREATE | O_RDWR); + if(fd < 0){ + printf(1, "create unlinkread failed\n"); + exit(); + } + write(fd, "hello", 5); + close(fd); + + fd = open("unlinkread", O_RDWR); + if(fd < 0){ + printf(1, "open unlinkread failed\n"); + exit(); + } + if(unlink("unlinkread") != 0){ + printf(1, "unlink unlinkread failed\n"); + exit(); + } + + fd1 = open("unlinkread", O_CREATE | O_RDWR); + write(fd1, "yyy", 3); + close(fd1); + + if(read(fd, buf, sizeof(buf)) != 5){ + printf(1, "unlinkread read failed"); + exit(); + } + if(buf[0] != 'h'){ + printf(1, "unlinkread wrong data\n"); + exit(); + } + if(write(fd, buf, 10) != 10){ + printf(1, "unlinkread write failed\n"); + exit(); + } + close(fd); + unlink("unlinkread"); + printf(1, "unlinkread ok\n"); +} + +void +linktest() +{ + int fd; + + printf(1, "linktest\n"); + + unlink("lf1"); + unlink("lf2"); + + fd = open("lf1", O_CREATE|O_RDWR); + if(fd < 0){ + printf(1, "create lf1 failed\n"); + exit(); + } + if(write(fd, "hello", 5) != 5){ + printf(1, "write lf1 failed\n"); + exit(); + } + close(fd); + + if(link("lf1", "lf2") < 0){ + printf(1, "link lf1 lf2 failed\n"); + exit(); + } + unlink("lf1"); + + if(open("lf1", 0) >= 0){ + printf(1, "unlinked lf1 but it is still there!\n"); + exit(); + } + + fd = open("lf2", 0); + if(fd < 0){ + printf(1, "open lf2 failed\n"); + exit(); + } + if(read(fd, buf, sizeof(buf)) != 5){ + printf(1, "read lf2 failed\n"); + exit(); + } + close(fd); + + if(link("lf2", "lf2") >= 0){ + printf(1, "link lf2 lf2 succeeded! oops\n"); + exit(); + } + + unlink("lf2"); + if(link("lf2", "lf1") >= 0){ + printf(1, "link non-existant succeeded! oops\n"); + exit(); + } + + if(link(".", "lf1") >= 0){ + printf(1, "link . lf1 succeeded! oops\n"); + exit(); + } + + printf(1, "linktest ok\n"); +} + +// test concurrent create of the same file +void +concreate() +{ + char file[3]; + int i, pid, n, fd; + char fa[40]; + struct { + unsigned short inum; + char name[14]; + } de; + + printf(1, "concreate test\n"); + file[0] = 'C'; + file[2] = '\0'; + for(i = 0; i < 40; i++){ + file[1] = '0' + i; + unlink(file); + pid = fork(); + if(pid && (i % 3) == 1){ + link("C0", file); + } else if(pid == 0 && (i % 5) == 1){ + link("C0", file); + } else { + fd = open(file, O_CREATE | O_RDWR); + if(fd < 0){ + printf(1, "concreate create %s failed\n", file); + exit(); + } + close(fd); + } + if(pid == 0) + exit(); + else + wait(); + } + + memset(fa, 0, sizeof(fa)); + fd = open(".", 0); + n = 0; + while(read(fd, &de, sizeof(de)) > 0){ + if(de.inum == 0) + continue; + if(de.name[0] == 'C' && de.name[2] == '\0'){ + i = de.name[1] - '0'; + if(i < 0 || i >= sizeof(fa)){ + printf(1, "concreate weird file %s\n", de.name); + exit(); + } + if(fa[i]){ + printf(1, "concreate duplicate file %s\n", de.name); + exit(); + } + fa[i] = 1; + n++; + } + } + close(fd); + + if(n != 40){ + printf(1, "concreate not enough files in directory listing\n"); + exit(); + } + + for(i = 0; i < 40; i++){ + file[1] = '0' + i; + unlink(file); + } + + printf(1, "concreate ok\n"); +} + +// directory that uses indirect blocks +void +bigdir() +{ + int i, fd; + char name[10]; + + printf(1, "bigdir test\n"); + unlink("bd"); + + fd = open("bd", O_CREATE); + if(fd < 0){ + printf(1, "bigdir create failed\n"); + exit(); + } + close(fd); + + for(i = 0; i < 500; i++){ + name[0] = 'x'; + name[1] = '0' + (i / 64); + name[2] = '0' + (i % 64); + name[3] = '\0'; + if(link("bd", name) != 0){ + printf(1, "bigdir link failed\n"); + exit(); + } + } + + unlink("bd"); + for(i = 0; i < 500; i++){ + name[0] = 'x'; + name[1] = '0' + (i / 64); + name[2] = '0' + (i % 64); + name[3] = '\0'; + if(unlink(name) != 0){ + printf(1, "bigdir unlink failed"); + exit(); + } + } + + printf(1, "bigdir ok\n"); +} + +void +subdir() +{ + int fd, cc; + + printf(1, "subdir test\n"); + + unlink("ff"); + if(mkdir("dd") != 0){ + printf(1, "subdir mkdir dd failed\n"); + exit(); + } + + fd = open("dd/ff", O_CREATE | O_RDWR); + if(fd < 0){ + printf(1, "create dd/ff failed\n"); + exit(); + } + write(fd, "ff", 2); + close(fd); + + if(mkdir("/dd/dd") != 0){ + printf(1, "subdir mkdir dd/dd failed\n"); + exit(); + } + + fd = open("dd/dd/ff", O_CREATE | O_RDWR); + if(fd < 0){ + printf(1, "create dd/dd/ff failed\n"); + exit(); + } + write(fd, "FF", 2); + close(fd); + + fd = open("dd/dd/../ff", 0); + if(fd < 0){ + printf(1, "open dd/dd/../ff failed\n"); + exit(); + } + cc = read(fd, buf, sizeof(buf)); + if(cc != 2 || buf[0] != 'f'){ + printf(1, "dd/dd/../ff wrong content\n"); + exit(); + } + close(fd); + + if(link("dd/dd/ff", "dd/dd/ffff") != 0){ + printf(1, "link dd/dd/ff dd/dd/ffff failed\n"); + exit(); + } + + if(unlink("dd/dd/ff") != 0){ + printf(1, "unlink dd/dd/ff failed\n"); + exit(); + } + + if(chdir("dd") != 0){ + printf(1, "chdir dd failed\n"); + exit(); + } + if(chdir("dd/../../dd") != 0){ + printf(1, "chdir dd/../../dd failed\n"); + exit(); + } + if(chdir("./..") != 0){ + printf(1, "chdir ./.. failed\n"); + exit(); + } + + fd = open("dd/dd/ffff", 0); + if(fd < 0){ + printf(1, "open dd/dd/ffff failed\n"); + exit(); + } + if(read(fd, buf, sizeof(buf)) != 2){ + printf(1, "read dd/dd/ffff wrong len\n"); + exit(); + } + close(fd); + + if(open("dd/dd/ff", 0) >= 0){ + printf(1, "open dd/dd/ff succeeded!\n"); + exit(); + } + + if(open("dd/ff/ff", O_CREATE|O_RDWR) >= 0){ + printf(1, "create dd/ff/ff succeeded!\n"); + exit(); + } + if(open("dd/xx/ff", O_CREATE|O_RDWR) >= 0){ + printf(1, "create dd/xx/ff succeeded!\n"); + exit(); + } + if(open("dd", O_CREATE) >= 0){ + printf(1, "create dd succeeded!\n"); + exit(); + } + if(open("dd", O_RDWR) >= 0){ + printf(1, "open dd rdwr succeeded!\n"); + exit(); + } + if(open("dd", O_WRONLY) >= 0){ + printf(1, "open dd wronly succeeded!\n"); + exit(); + } + if(link("dd/ff/ff", "dd/dd/xx") == 0){ + printf(1, "link dd/ff/ff dd/dd/xx succeeded!\n"); + exit(); + } + if(link("dd/xx/ff", "dd/dd/xx") == 0){ + printf(1, "link dd/xx/ff dd/dd/xx succeeded!\n"); + exit(); + } + if(link("dd/ff", "dd/dd/ffff") == 0){ + printf(1, "link dd/ff dd/dd/ffff succeeded!\n"); + exit(); + } + if(mkdir("dd/ff/ff") == 0){ + printf(1, "mkdir dd/ff/ff succeeded!\n"); + exit(); + } + if(mkdir("dd/xx/ff") == 0){ + printf(1, "mkdir dd/xx/ff succeeded!\n"); + exit(); + } + if(mkdir("dd/dd/ffff") == 0){ + printf(1, "mkdir dd/dd/ffff succeeded!\n"); + exit(); + } + if(unlink("dd/xx/ff") == 0){ + printf(1, "unlink dd/xx/ff succeeded!\n"); + exit(); + } + if(unlink("dd/ff/ff") == 0){ + printf(1, "unlink dd/ff/ff succeeded!\n"); + exit(); + } + if(chdir("dd/ff") == 0){ + printf(1, "chdir dd/ff succeeded!\n"); + exit(); + } + if(chdir("dd/xx") == 0){ + printf(1, "chdir dd/xx succeeded!\n"); + exit(); + } + + if(unlink("dd/dd/ffff") != 0){ + printf(1, "unlink dd/dd/ff failed\n"); + exit(); + } + if(unlink("dd/ff") != 0){ + printf(1, "unlink dd/ff failed\n"); + exit(); + } + + // unlink dd/dd + // unlink dd + + printf(1, "subdir ok\n"); +} + +void +bigfile() +{ + int fd, i, total, cc; + + printf(1, "bigfile test\n"); + + unlink("bigfile"); + fd = open("bigfile", O_CREATE | O_RDWR); + if(fd < 0){ + printf(1, "cannot create bigfile"); + exit(); + } + for(i = 0; i < 20; i++){ + memset(buf, i, 600); + if(write(fd, buf, 600) != 600){ + printf(1, "write bigfile failed\n"); + exit(); + } + } + close(fd); + + fd = open("bigfile", 0); + if(fd < 0){ + printf(1, "cannot open bigfile\n"); + exit(); + } + total = 0; + for(i = 0; ; i++){ + cc = read(fd, buf, 300); + if(cc < 0){ + printf(1, "read bigfile failed\n"); + exit(); + } + if(cc == 0) + break; + if(cc != 300){ + printf(1, "short read bigfile\n"); + exit(); + } + if(buf[0] != i/2 || buf[299] != i/2){ + printf(1, "read bigfile wrong data\n"); + exit(); + } + total += cc; + } + close(fd); + if(total != 20*600){ + printf(1, "read bigfile wrong total\n"); + exit(); + } + unlink("bigfile"); + + printf(1, "bigfile test ok\n"); +} + +void +fourteen() +{ + int fd; + + printf(1, "fourteen test\n"); + + if(mkdir("12345678901234") != 0){ + printf(1, "mkdir 12345678901234 failed\n"); + exit(); + } + if(mkdir("12345678901234/123456789012345") != 0){ + printf(1, "mkdir 12345678901234/123456789012345 failed\n"); + exit(); + } + fd = open("123456789012345/123456789012345/123456789012345", O_CREATE); + if(fd < 0){ + printf(1, "create 123456789012345/123456789012345/123456789012345 failed\n"); + exit(); + } + close(fd); + fd = open("12345678901234/12345678901234/12345678901234", 0); + if(fd < 0){ + printf(1, "open 12345678901234/12345678901234/12345678901234 failed\n"); + exit(); + } + close(fd); + + if(mkdir("12345678901234/12345678901234") == 0){ + printf(1, "mkdir 12345678901234/12345678901234 succeeded!\n"); + exit(); + } + if(mkdir("123456789012345/12345678901234") == 0){ + printf(1, "mkdir 12345678901234/123456789012345 succeeded!\n"); + exit(); + } + + printf(1, "fourteen ok\n"); +} + int main(int argc, char *argv[]) { - puts("usertests starting\n"); + printf(1, "usertests starting\n"); + + opentest(); + writetest(); + writetest1(); + createtest(); mem(); pipe1(); preempt(); exitwait(); - puts("usertests finished\n"); + fourteen(); + bigfile(); + subdir(); + bigdir(); // slow + concreate(); + linktest(); + unlinkread(); + createdelete(); + twofiles(); + sharedfd(); + + exectest(); + exit(); }