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 68typedef 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 84static 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 532static testcase *thiscase; 533static struct flock flock; 534static int parent, child, status, fail = 0; 535static int got1 = 0; 536static int fd; 537static int test; 538static char tmpname[40]; 539 540#define FILEDATA "ten bytes!" 541 542void catch1(int sig); 543void catch_alarm(int sig); 544 545char *TCID = "fcntl14"; 546int TST_TOTAL = 1; 547int NO_NFS = 1; 548 549#ifdef UCLINUX 550static char *argv0; 551#endif 552 553void cleanup(void) 554{ 555 tst_rmdir(); 556} 557 558void 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 592void 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 601void do_usleep_child(void) 602{ 603 usleep(100000); /* XXX how long is long enough? */ 604 wake_parent(); 605 exit(0); 606} 607 608void 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 776void run_test(int file_flag, int file_mode, int seek, int start, int end) 777{ 778 fail = 0; 779 780 for (test = start; test < end; test++) { 781 fd = open(tmpname, file_flag, file_mode); 782 if (fd < 0) 783 tst_brkm(TBROK, cleanup, "open() failed"); 784 785 if (write(fd, FILEDATA, 10) < 0) 786 tst_brkm(TBROK, cleanup, "write() failed"); 787 788 if (seek) { 789 if (lseek(fd, seek, 0) < 0) 790 tst_brkm(TBROK, cleanup, "lseek() failed"); 791 } 792 793 thiscase = &testcases[test]; 794 flock.l_type = thiscase->a_type; 795 flock.l_whence = thiscase->a_whence; 796 flock.l_start = thiscase->a_start; 797 flock.l_len = thiscase->a_len; 798 799 /* set the initial parent lock on the file */ 800 if ((fcntl(fd, F_SETLK, &flock)) < 0) { 801 tst_resm(TFAIL, "First parent lock failed"); 802 tst_resm(TFAIL, "Test case %d, errno = %d", 803 test + 1, errno); 804 fail = 1; 805 } 806 807 if ((thiscase->b_type) != SKIP) { 808 flock.l_type = thiscase->b_type; 809 flock.l_whence = thiscase->b_whence; 810 flock.l_start = thiscase->b_start; 811 flock.l_len = thiscase->b_len; 812 813 /* set the second parent lock */ 814 if ((fcntl(fd, F_SETLK, &flock)) < 0) { 815 tst_resm(TFAIL, "Second parent lock failed"); 816 tst_resm(TFAIL, "Test case %d, errno = %d", 817 test + 1, errno); 818 fail = 1; 819 } 820 } 821 if ((thiscase->c_type) == SKIP) { 822 close(fd); 823 tst_resm(TINFO, "skipping test %d", test + 1); 824 continue; 825 } 826 827 /* Mask SIG_USR1 before forking child, to avoid race */ 828 (void)sighold(SIGUSR1); 829 830 /* flush the stdout to avoid garbled output */ 831 fflush(stdout); 832 833 if ((child = FORK_OR_VFORK()) == 0) { 834#ifdef UCLINUX 835 if (self_exec(argv0, "nddddddddd", 2, thiscase->c_type, 836 thiscase->c_whence, thiscase->c_start, 837 thiscase->c_len, thiscase->c_flag, 838 thiscase->a_type, fd, test, parent) < 0) { 839 tst_resm(TFAIL, "self_exec failed"); 840 cleanup(); 841 } 842#else 843 dochild(); 844#endif 845 } 846 if (child < 0) 847 tst_brkm(TBROK|TERRNO, cleanup, "Fork failed"); 848 849 if ((thiscase->c_flag) == WILLBLOCK) { 850 /* 851 * Wait for a signal from the child then remove 852 * blocking lock. Set a 60 second alarm to break the 853 * pause just in case the child never signals us. 854 */ 855 alarm(TIME_OUT); 856 sigpause(SIGUSR1); 857 858 /* turn off the alarm timer */ 859 alarm((unsigned)0); 860 if (got1 != 1) 861 tst_resm(TINFO, "Pause terminated without " 862 "signal SIGUSR1 from child"); 863 got1 = 0; 864 865 /* 866 * setup lock structure for parent to delete 867 * blocking lock then wait for child to exit 868 */ 869 flock.l_type = F_UNLCK; 870 flock.l_whence = 0; 871 flock.l_start = 0L; 872 flock.l_len = 0L; 873 if ((fcntl(fd, F_SETLK, &flock)) < 0) { 874 tst_resm(TFAIL, "Attempt to release parent " 875 "lock failed"); 876 tst_resm(TFAIL, "Test case %d, errno = %d", 877 test + 1, errno); 878 fail = 1; 879 } 880 } 881 /* 882 * set a 60 second alarm to break the wait just in case the 883 * child doesn't terminate on its own accord 884 */ 885 alarm(TIME_OUT); 886 887 /* wait for the child to terminate and close the file */ 888 waitpid(child, &status, 0); 889 /* turn off the alarm clock */ 890 alarm((unsigned)0); 891 if (status != 0) { 892 tst_resm(TFAIL, "tchild returned status 0x%x", status); 893 fail = 1; 894 } 895 close(fd); 896 if (fail) 897 tst_resm(TFAIL, "testcase:%d FAILED", test + 1); 898 else 899 tst_resm(TPASS, "testcase:%d PASSED", test + 1); 900 } 901 unlink(tmpname); 902} 903 904void catch_alarm(int sig) 905{ 906 /* 907 * Timer has runout and child has not signaled, need 908 * to kill off the child as it appears it will not 909 * on its own accord. Check that it is still around 910 * as it may have terminated abnormally while parent 911 * was waiting for SIGUSR1 signal from it. 912 */ 913 if (kill(child, 0) == 0) { 914 kill(child, SIGKILL); 915 perror("The child didnot terminate on its own accord"); 916 } 917} 918 919void catch1(int sig) 920{ 921 struct sigaction act; 922 923 /* 924 * Set flag to let parent know that child is ready to have lock 925 * removed 926 */ 927 memset(&act, 0, sizeof(act)); 928 act.sa_handler = catch1; 929 sigemptyset(&act.sa_mask); 930 sigaddset(&act.sa_mask, SIGUSR1); 931 sigaction(SIGUSR1, &act, NULL); 932 got1++; 933} 934 935static void testcheck_end(int check_fail, char *msg) 936{ 937 if (check_fail) 938 tst_resm(TFAIL, "%s FAILED", msg); 939 else 940 tst_resm(TPASS, "%s PASSED", msg); 941} 942 943int main(int ac, char **av) 944{ 945 int lc; 946 947 tst_parse_opts(ac, av, NULL, NULL); 948#ifdef UCLINUX 949 argv0 = av[0]; 950 951 maybe_run_child(&do_usleep_child, "nd", 1, &parent); 952 thiscase = malloc(sizeof(testcase)); 953 954 maybe_run_child(&dochild, "nddddddddd", 2, &thiscase->c_type, 955 &thiscase->c_whence, &thiscase->c_start, 956 &thiscase->c_len, &thiscase->c_flag, &thiscase->a_type, 957 &fd, &test, &parent); 958#endif 959 960 setup(); 961 962 if (tst_fs_type(cleanup, ".") == TST_NFS_MAGIC) 963 NO_NFS = 0; 964 965 for (lc = 0; TEST_LOOPING(lc); lc++) { 966 tst_count = 0; 967 968/* //block1: */ 969 tst_resm(TINFO, "Enter block 1: without mandatory locking"); 970 fail = 0; 971 /* 972 * try various file locks on an ordinary file without 973 * mandatory locking 974 */ 975 (void)run_test(O_CREAT | O_RDWR | O_TRUNC, 0777, 0, 0, 36); 976 testcheck_end(fail, "Block 1, test 1"); 977 978 /* Now try with negative values for L_start and L_len */ 979 (void)run_test(O_CREAT | O_RDWR | O_TRUNC, 0777, 5, 36, 45); 980 testcheck_end(fail, "Block 1, test 2"); 981 982 tst_resm(TINFO, "Exit block 1"); 983 984/* //block2: */ 985 /* 986 * Skip block2 if test on NFS, since NFS does not support 987 * mandatory locking 988 */ 989 tst_resm(TINFO, "Enter block 2: with mandatory locking"); 990 if (NO_NFS) { 991 fail = 0; 992 /* 993 * Try various locks on a file with mandatory 994 * record locking this should behave the same 995 * as an ordinary file 996 */ 997 (void)run_test(O_CREAT | O_RDWR | O_TRUNC, 998 S_ENFMT | S_IRUSR | S_IWUSR, 0, 0, 36); 999 testcheck_end(fail, "Block 2, test 1"); 1000 1001 /* Now try negative values for L_start and L_len */ 1002 (void)run_test(O_CREAT | O_RDWR | O_TRUNC, 1003 S_ENFMT | S_IRUSR | S_IWUSR, 5, 36, 45); 1004 testcheck_end(fail, "Block 2, test 2"); 1005 } else { 1006 tst_resm(TCONF, "Skip block 2 as NFS does not" 1007 " support mandatory locking"); 1008 } 1009 1010 tst_resm(TINFO, "Exit block 2"); 1011 1012/* //block3: */ 1013 tst_resm(TINFO, "Enter block 3"); 1014 fail = 0; 1015 /* 1016 * Check that proper error status is returned when invalid 1017 * argument used for WHENCE (negative value) 1018 */ 1019 1020 fd = open(tmpname, O_CREAT | O_RDWR | O_TRUNC, 0777); 1021 if (fd < 0) 1022 tst_brkm(TBROK, cleanup, "open failed"); 1023 1024 if (write(fd, FILEDATA, 10) < 0) 1025 tst_brkm(TBROK, cleanup, "write failed"); 1026 1027 flock.l_type = F_WRLCK; 1028 flock.l_whence = -1; 1029 flock.l_start = 0L; 1030 flock.l_len = 0L; 1031 1032 if ((fcntl(fd, F_SETLK, &flock)) < 0) { 1033 if (errno != EINVAL) { 1034 tst_resm(TFAIL, "Expected %d got %d", 1035 EINVAL, errno); 1036 fail = 1; 1037 } 1038 } else { 1039 tst_resm(TFAIL, "Lock succeeded when it should have " 1040 "failed"); 1041 fail = 1; 1042 } 1043 1044 close(fd); 1045 unlink(tmpname); 1046 1047 testcheck_end(fail, "Test with negative whence locking"); 1048 tst_resm(TINFO, "Exit block 3"); 1049 1050/* //block4: */ 1051 tst_resm(TINFO, "Enter block 4"); 1052 fail = 0; 1053 /* 1054 * Check that a lock on end of file is still valid when 1055 * additional data is appended to end of file and a new 1056 * process attempts to lock new data 1057 */ 1058 fd = open(tmpname, O_CREAT | O_RDWR | O_TRUNC, 0777); 1059 if (fd < 0) 1060 tst_brkm(TBROK, cleanup, "open failed"); 1061 1062 if (write(fd, FILEDATA, 10) < 0) 1063 tst_brkm(TBROK, cleanup, "write failed"); 1064 1065 thiscase = &testcases[58]; 1066 flock.l_type = thiscase->a_type; 1067 flock.l_whence = thiscase->a_whence; 1068 flock.l_start = thiscase->a_start; 1069 flock.l_len = thiscase->a_len; 1070 1071 /* Set the initial parent lock on the file */ 1072 if ((fcntl(fd, F_SETLK, &flock)) < 0) { 1073 tst_resm(TFAIL, "First parent lock failed"); 1074 tst_resm(TFAIL, "Test case %d, errno = %d", 58, errno); 1075 fail = 1; 1076 } 1077 1078 /* Write some additional data to end of file */ 1079 if (write(fd, FILEDATA, 10) < 0) 1080 tst_brkm(TBROK, cleanup, "write failed"); 1081 1082 /* Mask signal to avoid race */ 1083 if (sighold(SIGUSR1) < 0) 1084 tst_brkm(TBROK, cleanup, "sighold failed"); 1085 1086 if ((child = FORK_OR_VFORK()) == 0) { 1087#ifdef UCLINUX 1088 if (self_exec(argv0, "nddddddddd", 2, thiscase->c_type, 1089 thiscase->c_whence, thiscase->c_start, 1090 thiscase->c_len, thiscase->c_flag, 1091 thiscase->a_type, fd, test, parent) < 0) { 1092 tst_resm(TFAIL, "self_exec failed"); 1093 cleanup(); 1094 } 1095#else 1096 dochild(); 1097#endif 1098 } 1099 if (child < 0) 1100 tst_brkm(TBROK|TERRNO, cleanup, "Fork failed"); 1101 1102 /* 1103 * Wait for a signal from the child then remove blocking lock. 1104 * Set a 60 sec alarm to break the pause just in case the 1105 * child doesn't terminate on its own accord 1106 */ 1107 (void)alarm(TIME_OUT); 1108 1109 (void)sigpause(SIGUSR1); 1110 1111 /* turn off the alarm timer */ 1112 (void)alarm((unsigned)0); 1113 if (got1 != 1) { 1114 tst_resm(TINFO, "Pause terminated without signal " 1115 "SIGUSR1 from child"); 1116 } 1117 got1 = 0; 1118 1119 /* 1120 * Set up lock structure for parent to delete 1121 * blocking lock then wait for child to exit 1122 */ 1123 flock.l_type = F_UNLCK; 1124 flock.l_whence = 0; 1125 flock.l_start = 0L; 1126 flock.l_len = 0L; 1127 if ((fcntl(fd, F_SETLK, &flock)) < 0) { 1128 tst_resm(TFAIL, "Attempt to release parent lock " 1129 "failed"); 1130 tst_resm(TFAIL, "Test case %d, errno = %d", test + 1, 1131 errno); 1132 fail = 1; 1133 } 1134 1135 /* 1136 * set a 60 sec alarm to break the wait just in case the 1137 * child doesn't terminate on its own accord 1138 */ 1139 (void)alarm(TIME_OUT); 1140 1141 waitpid(child, &status, 0); 1142 if (WEXITSTATUS(status) != 0) { 1143 fail = 1; 1144 tst_resm(TFAIL, "child returned bad exit status"); 1145 } 1146 1147 /* turn off the alarm clock */ 1148 (void)alarm((unsigned)0); 1149 if (status != 0) { 1150 tst_resm(TFAIL, "child returned status 0x%x", status); 1151 fail = 1; 1152 } 1153 close(fd); 1154 unlink(tmpname); 1155 1156 testcheck_end(fail, "Test of locks on file"); 1157 tst_resm(TINFO, "Exit block 4"); 1158 } 1159 cleanup(); 1160 tst_exit(); 1161} 1162