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, newfd3, newfd4; 217 struct stat stat1, stat2, stat3, stat4, stat5; 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 /* Also test F_DUPFD_CLOEXEC. */ 268 if ( (newfd3 = fcntl(fd, F_DUPFD_CLOEXEC, 0)) != 4) e(0); 269 if (fcntl(newfd3, F_GETFD) != FD_CLOEXEC) e(0); /* FD_CLOEXEC must be set */ 270 if (close(newfd3) != 0) e(0); 271 if ( (newfd3 = fcntl(fd, F_DUPFD_CLOEXEC, 12)) != 12) e(0); 272 if (fcntl(newfd3, F_GETFD) != FD_CLOEXEC) e(0); /* FD_CLOEXEC must be set */ 273 if ( (newfd4 = fcntl(newfd3, F_DUPFD, 0)) != 4) e(0); 274 if (fcntl(newfd4, F_GETFD) != 0) e(0); /* FD_CLOEXEC must be unset */ 275 if (close(newfd4) != 0) e(0); 276 if ( (newfd4 = fcntl(newfd3, F_DUPFD_CLOEXEC, 15)) != 15) e(0); 277 if (fcntl(newfd4, F_GETFD) != FD_CLOEXEC) e(0); /* FD_CLOEXEC must be set */ 278 if (fcntl(newfd4, F_SETFD, 0) != 0) e(0); /* turn FD_CLOEXEC off */ 279 if (fcntl(newfd4, F_GETFD) != 0) e(0); /* FD_CLOEXEC must be unset */ 280 281 /* Check if all file descriptors are for the same inode. */ 282 if (fstat(fd, &stat1) != 0) e(32); 283 if (fstat(newfd, &stat2) != 0) e(33); 284 if (fstat(newfd2, &stat3) != 0) e(34); 285 if (fstat(newfd3, &stat4) != 0) e(0); 286 if (fstat(newfd4, &stat5) != 0) e(0); 287 if (stat1.st_dev != stat2.st_dev) e(35); 288 if (stat1.st_dev != stat3.st_dev) e(36); 289 if (stat1.st_dev != stat4.st_dev) e(0); 290 if (stat1.st_dev != stat5.st_dev) e(0); 291 if (stat1.st_ino != stat2.st_ino) e(37); 292 if (stat1.st_ino != stat3.st_ino) e(38); 293 if (stat1.st_ino != stat4.st_ino) e(0); 294 if (stat1.st_ino != stat5.st_ino) e(0); 295 296 /* Now check on the FD_CLOEXEC flag. Set it for fd (3) and newfd2 (10) */ 297 if (fd != 3 || newfd2 != 10 || newfd3 != 12 || newfd4 != 15 || newfd != 6) 298 e(39); 299 if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) e(40); /* close 3 on exec */ 300 if (fcntl(newfd2, F_SETFD, FD_CLOEXEC) != 0) e(41); /* close 10 on exec */ 301 if (fcntl(newfd, F_SETFD, 0) != 0) e(42); /* don't close 6 */ 302 /* leave 12 and 15 as is */ 303 if (fork()) { 304 wait(&s); /* parent just waits */ 305 if (WEXITSTATUS(s) != 0) e(43); 306 } else { 307 execle("../test7", "test7", "0", (char *) 0, environ); 308 exit(1); /* the impossible never happens, right? */ 309 } 310 311 /* Finally, close all the files. */ 312 if (fcntl(fd, F_SETFD, 0) != 0) e(44); /* FD_CLOEXEC off */ 313 if (fcntl(newfd2, F_SETFD, 0) != 0) e(45); /* FD_CLOEXEC off */ 314 if (close(fd) != 0) e(46); 315 if (close(newfd) != 0) e(47); 316 if (close(newfd2) != 0) e(48); 317 } 318 319 void test7d() 320 { 321 /* Test file locking. */ 322 323 subtest = 4; 324 325 if ( (xfd = creat("T7.d", 0777)) != 3) e(1); 326 close(xfd); 327 if ( (xfd = open("T7.d", O_RDWR)) < 0) e(2); 328 if (write(xfd, buf, ITEMS) != ITEMS) e(3); 329 if (set(WRITE, 0, 3) != 0) e(4); 330 if (set(WRITE, 5, 9) != 0) e(5); 331 if (set(UNLOCK, 0, 3) != 0) e(6); 332 if (set(UNLOCK, 4, 9) != 0) e(7); 333 334 if (set(READ, 1, 4) != 0) e(8); 335 if (set(READ, 4, 7) != 0) e(9); 336 if (set(UNLOCK, 4, 7) != 0) e(10); 337 if (set(UNLOCK, 1, 4) != 0) e(11); 338 339 if (set(WRITE, 0, 3) != 0) e(12); 340 if (set(WRITE, 5, 7) != 0) e(13); 341 if (set(WRITE, 9 ,10) != 0) e(14); 342 if (set(UNLOCK, 0, 4) != 0) e(15); 343 if (set(UNLOCK, 0, 7) != 0) e(16); 344 if (set(UNLOCK, 0, 2000) != 0) e(17); 345 346 if (set(WRITE, 0, 3) != 0) e(18); 347 if (set(WRITE, 5, 7) != 0) e(19); 348 if (set(WRITE, 9 ,10) != 0) e(20); 349 if (set(UNLOCK, 0, 100) != 0) e(21); 350 351 if (set(WRITE, 0, 9) != 0) e(22); 352 if (set(UNLOCK, 8, 9) != 0) e(23); 353 if (set(UNLOCK, 0, 2) != 0) e(24); 354 if (set(UNLOCK, 5, 5) != 0) e(25); 355 if (set(UNLOCK, 4, 6) != 0) e(26); 356 if (set(UNLOCK, 3, 3) != 0) e(27); 357 if (set(UNLOCK, 7, 7) != 0) e(28); 358 359 if (set(WRITE, 0, 10) != 0) e(29); 360 if (set(UNLOCK, 0, 1000) != 0) e(30); 361 362 /* Up until now, all locks have been disjoint. Now try conflicts. */ 363 if (set(WRITE, 0, 4) != 0) e(31); 364 if (set(WRITE, 4, 7) != 0) e(32); /* owner may lock same byte twice */ 365 if (set(WRITE, 5, 10) != 0) e(33); 366 if (set(UNLOCK, 0, 11) != 0) e(34); 367 368 /* File is now unlocked. Length 0 means whole file. */ 369 if (set(WRITE, 2, 1) != 0) e(35); /* this locks whole file */ 370 if (set(WRITE, 9,10) != 0) e(36); /* a process can relock its file */ 371 if (set(WRITE, 3, 3) != 0) e(37); 372 if (set(UNLOCK, 0, -1) != 0) e(38); /* file is now unlocked. */ 373 374 /* Test F_GETLK. */ 375 if (set(WRITE, 2, 3) != 0) e(39); 376 if (locked(1) != U) e(40); 377 if (locked(2) != L) e(41); 378 if (locked(3) != L) e(42); 379 if (locked(4) != U) e(43); 380 if (set(UNLOCK, 2, 3) != 0) e(44); 381 if (locked(2) != U) e(45); 382 if (locked(3) != U) e(46); 383 384 close(xfd); 385 } 386 387 void test7e() 388 { 389 /* Test to see if SETLKW blocks as it should. */ 390 391 int pid, s; 392 393 subtest = 5; 394 395 if ( (xfd = creat("T7.e", 0777)) != 3) e(1); 396 if (close(xfd) != 0) e(2); 397 if ( (xfd = open("T7.e", O_RDWR)) < 0) e(3); 398 if (write(xfd, buf, ITEMS) != ITEMS) e(4); 399 if (set(WRITE, 0, 3) != 0) e(5); 400 401 if ( (pid = fork()) ) { 402 /* Parent waits until child has started before signaling it. */ 403 while (access("T7.e1", 0) != 0) ; 404 unlink("T7.e1"); 405 sleep(1); 406 if (kill(pid, SIGKILL) < 0) e(6); 407 if (wait(&s) != pid) e(7); 408 } else { 409 /* Child tries to lock and should block. */ 410 if (creat("T7.e1", 0777) < 0) e(8); 411 func_code = F_SETLKW; 412 if (set(WRITE, 0, 3) != 0) e(9); /* should block */ 413 errno = -1000; 414 e(10); /* process should be killed by signal */ 415 exit(0); /* should never happen */ 416 } 417 close(xfd); 418 } 419 420 void test7f() 421 { 422 /* Test to see if SETLKW gives EINTR when interrupted. */ 423 424 int pid, s; 425 426 subtest = 6; 427 428 if ( (xfd = creat("T7.f", 0777)) != 3) e(1); 429 if (close(xfd) != 0) e(2); 430 if ( (xfd = open("T7.f", O_RDWR)) < 0) e(3); 431 if (write(xfd, buf, ITEMS) != ITEMS) e(4); 432 if (set(WRITE, 0, 3) != 0) e(5); 433 434 if ( (pid = fork()) ) { 435 /* Parent waits until child has started before signaling it. */ 436 while (access("T7.f1", 0) != 0) ; 437 unlink("T7.f1"); 438 sleep(1); 439 if (kill(pid, SIGTERM) < 0) e(6); 440 if (wait(&s) != pid) e(7); 441 if ( (s>>8) != 19) e(8); 442 } else { 443 /* Child tries to lock and should block. 444 * `signal(SIGTERM, sigfunc);' to set the signal handler is inadequate 445 * because on systems like BSD the sigaction flags for signal include 446 * `SA_RESTART' so syscalls are restarted after they have been 447 * interrupted by a signal. 448 */ 449 struct sigaction sa, osa; 450 451 sa.sa_handler = sigfunc; 452 sigemptyset(&sa.sa_mask); 453 sa.sa_flags = 0; 454 if (sigaction(SIGTERM, &sa, &osa) < 0) e(999); 455 if (creat("T7.f1", 0777) < 0) e(9); 456 func_code = F_SETLKW; 457 if (set(WRITE, 0, 3) != -1) e(10); /* should block */ 458 if (errno != EINTR) e(11); /* signal should release it */ 459 exit(19); 460 } 461 close(xfd); 462 } 463 464 void test7g() 465 { 466 /* Test to see if SETLKW unlocks when the needed lock becomes available. */ 467 468 int pid, s; 469 470 subtest = 7; 471 472 if ( (xfd = creat("T7.g", 0777)) != 3) e(1); 473 if (close(xfd) != 0) e(2); 474 if ( (xfd = open("T7.g", O_RDWR)) < 0) e(3); 475 if (write(xfd, buf, ITEMS) != ITEMS) e(4); 476 if (set(WRITE, 0, 3) != 0) e(5); /* bytes 0 to 3 are now locked */ 477 478 if ( (pid = fork()) ) { 479 /* Parent waits for child to start. */ 480 while (access("T7.g1", 0) != 0) ; 481 unlink("T7.g1"); 482 sleep(1); 483 if (set(UNLOCK, 0, 3) != 0) e(5); 484 if (wait(&s) != pid) e(6); 485 if ( (s >> 8) != 29) e(7); 486 } else { 487 /* Child tells parent it is alive, then tries to lock and is blocked.*/ 488 func_code = F_SETLKW; 489 if (creat("T7.g1", 0777) < 0) e(8); 490 if (set(WRITE, 3, 3) != 0) e(9); /* process must block now */ 491 if (set(UNLOCK, 3, 3) != 0) e(10); 492 exit(29); 493 } 494 close(xfd); 495 } 496 497 void test7h() 498 { 499 /* Test to see what happens if two processed block on the same lock. */ 500 501 int pid, pid2, s, w; 502 503 subtest = 8; 504 505 if ( (xfd = creat("T7.h", 0777)) != 3) e(1); 506 if (close(xfd) != 0) e(2); 507 if ( (xfd = open("T7.h", O_RDWR)) < 0) e(3); 508 if (write(xfd, buf, ITEMS) != ITEMS) e(4); 509 if (set(WRITE, 0, 3) != 0) e(5); /* bytes 0 to 3 are now locked */ 510 511 if ( (pid = fork()) ) { 512 if ( (pid2 = fork()) ) { 513 /* Parent waits for child to start. */ 514 while (access("T7.h1", 0) != 0) ; 515 while (access("T7.h2", 0) != 0) ; 516 unlink("T7.h1"); 517 unlink("T7.h2"); 518 sleep(1); 519 if (set(UNLOCK, 0, 3) != 0) e(6); 520 w = wait(&s); 521 if (w != pid && w != pid2) e(7); 522 s = s >> 8; 523 if (s != 39 && s != 49) e(8); 524 w = wait(&s); 525 if (w != pid && w != pid2) e(9); 526 s = s >> 8; 527 if (s != 39 && s != 49) e(10); 528 } else { 529 func_code = F_SETLKW; 530 if (creat("T7.h1", 0777) < 0) e(11); 531 if (set(WRITE, 0, 0) != 0) e(12); /* block now */ 532 if (set(UNLOCK, 0, 0) != 0) e(13); 533 exit(39); 534 } 535 } else { 536 /* Child tells parent it is alive, then tries to lock and is blocked.*/ 537 func_code = F_SETLKW; 538 if (creat("T7.h2", 0777) < 0) e(14); 539 if (set(WRITE, 0, 1) != 0) e(15); /* process must block now */ 540 if (set(UNLOCK, 0, 1) != 0) e(16); 541 exit(49); 542 } 543 close(xfd); 544 } 545 546 void test7i() 547 { 548 /* Check error conditions for fcntl(). */ 549 550 int tfd, i; 551 552 subtest = 9; 553 554 errno = 0; 555 if ( (xfd = creat("T7.i", 0777)) != 3) e(1); 556 if (close(xfd) != 0) e(2); 557 if ( (xfd = open("T7.i", O_RDWR)) < 0) e(3); 558 if (write(xfd, buf, ITEMS) != ITEMS) e(4); 559 if (set(WRITE, 0, 3) != 0) e(5); /* bytes 0 to 3 are now locked */ 560 if (set(WRITE, 0, 0) != 0) e(6); 561 if (errno != 0) e(7); 562 errno = 0; 563 if (set(WRITE, 3, 3) != 0) e(8); 564 if (errno != 0) e(9); 565 tfd = xfd; /* hold good value */ 566 xfd = -99; 567 errno = 0; 568 if (set(WRITE, 0, 0) != -1) e(10); 569 if (errno != EBADF) e(11); 570 571 errno = 0; 572 if ( (xfd = open("T7.i", O_WRONLY)) < 0) e(12); 573 if (set(READ, 0, 0) != -1) e(13); 574 if (errno != EBADF) e(14); 575 if (close(xfd) != 0) e(15); 576 577 errno = 0; 578 if ( (xfd = open("T7.i", O_RDONLY)) < 0) e(16); 579 if (set(WRITE, 0, 0) != -1) e(17); 580 if (errno != EBADF) e(18); 581 if (close(xfd) != 0) e(19); 582 xfd = tfd; /* restore legal xfd value */ 583 584 /* Check for EINVAL. */ 585 errno = 0; 586 if (fcntl(xfd, F_DUPFD, OPEN_MAX) != -1) e(20); 587 if (errno != EINVAL) e(21); 588 errno = 0; 589 if (fcntl(xfd, F_DUPFD, -1) != -1) e(22); 590 if (errno != EINVAL) e(23); 591 592 xfd = 0; /* stdin does not support locking */ 593 errno = 0; 594 if (set(READ, 0, 0) != -1) e(24); 595 if (errno != EINVAL) e(25); 596 xfd = tfd; 597 598 /* Check ENOLCK. */ 599 for (i = 0; i < ITEMS; i++) { 600 if (set(WRITE, i, i) == 0) continue; 601 if (errno != ENOLCK) { 602 e(26); 603 break; 604 } 605 } 606 607 /* Check EMFILE. */ 608 for (i = xfd + 1; i < OPEN_MAX; i++) open("T7.i", 0); /* use up all fds */ 609 errno = 0; 610 if (fcntl(xfd, F_DUPFD, 0) != -1) e(27); /* No fds left */ 611 if (errno != EMFILE) e(28); 612 613 for (i = xfd; i < OPEN_MAX; i++) if (close(i) != 0) e(29); 614 } 615 616 void test7j() 617 { 618 /* Test file locking with two processes. */ 619 620 int s; 621 622 subtest = 10; 623 624 if ( (xfd = creat("T7.j", 0777)) != 3) e(1); 625 close(xfd); 626 if ( (xfd = open("T7.j", O_RDWR)) < 0) e(2); 627 if (write(xfd, buf, ITEMS) != ITEMS) e(3); 628 if (set(WRITE, 0, 4) != 0) e(4); /* lock belongs to parent */ 629 if (set(READ, 10, 16) != 0) e(5); /* lock belongs to parent */ 630 631 /* Up until now, all locks have been disjoint. Now try conflicts. */ 632 if (fork()) { 633 /* Parent just waits for child to finish. */ 634 wait(&s); 635 } else { 636 /* Child does the testing. */ 637 errno = -100; 638 if (set(WRITE, 5, 7) < 0) e(6); /* should work */ 639 if (set(WRITE, 4, 7) >= 0) e(7); /* child may not lock byte 4 */ 640 if (errno != EACCES && errno != EAGAIN) e(8); 641 if (set(WRITE, 5, 9) != 0) e(9); 642 if (set(UNLOCK, 5, 9) != 0) e(10); 643 if (set(READ, 9, 17) < 0) e(11); /* shared READ lock is ok */ 644 exit(0); 645 } 646 close(xfd); 647 } 648 649 void cloexec_test() 650 { 651 /* To text whether the FD_CLOEXEC flag actually causes files to be 652 * closed upon exec, we have to exec something. The test is carried 653 * out by forking, and then having the child exec test7 itself, but 654 * with argument 0. This is detected, and control comes here. 655 * File descriptors 3, 10, and 12 should be closed here, and 6 and 15 open. 656 */ 657 658 if (close(3) == 0) e(1001); /* close should fail; it was closed on exec */ 659 if (close(6) != 0) e(1002); /* close should succeed */ 660 if (close(10) == 0) e(1003); /* close should fail */ 661 if (close(12) == 0) e(1004); /* close should fail */ 662 if (close(15) != 0) e(1005); /* close should succeed */ 663 fflush(stdout); 664 exit(0); 665 } 666 667 int set(how, first, last) 668 int how, first, last; 669 { 670 int r; 671 struct flock flock; 672 673 if (how == READ) flock.l_type = F_RDLCK; 674 if (how == WRITE) flock.l_type = F_WRLCK; 675 if (how == UNLOCK) flock.l_type = F_UNLCK; 676 flock.l_whence = whence; 677 flock.l_start = (long) first; 678 flock.l_len = (long) last - (long) first + 1; 679 r = fcntl(xfd, func_code, &flock); 680 if (r != -1) 681 return(0); 682 else 683 return(-1); 684 } 685 686 int locked(b) 687 int b; 688 /* Test to see if byte b is locked. Return L or U */ 689 { 690 struct flock flock; 691 pid_t pid; 692 int status; 693 694 flock.l_type = F_WRLCK; 695 flock.l_whence = whence; 696 flock.l_start = (long) b; 697 flock.l_len = 1; 698 699 /* Process' own locks are invisible to F_GETLK, so fork a child to test. */ 700 pid = fork(); 701 if (pid == 0) { 702 if (fcntl(xfd, F_GETLK, &flock) != 0) e(2000); 703 exit(flock.l_type == F_UNLCK ? U : L); 704 } 705 if (pid == -1) e(2001); 706 if (fcntl(xfd, F_GETLK, &flock) != 0) e(2002); 707 if (flock.l_type != F_UNLCK) e(2003); 708 if (wait(&status) != pid) e(2004); 709 if (!WIFEXITED(status)) e(2005); 710 return(WEXITSTATUS(status)); 711 } 712 713 void sigfunc(s) 714 int s; /* for ANSI */ 715 { 716 } 717 718