1 /* POSIX test program (7). Author: Andy Tanenbaum */ 2 3 /* The following POSIX calls are tested: 4 * pipe(), mkfifo(), fcntl() 5 */ 6 7 #include <sys/types.h> 8 #include <sys/stat.h> 9 #include <sys/wait.h> 10 #include <errno.h> 11 #include <fcntl.h> 12 #include <limits.h> 13 #include <signal.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <unistd.h> 17 #include <stdio.h> 18 #include <setjmp.h> 19 20 #define ITERATIONS 4 21 int max_error = 3; 22 #include "common.h" 23 24 #define ITEMS 32 25 #define READ 10 26 #define WRITE 20 27 #define UNLOCK 30 28 #define U 70 29 #define L 80 30 31 char buf[ITEMS] = {0,1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1,0,1,2,3,4,5,6,7,8,9}; 32 33 34 int subtes, xfd; 35 int whence = SEEK_SET, func_code = F_SETLK; 36 extern char **environ; 37 38 #define timed_test(func) (timed_test_func(#func, func)); 39 40 int main(int argc, char *argv []); 41 void timed_test_func(const char *s, void (* func)(void)); 42 void timed_test_timeout(int signum); 43 void test7a(void); 44 void test7b(void); 45 void test7c(void); 46 void test7d(void); 47 void test7e(void); 48 void test7f(void); 49 void test7g(void); 50 void test7h(void); 51 void test7i(void); 52 void test7j(void); 53 void cloexec_test(void); 54 int set(int how, int first, int last); 55 int locked(int b); 56 void sigfunc(int s); 57 58 int main(argc, argv) 59 int argc; 60 char *argv[]; 61 { 62 63 int i, m = 0xFFFF; 64 65 if (argc == 2) m = atoi(argv[1]); 66 if (m == 0) cloexec_test(); /* important; do not remove this! */ 67 68 start(7); 69 70 for (i = 0; i < ITERATIONS; i++) { 71 if (m & 00001) timed_test(test7a); 72 if (m & 00002) timed_test(test7b); 73 if (m & 00004) timed_test(test7c); 74 if (m & 00010) timed_test(test7d); 75 if (m & 00020) timed_test(test7e); 76 if (m & 00040) timed_test(test7f); 77 if (m & 00100) timed_test(test7g); 78 if (m & 00200) timed_test(test7h); 79 if (m & 00400) timed_test(test7i); 80 if (m & 01000) timed_test(test7j); 81 } 82 quit(); 83 return(-1); /* impossible */ 84 } 85 86 static jmp_buf timed_test_context; 87 88 void timed_test_timeout(int signum) 89 { 90 longjmp(timed_test_context, -1); 91 e(700); 92 quit(); 93 exit(-1); 94 } 95 96 void timed_test_func(const char *s, void (* func)(void)) 97 { 98 if (setjmp(timed_test_context) == 0) 99 { 100 /* the function gets 60 seconds to complete */ 101 if (signal(SIGALRM, timed_test_timeout) == SIG_ERR) { e(701); return; } 102 alarm(60); 103 func(); 104 alarm(0); 105 } 106 else 107 { 108 /* report timeout as error */ 109 printf("timeout in %s\n", s); 110 e(702); 111 } 112 } 113 114 void test7a() 115 { 116 /* Test pipe(). */ 117 118 int i, fd[2], ect; 119 char buf2[ITEMS+1]; 120 121 /* Create a pipe, write on it, and read it back. */ 122 subtest = 1; 123 if (pipe(fd) != 0) e(1); 124 if (write(fd[1], buf, ITEMS) != ITEMS) e(2); 125 buf2[0] = 0; 126 if (read(fd[0], buf2, ITEMS+1) != ITEMS) e(3); 127 ect = 0; 128 for (i = 0; i < ITEMS; i++) if (buf[i] != buf2[i]) ect++; 129 if (ect != 0) e(4); 130 if (close(fd[0]) != 0) e(5); 131 if (close(fd[1]) != 0) e(6); 132 133 /* Error test. Keep opening pipes until it fails. Check error code. */ 134 errno = 0; 135 while (1) { 136 if (pipe(fd) < 0) break; 137 } 138 if (errno != EMFILE) e(7); 139 140 /* Close all the pipes. */ 141 for (i = 3; i < OPEN_MAX; i++) close(i); 142 } 143 144 void test7b() 145 { 146 /* Test mkfifo(). */ 147 148 int fdr, fdw, status; 149 char buf2[ITEMS+1]; 150 int efork; 151 152 /* Create a fifo, write on it, and read it back. */ 153 subtest = 2; 154 if (mkfifo("T7.b", 0777) != 0) e(1); 155 switch (fork()) { 156 case -1: 157 efork = errno; 158 printf("Fork failed: %s (%d)\n", strerror(efork), efork); 159 exit(1); 160 case 0: 161 /* Child reads from the fifo. */ 162 if ( (fdr = open("T7.b", O_RDONLY)) < 0) e(5); 163 if (read(fdr, buf2, ITEMS+1) != ITEMS) e(6); 164 if (strcmp(buf, buf2) != 0) e(7); 165 if (close(fdr) != 0) e(8); 166 exit(0); 167 default: 168 /* Parent writes on the fifo. */ 169 if ( (fdw = open("T7.b", O_WRONLY)) < 0) e(2); 170 if (write(fdw, buf, ITEMS) != ITEMS) e(3); 171 wait(&status); 172 if (close(fdw) != 0) e(4); 173 } 174 175 /* Check some error conditions. */ 176 if (mkfifo("T7.b", 0777) != -1) e(9); 177 errno = 0; 178 if (mkfifo("a/b/c", 0777) != -1) e(10); 179 if (errno != ENOENT) e(11); 180 errno = 0; 181 if (mkfifo("", 0777) != -1) e(12); 182 if (errno != ENOENT) e(13); 183 errno = 0; 184 if (mkfifo("T7.b/x", 0777) != -1) e(14); 185 if (errno != ENOTDIR) e(15); 186 if (unlink("T7.b") != 0) e(16); 187 188 /* Now check fifos and the O_NONBLOCK flag. */ 189 if (mkfifo("T7.b", 0600) != 0) e(17); 190 errno = 0; 191 if (open("T7.b", O_WRONLY | O_NONBLOCK) != -1) e(18); 192 if (errno != ENXIO) e(19); 193 if ( (fdr = open("T7.b", O_RDONLY | O_NONBLOCK)) < 0) e(20); 194 if (fork()) { 195 /* Parent reads from fdr. */ 196 wait(&status); /* but first make sure writer has already run*/ 197 if ( ( (status>>8) & 0377) != 77) e(21); 198 if (read(fdr, buf2, ITEMS+1) != ITEMS) e(22); 199 if (strcmp(buf, buf2) != 0) e(23); 200 if (close(fdr) != 0) e(24); 201 } else { 202 /* Child opens the fifo for writing and writes to it. */ 203 if ( (fdw = open("T7.b", O_WRONLY | O_NONBLOCK)) < 0) e(25); 204 if (write(fdw, buf, ITEMS) != ITEMS) e(26); 205 if (close(fdw) != 0) e(27); 206 exit(77); 207 } 208 209 if (unlink("T7.b") != 0) e(28); 210 } 211 212 void test7c() 213 { 214 /* Test fcntl(). */ 215 216 int fd, m, s, newfd, newfd2; 217 struct stat stat1, stat2, stat3; 218 219 subtest = 3; 220 errno = -100; 221 if ( (fd = creat("T7.c", 0777)) < 0) e(1); 222 223 /* Turn the per-file-descriptor flags on and off. */ 224 if (fcntl(fd, F_GETFD) != 0) e(2); /* FD_CLOEXEC is initially off */ 225 if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) e(3);/* turn it on */ 226 if (fcntl(fd, F_GETFD) != FD_CLOEXEC) e(4); /* should be on now */ 227 if (fcntl(fd, F_SETFD, 0) != 0) e(5); /* turn it off */ 228 if (fcntl(fd, F_GETFD) != 0) e(6); /* should be off now */ 229 230 /* Turn the open-file-description flags on and off. Start with O_APPEND. */ 231 m = O_WRONLY; 232 if (fcntl(fd, F_GETFL) != m) e(7); /* O_APPEND, O_NONBLOCK are off */ 233 if (fcntl(fd, F_SETFL, O_APPEND) != 0) e(8); /* turn on O_APPEND */ 234 if (fcntl(fd, F_GETFL) != (O_APPEND | m)) e(9);/* should be on now */ 235 if (fcntl(fd, F_SETFL, 0) != 0) e(10); /* turn it off */ 236 if (fcntl(fd, F_GETFL) != m) e(11); /* should be off now */ 237 238 /* Turn the open-file-description flags on and off. Now try O_NONBLOCK. */ 239 if (fcntl(fd, F_SETFL, O_NONBLOCK) != 0) e(12); /* turn on O_NONBLOCK */ 240 if (fcntl(fd, F_GETFL) != (O_NONBLOCK | m)) e(13); /* should be on now */ 241 if (fcntl(fd, F_SETFL, 0) != 0) e(14); /* turn it off */ 242 if (fcntl(fd, F_GETFL) != m) e(15); /* should be off now */ 243 244 /* Now both at once. */ 245 if (fcntl(fd, F_SETFL, O_APPEND|O_NONBLOCK) != 0) e(16); 246 if (fcntl(fd, F_GETFL) != (O_NONBLOCK | O_APPEND | m)) e(17); 247 if (fcntl(fd, F_SETFL, 0) != 0) e(18); 248 if (fcntl(fd, F_GETFL) != m) e(19); 249 250 /* Now test F_DUPFD. */ 251 if ( (newfd = fcntl(fd, F_DUPFD, 0)) != 4) e(20); /* 0-4 open */ 252 if ( (newfd2 = fcntl(fd, F_DUPFD, 0)) != 5) e(21); /* 0-5 open */ 253 if (close(newfd) != 0) e(22); /* 0-3, 5 open */ 254 if ( (newfd = fcntl(fd, F_DUPFD, 0)) != 4) e(23); /* 0-5 open */ 255 if (close(newfd) != 0) e(24); /* 0-3, 5 open */ 256 if ( (newfd = fcntl(fd, F_DUPFD, 5)) != 6) e(25); /* 0-3, 5, 6 open */ 257 if (close(newfd2) != 0) e(26); /* 0-3, 6 open */ 258 259 /* O_APPEND should be inherited, but FD_CLOEXEC should be cleared. Check. */ 260 if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) e(26);/* turn FD_CLOEXEC on */ 261 if (fcntl(fd, F_SETFL, O_APPEND) != 0) e(27); /* turn O_APPEND on */ 262 if ( (newfd2 = fcntl(fd, F_DUPFD, 10)) != 10) e(28); /* 0-3, 6, 10 open */ 263 if (fcntl(newfd2, F_GETFD) != 0) e(29); /* FD_CLOEXEC must be 0 */ 264 if (fcntl(newfd2, F_GETFL) != (O_APPEND | m)) e(30); /* O_APPEND set */ 265 if (fcntl(fd, F_SETFD, 0) != 0) e(31);/* turn FD_CLOEXEC off */ 266 267 /* Check if newfd and newfd2 are the same inode. */ 268 if (fstat(fd, &stat1) != 0) e(32); 269 if (fstat(fd, &stat2) != 0) e(33); 270 if (fstat(fd, &stat3) != 0) e(34); 271 if (stat1.st_dev != stat2.st_dev) e(35); 272 if (stat1.st_dev != stat3.st_dev) e(36); 273 if (stat1.st_ino != stat2.st_ino) e(37); 274 if (stat1.st_ino != stat3.st_ino) e(38); 275 276 /* Now check on the FD_CLOEXEC flag. Set it for fd (3) and newfd2 (10) */ 277 if (fd != 3 || newfd2 != 10 || newfd != 6) e(39); 278 if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) e(40); /* close 3 on exec */ 279 if (fcntl(newfd2, F_SETFD, FD_CLOEXEC) != 0) e(41); /* close 10 on exec */ 280 if (fcntl(newfd, F_SETFD, 0) != 0) e(42); /* don't close 6 */ 281 if (fork()) { 282 wait(&s); /* parent just waits */ 283 if (WEXITSTATUS(s) != 0) e(43); 284 } else { 285 execle("../test7", "test7", "0", (char *) 0, environ); 286 exit(1); /* the impossible never happens, right? */ 287 } 288 289 /* Finally, close all the files. */ 290 if (fcntl(fd, F_SETFD, 0) != 0) e(44); /* FD_CLOEXEC off */ 291 if (fcntl(newfd2, F_SETFD, 0) != 0) e(45); /* FD_CLOEXEC off */ 292 if (close(fd) != 0) e(46); 293 if (close(newfd) != 0) e(47); 294 if (close(newfd2) != 0) e(48); 295 } 296 297 void test7d() 298 { 299 /* Test file locking. */ 300 301 subtest = 4; 302 303 if ( (xfd = creat("T7.d", 0777)) != 3) e(1); 304 close(xfd); 305 if ( (xfd = open("T7.d", O_RDWR)) < 0) e(2); 306 if (write(xfd, buf, ITEMS) != ITEMS) e(3); 307 if (set(WRITE, 0, 3) != 0) e(4); 308 if (set(WRITE, 5, 9) != 0) e(5); 309 if (set(UNLOCK, 0, 3) != 0) e(6); 310 if (set(UNLOCK, 4, 9) != 0) e(7); 311 312 if (set(READ, 1, 4) != 0) e(8); 313 if (set(READ, 4, 7) != 0) e(9); 314 if (set(UNLOCK, 4, 7) != 0) e(10); 315 if (set(UNLOCK, 1, 4) != 0) e(11); 316 317 if (set(WRITE, 0, 3) != 0) e(12); 318 if (set(WRITE, 5, 7) != 0) e(13); 319 if (set(WRITE, 9 ,10) != 0) e(14); 320 if (set(UNLOCK, 0, 4) != 0) e(15); 321 if (set(UNLOCK, 0, 7) != 0) e(16); 322 if (set(UNLOCK, 0, 2000) != 0) e(17); 323 324 if (set(WRITE, 0, 3) != 0) e(18); 325 if (set(WRITE, 5, 7) != 0) e(19); 326 if (set(WRITE, 9 ,10) != 0) e(20); 327 if (set(UNLOCK, 0, 100) != 0) e(21); 328 329 if (set(WRITE, 0, 9) != 0) e(22); 330 if (set(UNLOCK, 8, 9) != 0) e(23); 331 if (set(UNLOCK, 0, 2) != 0) e(24); 332 if (set(UNLOCK, 5, 5) != 0) e(25); 333 if (set(UNLOCK, 4, 6) != 0) e(26); 334 if (set(UNLOCK, 3, 3) != 0) e(27); 335 if (set(UNLOCK, 7, 7) != 0) e(28); 336 337 if (set(WRITE, 0, 10) != 0) e(29); 338 if (set(UNLOCK, 0, 1000) != 0) e(30); 339 340 /* Up until now, all locks have been disjoint. Now try conflicts. */ 341 if (set(WRITE, 0, 4) != 0) e(31); 342 if (set(WRITE, 4, 7) != 0) e(32); /* owner may lock same byte twice */ 343 if (set(WRITE, 5, 10) != 0) e(33); 344 if (set(UNLOCK, 0, 11) != 0) e(34); 345 346 /* File is now unlocked. Length 0 means whole file. */ 347 if (set(WRITE, 2, 1) != 0) e(35); /* this locks whole file */ 348 if (set(WRITE, 9,10) != 0) e(36); /* a process can relock its file */ 349 if (set(WRITE, 3, 3) != 0) e(37); 350 if (set(UNLOCK, 0, -1) != 0) e(38); /* file is now unlocked. */ 351 352 /* Test F_GETLK. */ 353 if (set(WRITE, 2, 3) != 0) e(39); 354 if (locked(1) != U) e(40); 355 if (locked(2) != L) e(41); 356 if (locked(3) != L) e(42); 357 if (locked(4) != U) e(43); 358 if (set(UNLOCK, 2, 3) != 0) e(44); 359 if (locked(2) != U) e(45); 360 if (locked(3) != U) e(46); 361 362 close(xfd); 363 } 364 365 void test7e() 366 { 367 /* Test to see if SETLKW blocks as it should. */ 368 369 int pid, s; 370 371 subtest = 5; 372 373 if ( (xfd = creat("T7.e", 0777)) != 3) e(1); 374 if (close(xfd) != 0) e(2); 375 if ( (xfd = open("T7.e", O_RDWR)) < 0) e(3); 376 if (write(xfd, buf, ITEMS) != ITEMS) e(4); 377 if (set(WRITE, 0, 3) != 0) e(5); 378 379 if ( (pid = fork()) ) { 380 /* Parent waits until child has started before signaling it. */ 381 while (access("T7.e1", 0) != 0) ; 382 unlink("T7.e1"); 383 sleep(1); 384 if (kill(pid, SIGKILL) < 0) e(6); 385 if (wait(&s) != pid) e(7); 386 } else { 387 /* Child tries to lock and should block. */ 388 if (creat("T7.e1", 0777) < 0) e(8); 389 func_code = F_SETLKW; 390 if (set(WRITE, 0, 3) != 0) e(9); /* should block */ 391 errno = -1000; 392 e(10); /* process should be killed by signal */ 393 exit(0); /* should never happen */ 394 } 395 close(xfd); 396 } 397 398 void test7f() 399 { 400 /* Test to see if SETLKW gives EINTR when interrupted. */ 401 402 int pid, s; 403 404 subtest = 6; 405 406 if ( (xfd = creat("T7.f", 0777)) != 3) e(1); 407 if (close(xfd) != 0) e(2); 408 if ( (xfd = open("T7.f", O_RDWR)) < 0) e(3); 409 if (write(xfd, buf, ITEMS) != ITEMS) e(4); 410 if (set(WRITE, 0, 3) != 0) e(5); 411 412 if ( (pid = fork()) ) { 413 /* Parent waits until child has started before signaling it. */ 414 while (access("T7.f1", 0) != 0) ; 415 unlink("T7.f1"); 416 sleep(1); 417 if (kill(pid, SIGTERM) < 0) e(6); 418 if (wait(&s) != pid) e(7); 419 if ( (s>>8) != 19) e(8); 420 } else { 421 /* Child tries to lock and should block. 422 * `signal(SIGTERM, sigfunc);' to set the signal handler is inadequate 423 * because on systems like BSD the sigaction flags for signal include 424 * `SA_RESTART' so syscalls are restarted after they have been 425 * interrupted by a signal. 426 */ 427 struct sigaction sa, osa; 428 429 sa.sa_handler = sigfunc; 430 sigemptyset(&sa.sa_mask); 431 sa.sa_flags = 0; 432 if (sigaction(SIGTERM, &sa, &osa) < 0) e(999); 433 if (creat("T7.f1", 0777) < 0) e(9); 434 func_code = F_SETLKW; 435 if (set(WRITE, 0, 3) != -1) e(10); /* should block */ 436 if (errno != EINTR) e(11); /* signal should release it */ 437 exit(19); 438 } 439 close(xfd); 440 } 441 442 void test7g() 443 { 444 /* Test to see if SETLKW unlocks when the needed lock becomes available. */ 445 446 int pid, s; 447 448 subtest = 7; 449 450 if ( (xfd = creat("T7.g", 0777)) != 3) e(1); 451 if (close(xfd) != 0) e(2); 452 if ( (xfd = open("T7.g", O_RDWR)) < 0) e(3); 453 if (write(xfd, buf, ITEMS) != ITEMS) e(4); 454 if (set(WRITE, 0, 3) != 0) e(5); /* bytes 0 to 3 are now locked */ 455 456 if ( (pid = fork()) ) { 457 /* Parent waits for child to start. */ 458 while (access("T7.g1", 0) != 0) ; 459 unlink("T7.g1"); 460 sleep(1); 461 if (set(UNLOCK, 0, 3) != 0) e(5); 462 if (wait(&s) != pid) e(6); 463 if ( (s >> 8) != 29) e(7); 464 } else { 465 /* Child tells parent it is alive, then tries to lock and is blocked.*/ 466 func_code = F_SETLKW; 467 if (creat("T7.g1", 0777) < 0) e(8); 468 if (set(WRITE, 3, 3) != 0) e(9); /* process must block now */ 469 if (set(UNLOCK, 3, 3) != 0) e(10); 470 exit(29); 471 } 472 close(xfd); 473 } 474 475 void test7h() 476 { 477 /* Test to see what happens if two processed block on the same lock. */ 478 479 int pid, pid2, s, w; 480 481 subtest = 8; 482 483 if ( (xfd = creat("T7.h", 0777)) != 3) e(1); 484 if (close(xfd) != 0) e(2); 485 if ( (xfd = open("T7.h", O_RDWR)) < 0) e(3); 486 if (write(xfd, buf, ITEMS) != ITEMS) e(4); 487 if (set(WRITE, 0, 3) != 0) e(5); /* bytes 0 to 3 are now locked */ 488 489 if ( (pid = fork()) ) { 490 if ( (pid2 = fork()) ) { 491 /* Parent waits for child to start. */ 492 while (access("T7.h1", 0) != 0) ; 493 while (access("T7.h2", 0) != 0) ; 494 unlink("T7.h1"); 495 unlink("T7.h2"); 496 sleep(1); 497 if (set(UNLOCK, 0, 3) != 0) e(6); 498 w = wait(&s); 499 if (w != pid && w != pid2) e(7); 500 s = s >> 8; 501 if (s != 39 && s != 49) e(8); 502 w = wait(&s); 503 if (w != pid && w != pid2) e(9); 504 s = s >> 8; 505 if (s != 39 && s != 49) e(10); 506 } else { 507 func_code = F_SETLKW; 508 if (creat("T7.h1", 0777) < 0) e(11); 509 if (set(WRITE, 0, 0) != 0) e(12); /* block now */ 510 if (set(UNLOCK, 0, 0) != 0) e(13); 511 exit(39); 512 } 513 } else { 514 /* Child tells parent it is alive, then tries to lock and is blocked.*/ 515 func_code = F_SETLKW; 516 if (creat("T7.h2", 0777) < 0) e(14); 517 if (set(WRITE, 0, 1) != 0) e(15); /* process must block now */ 518 if (set(UNLOCK, 0, 1) != 0) e(16); 519 exit(49); 520 } 521 close(xfd); 522 } 523 524 void test7i() 525 { 526 /* Check error conditions for fcntl(). */ 527 528 int tfd, i; 529 530 subtest = 9; 531 532 errno = 0; 533 if ( (xfd = creat("T7.i", 0777)) != 3) e(1); 534 if (close(xfd) != 0) e(2); 535 if ( (xfd = open("T7.i", O_RDWR)) < 0) e(3); 536 if (write(xfd, buf, ITEMS) != ITEMS) e(4); 537 if (set(WRITE, 0, 3) != 0) e(5); /* bytes 0 to 3 are now locked */ 538 if (set(WRITE, 0, 0) != 0) e(6); 539 if (errno != 0) e(7); 540 errno = 0; 541 if (set(WRITE, 3, 3) != 0) e(8); 542 if (errno != 0) e(9); 543 tfd = xfd; /* hold good value */ 544 xfd = -99; 545 errno = 0; 546 if (set(WRITE, 0, 0) != -1) e(10); 547 if (errno != EBADF) e(11); 548 549 errno = 0; 550 if ( (xfd = open("T7.i", O_WRONLY)) < 0) e(12); 551 if (set(READ, 0, 0) != -1) e(13); 552 if (errno != EBADF) e(14); 553 if (close(xfd) != 0) e(15); 554 555 errno = 0; 556 if ( (xfd = open("T7.i", O_RDONLY)) < 0) e(16); 557 if (set(WRITE, 0, 0) != -1) e(17); 558 if (errno != EBADF) e(18); 559 if (close(xfd) != 0) e(19); 560 xfd = tfd; /* restore legal xfd value */ 561 562 /* Check for EINVAL. */ 563 errno = 0; 564 if (fcntl(xfd, F_DUPFD, OPEN_MAX) != -1) e(20); 565 if (errno != EINVAL) e(21); 566 errno = 0; 567 if (fcntl(xfd, F_DUPFD, -1) != -1) e(22); 568 if (errno != EINVAL) e(23); 569 570 xfd = 0; /* stdin does not support locking */ 571 errno = 0; 572 if (set(READ, 0, 0) != -1) e(24); 573 if (errno != EINVAL) e(25); 574 xfd = tfd; 575 576 /* Check ENOLCK. */ 577 for (i = 0; i < ITEMS; i++) { 578 if (set(WRITE, i, i) == 0) continue; 579 if (errno != ENOLCK) { 580 e(26); 581 break; 582 } 583 } 584 585 /* Check EMFILE. */ 586 for (i = xfd + 1; i < OPEN_MAX; i++) open("T7.i", 0); /* use up all fds */ 587 errno = 0; 588 if (fcntl(xfd, F_DUPFD, 0) != -1) e(27); /* No fds left */ 589 if (errno != EMFILE) e(28); 590 591 for (i = xfd; i < OPEN_MAX; i++) if (close(i) != 0) e(29); 592 } 593 594 void test7j() 595 { 596 /* Test file locking with two processes. */ 597 598 int s; 599 600 subtest = 10; 601 602 if ( (xfd = creat("T7.j", 0777)) != 3) e(1); 603 close(xfd); 604 if ( (xfd = open("T7.j", O_RDWR)) < 0) e(2); 605 if (write(xfd, buf, ITEMS) != ITEMS) e(3); 606 if (set(WRITE, 0, 4) != 0) e(4); /* lock belongs to parent */ 607 if (set(READ, 10, 16) != 0) e(5); /* lock belongs to parent */ 608 609 /* Up until now, all locks have been disjoint. Now try conflicts. */ 610 if (fork()) { 611 /* Parent just waits for child to finish. */ 612 wait(&s); 613 } else { 614 /* Child does the testing. */ 615 errno = -100; 616 if (set(WRITE, 5, 7) < 0) e(6); /* should work */ 617 if (set(WRITE, 4, 7) >= 0) e(7); /* child may not lock byte 4 */ 618 if (errno != EACCES && errno != EAGAIN) e(8); 619 if (set(WRITE, 5, 9) != 0) e(9); 620 if (set(UNLOCK, 5, 9) != 0) e(10); 621 if (set(READ, 9, 17) < 0) e(11); /* shared READ lock is ok */ 622 exit(0); 623 } 624 close(xfd); 625 } 626 627 void cloexec_test() 628 { 629 /* To text whether the FD_CLOEXEC flag actually causes files to be 630 * closed upon exec, we have to exec something. The test is carried 631 * out by forking, and then having the child exec test7 itself, but 632 * with argument 0. This is detected, and control comes here. 633 * File descriptors 3 and 10 should be closed here, and 10 open. 634 */ 635 636 if (close(3) == 0) e(1001); /* close should fail; it was closed on exec */ 637 if (close(6) != 0) e(1002); /* close should succeed */ 638 if (close(10) == 0) e(1003); /* close should fail */ 639 fflush(stdout); 640 exit(0); 641 } 642 643 int set(how, first, last) 644 int how, first, last; 645 { 646 int r; 647 struct flock flock; 648 649 if (how == READ) flock.l_type = F_RDLCK; 650 if (how == WRITE) flock.l_type = F_WRLCK; 651 if (how == UNLOCK) flock.l_type = F_UNLCK; 652 flock.l_whence = whence; 653 flock.l_start = (long) first; 654 flock.l_len = (long) last - (long) first + 1; 655 r = fcntl(xfd, func_code, &flock); 656 if (r != -1) 657 return(0); 658 else 659 return(-1); 660 } 661 662 int locked(b) 663 int b; 664 /* Test to see if byte b is locked. Return L or U */ 665 { 666 struct flock flock; 667 pid_t pid; 668 int status; 669 670 flock.l_type = F_WRLCK; 671 flock.l_whence = whence; 672 flock.l_start = (long) b; 673 flock.l_len = 1; 674 675 /* Process' own locks are invisible to F_GETLK, so fork a child to test. */ 676 pid = fork(); 677 if (pid == 0) { 678 if (fcntl(xfd, F_GETLK, &flock) != 0) e(2000); 679 exit(flock.l_type == F_UNLCK ? U : L); 680 } 681 if (pid == -1) e(2001); 682 if (fcntl(xfd, F_GETLK, &flock) != 0) e(2002); 683 if (flock.l_type != F_UNLCK) e(2003); 684 if (wait(&status) != pid) e(2004); 685 if (!WIFEXITED(status)) e(2005); 686 return(WEXITSTATUS(status)); 687 } 688 689 void sigfunc(s) 690 int s; /* for ANSI */ 691 { 692 } 693 694