/* test25: open (), close () (p) Jan-Mark Wams. email: jms@cs.vu.nl */ /* Not tested: O_NONBLOCK on special files, supporting it. ** On a read-only file system, some error reports are to be expected. */ #include #include #include #include #include #include #include #include #include #include #include #define MAX_ERROR 4 #define ITERATIONS 2 #define System(cmd) if (system(cmd) != 0) printf("``%s'' failed\n", cmd) #define Chdir(dir) if (chdir(dir) != 0) printf("Can't goto %s\n", dir) #define Stat(a,b) if (stat(a,b) != 0) printf("Can't stat %s\n", a) #define Creat(f) if (close(creat(f,0777))!=0) printf("Can't creat %s\n",f) #define Report(s,n) printf("Subtest %d" s,subtest,(n)) int errct = 0; int subtest = 1; int superuser; char MaxName[NAME_MAX + 1]; /* Name of maximum length */ char MaxPath[PATH_MAX]; /* Same for path */ char ToLongName[NAME_MAX + 2]; /* Name of maximum +1 length */ char ToLongPath[PATH_MAX + 1]; /* Same for path, both too long */ _PROTOTYPE(void main, (int argc, char *argv[])); _PROTOTYPE(void test25a, (void)); _PROTOTYPE(void test25b, (void)); _PROTOTYPE(void test25c, (void)); _PROTOTYPE(void test25d, (void)); _PROTOTYPE(void test25e, (void)); _PROTOTYPE(void makelongnames, (void)); _PROTOTYPE(void e, (int number)); _PROTOTYPE(void quit, (void)); void main(argc, argv) int argc; char *argv[]; { int i, m = 0xFFFF; sync(); if (geteuid() == 0 || getuid() == 0) { printf("Test 25 cannot run as root; test aborted\n"); exit(1); } if (argc == 2) m = atoi(argv[1]); printf("Test 25 "); fflush(stdout); System("rm -rf DIR_25; mkdir DIR_25"); Chdir("DIR_25"); makelongnames(); superuser = (geteuid() == 0); /* Close all files, the parent might have opened. */ for (i = 3; i < 100; i++) close(i); for (i = 0; i < ITERATIONS; i++) { if (m & 001) test25a(); if (m & 002) test25b(); if (m & 004) test25c(); if (m & 010) test25d(); if (m & 020) test25e(); } quit(); } void test25a() { /* Test fcntl flags. */ subtest = 1; #define EXCLUDE(a,b) (((a)^(b)) == ((a)|(b))) #define ADDIT (O_APPEND | O_CREAT | O_EXCL | O_NONBLOCK | O_TRUNC) /* If this compiles all flags are defined but they have to be or-able. */ if (!(EXCLUDE(O_NONBLOCK, O_TRUNC))) e(1); if (!(EXCLUDE(O_EXCL, O_NONBLOCK | O_TRUNC))) e(2); if (!(EXCLUDE(O_CREAT, O_EXCL | O_NONBLOCK | O_TRUNC))) e(3); if (!(EXCLUDE(O_APPEND, O_CREAT | O_EXCL | O_NONBLOCK | O_TRUNC))) e(4); if (!(EXCLUDE(O_RDONLY, ADDIT))) e(5); if (!(EXCLUDE(O_WRONLY, ADDIT))) e(6); if (!(EXCLUDE(O_RDWR, ADDIT))) e(7); } void test25b() { /* Test normal operation. */ #define BUF_SIZE 1024 int fd1, fd2, fd3, fd4, fd5; char buf[BUF_SIZE]; struct stat st1, st2, st3; time_t time1, time2; int stat_loc; subtest = 2; System("rm -rf ../DIR_25/*"); System("echo Hello > he"); /* make test files */ System("echo Hello > ha"); /* size 6 bytes */ System("echo Hello > hi"); System("echo Hello > ho"); /* Check path resolution. Check if lowest fds are returned */ if ((fd1 = open("he", O_RDONLY)) != 3) e(1); if (read(fd1, buf, BUF_SIZE) != 6) e(2); if ((fd2 = open("./ha", O_RDONLY)) != 4) e(3); if ((fd3 = open("../DIR_25/he", O_RDWR)) != 5) e(4); if ((fd4 = open("ho", O_WRONLY)) != 6) e(5); if (close(fd4) != 0) e(6); if (close(fd1) != 0) e(7); if ((fd1 = open("./././ho", O_RDWR)) != 3) e(8); if ((fd4 = open("../DIR_25/he", O_RDONLY)) != 6) e(9); if (close(fd2) != 0) e(10); if (close(fd3) != 0) e(11); if ((fd2 = open("ha", O_RDONLY)) != 4) e(12); if ((fd3 = open("/etc/passwd", O_RDONLY)) != 5) e(13); if (close(fd4) != 0) e(14); /* close all */ if (close(fd1) != 0) e(15); if (close(fd3) != 0) e(16); /* Check if processes share fd2, and if they have independent new fds */ System("rm -rf /tmp/sema.25"); switch (fork()) { case -1: printf("Can't fork\n"); break; case 0: if ((fd1 = open("he", O_WRONLY)) != 3) e(17); if ((fd3 = open("../././DIR_25/ha", O_WRONLY)) != 5) e(18); if ((fd4 = open("../DIR_25/hi", O_WRONLY)) != 6) e(19); if ((fd5 = open("ho", O_WRONLY)) != 7) e(20); system("while test ! -f /tmp/sema.25; do sleep 1; done"); /* parent */ if (read(fd2, buf, BUF_SIZE) != 3) e(21); /* gets Hel */ if (strncmp(buf, "lo\n", 3) != 0) e(22); /* we get lo */ if (close(fd1) != 0) e(23); if (close(fd2) != 0) e(24); if (close(fd3) != 0) e(25); if (close(fd4) != 0) e(26); if (close(fd5) != 0) e(27); exit(0); default: if ((fd1 = open("ha", O_RDONLY)) != 3) e(28); if ((fd3 = open("./he", O_RDONLY)) != 5) e(29); if ((fd4 = open("../DIR_25/hi", O_RDWR)) != 6) e(30); if ((fd5 = open("ho", O_WRONLY)) != 7) e(31); if (close(fd1) != 0) e(32); if (read(fd2, buf, 3) != 3) e(33); /* get Hel */ Creat("/tmp/sema.25"); if (strncmp(buf, "Hel", 3) != 0) e(34); if (close(fd2) != 0) e(35); if (close(fd3) != 0) e(36); if (close(fd4) != 0) e(37); if (close(fd5) != 0) e(38); if (wait(&stat_loc) == -1) e(39); if (stat_loc != 0) e(40); } System("rm -f /tmp/sema.25"); /* Check if the file status information is updated correctly */ Stat("hi", &st1); /* get info */ Stat("ha", &st2); /* of files */ time(&time1); while (time1 >= time((time_t *)0)) ; /* wait a sec */ if ((fd1 = open("hi", O_RDONLY)) != 3) e(41); /* open files */ if ((fd2 = open("ha", O_WRONLY)) != 4) e(42); if (read(fd1, buf, 1) != 1) e(43); /* read one */ if (close(fd1) != 0) e(44); /* close one */ Stat("hi", &st3); /* get info */ if (st1.st_uid != st3.st_uid) e(45); if (st1.st_gid != st3.st_gid) e(46); /* should be same */ if (st1.st_mode != st3.st_mode) e(47); if (st1.st_size != st3.st_size) e(48); if (st1.st_nlink != st3.st_nlink) e(49); if (st1.st_mtime != st3.st_mtime) e(50); if (st1.st_ctime != st3.st_ctime) e(51); #ifndef V1_FILESYSTEM if (st1.st_atime >= st3.st_atime) e(52); /* except for atime. */ #endif if (write(fd2, "Howdy\n", 6) != 6) e(53); /* Update c & mtime. */ if ((fd1 = open("ha", O_RDWR)) != 3) e(54); if (read(fd1, buf, 6) != 6) e(55); /* Update atime. */ if (strncmp(buf, "Howdy\n", 6) != 0) e(56); if (close(fd1) != 0) e(57); Stat("ha", &st3); if (st2.st_uid != st3.st_uid) e(58); if (st2.st_gid != st3.st_gid) e(59); /* should be same */ if (st2.st_mode != st3.st_mode) e(60); if (st2.st_nlink != st3.st_nlink) e(61); if (st2.st_ctime >= st3.st_ctime) e(62); #ifndef V1_FILESYSTEM if (st2.st_atime >= st3.st_atime) e(63); #endif if (st2.st_mtime >= st3.st_mtime) e(64); if (st2.st_size != st3.st_size) e(65); if (close(fd2) != 0) e(66); /* Let's see if RDONLY files are read only. */ if ((fd1 = open("hi", O_RDONLY)) != 3) e(67); if (write(fd1, " again", 7) != -1) e(68); /* we can't write */ if (errno != EBADF) e(69); /* a read only fd */ if (read(fd1, buf, 7) != 6) e(70); /* but we can read */ if (close(fd1) != 0) e(71); /* Let's see if WRONLY files are write only. */ if ((fd1 = open("hi", O_WRONLY)) != 3) e(72); if (read(fd1, buf, 7) != -1) e(73); /* we can't read */ if (errno != EBADF) e(74); /* a write only fd */ if (write(fd1, "hELLO", 6) != 6) e(75); /* but we can write */ if (close(fd1) != 0) e(76); /* Let's see if files are closable only once. */ if (close(fd1) != -1) e(77); if (errno != EBADF) e(78); /* Let's see how calling close() with bad fds is handled. */ if (close(10) != -1) e(79); if (errno != EBADF) e(80); if (close(111) != -1) e(81); if (errno != EBADF) e(82); if (close(-432) != -1) e(83); if (errno != EBADF) e(84); /* Let's see if RDWR files are read & write able. */ if ((fd1 = open("hi", O_RDWR)) != 3) e(85); if (read(fd1, buf, 6) != 6) e(86); /* we can read */ if (strncmp(buf, "hELLO", 6) != 0) e(87); /* and we can write */ if (write(fd1, "Hello", 6) != 6) e(88); /* a read write fd */ if (close(fd1) != 0) e(89); /* Check if APPENDed files are realy appended */ if ((fd1 = open("hi", O_RDWR | O_APPEND)) != 3) e(90); /* open hi */ /* An open should set the file offset to 0. */ if (lseek(fd1, (off_t) 0, SEEK_CUR) != 0) e(91); /* Writing 0 bytes should not have an effect. */ if (write(fd1, "", 0) != 0) e(92); if (lseek(fd1, (off_t) 0, SEEK_CUR) != 0) e(93); /* the end? */ /* A seek befor a wirte should not matter with O_APPEND. */ Stat("hi", &st1); if (lseek(fd1, (off_t) - 3, SEEK_END) != st1.st_size - 3) e(94); /* By writing 1 byte, we force the offset to the end of the file */ if (write(fd1, "1", 1) != 1) e(95); Stat("hi", &st1); if (lseek(fd1, (off_t) 0, SEEK_CUR) != st1.st_size) e(96); if (write(fd1, "2", 1) != 1) e(97); Stat("hi", &st1); if (lseek(fd1, (off_t) 0, SEEK_CUR) != st1.st_size) e(98); if (write(fd1, "3", 1) != 1) e(99); Stat("hi", &st1); if (lseek(fd1, (off_t) 0, SEEK_CUR) != st1.st_size) e(100); if (lseek(fd1, (off_t) - 2, SEEK_CUR) <= 0) e(101); if (write(fd1, "4", 1) != 1) e(102); /* Since the mode was O_APPEND, the offset should be reset to EOF */ Stat("hi", &st1); if (lseek(fd1, (off_t) 0, SEEK_CUR) != st1.st_size) e(103); if (lseek(fd1, (off_t) - 4, SEEK_CUR) != st1.st_size - 4) e(104); if (read(fd1, buf, BUF_SIZE) != 4) e(105); if (strncmp(buf, "1234", 4) != 0) e(106); if (close(fd1) != 0) e(107); /* Check the effect of O_CREAT */ Stat("ho", &st1); fd1 = open("ho", O_RDWR | O_CREAT, 0000); if (fd1 != 3) e(108); Stat("ho", &st2); if (memcmp(&st1, &st2, sizeof(struct stat)) != 0) e(109); if (read(fd1, buf, 6) != 6) e(110); if (strncmp(buf, "Hello\n", 6) != 0) e(111); if (write(fd1, "@", 1) != 1) e(112); if (close(fd1) != 0) e(113); (void) umask(0000); fd1 = open("ho", O_RDWR | O_CREAT | O_EXCL, 0777); if (fd1 != -1) e(114); /* ho exists */ System("rm -rf new"); time(&time1); while (time1 >= time((time_t *)0)) ; fd1 = open("new", O_RDWR | O_CREAT, 0716); if (fd1 != 3) e(115); /* new file */ Stat("new", &st1); time(&time2); while (time2 >= time((time_t *)0)) ; time(&time2); if (st1.st_uid != geteuid()) e(116); /* try this as superuser. */ if (st1.st_gid != getegid()) e(117); if ((st1.st_mode & 0777) != 0716) e(118); if (st1.st_nlink != 1) e(119); if (st1.st_mtime <= time1) e(120); if (st1.st_mtime >= time2) e(121); #ifndef V1_FILESYSTEM if (st1.st_atime != st1.st_mtime) e(122); #endif if (st1.st_ctime != st1.st_mtime) e(123); if (st1.st_size != 0) e(124); if (write(fd1, "I'm new in town", 16) != 16) e(125); if (lseek(fd1, (off_t) - 5, SEEK_CUR) != 11) e(126); if (read(fd1, buf, 5) != 5) e(127); if (strncmp(buf, "town", 5) != 0) e(128); if (close(fd1) != 0) e(129); /* Let's test the O_TRUNC flag on this new file. */ time(&time1); while (time1 >= time((time_t *)0)); if ((fd1 = open("new", O_RDWR | O_TRUNC)) != 3) e(130); Stat("new", &st1); time(&time2); while (time2 >= time((time_t *)0)); time(&time2); if ((st1.st_mode & 0777) != 0716) e(131); if (st1.st_size != (size_t) 0) e(132); /* TRUNCed ? */ if (st1.st_mtime <= time1) e(133); if (st1.st_mtime >= time2) e(134); if (st1.st_ctime != st1.st_mtime) e(135); if (close(fd1) != 0) e(136); /* Test if file permission bits and the file ownership are unchanged. */ /* So we will see if `O_CREAT' has no effect if the file exists. */ if (superuser) { System("echo > bar; chmod 077 bar"); /* Make bar 077 */ System("chown daemon bar"); System("chgrp daemon bar"); /* Daemon's bar */ fd1 = open("bar", O_RDWR | O_CREAT | O_TRUNC, 0777); /* knock knock */ if (fd1 == -1) e(137); if (write(fd1, "foo", 3) != 3) e(138); /* rewrite bar */ if (close(fd1) != 0) e(139); Stat("bar", &st1); if (st1.st_uid != 1) e(140); /* bar is still */ if (st1.st_gid != 1) e(141); /* owned by daemon */ if ((st1.st_mode & 0777) != 077) e(142); /* mode still is 077 */ if (st1.st_size != (size_t) 3) e(143); /* 3 bytes long */ /* We do the whole thing again, but with O_WRONLY */ fd1 = open("bar", O_WRONLY | O_CREAT | O_TRUNC, 0777); if (fd1 == -1) e(144); if (write(fd1, "foobar", 6) != 6) e(145); /* rewrite bar */ if (close(fd1) != 0) e(146); Stat("bar", &st1); if (st1.st_uid != 1) e(147); /* bar is still */ if (st1.st_gid != 1) e(148); /* owned by daemon */ if ((st1.st_mode & 0777) != 077) e(149); /* mode still is 077 */ if (st1.st_size != (size_t) 6) e(150); /* 6 bytes long */ } } void test25c() { /* Test normal operation Part two. */ int fd1, fd2; char buf[BUF_SIZE]; struct stat st; int stat_loc; static int iteration=0; subtest = 3; iteration++; System("rm -rf ../DIR_25/*"); /* Fifo file test here. */ if (mkfifo("fifo", 0777) != 0) e(1); switch (fork()) { case -1: printf("Can't fork\n"); break; case 0: alarm(20); /* Give child 20 seconds to live. */ if ((fd1 = open("fifo", O_RDONLY)) != 3) e(2); if (read(fd1, buf, BUF_SIZE) != 23) e(3); if (strncmp(buf, "1 2 3 testing testing\n", 23) != 0) e(4); if (close(fd1) != 0) e(5); exit(0); default: if ((fd1 = open("fifo", O_WRONLY)) != 3) e(6); if (write(fd1, "1 2 3 testing testing\n", 23) != 23) e(7); if (close(fd1) != 0) e(8); if (wait(&stat_loc) == -1) e(9); if (stat_loc != 0) e(10); /* The alarm went off? */ } /* Try opening for writing with O_NONBLOCK. */ fd1 = open("fifo", O_WRONLY | O_NONBLOCK); if (fd1 != -1) e(11); if (errno != ENXIO) e(12); close(fd1); /* Try opening for writing with O_NONBLOCK and O_CREAT. */ fd1 = open("fifo", O_WRONLY | O_CREAT | O_NONBLOCK, 0777); if (fd1 != -1) e(13); if (errno != ENXIO) e(14); close(fd1); /* Both the NONBLOCK and the EXCLusive give raise to error. */ fd1 = open("fifo", O_WRONLY | O_CREAT | O_EXCL | O_NONBLOCK, 0777); if (fd1 != -1) e(15); if (errno != EEXIST && errno != ENXIO) e(16); close(fd1); /* Just in case. */ /* Try opening for reading with O_NONBLOCK. */ fd1 = open("fifo", O_RDONLY | O_NONBLOCK); if (fd1 != 3) e(17); if (close(fd1) != 0) e(18); /* Nopt runs out of memory. ;-< We just cut out some valid code */ /* FIFO's should always append. (They have no file position.) */ switch (fork()) { case -1: printf("Can't fork\n"); break; case 0: alarm(20); /* Give child 20 seconds to live. */ if ((fd1 = open("fifo", O_WRONLY)) != 3) e(19); if ((fd2 = open("fifo", O_WRONLY)) != 4) e(20); if (write(fd1, "I did see Elvis.\n", 18) != 18) e(21); if (write(fd2, "I DID.\n", 8) != 8) e(22); if (close(fd2) != 0) e(23); if (close(fd1) != 0) e(24); exit(0); default: if ((fd1 = open("fifo", O_RDONLY)) != 3) e(25); if (read(fd1, buf, 18) != 18) e(26); if (strncmp(buf, "I did see Elvis.\n", 18) != 0) e(27); if (read(fd1, buf, BUF_SIZE) != 8) e(28); if (strncmp(buf, "I DID.\n", 8) != 0) e(29); if (close(fd1) != 0) e(30); if (wait(&stat_loc) == -1) e(31); if (stat_loc != 0) e(32); /* The alarm went off? */ } /* O_TRUNC should have no effect on FIFO files. */ switch (fork()) { case -1: printf("Can't fork\n"); break; case 0: alarm(20); /* Give child 20 seconds to live. */ if ((fd1 = open("fifo", O_WRONLY)) != 3) e(33); if (write(fd1, "I did see Elvis.\n", 18) != 18) e(34); if ((fd2 = open("fifo", O_WRONLY | O_TRUNC)) != 4) e(35); if (write(fd2, "I DID.\n", 8) != 8) e(36); if (close(fd2) != 0) e(37); if (close(fd1) != 0) e(38); exit(0); default: if ((fd1 = open("fifo", O_RDONLY)) != 3) e(39); if (read(fd1, buf, 18) != 18) e(40); if (strncmp(buf, "I did see Elvis.\n", 18) != 0) e(41); if (read(fd1, buf, BUF_SIZE) != 8) e(42); if (strncmp(buf, "I DID.\n", 8) != 0) e(43); if (close(fd1) != 0) e(44); if (wait(&stat_loc) == -1) e(45); if (stat_loc != 0) e(46); /* The alarm went off? */ } /* Closing the last fd should flush all data to the bitbucket. */ System("rm -rf /tmp/sema.25"); switch (fork()) { case -1: printf("Can't fork\n"); break; case 0: alarm(20); /* Give child 20 seconds to live. */ if ((fd1 = open("fifo", O_WRONLY)) != 3) e(47); if (write(fd1, "I did see Elvis.\n", 18) != 18) e(48); Creat("/tmp/sema.25"); sleep(2); /* give parent a chance to open */ /* this was sleep(1), but that's too short: child also sleeps(1) */ if (close(fd1) != 0) e(49); exit(0); default: if ((fd1 = open("fifo", O_RDONLY)) != 3) e(50); /* Make `sure' write has closed. */ while (stat("/tmp/sema.25", &st) != 0) sleep(1); if (close(fd1) != 0) e(51); if ((fd1 = open("fifo", O_RDONLY | O_NONBLOCK)) != 3) e(52); if (read(fd1, buf, BUF_SIZE) != 18) e(53); if (close(fd1) != 0) e(54); if (wait(&stat_loc) == -1) e(55); if (stat_loc != 0) e(56); /* The alarm went off? */ } /* Let's try one too many. */ System("rm -rf /tmp/sema.25"); switch (fork()) { case -1: printf("Can't fork\n"); break; case 0: alarm(20); /* Give child 20 seconds to live. */ if ((fd1 = open("fifo", O_WRONLY)) != 3) e(57); if (write(fd1, "I did see Elvis.\n", 18) != 18) e(58); /* Keep open till second reader is opened. */ while (stat("/tmp/sema.25", &st) != 0) sleep(1); if (close(fd1) != 0) e(59); exit(0); default: if ((fd1 = open("fifo", O_RDONLY)) != 3) e(60); if (read(fd1, buf, 2) != 2) e(61); if (strncmp(buf, "I ", 2) != 0) e(62); if (close(fd1) != 0) e(63); if ((fd1 = open("fifo", O_RDONLY)) != 3) e(64); /* Signal second reader is open. */ Creat("/tmp/sema.25"); if (read(fd1, buf, 4) != 4) e(65); if (strncmp(buf, "did ", 4) != 0) e(66); if ((fd2 = open("fifo", O_RDONLY)) != 4) e(67); if (read(fd2, buf, BUF_SIZE) != 12) e(68); if (strncmp(buf, "see Elvis.\n", 12) != 0) e(69); if (close(fd2) != 0) e(70); if (close(fd1) != 0) e(71); if (wait(&stat_loc) == -1) e(72); if (stat_loc != 0) e(73); /* The alarm went off? */ } System("rm -rf fifo /tmp/sema.25"); /* O_TRUNC should have no effect on directroys. */ System("mkdir dir; touch dir/f1 dir/f2 dir/f3"); if ((fd1 = open("dir", O_WRONLY | O_TRUNC)) != -1) e(74); if (errno != EISDIR) e(75); close(fd1); /* Opening a directory for reading should be possible. */ if ((fd1 = open("dir", O_RDONLY)) != 3) e(76); if (close(fd1) != 0) e(77); if (unlink("dir/f1") != 0) e(78); /* Should still be there. */ if (unlink("dir/f2") != 0) e(79); if (unlink("dir/f3") != 0) e(80); if (rmdir("dir") != 0) e(81); if (!superuser) { /* Test if O_CREAT is not usable to open files with the wrong mode */ (void) umask(0200); /* nono has no */ System("touch nono"); /* write bit */ (void) umask(0000); fd1 = open("nono", O_RDWR | O_CREAT, 0777); /* try to open */ if (fd1 != -1) e(82); if (errno != EACCES) e(83); /* but no access */ } } void test25d() { int fd; subtest = 4; System("rm -rf ../DIR_25/*"); /* Test maximal file name length. */ if ((fd = open(MaxName, O_RDWR | O_CREAT, 0777)) != 3) e(1); if (close(fd) != 0) e(2); MaxPath[strlen(MaxPath) - 2] = '/'; MaxPath[strlen(MaxPath) - 1] = 'a'; /* make ././.../a */ if ((fd = open(MaxPath, O_RDWR | O_CREAT, 0777)) != 3) e(3); if (close(fd) != 0) e(4); MaxPath[strlen(MaxPath) - 1] = '/'; /* make ././.../a */ } void test25e() { int fd; char *noread = "noread"; /* Name for unreadable file. */ char *nowrite = "nowrite"; /* Same for unwritable. */ int stat_loc; subtest = 5; System("rm -rf ../DIR_25/*"); mkdir("bar", 0777); /* make bar */ /* Check if no access on part of path generates the correct error. */ System("chmod 677 bar"); /* rw-rwxrwx */ if (open("bar/nono", O_RDWR | O_CREAT, 0666) != -1) e(1); if (errno != EACCES) e(2); /* Ditto for no write permission. */ System("chmod 577 bar"); /* r-xrwxrwx */ if (open("bar/nono", O_RDWR | O_CREAT, 0666) != -1) e(3); if (errno != EACCES) e(4); /* Clean up bar. */ System("rm -rf bar"); /* Improper flags set on existing file. */ System("touch noread; chmod 377 noread"); /* noread */ if (open(noread, O_RDONLY) != -1) e(5); if (open(noread, O_RDWR) != -1) e(6); if (open(noread, O_RDWR | O_CREAT, 0777) != -1) e(7); if (open(noread, O_RDWR | O_CREAT | O_TRUNC, 0777) != -1) e(8); if ((fd = open(noread, O_WRONLY)) != 3) e(9); if (close(fd) != 0) e(10); System("touch nowrite; chmod 577 nowrite"); /* nowrite */ if (open(nowrite, O_WRONLY) != -1) e(11); if (open(nowrite, O_RDWR) != -1) e(12); if (open(nowrite, O_RDWR | O_CREAT, 0777) != -1) e(13); if (open(nowrite, O_RDWR | O_CREAT | O_TRUNC, 0777) != -1) e(14); if ((fd = open(nowrite, O_RDONLY)) != 3) e(15); if (close(fd) != 0) e(16); if (superuser) { /* If we can make a file ownd by some one else, test access again. */ System("chmod 733 noread"); System("chown bin noread"); System("chgrp system noread"); System("chmod 755 nowrite"); System("chown bin nowrite"); System("chgrp system nowrite"); switch (fork()) { case -1: printf("Can't fork\n"); break; case 0: setuid(1); setgid(1); /* become daemon */ if (open(noread, O_RDONLY) != -1) e(17); if (open(noread, O_RDWR) != -1) e(18); if (open(noread, O_RDWR | O_CREAT, 0777) != -1) e(19); fd = open(noread, O_RDWR | O_CREAT | O_TRUNC, 0777); if (fd != -1) e(20); if ((fd = open(noread, O_WRONLY)) != 3) e(21); if (close(fd) != 0) e(22); if (open(nowrite, O_WRONLY) != -1) e(23); if (open(nowrite, O_RDWR) != -1) e(24); if (open(nowrite, O_RDWR | O_CREAT, 0777) != -1) e(25); fd = open(nowrite, O_RDWR | O_CREAT | O_TRUNC, 0777); if (fd != -1) e(26); if ((fd = open(nowrite, O_RDONLY)) != 3) e(27); if (close(fd) != 0) e(28); exit(0); default: if (wait(&stat_loc) == -1) e(29); } } /* Clean up the noread and nowrite files. */ System("rm -rf noread nowrite"); /* Test the O_EXCL flag. */ System("echo > exists"); if (open("exists", O_RDWR | O_CREAT | O_EXCL, 0777) != -1) e(30); if (errno != EEXIST) e(31); if (open("exists", O_RDONLY | O_CREAT | O_EXCL, 0777) != -1) e(32); if (errno != EEXIST) e(33); if (open("exists", O_WRONLY | O_CREAT | O_EXCL, 0777) != -1) e(34); if (errno != EEXIST) e(35); fd = open("exists", O_RDWR | O_CREAT | O_EXCL | O_TRUNC, 0777); if (fd != -1) e(36); if (errno != EEXIST) e(37); fd = open("exists", O_RDONLY | O_CREAT | O_EXCL | O_TRUNC, 0777); if (fd != -1) e(38); if (errno != EEXIST) e(39); fd = open("exists", O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0777); if (fd != -1) e(40); if (errno != EEXIST) e(41); /* Test ToLongName and ToLongPath */ if ((fd = open(ToLongName, O_RDWR | O_CREAT, 0777)) != 3) e(45); if (close(fd) != 0) e(46); ToLongPath[PATH_MAX - 2] = '/'; ToLongPath[PATH_MAX - 1] = 'a'; if ((fd = open(ToLongPath, O_RDWR | O_CREAT, 0777)) != -1) e(47); if (errno != ENAMETOOLONG) e(48); if (close(fd) != -1) e(49); ToLongPath[PATH_MAX - 1] = '/'; } void makelongnames() { register int i; memset(MaxName, 'a', NAME_MAX); MaxName[NAME_MAX] = '\0'; for (i = 0; i < PATH_MAX - 1; i++) { /* idem path */ MaxPath[i++] = '.'; MaxPath[i] = '/'; } MaxPath[PATH_MAX - 1] = '\0'; strcpy(ToLongName, MaxName); /* copy them Max to ToLong */ strcpy(ToLongPath, MaxPath); ToLongName[NAME_MAX] = 'a'; ToLongName[NAME_MAX + 1] = '\0'; /* extend ToLongName by one too many */ ToLongPath[PATH_MAX - 1] = '/'; ToLongPath[PATH_MAX] = '\0'; /* inc ToLongPath by one */ } void e(n) int n; { int err_num = errno; /* Save in case printf clobbers it. */ printf("Subtest %d, error %d errno=%d: ", subtest, n, errno); errno = err_num; perror(""); if (errct++ > MAX_ERROR) { printf("Too many errors; test aborted\n"); chdir(".."); system("rm -rf DIR*"); exit(1); } errno = 0; } void quit() { Chdir(".."); System("rm -rf DIR_25"); if (errct == 0) { printf("ok\n"); exit(0); } else { printf("%d errors\n", errct); exit(1); } }