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