/* Copyright (C) 2005 David Decotigny This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include "fstest_utils.h" static const int OPEN_BASE_FD = 3; /** * @file fstest.c * * File-system tests */ int main(void) { int fd, len; char buff[256]; bochs_printf("Hi from fstest\n"); ls("/", 1, 1); ls(".", 1, 1); ls("", 1, 1); ls(0, 1, 1); TEST_EXPECT_CONDITION(fd = open("", 0), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open(0, 0), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("/", O_RDWR), RETVAL == OPEN_BASE_FD + 0); TEST_EXPECT_CONDITION(fd = open("/", O_RDONLY), RETVAL == OPEN_BASE_FD + 1); TEST_EXPECT_CONDITION(fd = open("/", O_WRONLY), RETVAL == OPEN_BASE_FD + 2); TEST_EXPECT_CONDITION(close(OPEN_BASE_FD + 1), RETVAL == 0); TEST_EXPECT_CONDITION(fd = open("/", O_WRONLY), RETVAL == OPEN_BASE_FD + 1); TEST_EXPECT_CONDITION(fd = open("//", O_WRONLY), RETVAL == OPEN_BASE_FD + 3); TEST_EXPECT_CONDITION(fd = open("////////", O_WRONLY), RETVAL == OPEN_BASE_FD + 4); TEST_EXPECT_CONDITION(fd = open("/does not exist", O_WRONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("////does not exist", O_WRONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("/does not exist/", O_WRONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("////does not exist/", O_WRONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("/does not exist////", O_WRONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("////does not exist/////", O_WRONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("does not exist", O_WRONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("does not exist/", O_WRONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("does not exist////", O_WRONLY), RETVAL); TEST_EXPECT_CONDITION(fd = open("/does not exist/ab c d", O_WRONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("////does not exist/ab c d", O_WRONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("/does not exist////ab c d", O_WRONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("////does not exist/////ab c d", O_WRONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("does not exist", O_WRONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("does not exist/ab c d", O_WRONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("does not exist////ab c d", O_WRONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("/", O_RDWR), RETVAL == OPEN_BASE_FD + 5); TEST_EXPECT_CONDITION(fd = open("/tutu.txt", O_RDWR), RETVAL < 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(fd = open("/tutu.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR), RETVAL == OPEN_BASE_FD + 6); ls("/", 1, 1); TEST_EXPECT_CONDITION(fd = open("tutu.txt", O_RDWR | O_CREAT), RETVAL == OPEN_BASE_FD + 7); /* O_EXCL with an already-existing file */ TEST_EXPECT_CONDITION(fd = open("tutu.txt", O_RDWR | O_CREAT | O_EXCL), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("/toto.txt", O_RDWR | O_CREAT | O_EXCL, S_IRWXALL), RETVAL == OPEN_BASE_FD + 8); /* O_EXCL with an already-existing file */ TEST_EXPECT_CONDITION(fd = open("toto.txt", O_RDWR | O_CREAT | O_EXCL), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("toto.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR), RETVAL == OPEN_BASE_FD + 9); /* Trailing slash on non-dir entries */ TEST_EXPECT_CONDITION(fd = open("toto.txt/", O_RDWR), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("notdir/", O_RDWR | O_CREAT, S_IRWXALL), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("notdir/", O_RDWR), RETVAL < 0); /* Substring match */ TEST_EXPECT_CONDITION(fd = open("toto1.txt", O_RDWR), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("toto1.tx", O_RDWR | O_CREAT, S_IWUSR), RETVAL == OPEN_BASE_FD + 10); /* Substring match */ TEST_EXPECT_CONDITION(fd = open("toto.tx", O_RDWR), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("toto.tx", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR), RETVAL == OPEN_BASE_FD + 11); /* * read/write/seek */ TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 0); TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); strzcpy(buff, "Bonjour !", 256); TEST_EXPECT_CONDITION(len = write(fd, buff, 10), RETVAL == 10); ls("/", 1, 1); TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 10); bochs_printf("read s='%s'\n", buff); TEST_EXPECT_CONDITION(strcmp("Bonjour !", buff), RETVAL ==0); TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_CUR), RETVAL == 10); /* * truncate */ TEST_EXPECT_CONDITION(ftruncate(fd, 3), RETVAL == 0); /* The current position should not have changed */ TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_CUR), RETVAL == 10); /* Make sure we cannot read anything because we get past the end of the file */ strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 0); /* Now get back at the begining of the file */ TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); /* Make sure that we can read something with the correct first 3 characters */ strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 3); bochs_printf("read s='%s'\n", buff); TEST_EXPECT_CONDITION(strncmp("Bon", buff, len), RETVAL == 0); /* * open mode */ ls("/", 1, 1); /* Open r/w, create read-only */ TEST_EXPECT_CONDITION(fd = open("toto2.txt", O_RDWR | O_CREAT, S_IRUSR), RETVAL == OPEN_BASE_FD + 12); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 0); TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); strzcpy(buff, "Permission denied", 256); TEST_EXPECT_CONDITION(len = write(fd, buff, 10), RETVAL < 0); /* Permission denied ! */ TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 0); /* Open read-only, create r/w */ TEST_EXPECT_CONDITION(fd = open("toto3.txt", O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR), RETVAL == OPEN_BASE_FD + 13); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 0); TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); strzcpy(buff, "Permission denied 2", 256); TEST_EXPECT_CONDITION(len = write(fd, buff, 10), RETVAL < 0); /* Permission denied ! */ TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 0); /* Create another process that chdirs in it */ if (fork() == 0) { bochs_printf("Hello from child\n"); TEST_EXPECT_CONDITION(fd = open("shrd.txt", O_RDWR | O_CREAT, S_IRWXALL), RETVAL == OPEN_BASE_FD + 14); strzcpy(buff, "Hello from child !", 256); TEST_EXPECT_CONDITION(len = write(fd, buff, 19), RETVAL == 19); TEST_EXPECT_CONDITION(close(fd), RETVAL == 0); bochs_printf("Bye from child\n"); return 0; } bochs_printf("Father sleeping\n"); nanosleep(1, 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(fd = open("shrd.txt", O_RDONLY), RETVAL == OPEN_BASE_FD + 14); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 19); bochs_printf("read s='%s'\n", buff); TEST_EXPECT_CONDITION(strncmp("Hello from child !", buff, len), RETVAL == 0); TEST_EXPECT_CONDITION(close(fd), RETVAL == 0); TEST_EXPECT_CONDITION(unlink("shrd.txt"), RETVAL == 0); ls("/", 1, 1); /* * ioctl / fcntl */ TEST_EXPECT_CONDITION(fcntl(fd, 2, 3), RETVAL < 0); /* Not supported by virtfs */ TEST_EXPECT_CONDITION(ioctl(fd, 2, 3), RETVAL < 0); /* Not supported by virtfs */ ls("/", 1, 1); /* * creat/link/unlink/symlink */ TEST_EXPECT_CONDITION(creat("toto4.txt", S_IRUSR), RETVAL == 0); TEST_EXPECT_CONDITION(creat("toto4.txt", S_IRWXALL), RETVAL < 0); /*EEXIST*/ TEST_EXPECT_CONDITION(link("toto4.txt", "toto5.txt"), RETVAL == 0); TEST_EXPECT_CONDITION(link("toto4.txt", "toto5.txt"), RETVAL < 0); /*EEXIST*/ TEST_EXPECT_CONDITION(link("toto4.txt", "toto.txt"), RETVAL < 0); /*EEXIST*/ ls("/", 1, 1); TEST_EXPECT_CONDITION(chmod("toto5.txt", S_IRUSR | S_IWUSR), RETVAL == 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(fd = open("toto5.txt", O_RDWR), RETVAL == OPEN_BASE_FD + 14); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 0); TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); strzcpy(buff, "Hello world from toto5", 256); TEST_EXPECT_CONDITION(len = write(fd, buff, 24), RETVAL == 24); TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 24); bochs_printf("read s='%s'\n", buff); TEST_EXPECT_CONDITION(fd = open("toto4.txt", O_RDWR), RETVAL == OPEN_BASE_FD + 15); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 24); bochs_printf("read s='%s'\n", buff); ls("/", 1, 1); TEST_EXPECT_CONDITION(link("dangling", "toto42.txt"), RETVAL < 0); /*ENOENT*/ TEST_EXPECT_CONDITION(unlink("toto4.txt"), RETVAL == 0); TEST_EXPECT_CONDITION(unlink("toto42.txt"), RETVAL < 0); /* ENOENT */ TEST_EXPECT_CONDITION(unlink("toto4.txt"), RETVAL < 0); /* ENOENT */ TEST_EXPECT_CONDITION(creat("toto4.txt", S_IWUSR | S_IRUSR), RETVAL == 0); TEST_EXPECT_CONDITION(unlink("toto5.txt/"), RETVAL < 0); /* EISDIR ? */ TEST_EXPECT_CONDITION(rmdir("toto5.txt/"), RETVAL < 0); /* ENOTDIR ? */ TEST_EXPECT_CONDITION(rmdir("toto5.txt"), RETVAL < 0); /* ENOTDIR ? */ TEST_EXPECT_CONDITION(unlink("toto5.txt"), RETVAL == 0); TEST_EXPECT_CONDITION(unlink("toto5.txt"), RETVAL < 0); /* ENOENT */ TEST_EXPECT_CONDITION(creat("toto4.txt", S_IRWXALL), RETVAL < 0); /*EEXIST*/ ls("/", 1, 1); /* Change symlinks */ TEST_EXPECT_CONDITION(symlink("toto4.txt", "toto5.txt"), RETVAL == 0); TEST_EXPECT_CONDITION(symlink("toto4.txt", "toto5.txt"), RETVAL < 0); /*EEXIST*/ TEST_EXPECT_CONDITION(symlink("toto4.txt", "toto.txt"), RETVAL < 0); /*EEXIST*/ ls("/", 1, 1); TEST_EXPECT_CONDITION(fd = open("toto5.txt", O_RDWR), RETVAL == OPEN_BASE_FD + 16); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 0); TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); strzcpy(buff, "Hello world from toto5", 256); TEST_EXPECT_CONDITION(len = write(fd, buff, 24), RETVAL == 24); TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 24); bochs_printf("read s='%s'\n", buff); TEST_EXPECT_CONDITION(strcmp(buff, "Hello world from toto5"), RETVAL == 0); TEST_EXPECT_CONDITION(fd = open("toto4.txt", O_RDWR), RETVAL == OPEN_BASE_FD + 17); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 24); bochs_printf("read s='%s'\n", buff); TEST_EXPECT_CONDITION(strcmp(buff, "Hello world from toto5"), RETVAL == 0); TEST_EXPECT_CONDITION(symlink("dangling", "toto6.txt"), RETVAL == 0); TEST_EXPECT_CONDITION(symlink("dangling", "toto6.txt"), RETVAL < 0); /*EEXIST*/ TEST_EXPECT_CONDITION(fd = open("toto6.txt", O_RDWR), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("toto6.txt", O_RDWR | O_NOFOLLOW), RETVAL == OPEN_BASE_FD + 18); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 8); bochs_printf("read s='%s'\n", buff); TEST_EXPECT_CONDITION(strncmp(buff, "dangling", len), RETVAL == 0); ls("/", 1, 1); /* mkdir/rmdir */ TEST_EXPECT_CONDITION(mkdir("yo1", S_IRUSR | S_IXUSR), RETVAL == 0); TEST_EXPECT_CONDITION(mkdir("yo1", S_IRWXALL), RETVAL < 0); /*EEXIST*/ ls("/", 1, 1); TEST_EXPECT_CONDITION(unlink("yo1"), RETVAL < 0); /*EISDIR*/ TEST_EXPECT_CONDITION(unlink("yo1/"), RETVAL < 0); /*EISDIR*/ TEST_EXPECT_CONDITION(rmdir("yo1"), RETVAL == 0); TEST_EXPECT_CONDITION(rmdir("yo1"), RETVAL < 0); /*ENOENT*/ TEST_EXPECT_CONDITION(rmdir("yoda"), RETVAL < 0); /*ENOENT*/ ls("/", 1, 1); TEST_EXPECT_CONDITION(mkdir("yoplait1", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(rename("yoplait1", "mouf1"), RETVAL == 0); TEST_EXPECT_CONDITION(fd = open("mouf1/a", O_RDWR | O_CREAT, S_IRWXALL), RETVAL == OPEN_BASE_FD + 19); TEST_EXPECT_CONDITION(unlink("mouf1/a"), RETVAL == 0); TEST_EXPECT_CONDITION(rmdir("mouf1"), RETVAL == 0); TEST_EXPECT_CONDITION(mkdir("yoplait2", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(rename("yoplait2", "mouf2"), RETVAL == 0); TEST_EXPECT_CONDITION(fd = open("mouf2/a", O_RDWR | O_CREAT, S_IRWXALL), RETVAL == OPEN_BASE_FD + 20); TEST_EXPECT_CONDITION(rmdir("mouf2"), RETVAL < 0); TEST_EXPECT_CONDITION(mkdir("yoplait3", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(rename("yoplait3", "mouf3"), RETVAL == 0); TEST_EXPECT_CONDITION(creat("mouf3/a", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(unlink("mouf3/a"), RETVAL == 0); TEST_EXPECT_CONDITION(rmdir("mouf3"), RETVAL == 0); TEST_EXPECT_CONDITION(mkdir("yoplait4", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(rename("yoplait4", "mouf4"), RETVAL == 0); TEST_EXPECT_CONDITION(creat("mouf4/a", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(rmdir("mouf4"), RETVAL < 0); ls("/", 1, 1); /* Not supported by virtfs */ TEST_EXPECT_CONDITION(mknod("dev1", S_IRWXALL, S_IFCHR, 420, 268), RETVAL == 0); /* Make sure the device cannot be opened (no device should be associated to it */ TEST_EXPECT_CONDITION(open("dev1", O_RDONLY), RETVAL < 0); TEST_EXPECT_CONDITION(unlink("dev1"), RETVAL == 0); ls("/", 1, 1); ls("..", 1, 1); ls("../", 1, 1); ls("/..", 1, 1); /* subdirs */ TEST_EXPECT_CONDITION(fd = open("yo1/titi1.txt", O_RDONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("yo1/titi1.txt", O_RDONLY | O_CREAT, S_IRUSR), RETVAL < 0); ls("/", 1, 1); ls("/yo1", 1, 1); TEST_EXPECT_CONDITION(mkdir("yo1", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(fd = open("yo1/titi1.txt", O_RDONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("yo1/titi1.txt", O_RDONLY | O_CREAT, S_IRUSR), RETVAL == OPEN_BASE_FD + 21); ls("/", 1, 1); ls("/yo1", 1, 1); TEST_EXPECT_CONDITION(mkdir("yo2", S_IRUSR | S_IXUSR), RETVAL == 0); TEST_EXPECT_CONDITION(fd = open("yo2/titi1.txt", O_RDONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("yo2/titi1.txt", O_RDONLY | O_CREAT, S_IRUSR), RETVAL < 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(mkdir("yo3", S_IWUSR | S_IXUSR), RETVAL == 0); TEST_EXPECT_CONDITION(fd = open("yo3/titi1.txt", O_RDONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("yo3/titi1.txt", O_RDONLY | O_CREAT, S_IRUSR), RETVAL == OPEN_BASE_FD + 22); ls("/", 1, 1); TEST_EXPECT_CONDITION(mkdir("yo4", S_IWUSR), RETVAL == 0); TEST_EXPECT_CONDITION(fd = open("yo4/titi1.txt", O_RDONLY), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("yo4/titi1.txt", O_RDONLY | O_CREAT, S_IRUSR), RETVAL < 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(chdir("nowhere"), RETVAL < 0); TEST_EXPECT_CONDITION(chdir("yo1"), RETVAL == 0); ls(".", 1, 1); ls("/", 1, 1); ls("..", 1, 1); ls("../../../../", 1, 1); ls("/../../../../", 1, 1); /* Test chroot */ TEST_EXPECT_CONDITION(chroot("nowhere"), RETVAL < 0); TEST_EXPECT_CONDITION(chroot("."), RETVAL == 0); ls(".", 1, 1); ls("/", 1, 1); ls("..", 1, 1); ls("../../../../", 1, 1); ls("/../../../../", 1, 1); /* mount */ TEST_EXPECT_CONDITION(mount(NULL, "nowhere", NULL, 0, NULL), RETVAL < 0); TEST_EXPECT_CONDITION(mount(NULL, "nowhere", "yoplait", 0, NULL), RETVAL < 0); TEST_EXPECT_CONDITION(mount(NULL, "nowhere", "virtfs", 0, NULL), RETVAL < 0); TEST_EXPECT_CONDITION(mkdir("mnt", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(mkdir("mnt/subdir0", S_IRWXALL), RETVAL == 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(mount(NULL, "mnt", "virtfs", 0, NULL), RETVAL == 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(mkdir("mnt/subdir_mounted", S_IRWXALL), RETVAL == 0); ls("/", 1, 1); /* Make sure we cannot umount if the FS is in use */ TEST_EXPECT_CONDITION(fd = open("mnt/subdir_mounted", O_DIRECTORY), RETVAL == OPEN_BASE_FD + 23); TEST_EXPECT_CONDITION(umount("mnt"), RETVAL < 0); TEST_EXPECT_CONDITION(close(fd), RETVAL == 0); /* Make sure we cannot umount if the FS is in use */ TEST_EXPECT_CONDITION(chdir("mnt"), RETVAL == 0); TEST_EXPECT_CONDITION(umount("/mnt"), RETVAL < 0); TEST_EXPECT_CONDITION(chdir(".."), RETVAL == 0); ls(".", 1, 1); /* Create another process that chdirs in it */ if (fork() == 0) { bochs_printf("Hello from child\n"); TEST_EXPECT_CONDITION(chdir("mnt"), RETVAL == 0); TEST_EXPECT_CONDITION(fd = open("subdir_mounted", O_DIRECTORY), RETVAL == OPEN_BASE_FD + 23); bochs_printf("Child sleeping...\n"); nanosleep(2, 0); bochs_printf("Bye from child\n"); return 0; } else { bochs_printf("Father sleeping\n"); nanosleep(1, 0); bochs_printf("Father trying to umount, should fail (a process chdir'ed in it)\n"); TEST_EXPECT_CONDITION(umount("mnt"), RETVAL < 0); bochs_printf("Father Resuming normal operation in 3s...\n"); nanosleep(3, 0); } TEST_EXPECT_CONDITION(umount(NULL), RETVAL < 0); TEST_EXPECT_CONDITION(umount("nowhere"), RETVAL < 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(umount("mnt"), RETVAL == 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(umount("mnt"), RETVAL < 0); /* * Mountchain exploration */ TEST_EXPECT_CONDITION(mkdir("/mnt2", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(mkdir("/mnt2/nothing-mounted", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(mount(NULL, "mnt2", "virtfs", 0, NULL), RETVAL == 0); TEST_EXPECT_CONDITION(mkdir("/mnt2/mountpoint-1", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(mount(NULL, "mnt2", "virtfs", 0, NULL), RETVAL == 0); TEST_EXPECT_CONDITION(mkdir("/mnt2/mountpoint-2", S_IRWXALL), RETVAL == 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(umount("mnt2"), RETVAL == 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(umount("mnt2"), RETVAL == 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(umount("mnt2"), RETVAL < 0); /* * Erasing files while they are in use */ TEST_EXPECT_CONDITION(fd = open("toto8.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR), RETVAL == OPEN_BASE_FD + 23); ls("/", 1, 1); TEST_EXPECT_CONDITION(unlink("toto8.txt"), RETVAL == 0); ls("/", 1, 1); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 0); TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); strzcpy(buff, "Hello world from toto8", 256); TEST_EXPECT_CONDITION(len = write(fd, buff, 24), RETVAL == 24); TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 24); bochs_printf("read s='%s'\n", buff); /* * rmdir on still used dirs */ TEST_EXPECT_CONDITION(mkdir("plotch", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(chdir("plotch"), RETVAL == 0); TEST_EXPECT_CONDITION(rmdir("../plotch"), RETVAL < 0); TEST_EXPECT_CONDITION(chdir(".."), RETVAL == 0); TEST_EXPECT_CONDITION(rmdir("plotch"), RETVAL == 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(mkdir("plotch", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(creat("plotch/a", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(rmdir("plotch"), RETVAL < 0); TEST_EXPECT_CONDITION(unlink("plotch/a"), RETVAL == 0); TEST_EXPECT_CONDITION(rmdir("plotch"), RETVAL == 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(mkdir("plotch", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(fd = open("plotch/a", O_RDWR | O_CREAT, S_IRWXALL), RETVAL == OPEN_BASE_FD + 24); TEST_EXPECT_CONDITION(rmdir("plotch"), RETVAL < 0); TEST_EXPECT_CONDITION(unlink("plotch/a"), RETVAL == 0); TEST_EXPECT_CONDITION(rmdir("plotch"), RETVAL == 0); TEST_EXPECT_CONDITION(close(fd), RETVAL == 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(mkdir("this is ", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(mkdir("this is / a long path", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(mkdir("this is / a long path/tothe", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(mkdir("this is / a long path/tothe/destination ", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(mkdir("this is / a long path/tothe/destination / directory", S_IRWXALL), RETVAL == 0); TEST_EXPECT_CONDITION(fd = open("this is / a long path/tothe/destination / directory/a", O_RDWR | O_CREAT, S_IRWXALL), RETVAL == OPEN_BASE_FD + 24); TEST_EXPECT_CONDITION(rmdir("this is / a long path/tothe/destination / directory"), RETVAL < 0); TEST_EXPECT_CONDITION(unlink("this is / a long path/tothe/destination / directory/a"), RETVAL == 0); TEST_EXPECT_CONDITION(rmdir("this is / a long path/tothe/destination / directory"), RETVAL == 0); TEST_EXPECT_CONDITION(rmdir("this is / a long path/tothe/destination / directory/"), RETVAL < 0); TEST_EXPECT_CONDITION(rmdir("this is / a long path/tothe/destination "), RETVAL == 0); TEST_EXPECT_CONDITION(rmdir("this is / a long path/tothe/"), RETVAL == 0); TEST_EXPECT_CONDITION(rmdir("this is / a long path"), RETVAL == 0); TEST_EXPECT_CONDITION(rmdir("this is "), RETVAL == 0); TEST_EXPECT_CONDITION(close(fd), RETVAL == 0); ls("/", 1, 1); /* * Unlink/link files while they are in use */ TEST_EXPECT_CONDITION(fd = open("toto8.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR), RETVAL == OPEN_BASE_FD + 24); ls("/", 1, 1); TEST_EXPECT_CONDITION(link("toto8.txt", "toto9.txt"), RETVAL == 0); TEST_EXPECT_CONDITION(unlink("toto8.txt"), RETVAL == 0); ls("/", 1, 1); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 0); TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); strzcpy(buff, "Hello world from toto8", 256); TEST_EXPECT_CONDITION(len = write(fd, buff, 24), RETVAL == 24); TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 24); bochs_printf("read s='%s'\n", buff); TEST_EXPECT_CONDITION(fd = open("toto8.txt", O_RDWR), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("toto9.txt", O_RDWR), RETVAL == OPEN_BASE_FD + 25); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 24); bochs_printf("read s='%s'\n", buff); TEST_EXPECT_CONDITION(unlink("toto9.txt"), RETVAL == 0); ls("/", 1, 1); /* * Rename files while they are in use */ TEST_EXPECT_CONDITION(fd = open("toto8.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR), RETVAL == OPEN_BASE_FD + 26); ls("/", 1, 1); TEST_EXPECT_CONDITION(rename("toto8.txt", "toto9.txt"), RETVAL == 0); ls("/", 1, 1); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 0); TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); strzcpy(buff, "Hello world from toto8", 256); TEST_EXPECT_CONDITION(len = write(fd, buff, 24), RETVAL == 24); TEST_EXPECT_CONDITION(lseek(fd, 0, SEEK_SET), RETVAL == 0); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 24); bochs_printf("read s='%s'\n", buff); TEST_EXPECT_CONDITION(close(fd), RETVAL == 0); TEST_EXPECT_CONDITION(fd = open("toto8.txt", O_RDWR), RETVAL < 0); TEST_EXPECT_CONDITION(fd = open("toto9.txt", O_RDWR), RETVAL == OPEN_BASE_FD + 26); strzcpy(buff, "Garbage garbage garbage", 256); TEST_EXPECT_CONDITION(len = read(fd, buff, 256), RETVAL == 24); bochs_printf("read s='%s'\n", buff); TEST_EXPECT_CONDITION(unlink("toto9.txt"), RETVAL == 0); TEST_EXPECT_CONDITION(close(fd), RETVAL == 0); /* Rename */ ls("/", 1, 1); TEST_EXPECT_CONDITION(rename("/mnt/subdir0", "subdir42"), RETVAL == 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(rename("titi1.txt", "subdir42"), RETVAL < 0); ls("/", 1, 1); TEST_EXPECT_CONDITION(rename("titi1.txt", "subdir42/titi.txt"), RETVAL == 0); /* Rename a dir being used */ TEST_EXPECT_CONDITION(chdir("subdir42"), RETVAL == 0); ls(".", 1, 1); ls("..", 1, 1); ls("/", 1, 1); TEST_EXPECT_CONDITION(rename("../subdir42", "../subdir000"), RETVAL == 0); ls(".", 1, 1); ls("/", 1, 1); ls("..", 1, 1); /* * test mmap */ /* Common use: shared file suppressed as soon as possible */ TEST_EXPECT_CONDITION(fd = open("mmap.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR), RETVAL == OPEN_BASE_FD + 26); if (fork() == 0) { char *shrd; TEST_EXPECT_CONDITION(shrd = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 4096), shrd != NULL); nanosleep(1, 0); strzcpy(shrd, "Hello1 from the child (shared mapping) !", 4096); return 0; } else { char *shrd; TEST_EXPECT_CONDITION(shrd = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 4096), shrd != NULL); strzcpy(shrd, "Garbage garbage garbage", 256); nanosleep(2, 0); bochs_printf("Father woken up\n"); bochs_printf("Read string from child: '%s'\n", shrd); TEST_EXPECT_CONDITION(strcmp(shrd, "Hello1 from the child (shared mapping) !"), RETVAL == 0); munmap(shrd, 8192); } ls("/", 1, 1); TEST_EXPECT_CONDITION(unlink("mmap.txt"), RETVAL == 0); ls("/", 1, 1); /* Common use: shared file suppressed as soon as possible */ TEST_EXPECT_CONDITION(fd = open("mmap.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR), RETVAL == OPEN_BASE_FD + 27); TEST_EXPECT_CONDITION(unlink("mmap.txt"), RETVAL == 0); if (fork() == 0) { char *shrd; TEST_EXPECT_CONDITION(shrd = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 4096), shrd != NULL); nanosleep(1, 0); strzcpy(shrd, "Hello2 from the child (shared mapping) !", 4096); return 0; } else { char *shrd; TEST_EXPECT_CONDITION(shrd = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 4096), shrd != NULL); strzcpy(shrd, "Garbage garbage garbage", 256); nanosleep(2, 0); bochs_printf("Father woken up\n"); bochs_printf("Read string from child: '%s'\n", shrd); TEST_EXPECT_CONDITION(strcmp(shrd, "Hello2 from the child (shared mapping) !"), RETVAL == 0); } ls("/", 1, 1); /* Basic use */ TEST_EXPECT_CONDITION(creat("mmap.txt", S_IRUSR | S_IWUSR), RETVAL == 0); if (fork() == 0) { char *shrd; TEST_EXPECT_CONDITION(fd = open("mmap.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR), RETVAL == OPEN_BASE_FD + 28); TEST_EXPECT_CONDITION(shrd = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 4096), shrd != NULL); nanosleep(1, 0); strzcpy(shrd, "Hello3 from the child (shared mapping) !", 4096); return 0; } else { char *shrd; TEST_EXPECT_CONDITION(fd = open("mmap.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR), RETVAL == OPEN_BASE_FD + 28); TEST_EXPECT_CONDITION(shrd = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 4096), shrd != NULL); strzcpy(shrd, "Garbage garbage garbage", 256); nanosleep(2, 0); bochs_printf("Father woken up\n"); bochs_printf("Read string from child: '%s'\n", shrd); TEST_EXPECT_CONDITION(strcmp(shrd, "Hello3 from the child (shared mapping) !"), RETVAL == 0); } ls("/", 1, 1); bochs_printf("Bye from fstest\n"); ls("/", 1, 1); return 0; }