1 /* test25: open (), close () (p) Jan-Mark Wams. email: jms@cs.vu.nl */ 2 3 /* Not tested: O_NONBLOCK on special files, supporting it. 4 ** On a read-only file system, some error reports are to be expected. 5 */ 6 7 #include <sys/types.h> 8 #include <sys/stat.h> 9 #include <sys/wait.h> 10 #include <stdlib.h> 11 #include <unistd.h> 12 #include <string.h> 13 #include <fcntl.h> 14 #include <limits.h> 15 #include <errno.h> 16 #include <time.h> 17 #include <stdio.h> 18 19 int max_error = 4; 20 #include "common.h" 21 22 #define ITERATIONS 2 23 24 25 #define System(cmd) if (system(cmd) != 0) printf("``%s'' failed\n", cmd) 26 #define Chdir(dir) if (chdir(dir) != 0) printf("Can't goto %s\n", dir) 27 #define Stat(a,b) if (stat(a,b) != 0) printf("Can't stat %s\n", a) 28 #define Creat(f) if (close(creat(f,0777))!=0) printf("Can't creat %s\n",f) 29 #define Report(s,n) printf("Subtest %d" s,subtest,(n)) 30 31 int subtest = 1; 32 int superuser; 33 char *MaxName; /* Name of maximum length */ 34 char MaxPath[PATH_MAX]; /* Same for path */ 35 char *ToLongName; /* Name of maximum +1 length */ 36 char ToLongPath[PATH_MAX + 1]; /* Same for path, both too long */ 37 38 void test25a(void); 39 void test25b(void); 40 void test25c(void); 41 void test25d(void); 42 void test25e(void); 43 void makelongnames(void); 44 45 int main(int argc, char *argv[]) 46 { 47 int i, m = 0xFFFF; 48 49 sync(); 50 51 start(25); 52 if (argc == 2) m = atoi(argv[1]); 53 makelongnames(); 54 superuser = (geteuid() == 0); 55 56 /* Close all files, the parent might have opened. */ 57 for (i = 3; i < 100; i++) close(i); 58 59 for (i = 0; i < ITERATIONS; i++) { 60 if (m & 001) test25a(); 61 if (m & 002) test25b(); 62 if (m & 004) test25c(); 63 if (m & 010) test25d(); 64 if (m & 020) test25e(); 65 } 66 quit(); 67 68 return(-1); /* Unreachable */ 69 } 70 71 void test25a() 72 { /* Test fcntl flags. */ 73 subtest = 1; 74 75 #define EXCLUDE(a,b) (((a)^(b)) == ((a)|(b))) 76 #define ADDIT (O_APPEND | O_CREAT | O_EXCL | O_NONBLOCK | O_TRUNC) 77 78 /* If this compiles all flags are defined but they have to be or-able. */ 79 if (!(EXCLUDE(O_NONBLOCK, O_TRUNC))) e(1); 80 if (!(EXCLUDE(O_EXCL, O_NONBLOCK | O_TRUNC))) e(2); 81 if (!(EXCLUDE(O_CREAT, O_EXCL | O_NONBLOCK | O_TRUNC))) e(3); 82 if (!(EXCLUDE(O_APPEND, O_CREAT | O_EXCL | O_NONBLOCK | O_TRUNC))) e(4); 83 if (!(EXCLUDE(O_RDONLY, ADDIT))) e(5); 84 if (!(EXCLUDE(O_WRONLY, ADDIT))) e(6); 85 if (!(EXCLUDE(O_RDWR, ADDIT))) e(7); 86 } 87 88 void test25b() 89 { /* Test normal operation. */ 90 91 #define BUF_SIZE 1024 92 93 int fd1, fd2, fd3, fd4, fd5; 94 char buf[BUF_SIZE]; 95 struct stat st1, st2, st3; 96 time_t time1, time2; 97 int stat_loc; 98 99 subtest = 2; 100 101 System("rm -rf ../DIR_25/*"); 102 103 System("echo Hello > he"); /* make test files */ 104 System("echo Hello > ha"); /* size 6 bytes */ 105 System("echo Hello > hi"); 106 System("echo Hello > ho"); 107 108 /* Check path resolution. Check if lowest fds are returned */ 109 if ((fd1 = open("he", O_RDONLY)) != 3) e(1); 110 if (read(fd1, buf, BUF_SIZE) != 6) e(2); 111 if ((fd2 = open("./ha", O_RDONLY)) != 4) e(3); 112 if ((fd3 = open("../DIR_25/he", O_RDWR)) != 5) e(4); 113 if ((fd4 = open("ho", O_WRONLY)) != 6) e(5); 114 if (close(fd4) != 0) e(6); 115 if (close(fd1) != 0) e(7); 116 if ((fd1 = open("./././ho", O_RDWR)) != 3) e(8); 117 if ((fd4 = open("../DIR_25/he", O_RDONLY)) != 6) e(9); 118 if (close(fd2) != 0) e(10); 119 if (close(fd3) != 0) e(11); 120 if ((fd2 = open("ha", O_RDONLY)) != 4) e(12); 121 if ((fd3 = open("/etc/passwd", O_RDONLY)) != 5) e(13); 122 if (close(fd4) != 0) e(14); /* close all */ 123 if (close(fd1) != 0) e(15); 124 if (close(fd3) != 0) e(16); 125 126 /* Check if processes share fd2, and if they have independent new fds */ 127 System("rm -rf /tmp/sema.25"); 128 switch (fork()) { 129 case -1: printf("Can't fork\n"); break; 130 131 case 0: 132 if ((fd1 = open("he", O_WRONLY)) != 3) e(17); 133 if ((fd3 = open("../././DIR_25/ha", O_WRONLY)) != 5) e(18); 134 if ((fd4 = open("../DIR_25/hi", O_WRONLY)) != 6) e(19); 135 if ((fd5 = open("ho", O_WRONLY)) != 7) e(20); 136 system("while test ! -f /tmp/sema.25; do sleep 1; done"); /* parent */ 137 if (read(fd2, buf, BUF_SIZE) != 3) e(21); /* gets Hel */ 138 if (strncmp(buf, "lo\n", 3) != 0) e(22); /* we get lo */ 139 if (close(fd1) != 0) e(23); 140 if (close(fd2) != 0) e(24); 141 if (close(fd3) != 0) e(25); 142 if (close(fd4) != 0) e(26); 143 if (close(fd5) != 0) e(27); 144 exit(0); 145 146 default: 147 if ((fd1 = open("ha", O_RDONLY)) != 3) e(28); 148 if ((fd3 = open("./he", O_RDONLY)) != 5) e(29); 149 if ((fd4 = open("../DIR_25/hi", O_RDWR)) != 6) e(30); 150 if ((fd5 = open("ho", O_WRONLY)) != 7) e(31); 151 if (close(fd1) != 0) e(32); 152 if (read(fd2, buf, 3) != 3) e(33); /* get Hel */ 153 Creat("/tmp/sema.25"); 154 if (strncmp(buf, "Hel", 3) != 0) e(34); 155 if (close(fd2) != 0) e(35); 156 if (close(fd3) != 0) e(36); 157 if (close(fd4) != 0) e(37); 158 if (close(fd5) != 0) e(38); 159 if (wait(&stat_loc) == -1) e(39); 160 if (stat_loc != 0) e(40); 161 } 162 System("rm -f /tmp/sema.25"); 163 164 /* Check if the file status information is updated correctly */ 165 Stat("hi", &st1); /* get info */ 166 Stat("ha", &st2); /* of files */ 167 time(&time1); 168 while (time1 >= time((time_t *)0)) 169 ; /* wait a sec */ 170 if ((fd1 = open("hi", O_RDONLY)) != 3) e(41); /* open files */ 171 if ((fd2 = open("ha", O_WRONLY)) != 4) e(42); 172 if (read(fd1, buf, 1) != 1) e(43); /* read one */ 173 if (close(fd1) != 0) e(44); /* close one */ 174 Stat("hi", &st3); /* get info */ 175 if (st1.st_uid != st3.st_uid) e(45); 176 if (st1.st_gid != st3.st_gid) e(46); /* should be same */ 177 if (st1.st_mode != st3.st_mode) e(47); 178 if (st1.st_size != st3.st_size) e(48); 179 if (st1.st_nlink != st3.st_nlink) e(49); 180 if (st1.st_mtime != st3.st_mtime) e(50); 181 if (st1.st_ctime != st3.st_ctime) e(51); 182 #ifndef V1_FILESYSTEM 183 if (st1.st_atime >= st3.st_atime) e(52); /* except for atime. */ 184 #endif 185 if (write(fd2, "Howdy\n", 6) != 6) e(53); /* Update c & mtime. */ 186 if ((fd1 = open("ha", O_RDWR)) != 3) e(54); 187 if (read(fd1, buf, 6) != 6) e(55); /* Update atime. */ 188 if (strncmp(buf, "Howdy\n", 6) != 0) e(56); 189 if (close(fd1) != 0) e(57); 190 Stat("ha", &st3); 191 if (st2.st_uid != st3.st_uid) e(58); 192 if (st2.st_gid != st3.st_gid) e(59); /* should be same */ 193 if (st2.st_mode != st3.st_mode) e(60); 194 if (st2.st_nlink != st3.st_nlink) e(61); 195 if (st2.st_ctime >= st3.st_ctime) e(62); 196 #ifndef V1_FILESYSTEM 197 if (st2.st_atime >= st3.st_atime) e(63); 198 #endif 199 if (st2.st_mtime >= st3.st_mtime) e(64); 200 if (st2.st_size != st3.st_size) e(65); 201 if (close(fd2) != 0) e(66); 202 203 /* Let's see if RDONLY files are read only. */ 204 if ((fd1 = open("hi", O_RDONLY)) != 3) e(67); 205 if (write(fd1, " again", 7) != -1) e(68); /* we can't write */ 206 if (errno != EBADF) e(69); /* a read only fd */ 207 if (read(fd1, buf, 7) != 6) e(70); /* but we can read */ 208 if (close(fd1) != 0) e(71); 209 210 /* Let's see if WRONLY files are write only. */ 211 if ((fd1 = open("hi", O_WRONLY)) != 3) e(72); 212 if (read(fd1, buf, 7) != -1) e(73); /* we can't read */ 213 if (errno != EBADF) e(74); /* a write only fd */ 214 if (write(fd1, "hELLO", 6) != 6) e(75); /* but we can write */ 215 if (close(fd1) != 0) e(76); 216 217 /* Let's see if files are closable only once. */ 218 if (close(fd1) != -1) e(77); 219 if (errno != EBADF) e(78); 220 221 /* Let's see how calling close() with bad fds is handled. */ 222 if (close(10) != -1) e(79); 223 if (errno != EBADF) e(80); 224 if (close(111) != -1) e(81); 225 if (errno != EBADF) e(82); 226 if (close(-432) != -1) e(83); 227 if (errno != EBADF) e(84); 228 229 /* Let's see if RDWR files are read & write able. */ 230 if ((fd1 = open("hi", O_RDWR)) != 3) e(85); 231 if (read(fd1, buf, 6) != 6) e(86); /* we can read */ 232 if (strncmp(buf, "hELLO", 6) != 0) e(87); /* and we can write */ 233 if (write(fd1, "Hello", 6) != 6) e(88); /* a read write fd */ 234 if (close(fd1) != 0) e(89); 235 236 /* Check if APPENDed files are realy appended */ 237 if ((fd1 = open("hi", O_RDWR | O_APPEND)) != 3) e(90); /* open hi */ 238 239 /* An open should set the file offset to 0. */ 240 if (lseek(fd1, (off_t) 0, SEEK_CUR) != 0) e(91); 241 242 /* Writing 0 bytes should not have an effect. */ 243 if (write(fd1, "", 0) != 0) e(92); 244 if (lseek(fd1, (off_t) 0, SEEK_CUR) != 0) e(93); /* the end? */ 245 246 /* A seek befor a wirte should not matter with O_APPEND. */ 247 Stat("hi", &st1); 248 if (lseek(fd1, (off_t) - 3, SEEK_END) != st1.st_size - 3) e(94); 249 250 /* By writing 1 byte, we force the offset to the end of the file */ 251 if (write(fd1, "1", 1) != 1) e(95); 252 Stat("hi", &st1); 253 if (lseek(fd1, (off_t) 0, SEEK_CUR) != st1.st_size) e(96); 254 if (write(fd1, "2", 1) != 1) e(97); 255 Stat("hi", &st1); 256 if (lseek(fd1, (off_t) 0, SEEK_CUR) != st1.st_size) e(98); 257 if (write(fd1, "3", 1) != 1) e(99); 258 Stat("hi", &st1); 259 if (lseek(fd1, (off_t) 0, SEEK_CUR) != st1.st_size) e(100); 260 if (lseek(fd1, (off_t) - 2, SEEK_CUR) <= 0) e(101); 261 if (write(fd1, "4", 1) != 1) e(102); 262 263 /* Since the mode was O_APPEND, the offset should be reset to EOF */ 264 Stat("hi", &st1); 265 if (lseek(fd1, (off_t) 0, SEEK_CUR) != st1.st_size) e(103); 266 if (lseek(fd1, (off_t) - 4, SEEK_CUR) != st1.st_size - 4) e(104); 267 if (read(fd1, buf, BUF_SIZE) != 4) e(105); 268 if (strncmp(buf, "1234", 4) != 0) e(106); 269 if (close(fd1) != 0) e(107); 270 271 /* Check the effect of O_CREAT */ 272 Stat("ho", &st1); 273 fd1 = open("ho", O_RDWR | O_CREAT, 0000); 274 if (fd1 != 3) e(108); 275 Stat("ho", &st2); 276 if (memcmp(&st1, &st2, sizeof(struct stat)) != 0) e(109); 277 if (read(fd1, buf, 6) != 6) e(110); 278 if (strncmp(buf, "Hello\n", 6) != 0) e(111); 279 if (write(fd1, "@", 1) != 1) e(112); 280 if (close(fd1) != 0) e(113); 281 (void) umask(0000); 282 fd1 = open("ho", O_RDWR | O_CREAT | O_EXCL, 0777); 283 if (fd1 != -1) e(114); /* ho exists */ 284 System("rm -rf new"); 285 time(&time1); 286 while (time1 >= time((time_t *)0)) 287 ; 288 fd1 = open("new", O_RDWR | O_CREAT, 0716); 289 if (fd1 != 3) e(115); /* new file */ 290 Stat("new", &st1); 291 time(&time2); 292 while (time2 >= time((time_t *)0)) 293 ; 294 time(&time2); 295 if (st1.st_uid != geteuid()) e(116); /* try this as superuser. */ 296 if (st1.st_gid != getegid()) e(117); 297 if ((st1.st_mode & 0777) != 0716) e(118); 298 if (st1.st_nlink != 1) e(119); 299 if (st1.st_mtime <= time1) e(120); 300 if (st1.st_mtime >= time2) e(121); 301 #ifndef V1_FILESYSTEM 302 if (st1.st_atime != st1.st_mtime) e(122); 303 #endif 304 if (st1.st_ctime != st1.st_mtime) e(123); 305 if (st1.st_size != 0) e(124); 306 if (write(fd1, "I'm new in town", 16) != 16) e(125); 307 if (lseek(fd1, (off_t) - 5, SEEK_CUR) != 11) e(126); 308 if (read(fd1, buf, 5) != 5) e(127); 309 if (strncmp(buf, "town", 5) != 0) e(128); 310 if (close(fd1) != 0) e(129); 311 312 /* Let's test the O_TRUNC flag on this new file. */ 313 time(&time1); 314 while (time1 >= time((time_t *)0)); 315 if ((fd1 = open("new", O_RDWR | O_TRUNC)) != 3) e(130); 316 Stat("new", &st1); 317 time(&time2); 318 while (time2 >= time((time_t *)0)); 319 time(&time2); 320 if ((st1.st_mode & 0777) != 0716) e(131); 321 if (st1.st_size != (size_t) 0) e(132); /* TRUNCed ? */ 322 if (st1.st_mtime <= time1) e(133); 323 if (st1.st_mtime >= time2) e(134); 324 if (st1.st_ctime != st1.st_mtime) e(135); 325 if (close(fd1) != 0) e(136); 326 327 /* Test if file permission bits and the file ownership are unchanged. */ 328 /* So we will see if `O_CREAT' has no effect if the file exists. */ 329 if (superuser) { 330 System("echo > bar; chmod 077 bar"); /* Make bar 077 */ 331 System("chown daemon bar"); 332 System("chgrp daemon bar"); /* Daemon's bar */ 333 fd1 = open("bar", O_RDWR | O_CREAT | O_TRUNC, 0777); /* knock knock */ 334 if (fd1 == -1) e(137); 335 if (write(fd1, "foo", 3) != 3) e(138); /* rewrite bar */ 336 if (close(fd1) != 0) e(139); 337 Stat("bar", &st1); 338 if (st1.st_uid != 1) e(140); /* bar is still */ 339 if (st1.st_gid != 1) e(141); /* owned by daemon */ 340 if ((st1.st_mode & 0777) != 077) e(142); /* mode still is 077 */ 341 if (st1.st_size != (size_t) 3) e(143); /* 3 bytes long */ 342 343 /* We do the whole thing again, but with O_WRONLY */ 344 fd1 = open("bar", O_WRONLY | O_CREAT | O_TRUNC, 0777); 345 if (fd1 == -1) e(144); 346 if (write(fd1, "foobar", 6) != 6) e(145); /* rewrite bar */ 347 if (close(fd1) != 0) e(146); 348 Stat("bar", &st1); 349 if (st1.st_uid != 1) e(147); /* bar is still */ 350 if (st1.st_gid != 1) e(148); /* owned by daemon */ 351 if ((st1.st_mode & 0777) != 077) e(149); /* mode still is 077 */ 352 if (st1.st_size != (size_t) 6) e(150); /* 6 bytes long */ 353 } 354 } 355 356 void test25c() 357 { /* Test normal operation Part two. */ 358 int fd1, fd2; 359 char buf[BUF_SIZE]; 360 struct stat st; 361 int stat_loc; 362 static int iteration=0; 363 364 subtest = 3; 365 iteration++; 366 367 System("rm -rf ../DIR_25/*"); 368 369 /* Fifo file test here. */ 370 if (mkfifo("fifo", 0777) != 0) e(1); 371 switch (fork()) { 372 case -1: printf("Can't fork\n"); break; 373 case 0: 374 alarm(20); /* Give child 20 seconds to live. */ 375 if ((fd1 = open("fifo", O_RDONLY)) != 3) e(2); 376 if (read(fd1, buf, BUF_SIZE) != 23) e(3); 377 if (strncmp(buf, "1 2 3 testing testing\n", 23) != 0) e(4); 378 if (close(fd1) != 0) e(5); 379 exit(0); 380 default: 381 if ((fd1 = open("fifo", O_WRONLY)) != 3) e(6); 382 if (write(fd1, "1 2 3 testing testing\n", 23) != 23) e(7); 383 if (close(fd1) != 0) e(8); 384 if (wait(&stat_loc) == -1) e(9); 385 if (stat_loc != 0) e(10); /* The alarm went off? */ 386 } 387 388 /* Try opening for writing with O_NONBLOCK. */ 389 fd1 = open("fifo", O_WRONLY | O_NONBLOCK); 390 if (fd1 != -1) e(11); 391 if (errno != ENXIO) e(12); 392 close(fd1); 393 394 /* Try opening for writing with O_NONBLOCK and O_CREAT. */ 395 fd1 = open("fifo", O_WRONLY | O_CREAT | O_NONBLOCK, 0777); 396 if (fd1 != -1) e(13); 397 if (errno != ENXIO) e(14); 398 close(fd1); 399 400 /* Both the NONBLOCK and the EXCLusive give raise to error. */ 401 fd1 = open("fifo", O_WRONLY | O_CREAT | O_EXCL | O_NONBLOCK, 0777); 402 if (fd1 != -1) e(15); 403 if (errno != EEXIST && errno != ENXIO) e(16); 404 close(fd1); /* Just in case. */ 405 406 /* Try opening for reading with O_NONBLOCK. */ 407 fd1 = open("fifo", O_RDONLY | O_NONBLOCK); 408 if (fd1 != 3) e(17); 409 if (close(fd1) != 0) e(18); 410 411 /* Nopt runs out of memory. ;-< We just cut out some valid code */ 412 /* FIFO's should always append. (They have no file position.) */ 413 switch (fork()) { 414 case -1: printf("Can't fork\n"); break; 415 case 0: 416 alarm(20); /* Give child 20 seconds to live. */ 417 if ((fd1 = open("fifo", O_WRONLY)) != 3) e(19); 418 if ((fd2 = open("fifo", O_WRONLY)) != 4) e(20); 419 if (write(fd1, "I did see Elvis.\n", 18) != 18) e(21); 420 if (write(fd2, "I DID.\n", 8) != 8) e(22); 421 if (close(fd2) != 0) e(23); 422 if (close(fd1) != 0) e(24); 423 exit(0); 424 default: 425 if ((fd1 = open("fifo", O_RDONLY)) != 3) e(25); 426 if (read(fd1, buf, 18) != 18) e(26); 427 if (strncmp(buf, "I did see Elvis.\n", 18) != 0) e(27); 428 if (read(fd1, buf, BUF_SIZE) != 8) e(28); 429 if (strncmp(buf, "I DID.\n", 8) != 0) e(29); 430 if (close(fd1) != 0) e(30); 431 if (wait(&stat_loc) == -1) e(31); 432 if (stat_loc != 0) e(32); /* The alarm went off? */ 433 } 434 435 /* O_TRUNC should have no effect on FIFO files. */ 436 switch (fork()) { 437 case -1: printf("Can't fork\n"); break; 438 case 0: 439 alarm(20); /* Give child 20 seconds to live. */ 440 if ((fd1 = open("fifo", O_WRONLY)) != 3) e(33); 441 if (write(fd1, "I did see Elvis.\n", 18) != 18) e(34); 442 if ((fd2 = open("fifo", O_WRONLY | O_TRUNC)) != 4) e(35); 443 if (write(fd2, "I DID.\n", 8) != 8) e(36); 444 if (close(fd2) != 0) e(37); 445 if (close(fd1) != 0) e(38); 446 exit(0); 447 default: 448 if ((fd1 = open("fifo", O_RDONLY)) != 3) e(39); 449 if (read(fd1, buf, 18) != 18) e(40); 450 if (strncmp(buf, "I did see Elvis.\n", 18) != 0) e(41); 451 if (read(fd1, buf, BUF_SIZE) != 8) e(42); 452 if (strncmp(buf, "I DID.\n", 8) != 0) e(43); 453 if (close(fd1) != 0) e(44); 454 if (wait(&stat_loc) == -1) e(45); 455 if (stat_loc != 0) e(46); /* The alarm went off? */ 456 } 457 458 /* Closing the last fd should flush all data to the bitbucket. */ 459 System("rm -rf /tmp/sema.25"); 460 switch (fork()) { 461 case -1: printf("Can't fork\n"); break; 462 463 case 0: 464 alarm(20); /* Give child 20 seconds to live. */ 465 if ((fd1 = open("fifo", O_WRONLY)) != 3) e(47); 466 if (write(fd1, "I did see Elvis.\n", 18) != 18) e(48); 467 Creat("/tmp/sema.25"); 468 sleep(2); /* give parent a chance to open */ 469 /* this was sleep(1), but that's too short: child also sleeps(1) */ 470 if (close(fd1) != 0) e(49); 471 exit(0); 472 473 default: 474 if ((fd1 = open("fifo", O_RDONLY)) != 3) e(50); 475 /* Make `sure' write has closed. */ 476 while (stat("/tmp/sema.25", &st) != 0) sleep(1); 477 if (close(fd1) != 0) e(51); 478 if ((fd1 = open("fifo", O_RDONLY | O_NONBLOCK)) != 3) e(52); 479 if (read(fd1, buf, BUF_SIZE) != 18) e(53); 480 if (close(fd1) != 0) e(54); 481 if (wait(&stat_loc) == -1) e(55); 482 if (stat_loc != 0) e(56); /* The alarm went off? */ 483 } 484 485 /* Let's try one too many. */ 486 System("rm -rf /tmp/sema.25"); 487 switch (fork()) { 488 case -1: printf("Can't fork\n"); break; 489 case 0: 490 alarm(20); /* Give child 20 seconds to live. */ 491 if ((fd1 = open("fifo", O_WRONLY)) != 3) e(57); 492 if (write(fd1, "I did see Elvis.\n", 18) != 18) e(58); 493 494 /* Keep open till third reader is opened. */ 495 while (stat("/tmp/sema.25", &st) != 0) sleep(1); 496 if (close(fd1) != 0) e(59); 497 exit(0); 498 default: 499 if ((fd1 = open("fifo", O_RDONLY)) != 3) e(60); 500 if (read(fd1, buf, 2) != 2) e(61); 501 if (strncmp(buf, "I ", 2) != 0) e(62); 502 if (close(fd1) != 0) e(63); 503 if ((fd1 = open("fifo", O_RDONLY)) != 3) e(64); 504 if (read(fd1, buf, 4) != 4) e(65); 505 if (strncmp(buf, "did ", 4) != 0) e(66); 506 if ((fd2 = open("fifo", O_RDONLY)) != 4) e(67); 507 508 /* Signal third reader is open. */ 509 Creat("/tmp/sema.25"); 510 if (read(fd2, buf, BUF_SIZE) != 12) e(68); 511 if (strncmp(buf, "see Elvis.\n", 12) != 0) e(69); 512 if (close(fd2) != 0) e(70); 513 if (close(fd1) != 0) e(71); 514 if (wait(&stat_loc) == -1) e(72); 515 if (stat_loc != 0) e(73); /* The alarm went off? */ 516 } 517 System("rm -rf fifo /tmp/sema.25"); 518 519 /* O_TRUNC should have no effect on directroys. */ 520 System("mkdir dir; touch dir/f1 dir/f2 dir/f3"); 521 if ((fd1 = open("dir", O_WRONLY | O_TRUNC)) != -1) e(74); 522 if (errno != EISDIR) e(75); 523 close(fd1); 524 525 /* Opening a directory for reading should be possible. */ 526 if ((fd1 = open("dir", O_RDONLY)) != 3) e(76); 527 if (close(fd1) != 0) e(77); 528 if (unlink("dir/f1") != 0) e(78); /* Should still be there. */ 529 if (unlink("dir/f2") != 0) e(79); 530 if (unlink("dir/f3") != 0) e(80); 531 if (rmdir("dir") != 0) e(81); 532 533 if (!superuser) { 534 /* Test if O_CREAT is not usable to open files with the wrong mode */ 535 (void) umask(0200); /* nono has no */ 536 System("touch nono"); /* write bit */ 537 (void) umask(0000); 538 fd1 = open("nono", O_RDWR | O_CREAT, 0777); /* try to open */ 539 if (fd1 != -1) e(82); 540 if (errno != EACCES) e(83); /* but no access */ 541 } 542 } 543 544 void test25d() 545 { 546 int fd; 547 548 subtest = 4; 549 550 System("rm -rf ../DIR_25/*"); 551 552 /* Test maximal file name length. */ 553 if ((fd = open(MaxName, O_RDWR | O_CREAT, 0777)) != 3) e(1); 554 if (close(fd) != 0) e(2); 555 MaxPath[strlen(MaxPath) - 2] = '/'; 556 MaxPath[strlen(MaxPath) - 1] = 'a'; /* make ././.../a */ 557 if ((fd = open(MaxPath, O_RDWR | O_CREAT, 0777)) != 3) e(3); 558 if (close(fd) != 0) e(4); 559 MaxPath[strlen(MaxPath) - 1] = '/'; /* make ././.../a */ 560 } 561 562 void test25e() 563 { 564 int fd, does_truncate; 565 char *noread = "noread"; /* Name for unreadable file. */ 566 char *nowrite = "nowrite"; /* Same for unwritable. */ 567 int stat_loc; 568 569 subtest = 5; 570 571 System("rm -rf ../DIR_25/*"); 572 573 mkdir("bar", 0777); /* make bar */ 574 575 /* Check if no access on part of path generates the correct error. */ 576 System("chmod 677 bar"); /* rw-rwxrwx */ 577 if (open("bar/nono", O_RDWR | O_CREAT, 0666) != -1) e(1); 578 if (errno != EACCES) e(2); 579 580 /* Ditto for no write permission. */ 581 System("chmod 577 bar"); /* r-xrwxrwx */ 582 if (open("bar/nono", O_RDWR | O_CREAT, 0666) != -1) e(3); 583 if (errno != EACCES) e(4); 584 585 /* Clean up bar. */ 586 System("rm -rf bar"); 587 588 /* Improper flags set on existing file. */ 589 System("touch noread; chmod 377 noread"); /* noread */ 590 if (open(noread, O_RDONLY) != -1) e(5); 591 if (open(noread, O_RDWR) != -1) e(6); 592 if (open(noread, O_RDWR | O_CREAT, 0777) != -1) e(7); 593 if (open(noread, O_RDWR | O_CREAT | O_TRUNC, 0777) != -1) e(8); 594 if ((fd = open(noread, O_WRONLY)) != 3) e(9); 595 if (close(fd) != 0) e(10); 596 System("touch nowrite; chmod 577 nowrite"); /* nowrite */ 597 if (open(nowrite, O_WRONLY) != -1) e(11); 598 if (open(nowrite, O_RDWR) != -1) e(12); 599 if (open(nowrite, O_RDWR | O_CREAT, 0777) != -1) e(13); 600 if (open(nowrite, O_RDWR | O_CREAT | O_TRUNC, 0777) != -1) e(14); 601 if ((fd = open(nowrite, O_RDONLY)) != 3) e(15); 602 if (close(fd) != 0) e(16); 603 if (superuser) { 604 /* If we can make a file ownd by some one else, test access again. */ 605 System("chmod 733 noread"); 606 System("chown bin noread"); 607 System("chgrp system noread"); 608 System("chmod 755 nowrite"); 609 System("chown bin nowrite"); 610 System("chgrp system nowrite"); 611 switch (fork()) { 612 case -1: printf("Can't fork\n"); break; 613 case 0: 614 setuid(1); 615 setgid(1); /* become daemon */ 616 if (open(noread, O_RDONLY) != -1) e(17); 617 if (open(noread, O_RDWR) != -1) e(18); 618 if (open(noread, O_RDWR | O_CREAT, 0777) != -1) e(19); 619 fd = open(noread, O_RDWR | O_CREAT | O_TRUNC, 0777); 620 if (fd != -1) e(20); 621 if ((fd = open(noread, O_WRONLY)) != 3) e(21); 622 if (close(fd) != 0) e(22); 623 if (open(nowrite, O_WRONLY) != -1) e(23); 624 if (open(nowrite, O_RDWR) != -1) e(24); 625 if (open(nowrite, O_RDWR | O_CREAT, 0777) != -1) e(25); 626 fd = open(nowrite, O_RDWR | O_CREAT | O_TRUNC, 0777); 627 if (fd != -1) e(26); 628 if ((fd = open(nowrite, O_RDONLY)) != 3) e(27); 629 if (close(fd) != 0) e(28); 630 exit(0); 631 default: 632 if (wait(&stat_loc) == -1) e(29); 633 } 634 } 635 636 /* Clean up the noread and nowrite files. */ 637 System("rm -rf noread nowrite"); 638 639 /* Test the O_EXCL flag. */ 640 System("echo > exists"); 641 if (open("exists", O_RDWR | O_CREAT | O_EXCL, 0777) != -1) e(30); 642 if (errno != EEXIST) e(31); 643 if (open("exists", O_RDONLY | O_CREAT | O_EXCL, 0777) != -1) e(32); 644 if (errno != EEXIST) e(33); 645 if (open("exists", O_WRONLY | O_CREAT | O_EXCL, 0777) != -1) e(34); 646 if (errno != EEXIST) e(35); 647 fd = open("exists", O_RDWR | O_CREAT | O_EXCL | O_TRUNC, 0777); 648 if (fd != -1) e(36); 649 if (errno != EEXIST) e(37); 650 fd = open("exists", O_RDONLY | O_CREAT | O_EXCL | O_TRUNC, 0777); 651 if (fd != -1) e(38); 652 if (errno != EEXIST) e(39); 653 fd = open("exists", O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0777); 654 if (fd != -1) e(40); 655 if (errno != EEXIST) e(41); 656 657 /* open should fail when O_CREAT|O_EXCL are set and a symbolic link names 658 a file with EEXIST (regardless of link actually works or not) */ 659 if (symlink("exists", "slinktoexists") == -1) e(42); 660 if (open("slinktoexists", O_RDWR | O_CREAT | O_EXCL, 0777) != -1) e(43); 661 if (unlink("exists") == -1) e(44); 662 /* "slinktoexists has become a dangling symlink. open(2) should still fail 663 with EEXIST */ 664 if (open("slinktoexists", O_RDWR | O_CREAT | O_EXCL, 0777) != -1) e(45); 665 if (errno != EEXIST) e(46); 666 667 668 /* Test ToLongName and ToLongPath */ 669 does_truncate = does_fs_truncate(); 670 fd = open(ToLongName, O_RDWR | O_CREAT, 0777); 671 if (does_truncate) { 672 if (fd == -1) e(47); 673 if (close(fd) != 0) e(48); 674 } else { 675 if (fd != -1) e(49); 676 (void) close(fd); /* Just in case */ 677 } 678 679 ToLongPath[PATH_MAX - 2] = '/'; 680 ToLongPath[PATH_MAX - 1] = 'a'; 681 if ((fd = open(ToLongPath, O_RDWR | O_CREAT, 0777)) != -1) e(50); 682 if (errno != ENAMETOOLONG) e(51); 683 if (close(fd) != -1) e(52); 684 ToLongPath[PATH_MAX - 1] = '/'; 685 } 686 687 void makelongnames() 688 { 689 register int i; 690 int max_name_length; 691 692 max_name_length = name_max("."); /* Aka NAME_MAX, but not every FS supports 693 * the same length, hence runtime check */ 694 MaxName = malloc(max_name_length + 1); 695 ToLongName = malloc(max_name_length + 1 + 1); /* Name of maximum +1 length */ 696 memset(MaxName, 'a', max_name_length); 697 MaxName[max_name_length] = '\0'; 698 699 for (i = 0; i < PATH_MAX - 1; i++) { /* idem path */ 700 MaxPath[i++] = '.'; 701 MaxPath[i] = '/'; 702 } 703 MaxPath[PATH_MAX - 1] = '\0'; 704 705 strcpy(ToLongName, MaxName); /* copy them Max to ToLong */ 706 strcpy(ToLongPath, MaxPath); 707 708 ToLongName[max_name_length] = 'a'; 709 ToLongName[max_name_length+1] = '\0';/* extend ToLongName by one too many */ 710 ToLongPath[PATH_MAX - 1] = '/'; 711 ToLongPath[PATH_MAX] = '\0'; /* inc ToLongPath by one */ 712 } 713 714