1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /* 21 * NAME 22 * fcntl14.c 23 * 24 * DESCRIPTION 25 * File locking test cases for fcntl. In Linux, S_ENFMT is not implemented 26 * in the kernel. However all standard Unix kernels define S_ENFMT as 27 * S_ISGID. So this test defines S_ENFMT as S_ISGID. 28 * 29 * ALGORITHM 30 * Various test cases are used to lock a file opened without mandatory 31 * locking, with mandatory locking and mandatory locking with NOBLOCK 32 * 33 * USAGE 34 * fcntl14 35 * 36 * HISTORY 37 * 07/2001 Ported by Wayne Boyer 38 * 39 * RESTRICTIONS 40 * None 41 */ 42 #define _GNU_SOURCE 1 43 #include <fcntl.h> 44 #include <sys/types.h> 45 #include <sys/stat.h> 46 #include <signal.h> 47 #include <errno.h> 48 #include <sys/wait.h> 49 #include <inttypes.h> 50 #include "test.h" 51 52 #define SKIP 0x0c00 53 #if SKIP == F_RDLCK || SKIP== F_WRLCK 54 #error invalid value for SKIP, must be distinct from F_RDLCK and F_WRLCK 55 #endif 56 #ifndef S_ENFMT 57 #define S_ENFMT S_ISGID 58 #endif 59 60 /* NOBLOCK - immediate success */ 61 #define NOBLOCK 2 62 63 /* WILLBLOCK - blocks, then succeeds (parent must unlock records) */ 64 #define WILLBLOCK 3 65 66 #define TIME_OUT 60 67 68 typedef struct { 69 short a_type; 70 short a_whence; 71 long a_start; 72 long a_len; 73 short b_type; /* SKIP means suppress fcntl call */ 74 short b_whence; 75 long b_start; 76 long b_len; 77 short c_type; 78 int c_whence; 79 long c_start; 80 long c_len; 81 short c_flag; 82 } testcase; 83 84 static testcase testcases[] = { 85 /* Test cases: entire boundary */ 86 /* #1 Parent making a write lock on entire file */ 87 {F_WRLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L, 88 /* Child attempting a read lock on entire file */ 89 F_RDLCK, 0, 0L, 0L, WILLBLOCK}, 90 91 /* #2 Parent making a write lock on entire file */ 92 {F_WRLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L, 93 /* Child attempting a write lock on entire file */ 94 F_WRLCK, 0, 0L, 0L, WILLBLOCK}, 95 96 /* #3 Parent making a read lock on entire file */ 97 {F_RDLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L, 98 /* Child attempting a read lock on entire file */ 99 F_RDLCK, 0, 0L, 0L, NOBLOCK}, 100 101 /* #4 Parent making a read lock on entire file */ 102 {F_RDLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L, 103 /* Child attempting a write lock on entire file */ 104 F_WRLCK, 0, 0L, 0L, WILLBLOCK}, 105 106 /* Test case: start boundary */ 107 /* #5 Parent making a write lock on entire file */ 108 {F_WRLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L, 109 /* 110 * Child attempting a read lock from beginning of 111 * file for 5 bytes 112 */ 113 F_RDLCK, 0, 0L, 5L, WILLBLOCK}, 114 115 /* #6 Parent making a write lock on entire file */ 116 {F_WRLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L, 117 /* 118 * Child attempting a write lock from beginning of 119 * file for 5 bytes 120 */ 121 F_WRLCK, 0, 0L, 5L, WILLBLOCK}, 122 123 /* #7 Parent making a read lock on entire file */ 124 {F_RDLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L, 125 /* 126 * Child attempting a read lock from beginning of 127 * file for 5 bytes 128 */ 129 F_RDLCK, 0, 0L, 5L, NOBLOCK}, 130 131 /* #8 Parent making a read lock on entire file */ 132 {F_RDLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L, 133 /* 134 * Child attempting a write lock from beginning of 135 * file for 5 bytes 136 */ 137 F_WRLCK, 0, 0L, 5L, WILLBLOCK}, 138 139 /* Test cases: end boundary */ 140 /* #9 Parent making a write lock on entire file */ 141 {F_WRLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L, 142 /* Child attempting a read lock from byte 7 to end of file */ 143 F_RDLCK, 0, 7L, 0L, WILLBLOCK}, 144 145 /* #10 Parent making a write lock on entire file */ 146 {F_WRLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L, 147 /* Child attempting a write lock from byte 7 to end of file */ 148 F_WRLCK, 0, 7L, 0L, WILLBLOCK}, 149 150 /* #11 Parent making a read lock on entire file */ 151 {F_RDLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L, 152 /* Child attempting a read lock from byte 7 to end of file */ 153 F_RDLCK, 0, 7L, 0L, NOBLOCK}, 154 155 /* #12 Parent making a read lock on entire file */ 156 {F_RDLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L, 157 /* Child attempting a write lock from byte 7 to end of file */ 158 F_WRLCK, 0, 7L, 0L, WILLBLOCK}, 159 160 /* Test cases: entire boundary ( less than entire file) */ 161 /* 162 * #13 Parent making a write lock from beginning of 163 * file for 5 bytes 164 */ 165 {F_WRLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L, 166 /* 167 * Child attempting a read lock from beginning of 168 * file for 5 bytes 169 */ 170 F_RDLCK, 0, 0L, 5L, WILLBLOCK}, 171 172 /* 173 * #14 Parent making a write lock from beginning of file 174 * for 5 bytes 175 */ 176 {F_WRLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L, 177 /* 178 * Child attempting a write lock from beginning of 179 * file for 5 bytes 180 */ 181 F_WRLCK, 0, 0L, 5L, WILLBLOCK}, 182 183 /* 184 * #15 Parent making a read lock from beginning of 185 * file for 5 bytes 186 */ 187 {F_RDLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L, 188 /* 189 * Child attempting a read lock from beginning of 190 * file for 5 bytes 191 */ 192 F_RDLCK, 0, 0L, 5L, NOBLOCK}, 193 194 /* 195 * #16 Parent making a read lock from beginning of 196 * file for 5 bytes 197 */ 198 {F_RDLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L, 199 /* 200 * Child attempting a write lock from beginning 201 * of file for 5 bytes 202 */ 203 F_WRLCK, 0, 0L, 5L, WILLBLOCK}, 204 205 /* Test cases: inside boundary */ 206 /* 207 * #17 Parent making a write lock from beginning 208 * of file for 5 bytes 209 */ 210 {F_WRLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L, 211 /* Child attempting a read lock from byte 2 to byte 4 */ 212 F_RDLCK, 0, 1L, 3L, WILLBLOCK}, 213 214 /* 215 * #18 Parent making a write lock from beginning of 216 * file for 5 bytes 217 */ 218 {F_WRLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L, 219 /* Child attempting a write lock from byte 2 to byte 4 */ 220 F_WRLCK, 0, 1L, 3L, WILLBLOCK}, 221 222 /* 223 * #19 Parent making a read lock from beginning of 224 * file for 5 bytes 225 */ 226 {F_RDLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L, 227 /* Child attempting a read lock from byte 2 to byte 4 */ 228 F_RDLCK, 0, 1L, 3L, NOBLOCK}, 229 230 /* 231 * #20 Parent making a read lock from beginning of 232 * file for 5 bytes 233 */ 234 {F_RDLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L, 235 /* Child attempting a write lock from byte 2 to byte 4 */ 236 F_WRLCK, 0, 1L, 3L, WILLBLOCK}, 237 238 /* Test cases: cross boundary (inside to after) */ 239 /* 240 * #21 Parent making a write lock from beginning of 241 * file for 5 bytes 242 */ 243 {F_WRLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L, 244 /* Child attempting a read lock from byte 3 to byte 7 */ 245 F_RDLCK, 0, 2L, 5L, WILLBLOCK}, 246 247 /* 248 * #22 Parent making a write lock from beginning 249 * of file for 5 bytes 250 */ 251 {F_WRLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L, 252 /* Child attempting a write lock from byte 3 to byte 7 */ 253 F_WRLCK, 0, 2L, 5L, WILLBLOCK}, 254 255 /* 256 * #23 Parent making a read lock from beginning of 257 * file for 5 bytes 258 */ 259 {F_RDLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L, 260 /* Child attempting a read lock from byte 3 to byte 7 */ 261 F_RDLCK, 0, 2L, 5L, NOBLOCK}, 262 263 /* 264 * #24 Parent making a read lock from beginning of 265 * file for 5 bytes 266 */ 267 {F_RDLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L, 268 /* Child attempting a write lock from byte 3 to byte 7 */ 269 F_WRLCK, 0, 2L, 5L, WILLBLOCK}, 270 271 /* Test cases: outside boundary (after) */ 272 273 /* 274 * #25 Parent making a write lock from beginning of 275 * file for 5 bytes 276 */ 277 {F_WRLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L, 278 /* Child attempting a read lock from byte 7 to end of file */ 279 F_RDLCK, 0, 6L, 0L, NOBLOCK}, 280 281 /* 282 * #26 Parent making a write lock from beginning of 283 * file for 5 bytes 284 */ 285 {F_WRLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L, 286 /* Child attempting a write lock from byte 7 to end of file */ 287 F_WRLCK, 0, 6L, 0L, NOBLOCK}, 288 289 /* 290 * #27 Parent making a read lock from beginning of 291 * file for 5 bytes 292 */ 293 {F_RDLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L, 294 /* Child attempting a read lock from byte 7 to end of file */ 295 F_RDLCK, 0, 6L, 0L, NOBLOCK}, 296 297 /* 298 * #28 Parent making a read lock from beginning of 299 * file for 5 bytes 300 */ 301 {F_RDLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L, 302 /* Child attempting a write lock from byte 7 to end of file */ 303 F_WRLCK, 0, 6L, 0L, NOBLOCK}, 304 305 /* Test cases: outside boundary (before) */ 306 307 /* #29 Parent making a write lock from byte 3 to byte 7 */ 308 {F_WRLCK, 0, 2L, 5L, SKIP, 0, 0L, 0L, 309 /* Child attempting a read lock from beginning of file to byte 2 */ 310 F_RDLCK, 0, 0L, 2L, NOBLOCK}, 311 312 /* #30 Parent making a write lock from byte 3 to byte 7 */ 313 {F_WRLCK, 0, 2L, 5L, SKIP, 0, 0L, 0L, 314 /* Child attempting a write lock from beginning of file to byte 2 */ 315 F_WRLCK, 0, 0L, 2L, NOBLOCK}, 316 317 /* #31 Parent making a write lock from byte 3 to byte 7 */ 318 {F_RDLCK, 0, 2L, 5L, SKIP, 0, 0L, 0L, 319 /* Child attempting a read lock from beginning of file to byte 2 */ 320 F_RDLCK, 0, 0L, 2L, NOBLOCK}, 321 322 /* #32 Parent making a write lock from byte 3 to byte 7 */ 323 {F_RDLCK, 0, 2L, 5L, SKIP, 0, 0L, 0L, 324 /* Child attempting a write lock from beginning of file to byte 2 */ 325 F_WRLCK, 0, 0L, 2L, NOBLOCK}, 326 327 /* Test cases: cross boundary (before to inside) */ 328 /* #33 Parent making a write lock from byte 5 to end of file */ 329 {F_WRLCK, 0, 4L, 0L, SKIP, 0, 0L, 0L, 330 /* Child attempting a read lock from byte 3 to byte 7 */ 331 F_RDLCK, 0, 2L, 5L, WILLBLOCK}, 332 333 /* #34 Parent making a write lock from byte 5 to end of file */ 334 {F_WRLCK, 0, 4L, 0L, SKIP, 0, 0L, 0L, 335 /* Child attempting a write lock from byte 3 to byte 7 */ 336 F_WRLCK, 0, 2L, 5L, WILLBLOCK}, 337 338 /* #35 Parent making a read lock from byte 5 to end of file */ 339 {F_RDLCK, 0, 4L, 0L, SKIP, 0, 0L, 0L, 340 /* Child attempting a read lock from byte 3 to byte 7 */ 341 F_RDLCK, 0, 2L, 5L, NOBLOCK}, 342 343 /* #36 Parent making a read lock from byte 5 to end of file */ 344 {F_RDLCK, 0, 4L, 0L, SKIP, 0, 0L, 0L, 345 /* Child attempting a write lock from byte 3 to byte 7 */ 346 F_WRLCK, 0, 2L, 5L, WILLBLOCK}, 347 348 /* Start of negative L_start and L_len test cases */ 349 /* 350 * #37 Parent making write lock from byte 2 to byte 3 351 * with L_start = -3 352 */ 353 {F_WRLCK, 1, -3L, 2L, SKIP, 0, 0L, 0L, 354 /* Child attempting write lock on byte 1 */ 355 F_WRLCK, 0, 1L, 1L, NOBLOCK}, 356 357 /* 358 * #38 Parent making write lock from byte 2 to byte 3 359 * with L_start = -3 360 */ 361 {F_WRLCK, 1, -3L, 2L, SKIP, 0, 0L, 0L, 362 /* Child attempting write lock on byte 4 */ 363 F_WRLCK, 0, 4L, 1L, NOBLOCK}, 364 365 /* 366 * #39 Parent making write lock from byte 2 to byte 3 367 * with L_start = -3 368 */ 369 {F_WRLCK, 1, -3L, 2L, SKIP, 0, 0L, 0L, 370 /* Child attempting write lock on byte 2 */ 371 F_WRLCK, 0, 2L, 1L, WILLBLOCK}, 372 373 /* 374 * #40 Parent making write lock from byte 2 to byte 3 375 * with L_start = -3 376 */ 377 {F_WRLCK, 1, -3L, 2L, SKIP, 0, 0L, 0L, 378 /* Child attempting write lock on byte 3 */ 379 F_WRLCK, 0, 3L, 1L, WILLBLOCK}, 380 381 /* 382 * #41 Parent making write lock from byte 2 to byte 6 383 * with L_start = -3 384 */ 385 {F_WRLCK, 1, -3L, 5L, SKIP, 0, 0L, 0L, 386 /* Child attempting write lock on byte 1 */ 387 F_WRLCK, 0, 1L, 1L, NOBLOCK}, 388 389 /* 390 * #42 Parent making write lock from byte 2 to byte 6 391 * with L_start = -3 392 */ 393 {F_WRLCK, 1, -3L, 5L, SKIP, 0, 0L, 0L, 394 /* Child attempting write lock on byte 7 */ 395 F_WRLCK, 0, 1L, 1L, NOBLOCK}, 396 397 /* 398 * #43 Parent making write lock from byte 2 to byte 6 399 * with L_start = -3 400 */ 401 {F_WRLCK, 1, -3L, 5L, SKIP, 0, 0L, 0L, 402 /* Child attempting write lock on byte 2 */ 403 F_WRLCK, 0, 2L, 1L, WILLBLOCK}, 404 405 /* 406 * #44 Parent making write lock from byte 2 to byte 6 407 * with L_start = -3 408 */ 409 {F_WRLCK, 1, -3L, 5L, SKIP, 0, 0L, 0L, 410 /* Child attempting write lock on byte 5 */ 411 F_WRLCK, 0, 5L, 1L, WILLBLOCK}, 412 413 /* 414 * #45 Parent making write lock from byte 2 to byte 6 415 * with L_start = -3 416 */ 417 {F_WRLCK, 1, -3L, 5L, SKIP, 0, 0L, 0L, 418 /* Child attempting write lock on byte 6 */ 419 F_WRLCK, 0, 6L, 1L, WILLBLOCK}, 420 421 /* 422 * #46 Parent making write lock from byte 2 to byte 3 with 423 * L_start = -2 and L_len = -2 424 */ 425 {F_WRLCK, 1, 2L, -2L, SKIP, 0, 0L, 0L, 426 /* Child attempting write lock on byte 1 */ 427 F_WRLCK, 0, 1L, 1L, NOBLOCK}, 428 429 /* 430 * #47 Parent making write lock from byte 2 to byte 3 with 431 * L_start = -2 and L_len = -2 432 */ 433 {F_WRLCK, 1, -2L, -2L, SKIP, 0, 0L, 0L, 434 /* Child attempting write lock on byte 4 */ 435 F_WRLCK, 0, 4L, 1L, NOBLOCK}, 436 437 /* 438 * #48 Parent making write lock from byte 2 to byte 3 with 439 * L_start = -2 and L_len = -2 440 */ 441 {F_WRLCK, 1, -2L, -2L, SKIP, 0, 0L, 0L, 442 /* Child attempting write lock on byte 2 */ 443 F_WRLCK, 0, 2L, 1L, WILLBLOCK}, 444 445 /* 446 * #49 Parent making write lock from byte 2 to byte 3 with 447 * L_start = -2 and L_len = -2 448 */ 449 {F_WRLCK, 1, -2L, -2L, SKIP, 0, 0L, 0L, 450 /* Child attempting write lock on byte 3 */ 451 F_WRLCK, 0, 3L, 1L, WILLBLOCK}, 452 453 /* 454 * #50 Parent making write lock from byte 6 to byte 7 with 455 * L_start = 2 and L_len = -2 456 */ 457 {F_WRLCK, 1, 2L, -2L, SKIP, 0, 0L, 0L, 458 /* Child attempting write lock on byte 5 */ 459 F_WRLCK, 0, 5L, 1L, NOBLOCK}, 460 461 /* 462 * #51 Parent making write lock from byte 6 to byte 7 with 463 * L_start = 2 and L_len = -2 464 */ 465 {F_WRLCK, 1, 2L, -2L, SKIP, 0, 0L, 0L, 466 /* Child attempting write lock on byte 8 */ 467 F_WRLCK, 0, 8L, 1L, NOBLOCK}, 468 469 /* 470 * #52 Parent making write lock from byte 6 to byte 7 with 471 * L_start = 2 and L_len = -2 472 */ 473 {F_WRLCK, 1, 2L, -2L, SKIP, 0, 0L, 0L, 474 /* Child attempting write lock on byte 6 */ 475 F_WRLCK, 0, 6L, 1L, WILLBLOCK}, 476 477 /* 478 * #53 Parent making write lock from byte 6 to byte 7 with 479 * L_start = 2 and L_len = -2 480 */ 481 {F_WRLCK, 1, 2L, -2L, SKIP, 0, 0L, 0L, 482 /* Child attempting write lock on byte 7 */ 483 F_WRLCK, 0, 7L, 1L, WILLBLOCK}, 484 485 /* 486 * #54 Parent making write lock from byte 3 to byte 7 with 487 * L_start = 2 and L_len = -5 488 */ 489 {F_WRLCK, 1, 2L, -5L, SKIP, 0, 0L, 0L, 490 /* Child attempting write lock on byte 2 */ 491 F_WRLCK, 0, 2L, 1L, NOBLOCK}, 492 493 /* 494 * #55 Parent making write lock from byte 3 to byte 7 with 495 * L_start = 2 and L_len = -5 496 */ 497 {F_WRLCK, 1, 2L, -5L, SKIP, 0, 0L, 0L, 498 /* Child attempting write lock on byte 8 */ 499 F_WRLCK, 0, 8L, 1L, NOBLOCK}, 500 501 /* 502 * #56 Parent making write lock from byte 3 to byte 7 with 503 * L_start = 2 and L_len = -5 504 */ 505 {F_WRLCK, 1, 2L, -5L, SKIP, 0, 0L, 0L, 506 /* Child attempting write lock on byte 3 */ 507 F_WRLCK, 0, 3L, 1L, WILLBLOCK}, 508 509 /* 510 * #57 Parent making write lock from byte 3 to byte 7 with 511 * L_start = 2 and L_len = -5 512 */ 513 {F_WRLCK, 1, 2L, -5L, SKIP, 0, 0L, 0L, 514 /* Child attempting write lock on byte 5 */ 515 F_WRLCK, 0, 5L, 1L, WILLBLOCK}, 516 517 /* 518 * #58 Parent making write lock from byte 3 to byte 7 with 519 * L_start = 2 and L_len = -5 520 */ 521 {F_WRLCK, 1, 2L, -5L, SKIP, 0, 0L, 0L, 522 /* Child attempting write lock on byte 7 */ 523 F_WRLCK, 0, 7L, 1L, WILLBLOCK}, 524 525 /* Test case for block 4 */ 526 /* #59 Parent making write lock on entire file */ 527 {F_WRLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L, 528 /* Child attempting write lock on byte 15 to end of file */ 529 F_WRLCK, 0, 15L, 0L, WILLBLOCK}, 530 }; 531 532 static testcase *thiscase; 533 static struct flock flock; 534 static int parent, child, status, fail = 0; 535 static int got1 = 0; 536 static int fd; 537 static int test; 538 static char tmpname[40]; 539 540 #define FILEDATA "ten bytes!" 541 542 void catch1(int sig); 543 void catch_alarm(int sig); 544 545 char *TCID = "fcntl14"; 546 int TST_TOTAL = 1; 547 int NO_NFS = 1; 548 549 #ifdef UCLINUX 550 static char *argv0; 551 #endif 552 553 void cleanup(void) 554 { 555 tst_rmdir(); 556 } 557 558 void setup(void) 559 { 560 struct sigaction act; 561 562 tst_sig(FORK, DEF_HANDLER, cleanup); 563 signal(SIGHUP, SIG_IGN); 564 umask(0); 565 TEST_PAUSE; 566 tst_tmpdir(); 567 parent = getpid(); 568 569 sprintf(tmpname, "fcntl2.%d", parent); 570 571 /* setup signal handler for signal from child */ 572 memset(&act, 0, sizeof(act)); 573 act.sa_handler = catch1; 574 sigemptyset(&act.sa_mask); 575 sigaddset(&act.sa_mask, SIGUSR1); 576 if ((sigaction(SIGUSR1, &act, NULL)) < 0) { 577 tst_resm(TFAIL, "SIGUSR1 signal setup failed, errno = %d", 578 errno); 579 cleanup(); 580 } 581 582 memset(&act, 0, sizeof(act)); 583 act.sa_handler = catch_alarm; 584 sigemptyset(&act.sa_mask); 585 sigaddset(&act.sa_mask, SIGALRM); 586 if ((sigaction(SIGALRM, &act, NULL)) < 0) { 587 tst_resm(TFAIL, "SIGALRM signal setup failed"); 588 cleanup(); 589 } 590 } 591 592 void wake_parent(void) 593 { 594 if ((kill(parent, SIGUSR1)) < 0) { 595 tst_resm(TFAIL, "Attempt to send signal to parent " "failed"); 596 tst_resm(TFAIL, "Test case %d, errno = %d", test + 1, errno); 597 fail = 1; 598 } 599 } 600 601 void do_usleep_child(void) 602 { 603 usleep(100000); /* XXX how long is long enough? */ 604 wake_parent(); 605 exit(0); 606 } 607 608 void dochild(void) 609 { 610 int rc; 611 pid_t pid; 612 613 flock.l_type = thiscase->c_type; 614 flock.l_whence = thiscase->c_whence; 615 flock.l_start = thiscase->c_start; 616 flock.l_len = thiscase->c_len; 617 flock.l_pid = 0; 618 fail = 0; 619 620 /* 621 * Check to see if child lock will succeed. If it will, FLOCK 622 * structure will return with l_type changed to F_UNLCK. If it will 623 * not, the parent pid will be returned in l_pid and the type of 624 * lock that will block it in l_type. 625 */ 626 if ((rc = fcntl(fd, F_GETLK, &flock)) < 0) { 627 tst_resm(TFAIL, "Attempt to check lock status failed"); 628 tst_resm(TFAIL, "Test case %d, errno = %d", test + 1, errno); 629 fail = 1; 630 } else { 631 632 if ((thiscase->c_flag) == NOBLOCK) { 633 if (flock.l_type != F_UNLCK) { 634 tst_resm(TFAIL, 635 "Test case %d, GETLK: type = %d, " 636 "%d was expected", test + 1, 637 flock.l_type, F_UNLCK); 638 fail = 1; 639 } 640 641 if (flock.l_whence != thiscase->c_whence) { 642 tst_resm(TFAIL, 643 "Test case %d, GETLK: whence = %d, " 644 "should have remained %d", test + 1, 645 flock.l_whence, thiscase->c_whence); 646 fail = 1; 647 } 648 649 if (flock.l_start != thiscase->c_start) { 650 tst_resm(TFAIL, 651 "Test case %d, GETLK: start = %" PRId64 652 ", " "should have remained %" PRId64, 653 test + 1, (int64_t) flock.l_start, 654 (int64_t) thiscase->c_start); 655 fail = 1; 656 } 657 658 if (flock.l_len != thiscase->c_len) { 659 tst_resm(TFAIL, 660 "Test case %d, GETLK: len = %" PRId64 661 ", " "should have remained %" PRId64, 662 test + 1, (int64_t) flock.l_len, 663 (int64_t) thiscase->c_len); 664 fail = 1; 665 } 666 667 if (flock.l_pid != 0) { 668 tst_resm(TFAIL, 669 "Test case %d, GETLK: pid = %d, " 670 "should have remained 0", test + 1, 671 flock.l_pid); 672 fail = 1; 673 } 674 } else { 675 if (flock.l_pid != parent) { 676 tst_resm(TFAIL, 677 "Test case %d, GETLK: pid = %d, " 678 "should be parent's id of %d", 679 test + 1, flock.l_pid, parent); 680 fail = 1; 681 } 682 683 if (flock.l_type != thiscase->a_type) { 684 tst_resm(TFAIL, 685 "Test case %d, GETLK: type = %d, " 686 "should be parent's first lock type of %d", 687 test + 1, flock.l_type, 688 thiscase->a_type); 689 fail = 1; 690 } 691 } 692 } 693 694 /* 695 * now try to set the lock, nonblocking 696 * This will succeed for NOBLOCK, 697 * fail for WILLBLOCK 698 */ 699 flock.l_type = thiscase->c_type; 700 flock.l_whence = thiscase->c_whence; 701 flock.l_start = thiscase->c_start; 702 flock.l_len = thiscase->c_len; 703 flock.l_pid = 0; 704 705 if ((rc = fcntl(fd, F_SETLK, &flock)) < 0) { 706 if ((thiscase->c_flag) == NOBLOCK) { 707 tst_resm(TFAIL, "Attempt to set child NONBLOCKING " 708 "lock failed"); 709 tst_resm(TFAIL, "Test case %d, errno = %d", 710 test + 1, errno); 711 fail = 1; 712 } 713 } 714 715 if ((thiscase->c_flag) == WILLBLOCK) { 716 if (rc != -1 || (errno != EACCES && errno != EAGAIN)) { 717 tst_resm(TFAIL, 718 "SETLK: rc = %d, errno = %d, -1/EAGAIN or EACCES " 719 "was expected", rc, errno); 720 fail = 1; 721 } 722 if (rc == 0) { 723 /* accidentally got the lock */ 724 /* XXX how to clean up? */ 725 (void)fcntl(fd, F_UNLCK, &flock); 726 } 727 /* 728 * Lock should succeed after blocking and parent releases 729 * lock, tell the parent to release the locks. 730 * Do the lock in this process, send the signal in a child 731 * process, so that the SETLKW actually uses the blocking 732 * mechanism in the kernel. 733 * 734 * XXX inherent race: we want to wait until the 735 * F_SETLKW has started, but we don't have a way to 736 * check that reliably in the child. (We'd 737 * need some way to have fcntl() atomically unblock a 738 * signal and wait for the lock.) 739 */ 740 pid = FORK_OR_VFORK(); 741 switch (pid) { 742 case -1: 743 tst_resm(TFAIL, "Fork failed"); 744 fail = 1; 745 break; 746 case 0: 747 #ifdef UCLINUX 748 if (self_exec(argv0, "nd", 1, parent) < 0) { 749 tst_resm(TFAIL, "self_exec failed"); 750 break; 751 } 752 #else 753 do_usleep_child(); 754 #endif 755 break; 756 757 default: 758 if ((rc = fcntl(fd, F_SETLKW, &flock)) < 0) { 759 tst_resm(TFAIL, "Attempt to set child BLOCKING " 760 "lock failed"); 761 tst_resm(TFAIL, "Test case %d, errno = %d", 762 test + 1, errno); 763 fail = 1; 764 } 765 waitpid(pid, &status, 0); 766 break; 767 } 768 } 769 if (fail) { 770 exit(1); 771 } else { 772 exit(0); 773 } 774 } 775 776 void run_test(int file_flag, int file_mode, int seek, int start, int end) 777 { 778 extern long time(); 779 780 fail = 0; 781 782 for (test = start; test < end; test++) { 783 fd = open(tmpname, file_flag, file_mode); 784 if (fd < 0) 785 tst_brkm(TBROK, cleanup, "open() failed"); 786 787 if (write(fd, FILEDATA, 10) < 0) 788 tst_brkm(TBROK, cleanup, "write() failed"); 789 790 if (seek) { 791 if (lseek(fd, seek, 0) < 0) 792 tst_brkm(TBROK, cleanup, "lseek() failed"); 793 } 794 795 thiscase = &testcases[test]; 796 flock.l_type = thiscase->a_type; 797 flock.l_whence = thiscase->a_whence; 798 flock.l_start = thiscase->a_start; 799 flock.l_len = thiscase->a_len; 800 801 /* set the initial parent lock on the file */ 802 if ((fcntl(fd, F_SETLK, &flock)) < 0) { 803 tst_resm(TFAIL, "First parent lock failed"); 804 tst_resm(TFAIL, "Test case %d, errno = %d", 805 test + 1, errno); 806 fail = 1; 807 } 808 809 if ((thiscase->b_type) != SKIP) { 810 flock.l_type = thiscase->b_type; 811 flock.l_whence = thiscase->b_whence; 812 flock.l_start = thiscase->b_start; 813 flock.l_len = thiscase->b_len; 814 815 /* set the second parent lock */ 816 if ((fcntl(fd, F_SETLK, &flock)) < 0) { 817 tst_resm(TFAIL, "Second parent lock failed"); 818 tst_resm(TFAIL, "Test case %d, errno = %d", 819 test + 1, errno); 820 fail = 1; 821 } 822 } 823 if ((thiscase->c_type) == SKIP) { 824 close(fd); 825 tst_resm(TINFO, "skipping test %d", test + 1); 826 continue; 827 } 828 829 /* Mask SIG_USR1 before forking child, to avoid race */ 830 (void)sighold(SIGUSR1); 831 832 /* flush the stdout to avoid garbled output */ 833 fflush(stdout); 834 835 if ((child = FORK_OR_VFORK()) == 0) { 836 #ifdef UCLINUX 837 if (self_exec(argv0, "nddddddddd", 2, thiscase->c_type, 838 thiscase->c_whence, thiscase->c_start, 839 thiscase->c_len, thiscase->c_flag, 840 thiscase->a_type, fd, test, parent) < 0) { 841 tst_resm(TFAIL, "self_exec failed"); 842 cleanup(); 843 } 844 #else 845 dochild(); 846 #endif 847 } 848 if (child < 0) 849 tst_brkm(TBROK|TERRNO, cleanup, "Fork failed"); 850 851 if ((thiscase->c_flag) == WILLBLOCK) { 852 /* 853 * Wait for a signal from the child then remove 854 * blocking lock. Set a 60 second alarm to break the 855 * pause just in case the child never signals us. 856 */ 857 alarm(TIME_OUT); 858 sigpause(SIGUSR1); 859 860 /* turn off the alarm timer */ 861 alarm((unsigned)0); 862 if (got1 != 1) 863 tst_resm(TINFO, "Pause terminated without " 864 "signal SIGUSR1 from child"); 865 got1 = 0; 866 867 /* 868 * setup lock structure for parent to delete 869 * blocking lock then wait for child to exit 870 */ 871 flock.l_type = F_UNLCK; 872 flock.l_whence = 0; 873 flock.l_start = 0L; 874 flock.l_len = 0L; 875 if ((fcntl(fd, F_SETLK, &flock)) < 0) { 876 tst_resm(TFAIL, "Attempt to release parent " 877 "lock failed"); 878 tst_resm(TFAIL, "Test case %d, errno = %d", 879 test + 1, errno); 880 fail = 1; 881 } 882 } 883 /* 884 * set a 60 second alarm to break the wait just in case the 885 * child doesn't terminate on its own accord 886 */ 887 alarm(TIME_OUT); 888 889 /* wait for the child to terminate and close the file */ 890 waitpid(child, &status, 0); 891 /* turn off the alarm clock */ 892 alarm((unsigned)0); 893 if (status != 0) { 894 tst_resm(TFAIL, "tchild returned status 0x%x", status); 895 fail = 1; 896 } 897 close(fd); 898 if (fail) 899 tst_resm(TFAIL, "testcase:%d FAILED", test + 1); 900 else 901 tst_resm(TPASS, "testcase:%d PASSED", test + 1); 902 } 903 unlink(tmpname); 904 } 905 906 void catch_alarm(int sig) 907 { 908 /* 909 * Timer has runout and child has not signaled, need 910 * to kill off the child as it appears it will not 911 * on its own accord. Check that it is still around 912 * as it may have terminated abnormally while parent 913 * was waiting for SIGUSR1 signal from it. 914 */ 915 if (kill(child, 0) == 0) { 916 kill(child, SIGKILL); 917 perror("The child didnot terminate on its own accord"); 918 } 919 } 920 921 void catch1(int sig) 922 { 923 struct sigaction act; 924 925 /* 926 * Set flag to let parent know that child is ready to have lock 927 * removed 928 */ 929 memset(&act, 0, sizeof(act)); 930 act.sa_handler = catch1; 931 sigemptyset(&act.sa_mask); 932 sigaddset(&act.sa_mask, SIGUSR1); 933 sigaction(SIGUSR1, &act, NULL); 934 got1++; 935 } 936 937 static void testcheck_end(int check_fail, char *msg) 938 { 939 if (check_fail) 940 tst_resm(TFAIL, "%s FAILED", msg); 941 else 942 tst_resm(TPASS, "%s PASSED", msg); 943 } 944 945 int main(int ac, char **av) 946 { 947 int lc; 948 949 tst_parse_opts(ac, av, NULL, NULL); 950 #ifdef UCLINUX 951 argv0 = av[0]; 952 953 maybe_run_child(&do_usleep_child, "nd", 1, &parent); 954 thiscase = malloc(sizeof(testcase)); 955 956 maybe_run_child(&dochild, "nddddddddd", 2, &thiscase->c_type, 957 &thiscase->c_whence, &thiscase->c_start, 958 &thiscase->c_len, &thiscase->c_flag, &thiscase->a_type, 959 &fd, &test, &parent); 960 #endif 961 962 setup(); 963 964 if (tst_fs_type(cleanup, ".") == TST_NFS_MAGIC) 965 NO_NFS = 0; 966 967 for (lc = 0; TEST_LOOPING(lc); lc++) { 968 tst_count = 0; 969 970 /* //block1: */ 971 tst_resm(TINFO, "Enter block 1: without mandatory locking"); 972 fail = 0; 973 /* 974 * try various file locks on an ordinary file without 975 * mandatory locking 976 */ 977 (void)run_test(O_CREAT | O_RDWR | O_TRUNC, 0777, 0, 0, 36); 978 testcheck_end(fail, "Block 1, test 1"); 979 980 /* Now try with negative values for L_start and L_len */ 981 (void)run_test(O_CREAT | O_RDWR | O_TRUNC, 0777, 5, 36, 45); 982 testcheck_end(fail, "Block 1, test 2"); 983 984 tst_resm(TINFO, "Exit block 1"); 985 986 /* //block2: */ 987 /* 988 * Skip block2 if test on NFS, since NFS does not support 989 * mandatory locking 990 */ 991 tst_resm(TINFO, "Enter block 2: with mandatory locking"); 992 if (NO_NFS) { 993 fail = 0; 994 /* 995 * Try various locks on a file with mandatory 996 * record locking this should behave the same 997 * as an ordinary file 998 */ 999 (void)run_test(O_CREAT | O_RDWR | O_TRUNC, 1000 S_ENFMT | S_IRUSR | S_IWUSR, 0, 0, 36); 1001 testcheck_end(fail, "Block 2, test 1"); 1002 1003 /* Now try negative values for L_start and L_len */ 1004 (void)run_test(O_CREAT | O_RDWR | O_TRUNC, 1005 S_ENFMT | S_IRUSR | S_IWUSR, 5, 36, 45); 1006 testcheck_end(fail, "Block 2, test 2"); 1007 } else { 1008 tst_resm(TCONF, "Skip block 2 as NFS does not" 1009 " support mandatory locking"); 1010 } 1011 1012 tst_resm(TINFO, "Exit block 2"); 1013 1014 /* //block3: */ 1015 tst_resm(TINFO, "Enter block 3"); 1016 fail = 0; 1017 /* 1018 * Check that proper error status is returned when invalid 1019 * argument used for WHENCE (negative value) 1020 */ 1021 1022 fd = open(tmpname, O_CREAT | O_RDWR | O_TRUNC, 0777); 1023 if (fd < 0) 1024 tst_brkm(TBROK, cleanup, "open failed"); 1025 1026 if (write(fd, FILEDATA, 10) < 0) 1027 tst_brkm(TBROK, cleanup, "write failed"); 1028 1029 flock.l_type = F_WRLCK; 1030 flock.l_whence = -1; 1031 flock.l_start = 0L; 1032 flock.l_len = 0L; 1033 1034 if ((fcntl(fd, F_SETLK, &flock)) < 0) { 1035 if (errno != EINVAL) { 1036 tst_resm(TFAIL, "Expected %d got %d", 1037 EINVAL, errno); 1038 fail = 1; 1039 } 1040 } else { 1041 tst_resm(TFAIL, "Lock succeeded when it should have " 1042 "failed"); 1043 fail = 1; 1044 } 1045 1046 close(fd); 1047 unlink(tmpname); 1048 1049 testcheck_end(fail, "Test with negative whence locking"); 1050 tst_resm(TINFO, "Exit block 3"); 1051 1052 /* //block4: */ 1053 tst_resm(TINFO, "Enter block 4"); 1054 fail = 0; 1055 /* 1056 * Check that a lock on end of file is still valid when 1057 * additional data is appended to end of file and a new 1058 * process attempts to lock new data 1059 */ 1060 fd = open(tmpname, O_CREAT | O_RDWR | O_TRUNC, 0777); 1061 if (fd < 0) 1062 tst_brkm(TBROK, cleanup, "open failed"); 1063 1064 if (write(fd, FILEDATA, 10) < 0) 1065 tst_brkm(TBROK, cleanup, "write failed"); 1066 1067 thiscase = &testcases[58]; 1068 flock.l_type = thiscase->a_type; 1069 flock.l_whence = thiscase->a_whence; 1070 flock.l_start = thiscase->a_start; 1071 flock.l_len = thiscase->a_len; 1072 1073 /* Set the initial parent lock on the file */ 1074 if ((fcntl(fd, F_SETLK, &flock)) < 0) { 1075 tst_resm(TFAIL, "First parent lock failed"); 1076 tst_resm(TFAIL, "Test case %d, errno = %d", 58, errno); 1077 fail = 1; 1078 } 1079 1080 /* Write some additional data to end of file */ 1081 if (write(fd, FILEDATA, 10) < 0) 1082 tst_brkm(TBROK, cleanup, "write failed"); 1083 1084 /* Mask signal to avoid race */ 1085 if (sighold(SIGUSR1) < 0) 1086 tst_brkm(TBROK, cleanup, "sighold failed"); 1087 1088 if ((child = FORK_OR_VFORK()) == 0) { 1089 #ifdef UCLINUX 1090 if (self_exec(argv0, "nddddddddd", 2, thiscase->c_type, 1091 thiscase->c_whence, thiscase->c_start, 1092 thiscase->c_len, thiscase->c_flag, 1093 thiscase->a_type, fd, test, parent) < 0) { 1094 tst_resm(TFAIL, "self_exec failed"); 1095 cleanup(); 1096 } 1097 #else 1098 dochild(); 1099 #endif 1100 } 1101 if (child < 0) 1102 tst_brkm(TBROK|TERRNO, cleanup, "Fork failed"); 1103 1104 /* 1105 * Wait for a signal from the child then remove blocking lock. 1106 * Set a 60 sec alarm to break the pause just in case the 1107 * child doesn't terminate on its own accord 1108 */ 1109 (void)alarm(TIME_OUT); 1110 1111 (void)sigpause(SIGUSR1); 1112 1113 /* turn off the alarm timer */ 1114 (void)alarm((unsigned)0); 1115 if (got1 != 1) { 1116 tst_resm(TINFO, "Pause terminated without signal " 1117 "SIGUSR1 from child"); 1118 } 1119 got1 = 0; 1120 1121 /* 1122 * Set up lock structure for parent to delete 1123 * blocking lock then wait for child to exit 1124 */ 1125 flock.l_type = F_UNLCK; 1126 flock.l_whence = 0; 1127 flock.l_start = 0L; 1128 flock.l_len = 0L; 1129 if ((fcntl(fd, F_SETLK, &flock)) < 0) { 1130 tst_resm(TFAIL, "Attempt to release parent lock " 1131 "failed"); 1132 tst_resm(TFAIL, "Test case %d, errno = %d", test + 1, 1133 errno); 1134 fail = 1; 1135 } 1136 1137 /* 1138 * set a 60 sec alarm to break the wait just in case the 1139 * child doesn't terminate on its own accord 1140 */ 1141 (void)alarm(TIME_OUT); 1142 1143 waitpid(child, &status, 0); 1144 if (WEXITSTATUS(status) != 0) { 1145 fail = 1; 1146 tst_resm(TFAIL, "child returned bad exit status"); 1147 } 1148 1149 /* turn off the alarm clock */ 1150 (void)alarm((unsigned)0); 1151 if (status != 0) { 1152 tst_resm(TFAIL, "child returned status 0x%x", status); 1153 fail = 1; 1154 } 1155 close(fd); 1156 unlink(tmpname); 1157 1158 testcheck_end(fail, "Test of locks on file"); 1159 tst_resm(TINFO, "Exit block 4"); 1160 } 1161 cleanup(); 1162 tst_exit(); 1163 } 1164