1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /* Lock operation C testcase */
  28 
  29 #include "nfsgen.h"
  30 
  31 #define READ_FAIL       1
  32 #define WRITE_FAIL      2
  33 
  34 /* Functions */
  35 int scenarioA(int mode, int oflag, int expect[]);
  36 int scenarioB(int mode, int oflag, int expect[]);
  37 int scenarioC(int mode, int oflag, int expect[]);
  38 
  39 /* Globals */
  40 
  41 static char     *filename = NULL;
  42 char            *buf = NULL;
  43 int             N = 100;                /* used for scenario C loops */
  44 
  45 /*
  46  * Main test loop.
  47  */
  48 
  49 int
  50 main(int argc, char **argv)
  51 {
  52         int             i, j;
  53         int             ret = OK;
  54         char            *deleg, *scen, *mode_index, *oflag_index;
  55         static int      mode_set[] = {0600, 0400, 0200, 000},
  56                         oflag_set[] = {O_EXCL|O_RDWR, O_RDWR, O_WRONLY,
  57                                         O_RDONLY};
  58         static int      expect[4][4][6] =
  59         {
  60         {       {OK,            OK,     OK,     OK,     EAGAIN, EAGAIN},
  61                 {OK,            OK,     OK,     OK,     EAGAIN, EAGAIN},
  62                 {OK,            OK,     EBADF,  OK,     EBADF,  EAGAIN},
  63                 {OK,            OK,     OK,     EBADF,  EAGAIN, EBADF}},
  64         {       {EACCES,        EBADF,  EBADF,  EBADF,  EBADF,  EBADF},
  65                 {EACCES,        EBADF,  EBADF,  EBADF,  EBADF,  EBADF},
  66                 {EACCES,        EBADF,  EBADF,  EBADF,  EBADF,  EBADF},
  67                 {OK,            OK,     OK,     EBADF,  EAGAIN, EBADF}},
  68         {       {EACCES,        EBADF,  EBADF,  EBADF,  EBADF,  EBADF},
  69                 {EACCES,        EBADF,  EBADF,  EBADF,  EBADF,  EBADF},
  70                 {OK,            OK,     EBADF,  OK,     EBADF,  EAGAIN},
  71                 {EACCES,        EBADF,  EBADF,  EBADF,  EBADF,  EBADF}},
  72         {       {EACCES,        EBADF,  EBADF,  EBADF,  EBADF,  EBADF},
  73                 {EACCES,        EBADF,  EBADF,  EBADF,  EBADF,  EBADF},
  74                 {EACCES,        EBADF,  EBADF,  EBADF,  EBADF,  EBADF},
  75                 {EACCES,        EBADF,  EBADF,  EBADF,  EBADF,  EBADF}}
  76         };
  77 
  78         if ((buf = malloc(256)) == NULL) {
  79                 perror("main()- malloc() for buf");
  80                 return (NOOK);
  81         }
  82 
  83         parse_args(argc, argv);
  84 
  85         filename = lfilename;
  86 
  87         dprint("Try to remove test files, to avoid errors.\n");
  88         unlink_file(filename);
  89         unlink_file("linkfile.txt");
  90 
  91         /* modify name to include delgation policy */
  92         if ((deleg = getenv("DELG")) != NULL) {
  93                 if (strcasecmp(deleg, "on") == 0) {
  94                         strcat(Testname, "_Deleg");
  95                 }
  96                 if (strcasecmp(deleg, "off") == 0) {
  97                         strcat(Testname, "_NoDeleg");
  98                 }
  99         }
 100 
 101         scen = getenv("SCENARIO");
 102         if (!scen) {
 103                 printf("The scenario was not specified");
 104                 return (NOOK);
 105         }
 106 
 107         if ((mode_index = getenv("MODE_INDEX")) != NULL) {
 108                 i = atoi(mode_index);
 109                 if ((i > 3) && (strcmp(scen, "C") != 0)) {
 110                         printf("The mode index(%d) is more than 3 "\
 111                             "with scenario %s", i, scen);
 112                         return (NOOK);
 113                 } else if (i > 6) {
 114                         printf("The mode index(%d) is more than 6 "\
 115                             "with scenario %s", i, scen);
 116                         return (NOOK);
 117                 }
 118         }
 119 
 120         if ((oflag_index = getenv("OFLAG_INDEX")) != NULL) {
 121                 j = atoi(oflag_index);
 122                 if (j > 3) {
 123                         printf("The oflag index(%d) is more than 3 "\
 124                             "with scenario %s", i, scen);
 125                         return (NOOK);
 126                 }
 127         }
 128 
 129 
 130         /* run tests */
 131         switch (*scen) {
 132         case 'A':
 133                 ret = scenarioA(mode_set[i], oflag_set[j], expect[i][j]);
 134                 break;
 135         case 'B':
 136                 ret = scenarioB(mode_set[i], oflag_set[j], expect[i][j]);
 137                 break;
 138         case 'C':
 139                 scenarioC(0600, O_CREAT|O_TRUNC|O_RDWR, expect[0][1]);
 140                 break;
 141         default:
 142                 printf("Set invalid scenario(%s)", scen);
 143                 return (NOOK);
 144         }
 145 
 146         if (buf != NULL)
 147                 free(buf);
 148         if (GLOBdata != NULL)
 149                 free(GLOBdata);
 150 
 151         exit_test(ret);
 152         return (OK);    /* unreachable, used to quiet lint */
 153 }
 154 
 155 int
 156 scenarioA(int mode, int oflag, int expect[])
 157 {
 158         int     fd1, fd2;
 159         char    *DD;
 160         int     flg = 0;
 161         int     expt;
 162         int     ret = OK;
 163 
 164         scen = "ScenA";
 165         scen_mode = mode;
 166         scen_flag = oflag;
 167         expecterr = expect[0];
 168 
 169         fprintf(stdout, "\n\nExecuting Scenario A, with mode = 0%o and "\
 170             "oflag = %s\n\n", mode, oflagstr(oflag));
 171 
 172         DD = strbackup("#123456789");
 173 
 174         if (create_10K_test_data_file(filename, mode) ||
 175             link_file(filename, "linkfile.txt")) {
 176                 printf("The scenario initialization failed, "\
 177                     "and other subassertions won't run.\n\n");
 178                 exit_test(NOOK);
 179         }
 180 
 181         print("open a file on file desc fd1 and a hardlink to it on fd2.\n");
 182 
 183         fd1 = open_file(filename, oflag, mode);
 184         fd2 = open_file("linkfile.txt", oflag, mode);
 185         if ((fd1 < 0) || (fd2 < 0)) {
 186                 if (expect[0] == OK) {
 187                         printf("scenarioA{rest}: open call\n");
 188                         printf("\t Test OTHER: unexpected open failure\n");
 189                         ret = NOOK;
 190                 }
 191                 print("Scenario A, skipping rest of scenario.\n");
 192                 goto clean_up;
 193         }
 194 
 195         /* initialize pipes and create the child */
 196         initialize();
 197 
 198         if (me == PARENT) {
 199 /* assertion a) */
 200                 waitp();
 201                 assertion("a", "Parent read lock the file using fd2",
 202                     errtostr(expect[2]));
 203                 read_lock(fd2, MAND_NO, 0, SEEK_SET, TO_EOF);
 204                 if (errno != OK) {
 205                         flg |= READ_FAIL;
 206                 }
 207                 tresult(expect[2], errno);
 208                 admerrors(ASSERT);
 209                 contch();
 210                 waitp();
 211         }
 212 
 213         if (me == CHILD) {
 214                 contp();
 215                 waitch();
 216 
 217 /* assertion b) */
 218                 assertion("b", "Child read lock the file using fd1 & fd2,\n"
 219                     "then tries write lock using both fd1 & fd2",
 220                     "multiple");
 221                 read_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 222                 if (errno != OK) {
 223                         flg |= READ_FAIL;
 224                 }
 225                 tresult(expect[2], errno);
 226 
 227                 read_file(fd1, filename, buf, 0, 10);
 228                 tresult(expect[2], errno);
 229                 read_file(fd2, "linkfile.txt", buf, 0, 10);
 230                 tresult(expect[2], errno);
 231 
 232                 write_file(fd1, filename, DD, 0, 10);
 233                 tresult(expect[3], errno);
 234                 write_file(fd2, "linkfile.txt", DD, 0, 10);
 235                 tresult(expect[3], errno);
 236                 admerrors(ASSERT);
 237                 contp();
 238                 waitch();
 239         }
 240 
 241         if (me == PARENT) {
 242 /* assertion c) */
 243                 expt = expect[5];
 244                 if ((flg & READ_FAIL) != 0) {
 245                         expt = (expt == EAGAIN) ? OK : expt;
 246                 }
 247                 assertion("c", "Parent tries to write lock first 1 KB using "
 248                     "both fd1 & fd2", "multiple");
 249                 write_lock(fd1, MAND_NO, 0, SEEK_SET, 1024);
 250                 tresult(expt, errno);
 251                 write_lock(fd2, MAND_NO, 0, SEEK_SET, 1024);
 252                 tresult(expt, errno);
 253                 admerrors(ASSERT);
 254                 contch();
 255                 waitp();
 256         }
 257 
 258         if (me == CHILD) {
 259 /* assertion d) */
 260                 assertion("d", "Child unlocks first 1 KB using both fd1 & fd2",
 261                     "multiple");
 262                 un_lock(fd1, MAND_NO, 0, SEEK_SET, 1024);
 263                 tresult(expect[1], errno);
 264                 un_lock(fd2, MAND_NO, 0, SEEK_SET, 1024);
 265                 tresult(expect[1], errno);
 266                 admerrors(ASSERT);
 267                 contp();
 268                 waitch();
 269         }
 270 
 271         if (me == PARENT) {
 272 /* assertion e) */
 273                 assertion("e", "Parent retries write lock first 1 KB using "
 274                     "fd1 & fd2", "multiple");
 275                 write_lock(fd1, MAND_NO, 0, SEEK_SET, 1024);
 276                 tresult(expect[3], errno);
 277                 write_lock(fd2, MAND_NO, 0, SEEK_SET, 1024);
 278                 tresult(expect[3], errno);
 279                 admerrors(ASSERT);
 280 
 281 /* assertion f) */
 282                 assertion("f", "Parent tries to read/write first 10 bytes "
 283                     "using both fd1 & fd2", "multiple");
 284                 read_file(fd1, filename, buf, 0, 10);
 285                 tresult(expect[2], errno);
 286                 read_file(fd2, "linkfile.txt", buf, 0, 10);
 287                 tresult(expect[2], errno);
 288 
 289                 write_file(fd1, filename, DD, 0, 10);
 290                 tresult(expect[3], errno);
 291                 write_file(fd2, "linkfile.txt", DD, 0, 10);
 292                 tresult(expect[3], errno);
 293                 admerrors(ASSERT);
 294                 contch();
 295                 waitp();
 296         }
 297 
 298         if (me == CHILD) {
 299 /* assertion g) */
 300                 expt = expect[4];
 301                 if (oflag == O_RDONLY) {
 302                         expt = (expt == EAGAIN) ? OK : expt;
 303                 }
 304                 assertion("g", "Child read lock first 1 KB using both "
 305                     "fd1 & fd2", "multiple");
 306                 read_lock(fd1, MAND_NO, 0, SEEK_SET, 1024);
 307                 tresult(expt, errno);
 308                 read_lock(fd2, MAND_NO, 0, SEEK_SET, 1024);
 309                 tresult(expt, errno);
 310                 admerrors(ASSERT);
 311 
 312 /* assertion h) */
 313                 assertion("h", "Child tries to write lock first 1 KB using "
 314                     "both fd1 & fd2", "multiple");
 315                 write_lock(fd1, MAND_NO, 0, SEEK_SET, 1024);
 316                 tresult(expect[5], errno);
 317                 write_lock(fd2, MAND_NO, 0, SEEK_SET, 1024);
 318                 tresult(expect[5], errno);
 319                 admerrors(ASSERT);
 320 
 321 /* assertion i) */
 322                 expt = expect[5];
 323                 if ((flg & READ_FAIL) != 0) {
 324                         expt = (expt == EAGAIN) ? OK : expt;
 325                 }
 326                 assertion("i", "Child tries to write lock area from 1 KB + 1 to"
 327                     "2 KB using both fd1 & fd2", "multiple");
 328                 write_lock(fd1, MAND_NO, 1024+1, SEEK_SET, 2048);
 329                 tresult(expt, errno);
 330                 write_lock(fd2, MAND_NO, 1024+1, SEEK_SET, 2048);
 331                 tresult(expt, errno);
 332                 admerrors(ASSERT);
 333                 contp();
 334                 waitch();
 335         }
 336 
 337         if (me == PARENT) {
 338 /* assertion j) */
 339                 assertion("j", "Parent tries to unlock area from 1 KB + 1 to "
 340                     "EOF using both fd1 & fd2", "multiple");
 341                 un_lock(fd1, MAND_NO, 1024+1, SEEK_SET, TO_EOF);
 342                 tresult(expect[1], errno);
 343                 un_lock(fd2, MAND_NO, 1024+1, SEEK_SET, TO_EOF);
 344                 tresult(expect[1], errno);
 345                 admerrors(ASSERT);
 346                 contch();
 347                 waitp();
 348         }
 349 
 350         if (me == CHILD) {
 351 /* assertion k) */
 352                 assertion("k", "Child tries to read lock area from 1 KB + 1 to "
 353                     "2 KB using both fd1 & fd2", "multiple");
 354                 read_lock(fd1, MAND_NO, 1024+1, SEEK_SET, 2048);
 355                 tresult(expect[2], errno);
 356                 read_lock(fd2, MAND_NO, 1024+1, SEEK_SET, 2048);
 357                 tresult(expect[2], errno);
 358                 admerrors(ASSERT);
 359 
 360 /* assertion l) */
 361                 assertion("l", "Child tries to write lock area from 1 KB + 1 "
 362                     "to 2 KB using both fd1 & fd2", "multiple");
 363                 write_lock(fd1, MAND_NO, 1024+1, SEEK_SET, 2048);
 364                 tresult(expect[3], errno);
 365                 write_lock(fd2, MAND_NO, 1024+1, SEEK_SET, 2048);
 366                 tresult(expect[3], errno);
 367                 admerrors(ASSERT);
 368                 contp();
 369                 waitch();
 370         }
 371 
 372         if (me == PARENT) {
 373 /* assertion m) */
 374                 assertion("m", "Parent tries to read lock first 1 KB using "
 375                     "both fd1 & fd2", "multiple");
 376                 read_lock(fd1, MAND_NO, 0, SEEK_SET, 1024);
 377                 tresult(expect[2], errno);
 378                 read_lock(fd2, MAND_NO, 0, SEEK_SET, 1024);
 379                 tresult(expect[2], errno);
 380                 admerrors(ASSERT);
 381                 contch();
 382                 waitp();
 383         }
 384 
 385         if (me == CHILD) {
 386 /* assertion n) */
 387                 assertion("n", "Child tries to write lock the file using "
 388                     "both fd1 & fd2", "multiple");
 389                 write_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 390                 tresult(expect[5], errno);
 391                 write_lock(fd2, MAND_NO, 0, SEEK_SET, TO_EOF);
 392                 tresult(expect[5], errno);
 393                 admerrors(ASSERT);
 394 
 395 /* assertion o) */
 396                 assertion("o", "Child tries to read lock the file using "
 397                     "both fd1 & fd2", "multiple");
 398                 read_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 399                 tresult(expect[2], errno);
 400                 read_lock(fd2, MAND_NO, 0, SEEK_SET, TO_EOF);
 401                 tresult(expect[2], errno);
 402                 admerrors(ASSERT);
 403                 contp();
 404                 waitch();
 405         }
 406 
 407         if (me == PARENT) {
 408 /* assertion p) */
 409                 assertion("p", "Parent unlocks the file using fd1 & fd2",
 410                     "multiple");
 411                 un_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 412                 tresult(expect[1], errno);
 413                 un_lock(fd2, MAND_NO, 0, SEEK_SET, TO_EOF);
 414                 tresult(expect[1], errno);
 415                 admerrors(ASSERT);
 416                 contch();
 417                 waitp();
 418         }
 419 
 420         if (me == CHILD) {
 421 /* assertion q) */
 422                 assertion("q", "Child tries to write lock the file using both "
 423                     "fd1 & fd2", "multiple");
 424                 write_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 425                 tresult(expect[3], errno);
 426                 write_lock(fd2, MAND_NO, 0, SEEK_SET, TO_EOF);
 427                 tresult(expect[3], errno);
 428                 admerrors(ASSERT);
 429                 contp();
 430                 wait_send_cresult();
 431 
 432                 while (1)
 433                         sleep(1);
 434         }
 435 
 436         if (me == PARENT) {
 437 /* assertion r) */
 438                 assertion("r", "Parent tries to write lock the file using both "
 439                     "fd1 & fd2,\n\tand kills the child process",
 440                     "multiple");
 441                 write_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 442                 tresult(expect[5], errno);
 443                 write_lock(fd2, MAND_NO, 0, SEEK_SET, TO_EOF);
 444                 tresult(expect[5], errno);
 445                 admerrors(ASSERT);
 446 
 447                 if (wait_get_cresult())
 448                         ret = NOOK;
 449                 kill_child(OK);
 450 
 451 /* assertion s) */
 452                 assertion("s", "Parent tries to write lock the file using both "
 453                     "fd1 & fd2,\n\tand closes both files", "multiple");
 454                 write_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 455                 tresult(expect[3], errno);
 456                 write_lock(fd2, MAND_NO, 0, SEEK_SET, TO_EOF);
 457                 tresult(expect[3], errno);
 458 
 459                 close_file(fd1, filename);
 460                 tresult(expect[1], errno);
 461                 close_file(fd2, "linkfile.txt");
 462                 tresult(expect[1], errno);
 463                 admerrors(ASSERT);
 464 
 465 /* assertion t) */
 466                 assertion("t", "Parent reopens both files and tries to write "
 467                     "lock both using fd1 & fd2", "multiple");
 468                 fd1 = open_file(filename, oflag, mode);
 469                 tresult(expect[0], errno);
 470                 fd2 = open_file("linkfile.txt", oflag, mode);
 471                 tresult(expect[0], errno);
 472 
 473                 write_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 474                 tresult(expect[3], errno);
 475                 write_lock(fd2, MAND_NO, 0, SEEK_SET, TO_EOF);
 476                 tresult(expect[3], errno);
 477                 admerrors(ASSERT);
 478 
 479 /* assertion u) */
 480                 assertion("u", "Parent unlocks both files and closes them",
 481                     "multiple");
 482                 un_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 483                 tresult(expect[1], errno);
 484                 un_lock(fd2, MAND_NO, 0, SEEK_SET, TO_EOF);
 485                 tresult(expect[1], errno);
 486 
 487                 close_file(fd1, filename);
 488                 tresult(expect[1], errno);
 489                 close_file(fd2, "linkfile.txt");
 490                 tresult(expect[1], errno);
 491                 admerrors(ASSERT);
 492                 goto clean_up;
 493         }
 494 
 495         if (me == CHILD) {
 496                 print("ERROR: child should be dead. Quitting ...\n");
 497                 exit_test(NOOK);
 498         }
 499 
 500 clean_up:
 501         unlink_file(filename);
 502         unlink_file("linkfile.txt");
 503 
 504         ret = admerrors(SCENARIO);
 505         print("Scenario A finished.\n\n\n");
 506         return (ret);
 507 }
 508 
 509 int
 510 scenarioB(int mode, int oflag, int expect[])
 511 {
 512         int     fd1, fd2, fd3;
 513         char    *DD;
 514         int     flg = 0;
 515         int     expt;
 516         char    tmp[512];
 517         int     ret = OK;
 518 
 519         scen = "ScenB";
 520         scen_mode = mode;
 521         scen_flag = oflag;
 522         expecterr = expect[0];
 523 
 524         fprintf(stdout, "\n\nExecuting Scenario B, with mode = 0%o and "\
 525             "oflag = %s\n\n", mode, oflagstr(oflag));
 526 
 527         DD = strbackup("#123456789");
 528 
 529         if (create_10K_test_data_file(filename, mode) ||
 530             link_file(filename, "linkfile.txt")) {
 531                 printf("The scenario initialization failed, "\
 532                     "and other subassertions won't run.\n\n");
 533                 exit_test(NOOK);
 534         }
 535 
 536         print("open a file on file desc fd1 and a hardlink to it on fd2.\n");
 537 
 538         fd1 = open_file(filename, oflag, mode);
 539         fd2 = open_file("linkfile.txt", oflag, mode);
 540         if ((fd1 < 0) || (fd2 < 0)) {
 541                 if (expect[0] == OK) {
 542                         printf("scenarioB{rest}: open call\n");
 543                         printf("\t Test OTHER: unexpected open failure\n");
 544                         ret = NOOK;
 545                 }
 546                 print("Scenario B, skipping rest of scenario.\n");
 547                 goto clean_up;
 548         }
 549 
 550         /* initialize pipes and create the child */
 551         initialize();
 552 
 553         if (me == PARENT) {
 554 /* assertion a) */
 555                 waitp();
 556                 assertion("a", "Parent read lock the file using fd2",
 557                     errtostr(expect[2]));
 558                 read_lock(fd2, MAND_NO, 0, SEEK_SET, TO_EOF);
 559                 if (errno != OK) {
 560                         flg |= READ_FAIL;
 561                 }
 562                 tresult(expect[2], errno);
 563                 admerrors(ASSERT);
 564                 contch();
 565                 waitp();
 566         }
 567 
 568         if (me == CHILD) {
 569 /* assertion b) */
 570                 sprintf(tmp, "Child chages credentials to user %ld and group "
 571                     "%ld,\n\tthen read lock the file using fd1, and tries"
 572                     "to read/write first 10 bytes\n\tusing both fd1 & fd2",
 573                     uid2, gid2);
 574                 /*
 575                  * Mark the start of the assertion in debug mode, in a way that
 576                  * won't interfere with the summary gathering script
 577                  */
 578                 dprint("%s_%s_0%o_%s{%s}: %s, expect %s.\n", Testname, scen,
 579                     scen_mode, oflagstr(scen_flag), "b", tmp, "multiple");
 580                 if (Seteuid(0) < 0) {
 581                         print("Scenario B, seteuid(root) failed, skipping"\
 582                             " rest of scenario ...\n");
 583                         goto child_end;
 584                 }
 585                 if (Setegid(gid2) < 0) {
 586                         print("Scenario B, setegid(%d) failed, skipping"\
 587                             "rest of scenario ...\n", gid2);
 588                         goto child_end;
 589                 }
 590 
 591                 {
 592                 gid_t gid = gid2;
 593 
 594                 if (Setgroups(1, &gid) < 0) {
 595                         print("Scenario B, setgroups(1, %d) failed, "\
 596                             "skipping rest of scenario ...\n", gid);
 597                         goto child_end;
 598                 }
 599 
 600                 }
 601                 if (Seteuid(uid2) < 0) {
 602                         print("Scenario B, seteuid(%d) failed, skipping"\
 603                             " rest of scenario ...\n", uid2);
 604                         goto child_end;
 605                 }
 606                 contp();
 607                 waitch();
 608 
 609                 /* Now the real assertion message */
 610                 assertion("b", tmp, "multiple");
 611 
 612                 read_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 613                 if (errno != OK) {
 614                         flg |= READ_FAIL;
 615                 }
 616                 tresult(expect[2], errno);
 617 
 618                 read_file(fd1, filename, buf, 0, 10);
 619                 tresult(expect[2], errno);
 620                 read_file(fd2, "linkfile.txt", buf, 0, 10);
 621                 tresult(expect[2], errno);
 622 
 623                 write_file(fd1, filename, DD, 0, 10);
 624                 tresult(expect[3], errno);
 625                 write_file(fd2, "linkfile.txt", DD, 0, 10);
 626                 tresult(expect[3], errno);
 627                 admerrors(ASSERT);
 628                 contp();
 629                 waitch();
 630         }
 631 
 632         if (me == PARENT) {
 633 /* assertion c) */
 634                 expt = expect[5];
 635                 if ((flg & READ_FAIL) != 0) {
 636                         expt = (expt == EAGAIN) ? OK : expt;
 637                 }
 638                 assertion("c", "Parent tries to write lock first 1 KB using "
 639                     "both fd1 & fd2", "multiple");
 640                 write_lock(fd1, MAND_NO, 0, SEEK_SET, 1024);
 641                 tresult(expt, errno);
 642                 write_lock(fd2, MAND_NO, 0, SEEK_SET, 1024);
 643                 tresult(expt, errno);
 644                 admerrors(ASSERT);
 645                 contch();
 646                 waitp();
 647         }
 648 
 649         if (me == CHILD) {
 650 /* assertion d) */
 651                 assertion("d", "Child unlock first 1 KB using both fd1 & fd2",
 652                     "multiple");
 653                 un_lock(fd1, MAND_NO, 0, SEEK_SET, 1024);
 654                 tresult(expect[1], errno);
 655                 un_lock(fd2, MAND_NO, 0, SEEK_SET, 1024);
 656                 tresult(expect[1], errno);
 657                 admerrors(ASSERT);
 658                 contp();
 659                 waitch();
 660         }
 661 
 662         if (me == PARENT) {
 663 /* assertion e) */
 664                 assertion("e", "Parent retries write lock first 1 KB using "
 665                     "fd1 & fd2", "multiple");
 666                 write_lock(fd1, MAND_NO, 0, SEEK_SET, 1024);
 667                 tresult(expect[3], errno);
 668                 write_lock(fd2, MAND_NO, 0, SEEK_SET, 1024);
 669                 tresult(expect[3], errno);
 670                 admerrors(ASSERT);
 671 
 672 /* assertion f) */
 673                 assertion("f", "Parent tries to read/write first 10 bytes "
 674                     "using both fd1 & fd2", "multiple");
 675                 read_file(fd1, filename, buf, 0, 10);
 676                 tresult(expect[2], errno);
 677                 read_file(fd2, "linkfile.txt", buf, 0, 10);
 678                 tresult(expect[2], errno);
 679 
 680                 write_file(fd1, filename, DD, 0, 10);
 681                 tresult(expect[3], errno);
 682                 write_file(fd2, "linkfile.txt", DD, 0, 10);
 683                 tresult(expect[3], errno);
 684                 admerrors(ASSERT);
 685                 contch();
 686                 waitp();
 687         }
 688 
 689         if (me == CHILD) {
 690 /* assertion g) */
 691                 expt = expect[4];
 692                 if (oflag == O_RDONLY) {
 693                         expt = (expt == EAGAIN) ? OK : expt;
 694                 }
 695                 assertion("g", "Child read lock first 1 KB using both "
 696                     "fd1 & fd2", "multiple");
 697                 read_lock(fd1, MAND_NO, 0, SEEK_SET, 1024);
 698                 tresult(expt, errno);
 699                 read_lock(fd2, MAND_NO, 0, SEEK_SET, 1024);
 700                 tresult(expt, errno);
 701                 admerrors(ASSERT);
 702 
 703 /* assertion h) */
 704                 assertion("h", "Child tries to write lock first 1 KB using "
 705                     "both fd1 & fd2", "multiple");
 706                 write_lock(fd1, MAND_NO, 0, SEEK_SET, 1024);
 707                 tresult(expect[5], errno);
 708                 write_lock(fd2, MAND_NO, 0, SEEK_SET, 1024);
 709                 tresult(expect[5], errno);
 710                 admerrors(ASSERT);
 711 
 712 /* assertion i) */
 713                 expt = expect[5];
 714                 if ((flg & READ_FAIL) != 0) {
 715                         expt = (expt == EAGAIN) ? OK : expt;
 716                 }
 717                 assertion("i", "Child tries to write lock area from 1 KB + 1 to"
 718                     "2 KB using both fd1 & fd2", "multiple");
 719                 write_lock(fd1, MAND_NO, 1024+1, SEEK_SET, 2048);
 720                 tresult(expt, errno);
 721                 write_lock(fd2, MAND_NO, 1024+1, SEEK_SET, 2048);
 722                 tresult(expt, errno);
 723                 admerrors(ASSERT);
 724                 contp();
 725                 waitch();
 726         }
 727 
 728         if (me == PARENT) {
 729 /* assertion j) */
 730                 assertion("j", "Parent tries to unlock area from 1 KB + 1 to "
 731                     "EOF using both fd1 & fd2", "multiple");
 732                 un_lock(fd1, MAND_NO, 1024+1, SEEK_SET, TO_EOF);
 733                 tresult(expect[1], errno);
 734                 un_lock(fd2, MAND_NO, 1024+1, SEEK_SET, TO_EOF);
 735                 tresult(expect[1], errno);
 736                 admerrors(ASSERT);
 737                 contch();
 738                 waitp();
 739         }
 740 
 741         if (me == CHILD) {
 742 /* assertion k) */
 743                 assertion("k", "Child tries to read lock area from 1 KB + 1 to "
 744                     "2 KB using both fd1 & fd2", "multiple");
 745                 read_lock(fd1, MAND_NO, 1024+1, SEEK_SET, 2048);
 746                 tresult(expect[2], errno);
 747                 read_lock(fd2, MAND_NO, 1024+1, SEEK_SET, 2048);
 748                 tresult(expect[2], errno);
 749                 admerrors(ASSERT);
 750 
 751 /* assertion l) */
 752                 assertion("l", "Child tries to write lock area from 1 KB + 1 "
 753                     "to 2 KB using both fd1 & fd2", "multiple");
 754                 write_lock(fd1, MAND_NO, 1024+1, SEEK_SET, 2048);
 755                 tresult(expect[3], errno);
 756                 write_lock(fd2, MAND_NO, 1024+1, SEEK_SET, 2048);
 757                 tresult(expect[3], errno);
 758                 admerrors(ASSERT);
 759                 contp();
 760                 waitch();
 761         }
 762 
 763         if (me == PARENT) {
 764 /* assertion m) */
 765                 assertion("m", "Parent tries to read lock first 1 KB using "
 766                     "both fd1 & fd2", "multiple");
 767                 read_lock(fd1, MAND_NO, 0, SEEK_SET, 1024);
 768                 tresult(expect[2], errno);
 769                 read_lock(fd2, MAND_NO, 0, SEEK_SET, 1024);
 770                 tresult(expect[2], errno);
 771                 admerrors(ASSERT);
 772                 contch();
 773                 waitp();
 774         }
 775 
 776         if (me == CHILD) {
 777 /* assertion n) */
 778                 assertion("n", "Child tries to write lock the file using "
 779                     "both fd1 & fd2", "multiple");
 780                 write_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 781                 tresult(expect[5], errno);
 782                 write_lock(fd2, MAND_NO, 0, SEEK_SET, TO_EOF);
 783                 tresult(expect[5], errno);
 784                 admerrors(ASSERT);
 785 
 786 /* assertion o) */
 787                 assertion("o", "Child tries to read lock the file using "
 788                     "both fd1 & fd2", "multiple");
 789                 read_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 790                 tresult(expect[2], errno);
 791                 read_lock(fd2, MAND_NO, 0, SEEK_SET, TO_EOF);
 792                 tresult(expect[2], errno);
 793                 admerrors(ASSERT);
 794                 contp();
 795                 waitch();
 796         }
 797 
 798         if (me == PARENT) {
 799 /* assertion p) */
 800                 assertion("p", "Parent unlocks the file using fd1 & fd2",
 801                     "multiple");
 802                 un_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 803                 tresult(expect[1], errno);
 804                 un_lock(fd2, MAND_NO, 0, SEEK_SET, TO_EOF);
 805                 tresult(expect[1], errno);
 806                 admerrors(ASSERT);
 807                 contch();
 808                 waitp();
 809         }
 810 
 811         if (me == CHILD) {
 812 /* assertion q) */
 813                 assertion("q", "Child tries to write lock the file using both "
 814                     "fd1 & fd2", "multiple");
 815                 write_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 816                 tresult(expect[3], errno);
 817                 write_lock(fd2, MAND_NO, 0, SEEK_SET, TO_EOF);
 818                 tresult(expect[3], errno);
 819                 admerrors(ASSERT);
 820                 contp();
 821                 waitch();
 822         }
 823 
 824         if (me == PARENT) {
 825 /* assertion r) */
 826                 assertion("r", "Parent tries to write lock the file using both "
 827                     "fd1 & fd2", "multiple");
 828                 write_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 829                 tresult(expect[5], errno);
 830                 write_lock(fd2, MAND_NO, 0, SEEK_SET, TO_EOF);
 831                 tresult(expect[5], errno);
 832                 admerrors(ASSERT);
 833                 contch();
 834                 waitp();
 835                 }
 836 
 837         if (me == CHILD) {
 838 /* assertion r1) */
 839                 assertion("r1", "Child closes both files", "multiple");
 840                 close_file(fd1, filename);
 841                 tresult(expect[1], errno);
 842                 close_file(fd2, "linkfile.txt");
 843                 tresult(expect[1], errno);
 844                 admerrors(ASSERT);
 845                 contp();
 846                 wait_send_cresult();
 847 
 848                 while (1)
 849                         sleep(1);
 850                 }
 851 
 852         if (me == PARENT) {
 853 /* assertion s) */
 854                 assertion("s", "Parent tries to write lock the file using both "
 855                     "fd1 & fd2,\n\tcloses both files and kills the child"
 856                     " process", "multiple");
 857                 write_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 858                 tresult(expect[3], errno);
 859                 write_lock(fd2, MAND_NO, 0, SEEK_SET, TO_EOF);
 860                 tresult(expect[3], errno);
 861 
 862                 close_file(fd1, filename);
 863                 tresult(expect[1], errno);
 864                 close_file(fd2, "linkfile.txt");
 865                 tresult(expect[1], errno);
 866                 admerrors(ASSERT);
 867 
 868                 if (wait_get_cresult())
 869                         ret = NOOK;
 870                 kill_child(OK);
 871 
 872                 goto clean_up;
 873                 }
 874 
 875         if (me == CHILD) {
 876                 print("ERROR: child should be dead. Quitting ...\n");
 877                 exit_test(NOOK);
 878         }
 879 
 880 child_end:
 881         contp();
 882         wait_send_cresult();
 883         while (1)
 884                 sleep(1);
 885 
 886 clean_up:
 887         if (Seteuid(0) < 0) {
 888                 dprint("Scenario B, seteuid(root) failed\n");
 889         }
 890         unlink_file(filename);
 891         unlink_file("linkfile.txt");
 892         unlink_file("testfile2.txt");
 893         if (Seteuid(uid) < 0) {
 894                 dprint("Scenario B, seteuid(%d) failed\n", uid);
 895         }
 896 
 897         ret = admerrors(SCENARIO);
 898         print("Scenario B finished.\n\n\n");
 899         return (ret);
 900 }
 901 
 902 int
 903 scenarioC(int mode, int oflag, int expect[])
 904 {
 905         int     fd1;
 906         int     i;
 907         char    *DD;
 908         char    tmp[512];
 909         int     ret = OK;
 910 
 911         scen = "ScenC";
 912         scen_mode = mode;
 913         scen_flag = oflag;
 914         expecterr = expect[0];
 915 
 916         fprintf(stdout, "\n\nExecuting Scenario C, with mode = 0%o and "\
 917             "oflag = %s\n\n", mode, oflagstr(oflag));
 918 
 919         DD = strbackup("#123456789");
 920 
 921         if (create_10K_test_data_file(filename, mode)) {
 922                 printf("The scenario initialization failed, "\
 923                     "and other subassertions won't run.\n\n");
 924                 exit_test(NOOK);
 925         }
 926 
 927         print("open a file on file desc fd.\n");
 928 
 929         fd1 = open_file(filename, oflag, mode);
 930         if (fd1 < 0) {
 931                 if (expect[0] == OK) {
 932                         printf("scenarioC{rest}: open call\n");
 933                         printf("\t Test OTHER: unexpected open failure\n");
 934                         ret = NOOK;
 935                 }
 936                 print("Scenario C, skipping rest of scenario.\n");
 937                 goto clean_up;
 938         }
 939 
 940         /* initialize pipes and create the child */
 941         initialize();
 942 
 943         if (me == PARENT) {
 944                 sleep(1);       /* let child start */
 945                 contch();
 946                 waitp();
 947         }
 948 
 949         if (me == CHILD) {
 950                 waitch();
 951                 contp();
 952 /* assertion a) */
 953                 sprintf(tmp, "Child read lock and unlock the file %d times"
 954                     "concurrently with next assertion",
 955                     N);
 956                 /*
 957                  * Mark the start of the assertion in debug mode, in a way that
 958                  * won't interfere with the summary gathering script
 959                  */
 960                 dprint("%s_%s_0%o_%s{%s}: %s, expect %s.\n", Testname, scen,
 961                     scen_mode, oflagstr(scen_flag), "a", tmp, "multiple");
 962                 for (i = 0; i < N; i++) {
 963                         read_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 964                         tresult(expect[2], errno);
 965                         un_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 966                         tresult(expect[1], errno);
 967                 }
 968                 /* now the real assertion message */
 969                 assertion("a", tmp, "multiple");
 970                 admerrors(ASSERT);
 971                 /* print parent assertion message and result */
 972                 contp();
 973                 waitch();
 974                 /* now continue with next assertion */
 975                 contp();
 976                 waitch();
 977         }
 978 
 979         if (me == PARENT) {
 980 /* assertion b) */
 981                 sprintf(tmp, "Parent closes and reopens the file %d times, "
 982                     "then\n\tread locks the file", N);
 983 
 984                 /*
 985                  * Mark the start of the assertion in debug mode, in a way that
 986                  * won't interfere with the summary gathering script
 987                  */
 988                 dprint("%s_%s_0%o_%s{%s}: %s, expect %s.\n", Testname, scen,
 989                     scen_mode, oflagstr(scen_flag), "b", tmp, "multiple");
 990                 for (i = 0; i < N; i++) {
 991                         close_file(fd1, filename);
 992                         tresult(expect[1], errno);
 993                         fd1 = open_file(filename, oflag, mode);
 994                         tresult(expect[0], errno);
 995                 }
 996                 read_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
 997                 tresult(expect[2], errno);
 998                 /* wait for previous assertion to be printed */
 999                 waitp();
1000                 /* Now print the real assertion message */
1001                 assertion("b", tmp, "multiple");
1002                 admerrors(ASSERT);
1003 
1004                 contch();
1005                 waitp();
1006 
1007 /* assertion c) */
1008                 assertion("c", "Parent write locks the file",
1009                     errtostr(expect[3]));
1010                 write_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
1011                 tresult(expect[3], errno);
1012                 admerrors(ASSERT);
1013                 contch();
1014                 waitp();
1015         }
1016 
1017         if (me == CHILD) {
1018 /* assertion d) */
1019                 assertion("d", "Child read locks the file",
1020                     errtostr(expect[4]));
1021                 read_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
1022                 tresult(expect[4], errno);
1023                 admerrors(ASSERT);
1024                 contp();
1025                 waitch();
1026         }
1027 
1028         if (me == PARENT) {
1029 /* assertion e) */
1030                 sprintf(tmp, "Parent read locks the file, then unlocks and "
1031                     "read locks it for %d times", N);
1032                 assertion("e", tmp, "multiple");
1033                 read_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
1034                 tresult(expect[2], errno);
1035                 for (i = 0; i < N; i++) {
1036                         un_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
1037                         tresult(expect[1], errno);
1038                         read_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
1039                         tresult(expect[2], errno);
1040                 }
1041                 admerrors(ASSERT);
1042                 contch();
1043                 waitp();
1044         }
1045 
1046         if (me == CHILD) {
1047 /* assertion f) */
1048                 sprintf(tmp, "Child read locks the file, then unlocks and "
1049                     "read locks it for %d times", N);
1050                 assertion("f", tmp, "multiple");
1051                 read_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
1052                 tresult(expect[2], errno);
1053                 for (i = 0; i < N; i++) {
1054                         un_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
1055                         tresult(expect[1], errno);
1056                         read_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
1057                         tresult(expect[2], errno);
1058                 }
1059                 admerrors(ASSERT);
1060                 contp();
1061                 waitch();
1062         }
1063 
1064         if (me == PARENT) {
1065 /* assertion g) */
1066                 assertion("g", "Parent unlocks the file", errtostr(expect[1]));
1067                 un_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
1068                 tresult(expect[1], errno);
1069                 admerrors(ASSERT);
1070                 contch();
1071                 waitp();
1072         }
1073 
1074         if (me == CHILD) {
1075 /* assertion h) */
1076                 sprintf(tmp, "Child write locks the file and waits for the "
1077                     "lease period (%d + 2 seconds) to expire", renew);
1078                 assertion("h", tmp, errtostr(expect[3]));
1079                 write_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
1080                 tresult(expect[3], errno);
1081                 admerrors(ASSERT);
1082                 contp();
1083 
1084                 sleep(renew + 2);
1085         }
1086 
1087         if (me == PARENT) {
1088 /* assertion i) */
1089                 assertion("i", "Parent read locks first 1 KB",
1090                     errtostr(expect[4]));
1091                 read_lock(fd1, MAND_NO, 0, SEEK_SET, 1024);
1092                 tresult(expect[4], errno);
1093                 admerrors(ASSERT);
1094                 waitp();
1095         }
1096 
1097         if (me == CHILD) {
1098                 contp();
1099                 waitch();
1100         }
1101 
1102         if (me == PARENT) {
1103 /* assertion j) */
1104                 assertion("j", "Parent unlocks the file", errtostr(expect[1]));
1105                 un_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
1106                 tresult(expect[1], errno);
1107                 admerrors(ASSERT);
1108                 contch();
1109                 waitp();
1110         }
1111 
1112         if (me == CHILD) {
1113 /* assertion k) */
1114                 assertion("k", "Child write locks the file",
1115                     errtostr(expect[3]));
1116                 write_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
1117                 tresult(expect[3], errno);
1118                 admerrors(ASSERT);
1119                 contp();
1120                 wait_send_cresult();
1121 
1122                 while (1)
1123                         sleep(1);
1124         }
1125 
1126         if (me == PARENT) {
1127                 if (wait_get_cresult())
1128                         ret = NOOK;
1129                 kill_child(OK);
1130 
1131 /* assertion l) */
1132                 assertion("l", "Parent kills the child process and write locks"
1133                     " the file", errtostr(expect[3]));
1134                 write_lock(fd1, MAND_NO, 0, SEEK_SET, TO_EOF);
1135                 tresult(expect[3], errno);
1136                 admerrors(ASSERT);
1137                 goto clean_up;
1138         }
1139 
1140         if (me == CHILD) {
1141                 print("ERROR: child should be dead. Quitting ...\n");
1142                 exit_test(NOOK);
1143         }
1144 
1145 
1146 clean_up:
1147         close_file(fd1, filename);
1148         unlink_file(filename);
1149         ret = admerrors(SCENARIO);
1150 
1151         print("Scenario C finished.\n\n\n");
1152         return (ret);
1153 }