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 /* common C functions */
  28 
  29 #include "nfsgen.h"
  30 
  31 /* local constants */
  32 #define ASSERTION_MSG   2048
  33 
  34 
  35 /* global variables */
  36 int me = PARENT;                /* current process (PARENT or CHILD) */
  37 pid_t PidParent = -1,           /* Pids */
  38         PidChild = -1;
  39 int NBlocks = 0;                /* flag to avoid mandatory locks from waiting */
  40 int SYNCWRITE = 0;              /* force access to file (server) by */
  41                                 /*      invalidating mem copy */
  42 int mmflag = 0;                 /* flag to use mmap on read/writes */
  43 int debug = 0;                  /* debug flag */
  44 int showerror = 0;              /* display error messages flag */
  45 int expecterr = NOOK;           /* Expected return value for open & friends */
  46                                 /*      OK, errno, NOOK->unknown */
  47 int errflag = 0;                /* Number of errors */
  48 int tsflag = 0;                 /* Number of test steps failed */
  49 int tsprev = 0;                 /* Previous value for tsflag */
  50 int aflag = 0;                  /* Number of assertions failed */
  51 int tspflag = 0;                /* Number of succesful test steps */
  52 int apflag = 0;                 /* Number of successful assertions */
  53 int serrflag = 0;               /* Number of errors scenario */
  54 int stsflag = 0;                /* Number of test steps failed scenario */
  55 int saflag = 0;                 /* Number of assertions failed scenario */
  56 int stspflag = 0;               /* Number of succesful test steps scenario */
  57 int sapflag = 0;                /* Number of successful assertions scenario */
  58 int byeflag = 0;                /* insert atexit() notification once */
  59 char *GLOBdata = NULL;          /* temp storage used for verifying reads */
  60 int Glob_status = OK;           /* global status to control say_bye() msg */
  61 static int PChild[2];           /* Comm. pipes for child */
  62 static int PParent[2];          /* Comm. pipes for Parent */
  63 static char last_assert[ASSERTION_MSG] = "";
  64                                 /* last failed assertion message */
  65 struct timeval tpstart;         /* Time sttructure for event's starting time */
  66 struct timeval tpend;           /* Time sttructure for event's ending time */
  67 struct stat Stat;               /* file stat output */
  68 
  69 int     errtoout = 0;           /* make stderr same as sdtout */
  70 char    odir[512] = "";         /* original directory */
  71 char    cwd[512] = ".";         /* test directory */
  72 char    *Testname = NULL;       /* this process name */
  73 int     renew = -1;             /* lease period */
  74 
  75 char    *scen = NULL;           /* scenario name */
  76 int     scen_mode = 0;          /* mode for testscenarios */
  77 int     scen_flag = 0;          /* flags for test scenarios */
  78 
  79 char    lfilename[512] = "";    /* local machine path/filename for testfile */
  80 int     lperms = 0777;          /* testfile permissions */
  81 int     lflags = O_CREAT|O_RDWR;        /* testfile flags */
  82 int     delay = 0;              /* time delay in seconds */
  83 int     srv_local = 0;          /* flag to signal this process is running */
  84                                 /*      locally on the server */
  85 uid_t   uid = 999999999;        /* first user test uid */
  86 uid_t   uid2 = 888888888;       /* second test uid */
  87 gid_t   gid = 777777;           /* first user test gid */
  88 gid_t   gid2 = 666666;          /* second user test gid */
  89 
  90 int     skip_getdeleg = 0;      /* get delegation type or not */
  91 
  92 
  93 /* functions */
  94 
  95 /*
  96  * ****************************************************************************
  97  * function     print()
  98  * purpose      printing messages to stdout, preceded by calling proccess.
  99  * arguments    similar to printf().
 100  * returns      nothing.
 101  * ****************************************************************************
 102  */
 103 
 104 void
 105 print(char *fmt, ...)
 106 {
 107         va_list ap;
 108 
 109         va_start(ap, fmt);
 110         (void) fprintf(stdout, "%s: ", Whoami());
 111         (void) vfprintf(stdout, fmt, ap);
 112         va_end(ap);
 113         (void) fflush(stdout);
 114 }
 115 
 116 
 117 /*
 118  * ****************************************************************************
 119  * function     dprint()
 120  * purpose      printing debug messages to stdout, preceded by calling proccess,
 121  *              if global "debug" is set.
 122  * arguments    similar to printf().
 123  * returns      nothing.
 124  * ****************************************************************************
 125  */
 126 
 127 void
 128 dprint(char *fmt, ...)
 129 {
 130         va_list ap;
 131 
 132         if (!debug)
 133                 return;
 134         va_start(ap, fmt);
 135         (void) fprintf(stdout, "%s: ", Whoami());
 136         (void) vfprintf(stdout, fmt, ap);
 137         va_end(ap);
 138         (void) fflush(stdout);
 139 }
 140 
 141 
 142 /*
 143  * ****************************************************************************
 144  * function     eprint()
 145  * purpose      printing error messages to stderr, preceded by calling proccess,
 146  *              if global "showerror" is set. Also, global "errflag" is
 147  *              incremented.
 148  * arguments    similar to printf().
 149  * returns      nothing.
 150  * ***************************************************************************
 151  */
 152 
 153 void
 154 eprint(char *fmt, ...)
 155 {
 156         va_list ap;
 157 
 158         /* increment number of errors found so far */
 159         errflag++;
 160 
 161         if (!showerror)
 162                 return;
 163         va_start(ap, fmt);
 164         (void) fprintf(stderr, "E %s:", Whoami());
 165         (void) vfprintf(stderr, fmt, ap);
 166         va_end(ap);
 167         (void) fflush(stderr);
 168 }
 169 
 170 
 171 /*
 172  * ****************************************************************************
 173  * function     Perror()
 174  * purpose      call perror() conditionally upon global "showerror" being set.
 175  * arguments    Same as perror().
 176  * returns      nothing.
 177  * ****************************************************************************
 178  */
 179 
 180 void
 181 Perror(const char *s)
 182 {
 183         if (showerror)
 184                 perror(s);
 185 }
 186 
 187 
 188 /*
 189  * ****************************************************************************
 190  * function     errtostr()
 191  * purpose      Converts error codes returned in errno to name of constant
 192  *              (string) as defined in system include files.
 193  * arguments    error number to convert.
 194  * returns      name of constant for given error number, or "" if error.
 195  * ****************************************************************************
 196  */
 197 
 198 char *
 199 errtostr(int error)
 200 {
 201         static const char *errstring[] = {
 202         "OK",           /*   0 No error                         */
 203         "EPERM",        /*   1 Not super-user                   */
 204         "ENOENT",       /*   2 No such file or directory        */
 205         "ESRCH",        /*   3 No such process                  */
 206         "EINTR",        /*   4 interrupted system call          */
 207         "EIO",          /*   5 I/O error                        */
 208         "ENXIO",        /*   6 No such device or address        */
 209         "E2BIG",        /*   7 Arg list too long                */
 210         "ENOEXEC",      /*   8 Exec format error                */
 211         "EBADF",        /*   9 Bad file number                  */
 212         "ECHILD",       /*  10 No children                      */
 213         "EAGAIN",       /*  11 Resource temporarily unavailable */
 214         "ENOMEM",       /*  12 Not enough core                  */
 215         "EACCES",       /*  13 Permission denied                */
 216         "EFAULT",       /*  14 Bad address                      */
 217         "ENOTBLK",      /*  15 Block device required            */
 218         "EBUSY",        /*  16 Mount device busy                */
 219         "EEXIST",       /*  17 File exists                      */
 220         "EXDEV",        /*  18 Cross-device link                */
 221         "ENODEV",       /*  19 No such device                   */
 222         "ENOTDIR",      /*  20 Not a directory                  */
 223         "EISDIR",       /*  21 Is a directory                   */
 224         "EINVAL",       /*  22 Invalid argument                 */
 225         "ENFILE",       /*  23 File table overflow              */
 226         "EMFILE",       /*  24 Too many open files              */
 227         "ENOTTY",       /*  25 Inappropriate ioctl for device   */
 228         "ETXTBSY",      /*  26 Text file busy                   */
 229         "EFBIG",        /*  27 File too large                   */
 230         "ENOSPC",       /*  28 No space left on device          */
 231         "ESPIPE",       /*  29 Illegal seek                     */
 232         "EROFS",        /*  30 Read only file system            */
 233         "EMLINK",       /*  31 Too many links                   */
 234         "EPIPE",        /*  32 Broken pipe                      */
 235         "EDOM",         /*  33 Math arg out of domain of func   */
 236         "ERANGE",       /*  34 Math result not representable    */
 237         "ENOMSG",       /*  35 No message of desired type       */
 238         "EIDRM",        /*  36 Identifier removed               */
 239         "ECHRNG",       /*  37 Channel number out of range      */
 240         "EL2NSYNC",     /*  38 Level 2 not synchronized */
 241         "EL3HLT",       /*  39 Level 3 halted                   */
 242         "EL3RST",       /*  40 Level 3 reset                    */
 243         "ELNRNG",       /*  41 Link number out of range         */
 244         "EUNATCH",      /*  42 Protocol driver not attached     */
 245         "ENOCSI",       /*  43 No CSI structure available       */
 246         "EL2HLT",       /*  44 Level 2 halted                   */
 247         "EDEADLK",      /*  45 Deadlock condition.              */
 248         "ENOLCK",       /*  46 No record locks available.       */
 249         "ECANCELED",    /*  47 Operation canceled               */
 250         "ENOTSUP",      /*  48 Operation not supported          */
 251 
 252         /* Filesystem Quotas */
 253         "EDQUOT",       /*  49 Disc quota exceeded              */
 254 
 255         /* Convergent Error Returns */
 256         "EBADE",        /*  50 invalid exchange                 */
 257         "EBADR",        /*  51 invalid request descriptor       */
 258         "EXFULL",       /*  52 exchange full                    */
 259         "ENOANO",       /*  53 no anode                         */
 260         "EBADRQC",      /*  54 invalid request code             */
 261         "EBADSLT",      /*  55 invalid slot                     */
 262         "EDEADLOCK",    /*  56 file locking deadlock error      */
 263 
 264         "EBFONT",       /*  57 bad font file fmt                */
 265 
 266         /* Interprocess Robust Locks */
 267         "EOWNERDEAD",   /*  58 process died with the lock       */
 268         "ENOTRECOVERABLE",      /*  59 lock is not recoverable  */
 269 
 270         /* stream problems */
 271         "ENOSTR",       /*  60 Device not a stream              */
 272         "ENODATA",      /*  61 no data (for no delay io)        */
 273         "ETIME",        /*  62 timer expired                    */
 274         "ENOSR",        /*  63 out of streams resources         */
 275 
 276         "ENONET",       /*  64 Machine is not on the network    */
 277         "ENOPKG",       /*  65 Package not installed            */
 278         "EREMOTE",      /*  66 The object is remote             */
 279         "ENOLINK",      /*  67 the link has been severed        */
 280         "EADV",         /*  68 advertise error                  */
 281         "ESRMNT",       /*  69 srmount error                    */
 282 
 283         "ECOMM",        /*  70 Communication error on send      */
 284         "EPROTO",       /*  71 Protocol error                   */
 285 
 286         /* Interprocess Robust Locks */
 287         "ELOCKUNMAPPED",        /*  72 locked lock was unmapped         */
 288 
 289         "ENOTACTIVE",   /*  73 Facility is not active           */
 290         "EMULTIHOP",    /*  74 multihop attempted               */
 291         "EBADMSG",      /*  77 trying to read unreadable message        */
 292         "ENAMETOOLONG", /*  78 path name is too long            */
 293         "EOVERFLOW",    /*  79 value too large to be stored in data type */
 294         "ENOTUNIQ",     /*  80 given log. name not unique       */
 295         "EBADFD",       /*  81 f.d. invalid for this operation  */
 296         "EREMCHG",      /*  82 Remote address changed           */
 297 
 298         /* shared library problems */
 299         "ELIBACC",      /*  83 Can't access a needed shared lib.        */
 300         "ELIBBAD",      /*  84 Accessing a corrupted shared lib.        */
 301         "ELIBSCN",      /*  85 .lib section in a.out corrupted. */
 302         "ELIBMAX",      /*  86 Attempting to link in too many libs.     */
 303         "ELIBEXEC",     /*  87 Attempting to exec a shared library.     */
 304         "EILSEQ",       /*  88 Illegal byte sequence.           */
 305         "ENOSYS",       /*  89 Unsupported file system operation        */
 306         "ELOOP",        /*  90 Symbolic link loop               */
 307         "ERESTART",     /*  91 Restartable system call          */
 308         "ESTRPIPE",     /*  92 if pipe/FIFO, don't sleep in stream head */
 309         "ENOTEMPTY",    /*  93 directory not empty              */
 310         "EUSERS",       /*  94 Too many users (for UFS)         */
 311 
 312         /* BSD Networking Software */
 313                 /* argument errors */
 314         "ENOTSOCK",     /*  95 Socket operation on non-socket   */
 315         "EDESTADDRREQ", /*  96 Destination address required     */
 316         "EMSGSIZE",     /*  97 Message too long                 */
 317         "EPROTOTYPE",   /*  98 Protocol wrong type for socket   */
 318         "ENOPROTOOPT",  /*  99 Protocol not available           */
 319         "UNKOWN",       /* 100 Undefined error                  */
 320         "UNKOWN",       /* 101 Undefined error                  */
 321         "UNKOWN",       /* 102 Undefined error                  */
 322         "UNKOWN",       /* 103 Undefined error                  */
 323         "UNKOWN",       /* 104 Undefined error                  */
 324         "UNKOWN",       /* 105 Undefined error                  */
 325         "UNKOWN",       /* 106 Undefined error                  */
 326         "UNKOWN",       /* 107 Undefined error                  */
 327         "UNKOWN",       /* 108 Undefined error                  */
 328         "UNKOWN",       /* 109 Undefined error                  */
 329         "UNKOWN",       /* 110 Undefined error                  */
 330         "UNKOWN",       /* 111 Undefined error                  */
 331         "UNKOWN",       /* 112 Undefined error                  */
 332         "UNKOWN",       /* 113 Undefined error                  */
 333         "UNKOWN",       /* 114 Undefined error                  */
 334         "UNKOWN",       /* 115 Undefined error                  */
 335         "UNKOWN",       /* 116 Undefined error                  */
 336         "UNKOWN",       /* 117 Undefined error                  */
 337         "UNKOWN",       /* 118 Undefined error                  */
 338         "UNKOWN",       /* 119 Undefined error                  */
 339         "EPROTONOSUPPORT",      /* 120 Protocol not supported   */
 340         "ESOCKTNOSUPPORT",      /* 121 Socket type not supported        */
 341         "EOPNOTSUPP",   /* 122 Operation not supported on socket        */
 342         "EPFNOSUPPORT", /* 123 Protocol family not supported    */
 343         "EAFNOSUPPORT", /* 124 Address family not supported by  */
 344                                 /* protocol family              */
 345         "EADDRINUSE",   /* 125 Address already in use           */
 346         "EADDRNOTAVAIL",        /* 126 Can't assign requested address   */
 347                 /* operational errors */
 348         "ENETDOWN",     /* 127 Network is down                  */
 349         "ENETUNREACH",  /* 128 Network is unreachable           */
 350         "ENETRESET",    /* 129 Network dropped connection because       */
 351                                 /* of reset                     */
 352         "ECONNABORTED", /* 130 Software caused connection abort */
 353         "ECONNRESET",   /* 131 Connection reset by peer         */
 354         "ENOBUFS",      /* 132 No buffer space available        */
 355         "EISCONN",      /* 133 Socket is already connected      */
 356         "ENOTCONN",     /* 134 Socket is not connected          */
 357 
 358         /* XENIX has 135 - 142 */
 359         "XENIX",        /* 135 XENIX error                      */
 360         "XENIX",        /* 136 XENIX error                      */
 361         "XENIX",        /* 137 XENIX error                      */
 362         "XENIX",        /* 138 XENIX error                      */
 363         "XENIX",        /* 139 XENIX error                      */
 364         "XENIX",        /* 140 XENIX error                      */
 365         "XENIX",        /* 141 XENIX error                      */
 366         "XENIX",        /* 142 XENIX error                      */
 367         "ESHUTDOWN",    /* 143 Can't send after socket shutdown */
 368         "ETOOMANYREFS", /* 144 Too many references: can't splice        */
 369         "ETIMEDOUT",    /* 145 Connection timed out             */
 370         "ECONNREFUSED", /* 146 Connection refused               */
 371         "EHOSTDOWN",    /* 147 Host is down                     */
 372         "EHOSTUNREACH", /* 148 No route to host                 */
 373         /* EWOULDBLOCK  EAGAIN                                  */
 374         "EALREADY",     /* 149 operation already in progress    */
 375         "EINPROGRESS",  /* 150 operation now in progress        */
 376 
 377         /* SUN Network File System */
 378         "ESTALE"        /* 151 Stale NFS file handle            */
 379         };
 380         static const char *null = "";
 381 
 382         if ((error < 0) || (error > 151))
 383                 return ((char *)null);
 384         else
 385                 return ((char *)errstring[error]);
 386 }
 387 
 388 
 389 /*
 390  * ****************************************************************************
 391  * function     sigtostr()
 392  * purpose      Converts signal numbers name of constant
 393  *              (string) as defined in system include files.
 394  * arguments    signal number to convert.
 395  * returns      name of constant for given signal number, or signal number if
 396  *              not defined.
 397  * ****************************************************************************
 398  */
 399 
 400 char *
 401 sigtostr(int sig)
 402 {
 403         static const char *sigstring[] = {
 404         "NONE",         /* 0  ????   No signal */
 405         "SIGHUP",       /* 1  Exit   Hangup (see termio(7I)) */
 406         "SIGINT",       /* 2  Exit   Interrupt (see termio(7I)) */
 407         "SIGQUIT",      /* 3  Core   Quit (see termio(7I)) */
 408         "SIGILL",       /* 4  Core   Illegal Instruction */
 409         "SIGTRAP",      /* 5  Core   Trace or Breakpoint Trap */
 410         "SIGABRT",      /* 6  Core   Abort */
 411         "SIGEMT",       /* 7  Core   Emulation Trap */
 412         "SIGFPE",       /* 8  Core   Arithmetic Exception */
 413         "SIGKILL",      /* 9  Exit   Killed */
 414         "SIGBUS",       /* 10 Core   Bus Error */
 415         "SIGSEGV",      /* 11 Core   Segmentation Fault */
 416         "SIGSYS",       /* 12 Core   Bad System Call */
 417         "SIGPIPE",      /* 13 Exit   Broken Pipe */
 418         "SIGALRM",      /* 14 Exit   Alarm Clock */
 419         "SIGTERM",      /* 15 Exit   Terminated */
 420         "SIGUSR1",      /* 16 Exit   User Signal 1 */
 421         "SIGUSR2",      /* 17 Exit   User Signal 2 */
 422         "SIGCHLD",      /* 18 Ignore Child Status Changed */
 423         "SIGPWR",       /* 19 Ignore Power Fail or Restart */
 424         "SIGWINCH",     /* 20 Ignore Window Size Change */
 425         "SIGURG",       /* 21 Ignore Urgent Socket Condition */
 426         "SIGPOLL",      /* 22 Exit   Pollable Event (see streamio(7I)) */
 427         "SIGSTOP",      /* 23 Stop   Stopped (signal) */
 428         "SIGTSTP",      /* 24 Stop   Stopped (user) (see termio(7I)) */
 429         "SIGCONT",      /* 25 Ignore Continued */
 430         "SIGTTIN",      /* 26 Stop   Stopped (tty input) (see termio(7I)) */
 431         "SIGTTOU",      /* 27 Stop   Stopped (tty output) (see termio(7I)) */
 432         "SIGVTALRM",    /* 28 Exit   Virtual Timer Expired */
 433         "SIGPROF",      /* 29 Exit   Profiling Timer Expired */
 434         "SIGXCPU",      /* 30 Core   CPU time limit exceeded */
 435         "SIGXFSZ",      /* 31 Core   File size limit exceeded */
 436         "SIGWAITING",   /* 32 Ignore Concurrency signal reserved by threads */
 437                         /* library */
 438         "SIGLWP",       /* 33 Ignore Inter-LWP signal reserved by threads */
 439                         /* library */
 440         "SIGFREEZE",    /* 34 Ignore Check point Freeze */
 441         "SIGTHAW",      /* 35 Ignore Check point Thaw */
 442         "SIGCANCEL",    /* 36 Ignore Cancellation signal reserved by threads */
 443                         /* library */
 444         "SIGLOST",      /* 37 ????   resource lost (eg, record-lock lost) */
 445         "SIGXRES",      /* 38 ????   resource control exceeded */
 446         "SIGRTMIN",     /* 39 Exit   First real time signal */
 447         "SIGRTMIN+1",   /* 40 Exit   Second real time signal */
 448         "SIGRTMIN+2",   /* 41 Exit   Third real time signal */
 449         "SIGRTMIN+3",   /* 42 Exit   Fourth real time signal */
 450         "SIGRTMIN+4",   /* 43 Exit   Fifth real time signal */
 451         "SIGRTMIN+5",   /* 44 Exit   Sixth real time signal */
 452         "SIGRTMIN+6",   /* 45 Exit   Seventh real time signal */
 453         "SIGRTMAX"      /* 46 Exit   Last real time signal */
 454         };
 455 
 456         if ((sig < 0) || (sig > 46)) {
 457                 static char buf[10] = "";
 458 
 459                 (void) snprintf(buf, 10, "%d", sig);
 460                 return (buf);
 461         } else {
 462                 return ((char *)sigstring[sig]);
 463         }
 464 }
 465 
 466 
 467 /*
 468  * ****************************************************************************
 469  * function     mandtostr()
 470  * purpose      Converts mandatory flag to name of constant as defined in
 471  *              common.h. Used to made logs easily readable.
 472  * arguments    Value used in mandatory flag.
 473  * returns      Name of constant equivalent to mandatory flag value, or ""
 474  *              if error.
 475  * ****************************************************************************
 476  */
 477 
 478 char *
 479 mandtostr(int mand)
 480 {
 481         static const char *mandstring[] = {
 482                 "F_SETLK",              /* 0 MAND_NO */
 483                 "F_SETLK_NBMAND",       /* 1 MAND_YES */
 484                 "F_SETLKW"              /* 2 MANDW_YES */
 485         };
 486         static const char *null = "";
 487 
 488         if ((mand < 0) || (mand > 2))
 489                 return ((char *)null);
 490         else
 491                 return ((char *)mandstring[mand]);
 492 }
 493 
 494 
 495 /*
 496  * ****************************************************************************
 497  * function     whencetostr()
 498  * purpose      Converts value used in argument whence (utilized in several
 499  *              function calls) to a string for logs readability.
 500  * arguments    Value used for whence parameter.
 501  * returns      Name of constant as defined in system headers, or "" if error.
 502  * ****************************************************************************
 503  */
 504 
 505 char *
 506 whencetostr(int whence)
 507 {
 508         static const char *whencestring[] = {
 509                 "SEEK_SET",     /* 0 Set file pointer to "offset" */
 510                 "SEEK_CUR",     /* 1 Set file pointer to current + "offset" */
 511                 "SEEK_END"      /* 2 Set file pointer to EOF plus "offset" */
 512         };
 513         static const char *null = "";
 514 
 515         if ((whence < 0) || (whence > 2))
 516                 return ((char *)null);
 517         else
 518                 return ((char *)whencestring[whence]);
 519 }
 520 
 521 
 522 /*
 523  * ****************************************************************************
 524  * function     cmdtostr()
 525  * purpose      Converts the value for fcntl's argument cmd, to constant name
 526  *              as defined in system header files. Used for logs readability.
 527  * arguments    Value for cmd argument.
 528  * returns      String with name of cmd constant, or "" if error.
 529  * ****************************************************************************
 530  */
 531 
 532 char *
 533 cmdtostr(int cmdvalue)
 534 {
 535         static const char *null = "";
 536         static char *cmd;
 537 
 538         cmd = (char *)null;
 539 
 540         switch (cmdvalue) {
 541 #ifndef __sparcv9
 542         case F_SETLK:
 543                 cmd = "F_SETLK";        /* Set file lock */
 544                 break;
 545         case F_SETLKW:
 546                 cmd = "F_SETLKW";       /* Set file lock and wait */
 547                 break;
 548         case F_FREESP:
 549                 cmd = "F_FREESP";       /* Free file space */
 550                 break;
 551         case F_GETLK:
 552                 cmd = "F_GETLK";        /* Get file lock */
 553                 break;
 554         case F_SETLK_NBMAND:
 555                 cmd = "F_SETLK_NBMAND"; /* private */
 556                 break;
 557 #else
 558         case F_SETLK64:
 559                 cmd = "F_SETLK64";      /* Set file lock */
 560                 break;
 561         case F_SETLKW64:
 562                 cmd = "F_SETLKW64";     /* Set file lock and wait */
 563                 break;
 564         case F_FREESP64:
 565                 cmd = "F_FREESP64";     /* Free file space */
 566                 break;
 567         case F_GETLK64:
 568                 cmd = "F_GETLK64";      /* Get file lock */
 569                 break;
 570         case F_SETLK64_NBMAND:
 571                 cmd = "F_SETLK64_NBMAND";       /* private */
 572                 break;
 573 #endif
 574         case F_SHARE:
 575                 cmd = "F_SHARE";        /* Set a file share reservation */
 576                 break;
 577         case F_UNSHARE:
 578                 cmd = "F_UNSHARE";      /* Remove a file share reservation */
 579                 break;
 580         case F_SHARE_NBMAND:
 581                 cmd = "F_SHARE_NBMAND"; /* private */
 582                 break;
 583         default:
 584                 cmd = (char *)null;
 585         }
 586 
 587         return (cmd);
 588 }
 589 
 590 
 591 /*
 592  * ****************************************************************************
 593  * function     typetostr()
 594  * purpose      Convert the lock type (fcntl()) value to name of constant as
 595  *              defined in system header files. Used for logs readability.
 596  * arguments    Value of lock type argument.
 597  * returns      String with name of lock type, or "" if error.
 598  * ****************************************************************************
 599  */
 600 
 601 char *
 602 typetostr(int type)
 603 {
 604         static const char *typestring[] = {
 605                 "",
 606                 "F_RDLCK",      /* 1 Read lock */
 607                 "F_WRLCK",      /* 2 Write lock */
 608                 "F_UNLCK",      /* 3 Remove lock(s) */
 609                 "F_UNLKSYS"     /* 4 remove remote locks for a given system */
 610         };
 611         static const char *null = "";
 612 
 613 
 614         if ((type < 0) || (type > 4))
 615                 return ((char *)null);
 616         else
 617                 return ((char *)typestring[type]);
 618 }
 619 
 620 
 621 /*
 622  * ****************************************************************************
 623  * function     pidtostr()
 624  * purpose      Converts the PID given to either string "PARENT", "CHILD" or
 625  *              "proc pid XXXX". Used for logs readability.
 626  * arguments    PID of interest.
 627  * returns      String specifying parent, child or pid number.
 628  * ****************************************************************************
 629  */
 630 
 631 char *
 632 pidtostr(pid_t pid)
 633 {
 634         static char buf[256];
 635         static char *owner;
 636 
 637         if (pid == PidChild)
 638                 owner = "Child";
 639         else if (pid == PidParent)
 640                 owner = "Parent";
 641         else {
 642                 (void) snprintf(buf, 256, "proc pid %ld\0", (long)pid);
 643                 owner = buf;
 644         }
 645 
 646         return (owner);
 647 }
 648 
 649 
 650 /*
 651  * ****************************************************************************
 652  * function     oflagstr()
 653  * purpose      Convert the value of oflag parameter for open() to constant
 654  *              names as defined in system header files. Used for logs
 655  *              readability.
 656  * arguments    Value of oflag as described for open().
 657  * returns      String with all flags constant names described for open()
 658  *              sparated by "|".
 659  * ****************************************************************************
 660  */
 661 
 662 char *
 663 oflagstr(int flag)
 664 {
 665         static const char *flagstr[] = {
 666                 "O_RDONLY",     /* read only                            */
 667                 "O_WRONLY",     /* write only                           */
 668                 "O_RDWR",       /* read and write                       */
 669                 "O_NDELAY",     /* non-blocking I/O                     */
 670                 "O_APPEND",     /* append (writes guaranteed at the end) */
 671                 "O_SYNC",       /* synchronized file update option      */
 672                 "O_DSYNC",      /* synchronized data update option      */
 673                 "O_NONBLOCK",   /* non-blocking I/O (POSIX)             */
 674                 "O_PRIV",       /* Private access to file               */
 675                 "O_LARGEFILE",  /* large file (offset 64 bits)          */
 676                 "O_XATTR",      /* extended attribute                   */
 677                 "O_RSYNC",      /* synchronized file update option      */
 678                                 /* defines read/write file integrity    */
 679                 "O_CREAT",      /* open with file create (uses third arg) */
 680                 "O_TRUNC",      /* open with truncation                 */
 681                 "O_EXCL",       /* exclusive open                       */
 682                 "O_NOCTTY"      /* don't allocate controlling tty (POSIX) */
 683                 };
 684         static const int flagval[] = {
 685                 0,      /* read only                            */
 686                 1,      /* write only                           */
 687                 2,      /* read and write                       */
 688                 0x04,   /* non-blocking I/O                     */
 689                 0x08,   /* append (writes guaranteed at the end) */
 690                 0x10,   /* synchronized file update option      */
 691                 0x40,   /* synchronized data update option      */
 692                 0x80,   /* non-blocking I/O (POSIX)             */
 693                 0x1000, /* Private access to file               */
 694                 0x2000, /* large file (offset 64 bits)          */
 695                 0x4000, /* synchronized file update option      */
 696                 0x8000, /* synchronized file update option      */
 697                         /* defines read/write file integrity    */
 698                 0x100,  /* open with file create (uses third arg) */
 699                 0x200,  /* open with truncation                 */
 700                 0x400,  /* exclusive open                       */
 701                 0x800   /* don't allocate controlling tty (POSIX) */
 702                 };
 703         int i;
 704         static char buf[1024];
 705 
 706         buf[0] = '\0';
 707         for (i = 0; i < 15; i++)
 708                 if (flag & flagval[i])
 709                         if (buf[0] == 0)
 710                                 strcpy(buf, flagstr[i]);
 711                         else {
 712                         /* use underscore instead of spaces for summary func */
 713                                 strcat(buf, "_|_");
 714                                 strcat(buf, flagstr[i]);
 715                         }
 716         if (strlen(buf) == 0)
 717                 strcpy(buf, flagstr[0]);
 718 
 719         return (buf);
 720 }
 721 
 722 
 723 /*
 724  * ****************************************************************************
 725  * function     mmtypetostr()
 726  * purpose      Converts the type used for mmap to string.
 727  * arguments    type used in mmap.
 728  * returns      String specifying mmap type to be used.
 729  * ****************************************************************************
 730  */
 731 
 732 char *
 733 mmtypetostr(int type)
 734 {
 735         static char buf[256];
 736 
 737         buf[0] = '\0';
 738         if (type & MMREAD)
 739                 (void) snprintf(buf, 256, "PROT_READ");
 740         if (type & MMWRITE) {
 741                 if (buf[0] != '\0')
 742                         (void) strcat(buf, "|");
 743                 (void) strcat(buf, "PROT_WRITE");
 744         }
 745 
 746         return (buf);
 747 }
 748 
 749 
 750 /*
 751  * ****************************************************************************
 752  * function     tresult()
 753  * purpose      Checkpoint for test step. Compares actual and expected error
 754  *              codes (including OK), updating globals "tsflag" (tests step
 755  *              failures) and "tspflag" (teststep successes) as appropriate.
 756  * arguments    expect- expected error code.
 757  *              actual- actual error code.
 758  * returns      OK (0) upon success (expect == actual), otherwise NO OK (-1).
 759  * ****************************************************************************
 760  */
 761 
 762 int
 763 tresult(int expect, int actual)
 764 {
 765         char tmp[512] = "";
 766 
 767         if (expect != actual) {
 768                 (void) snprintf(tmp, 512, \
 769                     "\tTest FAIL: Expected message was %s, "
 770                     "actual message is %s\n",
 771                     errtostr(expect), errtostr(actual));
 772                 if (strlcat(last_assert, tmp, ASSERTION_MSG) >= ASSERTION_MSG) {
 773                         eprint("tresult() warning: buffer overflow.\n"
 774                             "\tassertion messages may be incomplete.\n");
 775                 }
 776                 dprint("%s\n", last_assert);
 777 
 778                 /* increment number of test steps failed so far */
 779                 tsflag++;
 780                 return (NOOK);
 781         } else {
 782                 dprint("Expected message %s was correct.\n", errtostr(expect));
 783                 /* increment number of test steps passed so far */
 784                 tspflag++;
 785                 return (OK);
 786         }
 787 }
 788 
 789 /*
 790  * ****************************************************************************
 791  * function     assertion()
 792  * purpose      Print information assertions.
 793  *
 794  * arguments    assert          name of the assertion.
 795  *              desc            string describing the assertion to run
 796  * returns      nothing.
 797  * ****************************************************************************
 798  */
 799 
 800 void
 801 assertion(char *assert, char *desc, char *expect)
 802 {
 803         (void) printf("%s_%s_0%o_%s{%s}: %s, expect %s.\n",
 804             Testname, scen, scen_mode,
 805             oflagstr(scen_flag), assert, desc, expect);
 806 }
 807 
 808 /*
 809  * ****************************************************************************
 810  * function     admerrors()
 811  * purpose      Handle and print information about errors, test steps and
 812  *              assertions.
 813  * arguments    command to obtain status on passes or failures (test steps and
 814  *              assertions) and number of errors, evaluate current assertion
 815  *              based on its test steps, and update information at the end of
 816  *              a scenario execution.
 817  * returns      nothing.
 818  * ****************************************************************************
 819  */
 820 
 821 int
 822 admerrors(int cmd)
 823 {
 824         int ret = OK;
 825 
 826         switch (cmd) {
 827         case TOTALS:
 828                 /* print totals for all pass and failure information */
 829                 dprint("A total of %d error(s) were found.\n", errflag);
 830                 dprint("A total of %d test step(s) failed.\n", tsflag);
 831                 dprint("A total of %d successful test step(s).\n", tspflag);
 832                 (void) print("Total assertion(s) failed %d and passed %d.\n",
 833                     aflag, apflag);
 834                 break;
 835 
 836         case TOTDB:
 837                 /* same as TOTALS, but immune to global "debug" */
 838                 (void) print("A total of %d error(s) were found.\n", errflag);
 839                 (void) print("A total of %d test step(s) failed.\n", tsflag);
 840                 (void) print("A total of %d test step(s) passed.\n", tspflag);
 841                 (void) print("Total assertion(s) failed: %d and passed: %d.\n",
 842                     aflag, apflag);
 843                 break;
 844 
 845         case TOTERROR:
 846                 /* only print total number of errors */
 847                 (void) print("A total of %d error(s) were found.\n", errflag);
 848                 break;
 849 
 850         case TOTSTEPS:
 851                 /* only print totals for test steps */
 852                 (void) print("A total of %d test step(s) failed.\n", tsflag);
 853                 (void) print("A total of %d test step(s) passed.\n", tspflag);
 854                 break;
 855 
 856         case TOTASSERT:
 857                 /* only print totals regarding assertions */
 858                 (void) print("A total of %d assertion(s) failed.\n", aflag);
 859                 (void) print("A total of %d assertion(s) passed.\n", apflag);
 860                 break;
 861 
 862         case ASSERT:
 863                 /* evaluate current assertion based on its test steps */
 864                 /* if more ts errors than previous time, assertion failed */
 865                 dprint("assert %d < %d.\n", tsprev, tsflag);
 866                 if (tsprev < tsflag) {
 867                         aflag ++;
 868                         tsprev = tsflag;
 869                         /* Test FAIL: message(s) */
 870                         (void) printf("%s\n", last_assert);
 871                         last_assert[0] = '\0'; /* reset */
 872                 } else {
 873                         apflag ++;
 874                         (void) printf("\tTest PASS\n");
 875                 }
 876                 last_assert[0] = '\0';
 877 
 878                 /* flush stdout and stderr before continuing */
 879                 (void) fflush(stdout);
 880                 (void) fflush(stderr);
 881                 break;
 882 
 883         case SCENARIO:
 884                 /* prints summary at the end of current test scenario */
 885                 /*  and updates status globals */
 886                 (void) fprintf(stdout, "\n\n");
 887                 dprint("A total of %d error(s) were found.\n",
 888                     errflag - serrflag);
 889                 dprint("A total of %d test step(s) failed.\n",
 890                     tsflag - stsflag);
 891                 dprint("A total of %d successful test step(s).\n",
 892                     tspflag - stspflag);
 893                 (void) print("Total assertion(s) failed %d and passed %d.\n",
 894                     aflag - saflag, apflag - sapflag);
 895                 if ((aflag - saflag) > 0)
 896                         ret = NOOK;
 897                 else if ((apflag - sapflag) == 0)
 898                         ret = UNTESTED;
 899 
 900                 serrflag = errflag;
 901                 stsflag = tsflag;
 902                 saflag = aflag;
 903                 stspflag = tspflag;
 904                 sapflag = apflag;
 905                 break;
 906 
 907         default:
 908                 (void) print("admerrors(%d): ERROR unknown command\n", cmd);
 909         }
 910 
 911         return (ret);
 912 }
 913 
 914 
 915 /*
 916  * ****************************************************************************
 917  * function     Whoami()
 918  * purpose      Returns either "Parent" or "Child" based on calling process.
 919  * arguments    None.
 920  * returns      String stating calling proccess identity.
 921  * ****************************************************************************
 922  */
 923 
 924 char *
 925 Whoami(void)
 926 {
 927         static char     parent[] = "Parent",
 928             child[]      = "Child";
 929 
 930         if (me == CHILD) {
 931                 return (child);
 932         } else {
 933                 return (parent);
 934         }
 935 }
 936 
 937 
 938 /*
 939  * ****************************************************************************
 940  * function     lock_reg()
 941  * purpose      Handle locks (regions of a files).
 942  * arguments    fd- file descriptor of targeted file.
 943  *              mand- mandatory flag as defined in common.h
 944  *              type- lock type as defined in fcntl().
 945  *              offset- starting offset of lock as described for fcntl().
 946  *              whence- lock base indicator as described for fcntl().
 947  *              len- length of lock as described for fcntl().
 948  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
 949  *              fail result code.
 950  * ****************************************************************************
 951  */
 952 
 953 int
 954 lock_reg(int fd, int mand, int type, off_t offset, int whence, off_t len)
 955 {
 956         struct flock lock;
 957         int cmd;
 958         int res;
 959 
 960         if (IS64BIT_OFF_T) {
 961                 dprint("Call to lock_reg(%d, %s, %s, %lld, %s, %lld).\n", fd,
 962                     mandtostr(mand), typetostr(type), offset,
 963                     whencetostr(whence), len);
 964         } else {
 965                 dprint("Call to lock_reg(%d, %s, %s, %ld, %s, %ld).\n", fd,
 966                     mandtostr(mand), typetostr(type), offset,
 967                     whencetostr(whence), len);
 968         }
 969 
 970         switch (mand) {
 971                 case 1: /* Non-blocking mandatory locking */
 972                         cmd = F_SETLK_NBMAND; break;
 973                 case 2: /* Blocking mandatory locking */
 974                         cmd = F_SETLKW; break;
 975                 default:        /* No mandatory locking */
 976                         cmd = F_SETLK;
 977         }
 978 
 979         /* global Non-Blocking locks substitute normal mandatory locks by */
 980         /*  checking lock_test first */
 981         if ((cmd == F_SETLKW) && (NBlocks)) {
 982                 pid_t pid;
 983                 int tmp;
 984 
 985                 tmp = debug;
 986                 debug = 0;
 987                 pid = lock_test(fd, type, offset, whence, len);
 988                 debug = tmp;
 989                 if (pid < 0) {
 990                         eprint("lock_reg()- lock_test() failed\n");
 991                         errno = OK;
 992                         return (NOOK);
 993                 } else if (pid > 0) {
 994                         if (IS64BIT_OFF_T) {
 995                                 dprint("lock_reg(%d, %s, %s, %lld, %s, %lld)-"\
 996                                     " lock already taken by %s.\n", fd,
 997                                     mandtostr(mand), typetostr(type),
 998                                     offset, whencetostr(whence), len,
 999                                     pidtostr(pid));
1000                         } else {
1001                                 dprint("lock_reg(%d, %s, %s, %ld, %s, %ld)-"\
1002                                     " lock already taken by %s.\n", fd,
1003                                     mandtostr(mand), typetostr(type),
1004                                     offset, whencetostr(whence), len,
1005                                     pidtostr(pid));
1006                         }
1007                         errno = OK;
1008                         return (NOOK);
1009                 } /* else pid == 0, OK to proceed */
1010         }
1011 
1012         /* perform actual lock using fcntl() */
1013         lock.l_type = type;
1014         lock.l_start = offset;
1015         lock.l_whence = whence;
1016         lock.l_len = len;
1017 
1018         if ((res = fcntl(fd, cmd, &lock)) == -1) {
1019                 if (IS64BIT_OFF_T) {
1020                         eprint("lock_reg()- Call to fcntl(%d, %s, {%s, %lld,"\
1021                             " %s, %lld}) failed\n", fd, cmdtostr(cmd),
1022                             typetostr(type), offset, whencetostr(whence),
1023                             len);
1024                 } else {
1025                         eprint("lock_reg()- Call to fcntl(%d, %s, {%s, %ld,"\
1026                             " %s, %ld}) failed\n", fd, cmdtostr(cmd),
1027                             typetostr(type), offset, whencetostr(whence),
1028                             len);
1029                 }
1030                 Perror("\t\t");
1031                 return (res);
1032         }
1033 
1034         if (IS64BIT_OFF_T) {
1035                 dprint("lock_reg(%d, %s, %s, %lld, %s, %lld) successful.\n",
1036                     fd, mandtostr(mand), typetostr(type), offset,
1037                     whencetostr(whence), len);
1038         } else {
1039                 dprint("lock_reg(%d, %s, %s, %ld, %s, %ld) successful.\n", fd,
1040                     mandtostr(mand), typetostr(type), offset,
1041                     whencetostr(whence), len);
1042         }
1043 
1044         errno = OK;
1045         return (res);   /* OK */
1046 }
1047 
1048 
1049 /*
1050  * ****************************************************************************
1051  * function     lock_test()
1052  * purpose      Test for ownership of lock (regions of a files).
1053  * arguments    fd- file descriptor of targeted file.
1054  *              type- lock type as defined in fcntl().
1055  *              offset- starting offset of lock as described for fcntl().
1056  *              whence- lock base indicator as described for fcntl().
1057  *              len- length of lock as described for fcntl().
1058  * returns      PID of process owner of lock (positive number), 0 if region is
1059  *              not locked, otherwise either NO OK (-1) or syscall fail result
1060  *              code.
1061  * ****************************************************************************
1062  */
1063 
1064 pid_t
1065 lock_test(int fd, int type, off_t offset, int whence, off_t len) {
1066         struct flock lock;
1067         int res;
1068 
1069         lock.l_type = type;
1070         lock.l_start = offset;
1071         lock.l_whence = whence;
1072         lock.l_len = len;
1073 
1074         if (IS64BIT_OFF_T) {
1075                 dprint("Call to lock_test(%d, %s, %lld, %s, %lld).\n", fd,
1076                         typetostr(type), offset,
1077                         whencetostr(whence), len);
1078         } else {
1079                 dprint("Call to lock_test(%d, %s, %ld, %s, %ld).\n", fd,
1080                         typetostr(type), offset,
1081                         whencetostr(whence), len);
1082         }
1083 
1084         if ((res = fcntl(fd,  F_GETLK, &lock)) < 0) {
1085                 if (IS64BIT_OFF_T) {
1086                         eprint("Call to lock_test(%d, %s, %lld, %s, %lld) "\
1087                                 "failed\n", fd, typetostr(type), offset,
1088                                 whencetostr(whence), len);
1089                 } else {
1090                         eprint("Call to lock_test(%d, %s, %ld, %s, %ld) "\
1091                                 "failed\n", fd, typetostr(type), offset,
1092                                 whencetostr(whence), len);
1093                 }
1094                 Perror("\t\t");
1095                 return (res);
1096         }
1097 
1098         if (IS64BIT_OFF_T) {
1099                 dprint("lock_test(%d, %s, %lld, %s, %lld) successful.\n",
1100                         fd, typetostr(type), offset, whencetostr(whence), len);
1101         } else {
1102                 dprint("lock_test(%d, %s, %ld, %s, %ld) successful.\n",
1103                         fd, typetostr(type), offset, whencetostr(whence), len);
1104         }
1105 
1106         if (lock.l_type == F_UNLCK) {
1107                 dprint("\tno lock assigned.\n");
1108 
1109                 errno = OK;
1110                 return (OK);
1111         } else {
1112                 pid_t pid = lock.l_pid;
1113 
1114                 dprint("\tthe owner of the lock is the %s.\n", pidtostr(pid));
1115 
1116                 errno = OK;
1117                 return (pid);
1118         }
1119 }
1120 
1121 /*
1122  * ****************************************************************************
1123  * function     ioFunc(...)
1124  * purpose      read or write data, check read/write func return value
1125  * arguments:
1126  *      $1 : file descriptor
1127  *      $2 : buffer which will save data for read, and provide data
1128  *           for write
1129  *      $3 : specify the number of bytes will written or read
1130  *      $4 : specify is read or write
1131  * return value: the number of bytes written or read is returned
1132  */
1133 ssize_t
1134 ioFunc(int fd, unsigned char *buf, size_t nbyte, int isread)
1135 {
1136         ssize_t tmp = 0;
1137         size_t bytes = 0;
1138 
1139         while (bytes != nbyte) {
1140                 if (isread == 1) {
1141                         tmp = read(fd, buf + bytes, nbyte - bytes);
1142                 } else {
1143                         tmp = write(fd, buf + bytes, nbyte - bytes);
1144                 }
1145 
1146                 if (tmp < 0) {
1147                         eprint("failed to read/write data, %s\n", \
1148                             strerror(errno));
1149                         // set return code as tmp to indicate
1150                         // the caller that IO failed
1151                         bytes = tmp;
1152                         break;
1153                 } else if ((tmp == 0) && (isread == 1)) {
1154                         dprint("read reach end of the file, bytes already \
1155                             read:%i\n", bytes);
1156                         break;
1157                 } else {
1158                         bytes += tmp;
1159                 }
1160         }
1161 
1162         return (bytes);
1163 }
1164 
1165 
1166 ssize_t
1167 nfsgenRead(int fd, void *buf, size_t nbyte)
1168 {
1169         ssize_t ret = ioFunc(fd, (unsigned char *)buf, nbyte, 1);
1170         return (ret);
1171 }
1172 
1173 
1174 ssize_t
1175 nfsgenWrite(int fd, void *buf, size_t nbyte)
1176 {
1177         ssize_t ret = ioFunc(fd, (unsigned char *)buf, nbyte, 0);
1178         return (ret);
1179 }
1180 
1181 
1182 /*
1183  * ****************************************************************************
1184  * function     create_test_data_file()
1185  * purpose      Create a small file (30 bytes) with a predefined content.
1186  * arguments    filename- path and filename for new file.
1187  *              mode- desired file permissions as defined in open().
1188  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
1189  *              fail result code.
1190  * ****************************************************************************
1191  */
1192 
1193 int
1194 create_test_data_file(char *filename, int mode) {
1195         int fd;
1196         int res;
1197         char buff[31] = "#123456789#123456789#123456789";
1198 
1199         dprint("Call to create_test_file(%s, 0%o).\n", filename, mode);
1200 
1201         if ((fd = open(filename, (O_RDWR | O_CREAT | O_TRUNC), 0600)) < 0) {
1202                 (void) print("Could not open %s\n", filename);
1203                 perror("\t\t");
1204                 exit_test(NOOK);
1205         }
1206 
1207         if ((res = nfsgenWrite(fd, buff, 30)) < 0) {
1208                 (void) print("Write to %s failed returned %d\n", filename, res);
1209                 perror("\t\t");
1210                 exit_test(NOOK);
1211         }
1212 
1213         if ((res = chmod_file(fd, filename, mode)) < 0) {
1214                 (void) print("Could not change file mode to %o\n", mode);
1215                 perror("\t\t");
1216                 exit_test(NOOK);
1217         }
1218 
1219         if ((res = close(fd)) < 0) {
1220                 (void) print("Close %s failed returned %d\n", filename, res);
1221                 perror("\t\t");
1222                 exit_test(NOOK);
1223         }
1224 
1225         dprint("test data file %s was succesfully created.\n", filename);
1226 
1227         errno = OK;
1228         return (OK);
1229 }
1230 
1231 
1232 /*
1233  * ****************************************************************************
1234  * function     create_10K_test_data_file()
1235  * purpose      Create a file (about 10Kbytes in size) with a predefined
1236  *              content written at intervals of 1K, but not aligned to the
1237  *              1K boundaries.
1238  * arguments    filename- path and filename for new file.
1239  *              mode- desired file permissions as defined in open().
1240  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
1241  *              fail result code.
1242  * ****************************************************************************
1243  */
1244 
1245 int
1246 create_10K_test_data_file(char *filename, int mode) {
1247         int fd;
1248         int res;
1249         off_t resl;
1250         char buff[] = "#123456789#1234567890";
1251         int i;
1252 
1253         dprint("Call to create_10K_test_file(%s, 0%o).\n", filename, mode);
1254 
1255         if ((fd = open(filename, (O_RDWR | O_CREAT | O_TRUNC), 0600)) < 0) {
1256                 (void) print("Could not open %s\n", filename);
1257                 perror("\t\t");
1258                 exit_test(NOOK);
1259         }
1260 
1261         /* write initial string at beggining of the file */
1262         if ((res = nfsgenWrite(fd, buff, 10)) < 0) {
1263                 (void) print("Write to %s failed returned %d\n", filename, res);
1264                 perror("\t\t");
1265                 exit_test(NOOK);
1266                 }
1267 
1268         for (i = 0; i < 10; i++) {
1269                 if ((resl = llseek(fd, 1014 + 1024*i, SEEK_SET)) == -1) {
1270                         (void) print("llseek failed on file %s returned %d\n",
1271                                 filename, resl);
1272                         perror("\t\t");
1273                         exit_test(NOOK);
1274                 }
1275 
1276                 /* Now just write the buf to the end of the file */
1277                 if ((res = nfsgenWrite(fd, buff, 10)) < 0) {
1278                         (void) print("Write to %s failed returned %d\n",
1279                                 filename, res);
1280                         perror("\t\t");
1281                         exit_test(NOOK);
1282                 }
1283         }
1284 
1285         if ((res = chmod_file(fd, filename, mode)) < 0) {
1286                 (void) print("Could not change file mode to %o\n", mode);
1287                 perror("\t\t");
1288                 exit_test(NOOK);
1289         }
1290 
1291         if ((res = close(fd)) < 0) {
1292                 (void) print("Close %s failed returned %d\n", filename, res);
1293                 perror("\t\t");
1294                 exit_test(NOOK);
1295         }
1296 
1297         dprint("10K test data file %s was succesfully created.\n", filename);
1298 
1299         errno = OK;
1300         return (OK);
1301 }
1302 
1303 /*
1304  * ****************************************************************************
1305  * function     pos_file()
1306  * purpose      Move a file pointer to specified position from start of file.
1307  * arguments    fd- file descriptor of target file.
1308  *              start- offset from start of file.
1309  * returns      newfile offset upon success, otherwise either NO OK (-1) or
1310  *              syscall fail result code.
1311  * ****************************************************************************
1312  */
1313 
1314 off_t
1315 pos_file(int fd, off_t start)
1316 {
1317         off_t res;
1318 
1319         if ((res = llseek(fd, start, SEEK_SET)) == -1) {
1320                 if (IS64BIT_OFF_T) {
1321                         eprint("pos_file(%d, %lld) failed returned %lld\n",
1322                             fd, start, res);
1323                 } else {
1324                         eprint("pos_file(%d, %ld) failed returned %ld\n",
1325                             fd, start, res);
1326                 }
1327                 Perror("\t\t");
1328                 return ((int)res);
1329         }
1330 
1331         if (IS64BIT_OFF_T) {
1332                 dprint("file (%d) pointer moved to %lld.\n",
1333                     fd, start);
1334         } else {
1335                 dprint("file (%d) pointer moved to %ld.\n",
1336                     fd, start);
1337         }
1338 
1339         errno = OK;
1340         return (res);   /* OK */
1341 }
1342 
1343 
1344 /*
1345  * ****************************************************************************
1346  * function     open_file()
1347  * purpose      Wraps syscall open() to handle log messages and errors.
1348  * arguments    Same as syscall open().
1349  * returns      filedescriptor upon success, otherwise either NO OK (-1) or
1350  *              syscall fail result code.
1351  * ****************************************************************************
1352  */
1353 
1354 int
1355 open_file(char *filename, int flags, int mode)
1356 {
1357         int     fd;
1358 
1359         dprint("Call to open_file(%s, %s, 0%o).\n", filename, oflagstr(flags),
1360             mode);
1361 
1362         if ((fd = open(filename, flags, mode)) < 0) {
1363                 if ((expecterr == NOOK) || (expecterr != errno)) {
1364                         (void) print("Open file %s,flags=%s,mode=0%o failed\n",
1365                             filename, oflagstr(flags), mode);
1366                         perror("\t\t");
1367                 } else {
1368                         eprint("Open file %s, flags=%s, mode=0%o failed\n",
1369                             filename, oflagstr(flags), mode);
1370                         Perror("\t\t");
1371                 }
1372                 return (fd);
1373         }
1374 
1375         dprint("Open file %s (flags=%s, mode=0%o fildes %d).\n",
1376             filename, oflagstr(flags), mode, fd);
1377 
1378         errno = OK;
1379         return (fd);    /* OK */
1380 }
1381 
1382 
1383 /*
1384  * ****************************************************************************
1385  * function     close_file()
1386  * purpose      Wraps syscall close() to handle log messages and errors.
1387  * arguments    fd- file descriptor to be used in close().
1388  *              filename- associated filename for log messages.
1389  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
1390  *              fail result code.
1391  * ****************************************************************************
1392  */
1393 
1394 int
1395 close_file(int fd, char *filename)
1396 {
1397         int res;
1398 
1399         dprint("Call to close_file(%d, %s).\n", fd, filename);
1400 
1401         if ((res = close(fd)) < 0) {
1402                 eprint("Close file %s, fildes %d failed\n",
1403                     filename, fd);
1404                 Perror("\t\t");
1405                 return (res);
1406         }
1407 
1408         dprint("file %s was closed.\n", filename);
1409 
1410         errno = OK;
1411         return (res);   /* OK */
1412 }
1413 
1414 
1415 /*
1416  * ****************************************************************************
1417  * function     chmod_file()
1418  * purpose      Wraps syscall fchmod() to handle log messages and errors.
1419  * arguments    fd- file descriptor to be used in fchmod().
1420  *              filename- associated filename for log messages.
1421  *              mode- mode parameter as described for fchmod().
1422  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
1423  *              fail result code.
1424  * ****************************************************************************
1425  */
1426 
1427 int
1428 chmod_file(int fd, char *filename,  mode_t mode)
1429 {
1430         int res;
1431 
1432         if ((res = fchmod(fd, mode)) < 0) {
1433                 eprint("fchmod(%d, 0%o) on %s failed\n", fd, mode, filename);
1434                 Perror("\t\t");
1435                 return (res);
1436         }
1437 
1438         dprint("File %s (fildes %d) mode was changed to 0%o.\n", filename, fd,
1439             mode);
1440 
1441         errno = OK;
1442         return (res);   /* OK */
1443 }
1444 
1445 
1446 /*
1447  * ****************************************************************************
1448  * function     link_file()
1449  * purpose      Wraps syscall link() to handle log messages and errors.
1450  * arguments    Same as syscall link().
1451  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
1452  *              fail result code.
1453  * ****************************************************************************
1454  */
1455 
1456 int
1457 link_file(char *old, char *new)
1458 {
1459         int res;
1460 
1461         dprint("Call to link_file(%s, %s).\n", old, new);
1462 
1463         if ((res = link(old, new)) < 0) {
1464                 if ((expecterr == NOOK) || (expecterr != errno)) {
1465                         (void) print("link(%s, %s) failed\n", old, new);
1466                         perror("\t\t");
1467                 } else {
1468                         eprint("link(%s, %s) failed\n", old, new);
1469                         Perror("\t\t");
1470                 }
1471                 return (res);
1472         }
1473 
1474         dprint("Hard link %s created, pointing to %s.\n", new, old);
1475 
1476         errno = OK;
1477         return (res);   /* OK */
1478 }
1479 
1480 
1481 /*
1482  * ****************************************************************************
1483  * function     unlink_file()
1484  * purpose      Wraps syscall unlink() to handle log messages and errors.
1485  * arguments    Same as syscall unlink().
1486  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
1487  *              fail result code.
1488  * ****************************************************************************
1489  */
1490 
1491 int
1492 unlink_file(char *filename)
1493 {
1494         int res;
1495 
1496         dprint("Call to unlink_file(%s).\n", filename);
1497 
1498         if ((res = unlink(filename)) < 0) {
1499                 eprint("Unlink file %s failed\n", filename);
1500                 Perror("\t\t");
1501                 return (res);
1502         }
1503 
1504         dprint("File %s was unlinked.\n", filename);
1505 
1506         errno = OK;
1507         return (res);   /* OK */
1508 }
1509 
1510 
1511 /*
1512  * ****************************************************************************
1513  * function     write_file()
1514  * purpose      Wraps syscalls lseek() and write() to handle log messages and
1515  *              errors. Additionally, based on global SYNCWRITE, calls fsync(),
1516  *              dirtyfile() and read_file() to make sure file is immediately
1517  *              updated at server (ignoring cache) and verifying the written
1518  *              information.
1519  * arguments    fd- file descriptor of targeted file.
1520  *              filename- correspondent filename for log messages purposes.
1521  *              datap- pointer to data to be written in file.
1522  *              offset- from start of file, where data is to be written.
1523  *                      a -1 causes to set it to file size
1524  *              count- size (number of bytes) of data to be written.
1525  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
1526  *              fail result code.
1527  * ****************************************************************************
1528  */
1529 
1530 int
1531 write_file(int fd, char *filename, char *datap, off_t offset, unsigned count)
1532 {
1533         int res;
1534         int result = OK;
1535         off_t resl;
1536         char *Datap;
1537         int append = offset == -1;
1538 
1539         if (offset == -1) {     /* move to EOF */
1540                 statfile(fd, filename);
1541                 offset = Stat.st_size;
1542                 dprint("offset to use: %lld\n", (long long) offset);
1543         }
1544 
1545         if ((Datap = malloc(count + 256)) == NULL) {
1546                 (void) print("write_file() out of mem. Aborting ...\n");
1547                 perror("\t\t");
1548                 exit_test(NOOK);
1549         }
1550 
1551         (void) strlcpy(Datap, datap, 31);
1552         if (strlen(datap) > 30)
1553                 strcat(Datap, " ...");
1554         if (IS64BIT_OFF_T) {
1555                 dprint("Call to write_file(%d, %s, %s, %lld, %u).\n", fd,
1556                     filename, Datap, offset, count);
1557         } else {
1558                 dprint("Call to write_file(%d, %s, %s, %ld, %u).\n", fd,
1559                     filename, Datap, offset, count);
1560         }
1561 
1562         (void) strncpy(Datap, datap, count);
1563         Datap[count] = '\0';
1564 
1565         if ((resl = lseek(fd, offset, SEEK_SET)) < 0) {
1566                 if (IS64BIT_OFF_T) {
1567                         eprint("write_file(%d, %s, %s, %lld, %u) "\
1568                             "lseek failed\n",
1569                             fd, filename, datap, offset, count);
1570                 } else {
1571                         eprint("write_file(%d, %s, %s, %ld, %u) "\
1572                             "lseek failed\n",
1573                             fd, filename, datap, offset, count);
1574                 }
1575                 Perror("\t\t");
1576                 free(Datap);
1577                 return (resl);
1578         }
1579         if (IS64BIT_OFF_T) {
1580                 dprint("write_file(%d, %s, %s, %lld, %u) "\
1581                     "lseek succeed\n",
1582                     fd, filename, datap, offset, count);
1583         } else {
1584                 dprint("write_file(%d, %s, %s, %ld, %u) "\
1585                     "lseek succeed\n",
1586                     fd, filename, datap, offset, count);
1587         }
1588 
1589         if (mmflag == 1) {
1590                 size_t size = (size_t)(offset + count);
1591                 off_t osize = size; /* for mmapfile */
1592                 void *Uaddr = NULL;
1593                 char *start = NULL;
1594                 size_t i;
1595 
1596                 /* adjust size to include new data */
1597                 if (append)
1598                         truncatefile(fd, filename, osize);
1599                 dprint("size (%llu) = offset (%llu) + count (%llu)\n",
1600                     (long long)size, (long long)offset, (long long)count);
1601                 if ((res = mmapfile(fd, (char **)&Uaddr, (off_t)0L,
1602                     &osize, MMREAD|MMWRITE)) != 0) {
1603                         eprint("write_file-mmapfile(%p, 0, %lld, %s) failed.\n",
1604                             Uaddr, (long long)osize,
1605                             mmtypetostr(MMREAD|MMWRITE));
1606                         return (res);
1607                 }
1608                 size = osize;
1609 
1610                 start = (char *)Uaddr + offset;
1611                 dprint("start (%p) = Uaddr (%p) + offset (0x%llx)\n",
1612                     (char *)start, (char *)Uaddr, (long long)offset);
1613                 (void) memcpy(start, datap, (size_t)count);
1614                 dprint("write- memcpy(to=%p, from=%p, size=0x%lx)\n",
1615                     start, datap, (size_t)count);
1616                 munmapfile(Uaddr, osize);
1617         } else {
1618                 if ((res = nfsgenWrite(fd, datap, count)) < 0) {
1619                         eprint("Cannot write to file %s.\n", filename);
1620                         Perror("\t\t");
1621                         free(Datap);
1622                         return (res);
1623                 }
1624 
1625                 if (res != count) {
1626                         eprint("Bad write len to file %s, got %u,"
1627                             " expected %d\n", filename, res, count);
1628                         /* adjust if wrote shorter string */
1629                         Datap[count] = '\0';
1630 
1631                         result = NOOK;
1632                 }
1633         }
1634 
1635         if (IS64BIT_OFF_T) {
1636                 dprint("Wrote <%.32s> to %s [ %lld, %u ].\n",
1637                     Datap, filename, offset, count);
1638         } else {
1639                 dprint("Wrote <%.32s> to %s [ %ld, %u ].\n",
1640                     Datap, filename, offset, count);
1641         }
1642 
1643         if (SYNCWRITE) {
1644                 size_t size = (size_t)(offset + count);
1645                 int tmp = debug;
1646                 int ress;
1647 
1648                 if ((ress = fsync(fd)) < 0) {
1649                         eprint("write_file()- fsync() failed\n");
1650                         Perror("\t\t");
1651                 }
1652                 /* invalidate cache is done at read_file() */
1653                 debug = 0;
1654                 if ((ress = read_file(fd, filename, Datap, offset, count))
1655                     < 0) {
1656                         eprint("write_file()- read error in data "\
1657                             "written\n");
1658 
1659                         result = NOOK;
1660                 }
1661                 debug = tmp;
1662 
1663                 if (strncmp(datap, Datap, (size_t)count) != 0) {
1664                         (void) print("Write_file()- Warning, read mismatch: "\
1665                             "Expected '%s', read '%s'\n",
1666                             datap, Datap);
1667                         result = NOOK;
1668                 }
1669         }
1670 
1671         free(Datap);
1672 
1673         errno = OK;
1674         return (result);
1675 }
1676 
1677 
1678 /*
1679  * ****************************************************************************
1680  * function     read_file()
1681  * purpose      Wraps syscalls lseek() and read() to handle log messages and
1682  *              errors. Additionally, based on global SYNCWRITE, calls
1683  *              dirtyfile() to make sure file is immediately read from server
1684  *              (ignoring cache) and verifying the read information.
1685  * arguments    fd- file descriptor of targeted file.
1686  *              filename- correspondent filename for log messages purposes.
1687  *              datap- pointer to data to be read from file.
1688  *              offset- from start of file, where data is to be read from.
1689  *              count- size (number of bytes) of data to be read.
1690  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
1691  *              fail result code.
1692  * ****************************************************************************
1693  */
1694 
1695 int
1696 read_file(int fd, char *filename, char *datap, off_t offset, unsigned count)
1697 {
1698         int res;
1699         int result = 0;
1700         off_t resl;
1701 
1702         if (IS64BIT_OFF_T) {
1703                 dprint("Call to read_file(%d, %s, %pp, %lld, %u).\n", fd,
1704                     filename, datap, offset, count);
1705         } else {
1706                 dprint("Call to read_file(%d, %s, %pp, %ld, %u).\n", fd,
1707                     filename, datap, offset, count);
1708         }
1709 
1710         if (mmflag == 1) {
1711                 size_t size = (size_t)(offset + count);
1712                 off_t osize = size; /* for mmapfile */
1713                 void *Uaddr = NULL;
1714                 char *start = NULL;
1715 
1716                 dprint("size (%llu) = offset (%llu) + count (%llu)\n",
1717                     (long long)size, (long long)offset, (long long)count);
1718                 if ((res = mmapfile(fd, (char **)&Uaddr, (off_t)0L, \
1719                     &osize, MMREAD)) != 0) {
1720                         eprint("read_file-mmapfile(%p, 0, %lld, %s) failed.\n",
1721                             Uaddr, (long long)osize, mmtypetostr(MMREAD));
1722                         return (res);
1723                 }
1724                 size = osize;
1725 
1726                 start = (char *)Uaddr + offset;
1727                 dprint("start (%p) = Uaddr (%p) + offset (0x%llx)\n",
1728                     (char *)start, (char *)Uaddr, (long long)offset);
1729                 (void) memcpy(datap, start, (size_t)count);
1730                 dprint("read- memcpy(to=%p, from=%p, size=0x%lx).\n",
1731                     datap, start, (size_t)count);
1732 
1733                 munmapfile(Uaddr, osize);
1734                 /* null terminate string */
1735                 datap[count] = '\0';
1736                 if (IS64BIT_OFF_T) {
1737                         dprint("Read <%.32s> from %s [ %lld, %u ].\n",
1738                             datap, filename, offset, count);
1739                 } else {
1740                         dprint("Read <%.32s> from %s [ %ld, %u ].\n",
1741                             datap, filename, offset, count);
1742                 }
1743                 errno = OK;
1744                 return (OK);
1745         }
1746 
1747         /* invalidate cache to force a read from server */
1748         if (SYNCWRITE) {
1749                 size_t size = (size_t)(offset + count);
1750 
1751                 if ((res = dirtyfile(fd, filename, size)) < 0) {
1752                         if (IS64BIT_OFF_T) {
1753                                 eprint("read_file()- "\
1754                                     "dirtyfile(%d, %s, %lld) failed\n",
1755                                     fd, filename, size);
1756                                 } else {
1757                                 eprint("read_file()- "\
1758                                     "dirtyfile(%d, %s, %ld) failed\n",
1759                                     fd, filename, size);
1760                                 }
1761                 }
1762         }
1763 
1764         if ((resl = lseek(fd, offset, SEEK_SET)) < 0) {
1765                 if (IS64BIT_OFF_T) {
1766                         eprint("read_file(%d, %s, %pp, %lld, %u) "\
1767                             "lseek failed\n",
1768                             fd, filename, datap, offset, count);
1769                 } else {
1770                         eprint("read_file(%d, %s, %pp, %ld, %u) "\
1771                             "lseek failed\n",
1772                             fd, filename, datap, offset, count);
1773                 }
1774                 Perror("\t\t");
1775                 return (resl);
1776         }
1777         if (IS64BIT_OFF_T) {
1778                 dprint("read_file(%d, %s, %pp, %lld, %u) lseek succeed\n",
1779                     fd, filename, datap, offset, count);
1780         } else {
1781                 dprint("read_file(%d, %s, %pp, %ld, %u) lseek succeed\n",
1782                     fd, filename, datap, offset, count);
1783         }
1784 
1785         if ((res = nfsgenRead(fd, datap, count)) < 0) {
1786                 eprint("Cannot read to file %s.\n", filename);
1787 
1788                 Perror("\t\t");
1789                 return (res);
1790         }
1791         /* null terminate string */
1792         datap[count] = '\0';
1793 
1794         if (res != count) {
1795                 eprint("Bad read len from file %s, got %d, expected %u\n",
1796                     filename, res, count);
1797                 datap[res] = '\0';      /* adjust if wrote short string */
1798                 result = NOOK;
1799         }
1800 
1801         if (IS64BIT_OFF_T) {
1802                 dprint("Read <%.32s> from %s [ %lld, %u ].\n",
1803                     datap, filename, offset, count);
1804         } else {
1805                 dprint("Read <%.32s> from %s [ %ld, %u ].\n",
1806                     datap, filename, offset, count);
1807         }
1808 
1809         /* If GLOBdata is non-null, make sure the bytes read are the same as */
1810         /*  what datap points to */
1811         if ((GLOBdata != NULL) && (strncmp(GLOBdata, datap, count) != 0)) {
1812                 (void) print("Read test warning. Expected '%s', read '%s'\n",
1813                     GLOBdata, datap);
1814                 result = NOOK;
1815         }
1816 
1817         errno = OK;
1818         return (result);
1819 }
1820 
1821 
1822 /*
1823  * ****************************************************************************
1824  * function     strbackup()
1825  * purpose      Stores a copy of data used in read_file() in global "GLOBdata".
1826  *              If GLOBdata is NULL (no mem allocated), no action is taken.
1827  * arguments    data- to be stored in "GLOBdata".
1828  * returns      Pointer to GLOBdata storage area, or data parameter value if
1829  *              GLOBdata has no memory allocated (is NULL).
1830  * ****************************************************************************
1831  */
1832 
1833 char *
1834 strbackup(char *data)
1835 {
1836         if (GLOBdata != NULL) {
1837                 (void) strcpy(GLOBdata, data);
1838                 dprint("'%s' stored in global test var.\n", data);
1839                 return (GLOBdata);
1840         } else {
1841                 dprint("strbackup() global test var no memory allocated\n");
1842                 return (data);
1843         }
1844 }
1845 
1846 
1847 /*
1848  * ****************************************************************************
1849  * function     dup_file()
1850  * purpose      Wraps syscall dup() to handle log messages and errors.
1851  * arguments    Same as syscall dup().
1852  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
1853  *              fail result code.
1854  * ****************************************************************************
1855  */
1856 
1857 int
1858 dupfile(int fdo)
1859 {
1860         int fd;
1861 
1862         dprint("Call to dupfile(%d).\n", fdo);
1863         if ((fd = dup(fdo)) < 0) {
1864                 if ((expecterr == NOOK) || (expecterr != errno)) {
1865                         (void) print("dupfile(%d) failed\n", fdo);
1866                         perror("\t\t");
1867                 } else {
1868                         eprint("dupfile(%d) failed\n", fdo);
1869                         Perror("\t\t");
1870                 }
1871                 return (fd);
1872         }
1873 
1874         dprint("Fildes %d was dupped in fildes %d.\n", fdo, fd);
1875 
1876         errno = OK;
1877         return (fd);    /* OK */
1878 }
1879 
1880 
1881 /*
1882  * ****************************************************************************
1883  * function     Seteuid()
1884  * purpose      Wraps syscall seteuid() to handle log messages and errors.
1885  * arguments    Same as syscall seteuid().
1886  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
1887  *              fail result code.
1888  * ****************************************************************************
1889  */
1890 
1891 int
1892 Seteuid(uid_t uid)
1893 {
1894         int res;
1895 
1896         dprint("Call to seteuid(%d).\n", uid);
1897 
1898         if ((res = seteuid(uid)) < 0) {
1899                 eprint("seteuid(%d) failed\n", uid);
1900                 Perror("\t\t");
1901                 return (res);
1902         }
1903 
1904         dprint("Effective UID set to %d.\n", uid);
1905 
1906         errno = OK;
1907         return (res);   /* OK */
1908 }
1909 
1910 
1911 /*
1912  * ****************************************************************************
1913  * function     Setegid()
1914  * purpose      Wraps syscall setegid() to handle log messages and errors.
1915  * arguments    Same as syscall setegid().
1916  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
1917  *              fail result code.
1918  * ****************************************************************************
1919  */
1920 
1921 int
1922 Setegid(gid_t gid)
1923 {
1924         int res;
1925 
1926         dprint("Call to setegid(%d).\n", gid);
1927 
1928         if ((res = setegid(gid)) < 0) {
1929                 eprint("setegid(%d) failed\n", gid);
1930                 Perror("\t\t");
1931                 return (res);
1932         }
1933 
1934         dprint("Effective GID set to %d.\n", gid);
1935 
1936         errno = OK;
1937         return (res);   /* OK */
1938 }
1939 
1940 
1941 /*
1942  * ****************************************************************************
1943  * function     Setgroups()
1944  * purpose      Wraps syscall setgroups() to handle log messages and errors.
1945  * arguments    Same as syscall setgroups().
1946  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
1947  *              fail result code.
1948  * ****************************************************************************
1949  */
1950 
1951 int
1952 Setgroups(int n, gid_t *gids)
1953 {
1954         int res;
1955         int i;
1956         char buf[2048], buf2[256];
1957 
1958         (void) snprintf(buf, 2048, "{%ld", (long)gids[0]);
1959         for (i = 1; i < n; i++) {
1960                 (void) snprintf(buf2, 256, ", %ld", (long)gids[i]);
1961                 (void) strcat(buf, buf2);
1962         }
1963         (void) strcat(buf, "}");
1964 
1965         dprint("Call to setgroups(%d, %s).\n", n, buf);
1966 
1967         if ((res = setgroups(n, gids)) < 0) {
1968                 eprint("setgroups(%d, %s) failed\n", buf);
1969                 Perror("\t\t");
1970                 return (res);
1971         }
1972 
1973         dprint("Supplemental groups set to %s.\n", buf);
1974 
1975         errno = OK;
1976         return (res);   /* OK */
1977 }
1978 
1979 
1980 /*
1981  * ****************************************************************************
1982  * function     truncatefile()
1983  * purpose      Wraps syscall ftruncate() to handle log messages and errors.
1984  * arguments    Same as syscall ftruncate() plus:
1985  *              filename- correspondent filename used for log messages.
1986  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
1987  *              fail result code.
1988  * ****************************************************************************
1989  */
1990 int
1991 truncatefile(int fd, char *filename, off_t offset)
1992 {
1993         int res;
1994 
1995         if (IS64BIT_OFF_T) {
1996                 dprint("Call to truncatefile(%d, %s, %lld).\n", fd, filename,
1997                     offset);
1998         } else {
1999                 dprint("Call to truncatefile(%d, %s, %ld).\n", fd, filename,
2000                     offset);
2001         }
2002 
2003         if ((res = ftruncate(fd, offset)) < 0) {
2004                 if (IS64BIT_OFF_T) {
2005                         eprint("truncatefile(%d, %s, %lld) failed\n",
2006                             fd, filename, offset);
2007                 } else {
2008                         eprint("truncatefile(%d, %s, %ld) failed\n",
2009                             fd, filename, offset);
2010                 }
2011                 Perror("\t\t");
2012                 return (res);
2013         }
2014 
2015         if (IS64BIT_OFF_T) {
2016                 dprint("File %s truncated to %lld.\n",
2017                     filename, offset);
2018         } else {
2019                 dprint("File %s truncated to %ld.\n",
2020                     filename, offset);
2021         }
2022 
2023         errno = OK;
2024         return (res);   /* OK */
2025 }
2026 
2027 
2028 /*
2029  * ****************************************************************************
2030  * function     statfile()
2031  * purpose      Wraps syscall fstat() to handle log messages and errors.
2032  * arguments    Same as syscall fstat() plus:
2033  *              filename- correspondent filename used for log messages.
2034  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
2035  *              fail result code.
2036  * ****************************************************************************
2037  */
2038 int
2039 statfile(int fd, char *filename)
2040 {
2041         int res;
2042 
2043         dprint("Call to statfile(%d, %s).\n", fd, filename);
2044 
2045         if ((res = fstat(fd, &Stat)) < 0) {
2046                 eprint("statfile(%d, %s) failed\n", fd, filename);
2047                 Perror("\t\t");
2048                 return (res);
2049         }
2050 
2051         dprint("File %s stats were gathered.\n", filename);
2052 
2053         errno = OK;
2054         return (res);   /* OK */
2055 }
2056 
2057 
2058 /*
2059  * ****************************************************************************
2060  * function     mmapfile()
2061  * purpose      Wraps syscall mmap() to handle log messages and errors.
2062  * arguments    Simplified version of syscall mmap():
2063  *              fd- file descriptor of targeted file.
2064  *              mapaddr- address of pointer var to hold area assigned in
2065  *                      mapping.
2066  *              offset- from start of file to be mappen into memory.
2067  *              len- pointer to size of area to be mapped (will be adjusted to
2068  *                      pagesize and then updated).
2069  *              type-   type of the mmap (READ, WRITE or both).
2070  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
2071  *              fail result code.
2072  * ****************************************************************************
2073  */
2074 
2075 int
2076 mmapfile(int fd, char **mapaddr, off_t offset, off_t *len, int type)
2077 {
2078         size_t size;
2079         int rem;
2080         int page;
2081         void *addr = 0;
2082         int tflag = 0;
2083 
2084         if (IS64BIT_OFF_T) {
2085                 dprint("Call to mmapfile(%d, %pp, %lld, %lld, %s).\n", fd,
2086                     *mapaddr, offset, *len, mmtypetostr(type));
2087         } else  {
2088                 dprint("Call to mmapfile(%d, %pp, %ld, %ld, %s).\n", fd,
2089                     *mapaddr, offset, *len, mmtypetostr(type));
2090         }
2091 
2092         page = sysconf(_SC_PAGESIZE);   /* page size */
2093 
2094         /* get mem size multiple of page size */
2095         size = offset / (off_t)page;
2096         offset = size;
2097 
2098         if ((type & MMREAD) != 0)
2099                 tflag |= PROT_READ;
2100         if ((type & MMWRITE) != 0)
2101                 tflag |= PROT_WRITE;
2102 
2103         size = *len;
2104         *mapaddr = mmap(addr, size, tflag, MAP_SHARED, fd, offset);
2105         if (*mapaddr == MAP_FAILED) {
2106                 if (IS64BIT_OFF_T) {
2107                         eprint("Call to mmap(%pp, %lld, %s, MAP_SHARED, "
2108                             "%d, %lld) failed\n",
2109                             addr, size, mmtypetostr(type), fd, offset);
2110                 } else {
2111                         eprint("Call to mmap(%pp, %ld, %s, MAP_SHARED,"
2112                             " %d, %ld) failed\n",
2113                             addr, size, mmtypetostr(type), fd, offset);
2114                 }
2115                 Perror("\t\t");
2116                 return (errno);
2117         }
2118 
2119         if (IS64BIT_OFF_T) {
2120                 dprint("Call to mmap(%pp, %lld, %s, MAP_SHARED,"
2121                     " %d, %lld) successful\n",
2122                     addr, size, mmtypetostr(type), fd, offset);
2123         } else {
2124                 dprint("Call to mmap(%pp, %ld, %s, MAP_SHARED,"
2125                     " %d, %ld) successful\n",
2126                     addr, size, mmtypetostr(type), fd, offset);
2127         }
2128 
2129         errno = OK;
2130         return (OK);
2131 }
2132 
2133 
2134 /*
2135  * ****************************************************************************
2136  * function     munmapfile()
2137  * purpose      Wraps syscall munmap() to handle log messages and errors.
2138  * arguments    Same as syscall munmap():
2139  * returns      OK (0) upon success, otherwise either NO OK (-1) or syscall
2140  *              fail result code.
2141  * ****************************************************************************
2142  */
2143 
2144 int
2145 munmapfile(char *mapaddr, off_t len)
2146 {
2147         int res;
2148 
2149         if (IS64BIT_OFF_T) {
2150                 dprint("Call to munmapfile(%pp, %lld).\n", mapaddr, len);
2151         } else {
2152                 dprint("Call to munmapfile(%pp, %ld).\n", mapaddr, len);
2153         }
2154 
2155         if ((res = munmap(mapaddr, (size_t)len)) < 0) {
2156                 if (IS64BIT_OFF_T) {
2157                         eprint("Call to munmap(%pp, %lld) failed\n",
2158                             mapaddr, len);
2159                 } else {
2160                         eprint("Call to munmap(%pp, %ld) failed\n",
2161                             mapaddr, len);
2162                 }
2163                 Perror("\t\t");
2164                 return (res);
2165         }
2166 
2167         if (IS64BIT_OFF_T) {
2168                 dprint("Call to munmap(%pp, %lld) successful.\n",
2169                     mapaddr,  len);
2170         } else {
2171                 dprint("Call to munmap(%pp, %ld) successful.\n",
2172                     mapaddr,  len);
2173         }
2174 
2175         mapaddr = (caddr_t)0xdeadbeef;
2176 
2177         errno = OK;
2178         return (OK);
2179 }
2180 
2181 
2182 /*
2183  * ****************************************************************************
2184  * function     dirtyfile()
2185  * purpose      Use memory mapping to invalidate client cache and force
2186  *              operations from server.
2187  * arguments    fd- file descriptor of targeted file.
2188  *              filename- correspondent file for log messages.
2189  *              size of area to be mapped from offset 0. (XXX improve to value)
2190  * returns      OK (0) upon success, otherwise NO OK (-1).
2191  * ****************************************************************************
2192  */
2193 
2194 int
2195 dirtyfile(int fd, char *filename, size_t size)
2196 {
2197         size_t  len;
2198         int     rem;
2199         int     page;
2200         void    *addr;
2201 
2202 
2203         page = sysconf(_SC_PAGESIZE);   /* page size */
2204 
2205         /* get mem size multiple of page size */
2206         rem = size % (off_t)page;
2207         len = size / (off_t)page;
2208         len += (rem > 0) ? page : 0;
2209 
2210         if ((addr = mmap((caddr_t)0, size, PROT_READ, MAP_PRIVATE, fd,
2211             (off_t)0)) == NULL) {
2212                 if (IS64BIT_OFF_T) {
2213                         eprint("dirtyfile(%d, %s, %lld) (mmap) failed\n",
2214                             fd, filename, size);
2215                 } else {
2216                         eprint("dirtyfile(%d, %s, %ld) (mmap) failed\n",
2217                             fd, filename, size);
2218                 }
2219                 Perror("\t\t");
2220                 return (NOOK);
2221         }
2222         if (msync(addr, len, MS_INVALIDATE) < 0) {
2223                 if (IS64BIT_OFF_T) {
2224                         eprint("dirtyfile(%d, %s, %lld) (msync) failed\n",
2225                             fd, filename, size);
2226                 } else {
2227                         eprint("dirtyfile(%d, %s, %ld) (msync) failed\n",
2228                             fd, filename, size);
2229                 }
2230                 Perror("\t\t");
2231                 return (NOOK);
2232         }
2233         if (munmap(addr, (size_t)size) < 0) {
2234                 if (IS64BIT_OFF_T) {
2235                         eprint("dirtyfile(%d, %s, %lld) (munmap) failed\n",
2236                             fd, filename, size);
2237                 } else {
2238                         eprint("dirtyfile(%d, %s, %ld) (munamp) failed\n",
2239                             fd, filename, size);
2240                 }
2241                 Perror("\t\t");
2242                 return (NOOK);
2243         }
2244 
2245         dprint("dirtyfile() on file %s (fildes %d) was successful.\n",
2246             filename, fd);
2247 
2248         errno = OK;
2249         return (OK);
2250 }
2251 
2252 
2253 /*
2254  * ****************************************************************************
2255  * function     get_deleg()
2256  * purpose      queries what delegation type was granted to the file specified
2257  *              by fd.
2258  * arguments    fd- file descriptor of targeted file.
2259  *              filename- correspondent file for log messages.
2260  * returns      delegation type upon success, otherwise NO OK (-1).
2261  *              If run on a server, it returns NO OK (-1).
2262  * ****************************************************************************
2263  */
2264 
2265 int
2266 get_deleg(int fd, char *filename)
2267 {
2268         struct nfs4_svc_args nsa;
2269         int dt = NOOK;
2270 
2271         if (srv_local == 0) {
2272                 nsa.fd = fd;
2273                 nsa.cmd = NFS4_DQUERY;
2274                 nsa.netid = (char *)&dt;
2275 
2276                 if (_nfssys(NFS4_SVC, &nsa)) {
2277                         eprint("_nfssys NFS4_SVC\n");
2278                         Perror("\t\t");
2279                         return (NOOK);
2280                 }
2281         } else {
2282                 dt = NOOK;
2283         }
2284 
2285         print("delegation type granted for file %s is %d\n", filename, dt);
2286 
2287         return (dt);
2288 }
2289 
2290 
2291 /*
2292  * ****************************************************************************
2293  * function     exit_test()
2294  * purpose      Gracefully exit testcase when parent and child exist. It
2295  *              restore some signals, pass testcase statistics (pass & fail
2296  *              type) from child to parent, prints those statistics, killing
2297  *              related process when needed, and Parents waits for child to
2298  *              exit.
2299  * arguments    Exit code to be used typically OK (0) upon success,
2300  *              otherwise NO OK (-1).
2301  * returns      nothing.
2302  * ****************************************************************************
2303  */
2304 
2305 void
2306 exit_test(int code)
2307 {
2308         pid_t Pid = 0;
2309         static int once = 0;
2310         int status;
2311 
2312 
2313         dprint("Call to exit_test(%d)\n", code);
2314         if (PidChild ==  -1)
2315                 goto DONE;
2316         if (me == PARENT) {
2317                 dprint("signal(SIGCLD, SIG_DFL) issued.\n");
2318                 signal(SIGCLD, SIG_DFL);
2319                 Pid = PidChild;
2320         } else {
2321                 Pid = PidParent;
2322         }
2323 
2324         if (code == OK) {
2325                 if (me == PARENT) {
2326                         contch();
2327                 } else {
2328                         waitch();
2329                 }
2330         }
2331 
2332         if (Pid >= 0) {
2333                 if ((once == 0) && (code != OK)) {
2334                         once++; /* send signal once */
2335                         dprint("signal(SIGINT, SIG_IGN) issued.\n");
2336                         signal(SIGINT, SIG_IGN);
2337                         dprint("kill(%s, SIGINT) issued.\n",
2338                             (Pid == PidChild) ? "Child" : "Parent");
2339                         kill(Pid, SIGINT);
2340                 }
2341         }
2342 
2343         if (code == OK) {
2344                 if (me == PARENT) {
2345                         if (PidChild >= 0) {
2346                                 decode_errors();
2347                                 wait(&status);
2348                         }
2349                 } else {
2350                         encode_errors();
2351                 }
2352         }
2353 
2354 DONE:
2355         Glob_status = code;
2356         exit(code);
2357 }
2358 
2359 
2360 /*
2361  * ****************************************************************************
2362  * function     kill_child()
2363  * purpose      Gracefully terminates child process.
2364  *              Parent restores some signals, and notify child to execute this
2365  *              function. Gets testcase statistics from child, closes its
2366  *              communication pipes to it, and waits for its exit.
2367  *              Child prints testcase statistics, send parent those statistics,
2368  *              close communications pipes and exits.
2369  * arguments    sig- not really used, but required by signal system syscall.
2370  * returns      nothing.
2371  * ****************************************************************************
2372  */
2373 
2374 void
2375 kill_child(int sig)
2376 {
2377         int status;
2378 
2379         dprint("Call to kill_child(%d)\n", sig);
2380         if (me == PARENT) {
2381                 int status;
2382 
2383                 dprint("Killing Child.\n");
2384 
2385                 dprint("signal(SIGCLD, SIG_DFL) issued.\n");
2386                 signal(SIGCLD, SIG_DFL);
2387                 if (PidChild != -1) {
2388                         dprint("kill(Child, SIGUSR1) issued.\n");
2389                         kill(PidChild, SIGUSR1);
2390                 } else {
2391                         print("kill_child()- Warning: child pid is unvalid,"\
2392                             " (already dead?).\n");
2393                         return;
2394                 }
2395 
2396                 waitp();
2397                 dprint("kill - decode()\n");
2398                 decode_errors();
2399 
2400                 /* close pipes */
2401                 close(PChild[1]);
2402                 dprint("Fildes %d (pipe end PChild[1]) was closed.\n",
2403                     PChild[1]);
2404                 close(PParent[0]);
2405                 dprint("Fildes %d (pipe end PParent[0]) was closed.\n",
2406                     PParent[0]);
2407 
2408                 wait(&status);
2409                 dprint("Child exited with status %d\n", status);
2410 
2411                 PidChild = -1;
2412 
2413         } else { /* child */
2414                 admerrors(TOTALS);
2415 
2416                 contp();
2417                 dprint("kill - encode()\n");
2418                 encode_errors();
2419 
2420                 /* close pipes */
2421                 close(PChild[0]);
2422                 dprint("Fildes %d (pipe end PChild[0]) was closed.\n",
2423                     PChild[0]);
2424                 close(PParent[1]);
2425                 dprint("Fildes %d (pipe end PParent[1]) was closed.\n",
2426                     PParent[1]);
2427 
2428                 exit(OK);
2429         }
2430 }
2431 
2432 
2433 /*
2434  * ****************************************************************************
2435  * function     encode_errors()
2436  * purpose      Child sends the parent, its testcase execution (pass &
2437  *              fail type) statistics.
2438  * arguments    none.
2439  * returns      nothing.
2440  * ****************************************************************************
2441  */
2442 
2443 void
2444 encode_errors(void)
2445 {
2446         dprint("Call to encode_errors()\n");
2447         sendintp(errflag);
2448         sendintp(tsflag);
2449         sendintp(aflag);
2450         sendintp(tspflag);
2451         sendintp(apflag);
2452 }
2453 
2454 
2455 /*
2456  * ****************************************************************************
2457  * function     decode_errors()
2458  * purpose      Parent receives its child testcase execution (pass &
2459  *              fail type) statistics.
2460  * arguments    none.
2461  * returns      nothing.
2462  * ****************************************************************************
2463  */
2464 
2465 void
2466 decode_errors(void)
2467 {
2468         int a, ts, err, ap, tsp;
2469 
2470         dprint("Call to decode_errors()\n");
2471         err = getintp();
2472         dprint("Child reported %d errors.\n", err);
2473         ts = getintp();
2474         dprint("Child reported %d test steps failed.\n", ts);
2475         a = getintp();
2476         dprint("Child reported %d assertions failed.\n", a);
2477         tsp = getintp();
2478         dprint("Child reported %d test steps passed.\n", tsp);
2479         ap = getintp();
2480         dprint("Child reported %d assertions passed.\n", ap);
2481 
2482         errflag += err;
2483         tsflag += ts;
2484         tsprev += ts;
2485         aflag += a;
2486         tspflag += tsp;
2487         apflag += ap;
2488 
2489         if (debug) {
2490                 admerrors(TOTALS);
2491         }
2492 }
2493 
2494 
2495 /*
2496  * ****************************************************************************
2497  * function     notify_parent()
2498  * purpose      Used to handle signals and terminate testcase gracefully.
2499  *              It is issued by the system only.
2500  * arguments    Signal received by system.
2501  * returns      nothing.
2502  * ****************************************************************************
2503  */
2504 
2505 void
2506 notify_parent(int sig)
2507 {
2508         print("Call to notify_parent(signal received %s)\n", sigtostr(sig));
2509         perror("last error registered: ");
2510 
2511         exit_test(NOOK);
2512 }
2513 
2514 
2515 /*
2516  * ****************************************************************************
2517  * function     notify_child()
2518  * purpose      Used to handle signals and terminate testcase gracefully.
2519  *              It is issued by the system only.
2520  * arguments    Signal received by system.
2521  * returns      nothing.
2522  * ****************************************************************************
2523  */
2524 
2525 void
2526 notify_child(int sig)
2527 {
2528         (void) print("Call to notify_child(signal received %s)\n",
2529             sigtostr(sig));
2530         perror("last error registered: ");
2531 
2532         exit_test(NOOK);
2533 }
2534 
2535 
2536 /*
2537  * ****************************************************************************
2538  * function     childisdead()
2539  * purpose      Used to notify child was killed by signal X.
2540  *              System initiated only.
2541  * arguments    Signal received by system.
2542  * returns      nothing.
2543  * ****************************************************************************
2544  */
2545 
2546 void
2547 childisdead(int sig)
2548 {
2549         (void) print("Call to childisdead(signal received %d)\n",
2550             sigtostr(sig));
2551 }
2552 
2553 
2554 /*
2555  * ****************************************************************************
2556  * function     say_bye(void)
2557  * purpose      prints a message the either Child or Parent is exiting.
2558  * arguments    None.
2559  * returns      nothing.
2560  * ****************************************************************************
2561  */
2562 
2563 void
2564 say_bye(void)
2565 {
2566         /* global var Glob_status keeps the status at exit time */
2567         if (Glob_status == OK || Glob_status == UNTESTED) {
2568                 dprint("Process terminating ...\n");
2569         } else {
2570                 (void) print("UNRESOLVED: aborting execution.\n\n\n");
2571         }
2572 }
2573 
2574 
2575 
2576 /*
2577  * ****************************************************************************
2578  * function     insert_bye(void)
2579  * purpose      insert the function say_bye with atexit() once only.
2580  * arguments    None.
2581  * returns      nothing.
2582  * ****************************************************************************
2583  */
2584 
2585 void
2586 insert_bye(void)
2587 {
2588         /* global var byeflag keeps count of calls to this function */
2589         if (byeflag == 0) {
2590                 atexit(say_bye);
2591         }
2592         byeflag++;
2593 }
2594 
2595 
2596 /*
2597  * ****************************************************************************
2598  * function     initialize()
2599  * purpose      Create communication pipes, forks a child (reseting testcase
2600  *              statistics on it), set some signal catching, PIDs information
2601  *              and closes unused ends of pipes.
2602  * arguments    none.
2603  * returns      nothing.
2604  * ****************************************************************************
2605  */
2606 
2607 void
2608 initialize(void)
2609 {
2610         dprint("Call to initialize()\n");
2611         dprint("Initializing and forking child.\n");
2612 
2613         init_comm();
2614 
2615         PidParent = getpid();
2616         dprint("Pid is %d.\n", PidParent);
2617 
2618         /* flush stdout and stderr before continuing */
2619         (void) fflush(stdout);
2620         (void) fflush(stderr);
2621 
2622         /* Fork child */
2623         if ((PidChild = fork()) == 0) {
2624                 /* reset error counters */
2625                 errflag = 0;            /* Number of errors */
2626                 tsflag = 0;             /* Number of test steps failed */
2627                 tsprev = 0;             /* Previous value for tsflag */
2628                 aflag = 0;              /* Number of assertions failed */
2629                 tspflag = 0;            /* Number of successful test steps */
2630                 apflag = 0;             /* Number of successful assertions */
2631                 serrflag = 0;   /* Number of errors scenario */
2632                 stsflag = 0;    /* Number of test steps failed scenario */
2633                 saflag = 0;     /* Number of assertions failed scenario */
2634                 stspflag = 0;   /* Number of succesful test steps scenario */
2635                 sapflag = 0;    /* Number of successful assertions scenario */
2636                 me = CHILD;
2637                 PidChild = getpid();
2638                 dprint("Pid is %d.\n", PidChild);
2639                 dprint("signal(SIGINT, notify_parent) issued.\n");
2640                 signal(SIGINT, notify_parent);
2641                 dprint("signal(SIGUSR1, kill_child) issued.\n");
2642                 signal(SIGUSR1, kill_child);
2643 
2644                 /* finish pipes config, closing unused ends */
2645                 close(PChild[1]);
2646                 dprint("Fildes %d (pipe end PChild[1]) was closed.\n",
2647                     PChild[1]);
2648                 close(PParent[0]);
2649                 dprint("Fildes %d (pipe end PParent[0]) was closed.\n",
2650                     PParent[0]);
2651         } else {
2652                 me = PARENT;
2653                 dprint("signal(SIGINT, notify_child) issued.\n");
2654                 signal(SIGINT, notify_child);
2655                 dprint("signal(SIGCLD, childisdead) issued.\n");
2656                 signal(SIGCLD, childisdead);
2657 
2658                 /* finish pipes config, closing unused ends */
2659                 close(PChild[0]);
2660                 dprint("Fildes %d (pipe end PChild[0]) was closed.\n",
2661                     PChild[0]);
2662                 close(PParent[1]);
2663                 dprint("Fildes %d (pipe end PParent[1]) was closed.\n",
2664                     PParent[1]);
2665         }
2666         insert_bye();
2667 }
2668 
2669 
2670 /*
2671  * ****************************************************************************
2672  * function     init_comm()
2673  * purpose      Create communication pipes using global vars PParent and PChild.
2674  * arguments    none.
2675  * returns      nothing.
2676  * ****************************************************************************
2677  */
2678 
2679 void
2680 init_comm(void)
2681 {
2682         dprint("Call to init_comm()\n");
2683         if (pipe(PParent) < 0 || pipe(PChild) < 0) {
2684                 (void) print("init_comm(): Pipe creation error.\n");
2685                 perror("\t\t");
2686                 exit_test(NOOK);
2687         }
2688 
2689         dprint("Pipes initialized:\n");
2690         dprint("\tPParent[0] = %d\n", PParent[0]);
2691         dprint("\tPParent[1] = %d\n", PParent[1]);
2692         dprint("\tPChild[0] = %d\n", PChild[0]);
2693         dprint("\tPChild[1] = %d\n\n", PChild[1]);
2694 }
2695 
2696 
2697 /*
2698  * ****************************************************************************
2699  * function     sendintp()
2700  * purpose      Sends an integer value to parent.
2701  * arguments    val- value to send.
2702  * returns      nothing.
2703  * ****************************************************************************
2704  */
2705 
2706 void
2707 sendintp(int val)
2708 {
2709         int i = val;
2710         int res;
2711 
2712         dprint("Call to sendintp(%d)\n", i);
2713         dprint("Sending <%x> thru PParent[%d].\n", i, 1);
2714         if ((res = nfsgenWrite(PParent[1], &i, sizeof (i))) != sizeof (i)) {
2715                 (void) print("Pipe write error (res=%d)\n", res);
2716                 perror("\t\t");
2717                 return;
2718         }
2719 
2720         dprint("<%d> sent thru PParent[%d].\n", i, 1);
2721         waitch();
2722 }
2723 
2724 
2725 /*
2726  * ****************************************************************************
2727  * function     getintp()
2728  * purpose      Receives an integer value send from child.
2729  * arguments    none.
2730  * returns      Integer received.
2731  * ****************************************************************************
2732  */
2733 
2734 int
2735 getintp(void)
2736 {
2737         int i = -1;
2738         int res;
2739 
2740         dprint("Call to getintp()\n");
2741         if ((res = nfsgenRead(PParent[0], &i, sizeof (i))) != sizeof (i)) {
2742                 (void) print("Pipe read error (res=%d)\n", res);
2743                 perror("\t\t");
2744                 return (-1);
2745         }
2746 
2747         dprint("<%d> received from PParent[%d].\n", i, 0);
2748         contch();
2749 
2750         return (i);
2751 }
2752 
2753 
2754 /*
2755  * Set of routines to sync parent and child to control test step
2756  *  (and assertion) execution.
2757  */
2758 
2759 
2760 /*
2761  * ****************************************************************************
2762  * function     contch()
2763  * purpose      Signal child to continue execution.
2764  * arguments    None.
2765  * returns      nothing.
2766  * ****************************************************************************
2767  */
2768 
2769 void
2770 contch(void)
2771 {
2772         char buf[] = "CHILD";
2773         char tmp[10];
2774         int st = 0;
2775 
2776         dprint("Call to contch()\n");
2777         (void) strlcpy(tmp, buf, 2);
2778         dprint("Sending <%s> thru PChild[%d].\n", tmp, 1);
2779 
2780         if ((st = nfsgenWrite(PChild[1], buf, 1)) != 1) {
2781                 (void) print("<%s> (size=%d) sent thru PChild[%d] status %d.\n",
2782                     buf, st, 1, errno);
2783                 (void) print("Pipe write error\n");
2784                 perror("\t\t");
2785                 exit_test(NOOK);
2786         }
2787 
2788         dprint("<%s> sent thru PChild[%d].\n", strncpy(tmp, buf, 1), 1);
2789 }
2790 
2791 
2792 /*
2793  * ****************************************************************************
2794  * function     waitch()
2795  * purpose      Child waits for parent to signal continue execution.
2796  * arguments    None.
2797  * returns      nothing.
2798  * ****************************************************************************
2799  */
2800 
2801 void
2802 waitch(void)
2803 {
2804         char    buf[10];
2805         int st = 0;
2806 
2807         dprint("Call to waitch()\n");
2808         if ((st = nfsgenRead(PChild[0], buf, 1)) != 1) {
2809                 (void) print("<%s> (size=%d) received from PChild[%d] "\
2810                     "status %d.\n", buf, st, 0, errno);
2811                 (void) print("Pipe read error\n");
2812                 perror("\t\t");
2813                 exit_test(NOOK);
2814         }
2815 
2816         if (buf[0] != CHILD) {
2817                 (void) print("Incorrect pipe data (%c != %c)\n", buf[0], CHILD);
2818                 exit_test(NOOK);
2819         }
2820         buf[1] = '\0';
2821         dprint("<%s> received from PChild[%d].\n", buf, 0);
2822 }
2823 
2824 
2825 /*
2826  * ****************************************************************************
2827  * function     contp()
2828  * purpose      Signal parent to continue execution.
2829  * arguments    None.
2830  * returns      nothing.
2831  * ****************************************************************************
2832  */
2833 
2834 void
2835 contp(void)
2836 {
2837         char buf[] = "PARENT";
2838         char tmp[10];
2839         int st = 0;
2840 
2841         dprint("Call to contp()\n");
2842         (void) strlcpy(tmp, buf, 2);
2843         dprint("Sending <%s> thru PParent[%d].\n", tmp, 1);
2844 
2845         if ((st = nfsgenWrite(PParent[1], buf, 1)) != 1) {
2846                 (void) print("<%s> (size=%d) sent thru PParent[%d] "\
2847                     "status %d.\n", buf, st, 1, errno);
2848                 (void) print("Pipe write error\n");
2849                 perror("\t\t");
2850                 exit_test(NOOK);
2851         }
2852 
2853         dprint("<%s> sent thru PParent[%d].\n",
2854             strncpy(tmp, buf, 1), 1);
2855 }
2856 
2857 
2858 /*
2859  * ****************************************************************************
2860  * function     waitp()
2861  * purpose      Parent waits for child to signal continue execution.
2862  * arguments    None.
2863  * returns      nothing.
2864  * ****************************************************************************
2865  */
2866 
2867 void
2868 waitp(void)
2869 {
2870         char buf[10];
2871         int st = 0;
2872 
2873         dprint("Call to waitp()\n");
2874         if ((st = nfsgenRead(PParent[0], buf, 1)) != 1) {
2875                 (void) print("<%s> (size=%d) received from PParent[%d] "\
2876                     "status %d.\n", buf, st, 0, errno);
2877                 (void) print("Pipe read error\n");
2878                 perror("\t\t");
2879                 exit_test(NOOK);
2880         }
2881         if (buf[0] != PARENT) {
2882                 (void) print("Incorrect pipe data (%c != %c)\n",
2883                     buf[0], PARENT);
2884                 exit_test(NOOK);
2885         }
2886         buf[1] = '\0';
2887 
2888         dprint("<%s> received from PParent[%d].\n", buf, 0);
2889 }
2890 
2891 
2892 /*
2893  * ****************************************************************************
2894  * function     wait_get_cresult()
2895  * purpose      Signal child to get the test result in child
2896  * arguments    None.
2897  * returns      nothing.
2898  * ****************************************************************************
2899  */
2900 
2901 int
2902 wait_get_cresult(void)
2903 {
2904         char buf[] = "RESULT";
2905         char tmp[10];
2906         int st = 0;
2907         int ret = OK;
2908 
2909         dprint("Call to wait_get_cresult()\n");
2910         (void) strlcpy(tmp, buf, 2);
2911         dprint("Sending <%s> thru PChild[%d].\n", tmp, 1);
2912 
2913         if ((st = nfsgenWrite(PChild[1], buf, 1)) != 1) {
2914                 (void) print("<%s> (size=%d) sent thru PChild[%d] status %d.\n",
2915                     buf, st, 1, errno);
2916                 (void) print("Pipe write error\n");
2917                 perror("\t\t");
2918                 exit_test(NOOK);
2919         }
2920         dprint("<%s> sent thru PChild[%d].\n", strncpy(tmp, buf, 1), 1);
2921 
2922         if ((st = nfsgenRead(PParent[0], buf, 1)) != 1) {
2923                 (void) print("<%s> (size=%d) received from PParent[%d] "\
2924                     "status %d.\n", buf, st, 0, errno);
2925                 (void) print("Pipe read error\n");
2926                 perror("\t\t");
2927                 exit_test(NOOK);
2928         }
2929 
2930         switch (buf[0]) {
2931         case 'F':
2932                 ret = NOOK;
2933                 break;
2934         case 'P':
2935                 ret = OK;
2936                 break;
2937         default:
2938                 (void) print("Incorrect pipe data (%c)\n", buf[0]);
2939                 exit_test(NOOK);
2940         }
2941         buf[1] = '\0';
2942         dprint("<%s> received from PParent[%d].\n", buf, 0);
2943         dprint("ret=%d", ret);
2944         return (ret);
2945 }
2946 
2947 /*
2948  * ****************************************************************************
2949  * function     wait_send_cresult()
2950  * purpose      Child waits for parent to signal get execution result.
2951  * arguments    None.
2952  * returns      nothing.
2953  * ****************************************************************************
2954  */
2955 
2956 int
2957 wait_send_cresult(void)
2958 {
2959         char buf[10];
2960         int st = 0;
2961 
2962         dprint("Call to wait_send_cresult()\n");
2963         if ((st = nfsgenRead(PChild[0], buf, 1)) != 1) {
2964                 (void) print("<%s> (size=%d) received from PChild[%d] "\
2965                     "status %d.\n", buf, st, 0, errno);
2966                 (void) print("Pipe read error\n");
2967                 perror("\t\t");
2968                 exit_test(NOOK);
2969         }
2970 
2971         if (buf[0] == 'R') {
2972                 buf[1] = '\0';
2973                 dprint("<%s> received from PChild[%d].\n", buf, 0);
2974                 if (aflag != 0)
2975                         (void) strcpy(buf, "FAIL");
2976                 else
2977                         (void) strcpy(buf, "PASS");
2978                 dprint("Sending <%s> thru PParent[%d].\n", buf, 1);
2979 
2980                 if ((st = nfsgenWrite(PParent[1], buf, 1)) != 1) {
2981                         (void) print("<%s> (size=%d) sent thru PParent[%d] "\
2982                             "status %d.\n", buf, st, 1, errno);
2983                         (void) print("Pipe write error\n");
2984                         perror("\t\t");
2985                         exit_test(NOOK);
2986                 }
2987                 dprint("<%s> sent thru PParent[%d].\n", buf, 1);
2988         } else {
2989                 (void) print("Incorrect pipe data (%c != %c)\n", buf[0], 'R');
2990                 exit_test(NOOK);
2991         }
2992 
2993         return (OK);
2994 }
2995 
2996 /*
2997  * ****************************************************************************
2998  * function     clientinfo()
2999  * purpose      Prints client information: name, release, version and machine
3000  *              type.
3001  * arguments    none.
3002  * returns      nothing.
3003  * ****************************************************************************
3004  */
3005 
3006 void
3007 clientinfo(void)
3008 {
3009         struct utsname mn;
3010 
3011         /* print the system information */
3012         if ((uname(&mn)) == -1) {
3013                 (void) fprintf(stderr, "warning uname() failed=%s\n",
3014                     strerror(errno));
3015         }
3016         (void) fprintf(stdout, "system info: %s %s %s %s %s\n\n\n", mn.nodename,
3017             mn.sysname, mn.release, mn.version, mn.machine);
3018         (void) fflush(stdout);
3019 }
3020 
3021 
3022 /*
3023  * ****************************************************************************
3024  * function     starttime()
3025  * purpose      Prints start time of an event (usually the current testcase).
3026  * arguments    msg- header of time stamp, or NULL if no header needed.
3027  * returns      nothing.
3028  * ****************************************************************************
3029  */
3030 
3031 void
3032 starttime(char *msg)
3033 {
3034         char *timeStr;
3035 
3036         if (msg != NULL)
3037                 (void) fprintf(stdout, "%s", msg);
3038 
3039         /* print the current date & time that the test started */
3040         gettimeofday(&tpstart, (void *)NULL);
3041         timeStr = ctime((clock_t *)&tpstart.tv_sec);
3042         (void) fprintf(stdout, "START TIME: %s\n", timeStr);
3043         (void) fflush(stdout);
3044 }
3045 
3046 
3047 /*
3048  * ****************************************************************************
3049  * function     endtime()
3050  * purpose      Prints ending time of an event (usually the testcase).
3051  * arguments    msg- header of time stamp, or NULL if no header needed.
3052  * returns      nothing.
3053  * ****************************************************************************
3054  */
3055 
3056 void
3057 endtime(char *msg)
3058 {
3059         char *timeStr;
3060 
3061         if (msg != NULL)
3062                 (void) fprintf(stdout, "%s", msg);
3063 
3064         gettimeofday(&tpend, (void *)NULL);
3065         timeStr = ctime((clock_t *)&tpend.tv_sec);
3066         (void) fprintf(stdout, "END TIME:   %s\n", timeStr);
3067         (void) fflush(stdout);
3068 }
3069 
3070 
3071 /*
3072  * ****************************************************************************
3073  * function     rsh_cmd()
3074  * purpose      Execute command on remote host as user.
3075  * arguments    cmd- command to execute.
3076  *              rhost- remote host name or IP address.
3077  *              user- target user on rhost.
3078  *              file- path and filename of .out (stdout) and .err (stderr) files
3079  * returns      nothing.
3080  * ****************************************************************************
3081  */
3082 
3083 int
3084 rsh_cmd(char *cmd, char *rhost, char *user, char *file)
3085 {
3086         int res;
3087         char buf[2048];
3088 
3089         /* execute testname in remote host as user and capture output */
3090         (void) snprintf(buf, 2048,
3091             "ssh %s@%s \"%s\" > %s.out 2> %s.err &",
3092             user, rhost, cmd, file, file);
3093 
3094         dprint("Executing remotely on %s:\n%s\n", rhost, buf);
3095 
3096         if ((res = system(buf)) < 0) {
3097                 eprint("Cannot start %s on %s. terminating ...\n",
3098                     Testname, rhost);
3099         }
3100 
3101         return (res);
3102 }
3103 
3104 
3105 /*
3106  * ****************************************************************************
3107  * function     cd_to_odir()
3108  * purpose      Restore original PWD at exit of testcase.
3109  * arguments    none.
3110  * returns      nothing.
3111  * ****************************************************************************
3112  */
3113 
3114 void
3115 cd_to_odir(void)
3116 {
3117         (void) strcpy(cwd, odir);
3118         (void) chdir(cwd);
3119 }
3120 
3121 
3122 /*
3123  * ****************************************************************************
3124  * function     Usage()
3125  * purpose      Print testcase parameter usage.
3126  * arguments    none.
3127  * returns      nothing.
3128  * ****************************************************************************
3129  */
3130 
3131 void
3132 Usage(void)
3133 {
3134         (void) printf("usage: %s -u testuser_uid -g testuser_gid [-heSDEWm]\n"
3135             "[-d debug_level] [-p perms] [-f flags] [-t delay]\n"
3136             "-l filename -U other_uid -G other_gid [test_directory]\n",
3137             Testname);
3138         (void) printf("Where:\n");
3139         (void) printf("-u uid to seteuid for user that runs "\
3140             "most of this tests\n");
3141         (void) printf("-g gid to setegid for user that runs "\
3142             "most of this tests\n");
3143         (void) printf("-U uid to seteuid for testing access as other user\n");
3144         (void) printf("-G gid to setegid for testing access as other user\n");
3145         (void) printf("-t delay time delay\n");
3146         (void) printf("-h Help - print this usage info\n");
3147         (void) printf("-s to notify this process is running on the server\n");
3148         (void) printf("-e synchronize stderr to stdout to check results, "\
3149             "default off\n");
3150         (void) printf("-S force writes to server and reads from server, "\
3151             "invalidating client cache\n");
3152         (void) printf("-D turn debug messages on\n");
3153         (void) printf("-E turn error messages on\n");
3154         (void) printf("-W cause mandatory locks to avoid waiting\n");
3155         (void) printf("-d debug_level   0 - none, 1 - error mmsgs, "\
3156             "2 - error and debug msgs\n");
3157         (void) printf("-m turn on use of mmap for reads/writes\n");
3158         (void) printf("-l file path and filename of test file\n");
3159         (void) printf("-p perm  creation permissions for test file\n");
3160         (void) printf("-f flags for test file");
3161         (void) printf("test_directory   is the working directory to be used"\
3162             " by this testcase\n");
3163 }
3164 
3165 
3166 /*
3167  * ****************************************************************************
3168  * function     parse_args()
3169  * purpose      parse testcase arguments, set flags and allocate global memory.
3170  * arguments    argc and argv from main().
3171  * returns      nothing.
3172  * ****************************************************************************
3173  */
3174 
3175 void
3176 parse_args(int argc, char **argv)
3177 {
3178         int c;
3179         char *buf;
3180         extern int optind;
3181         extern char *optarg;
3182         int errflg = 0;
3183         int i, j;
3184         unsigned int x;
3185         mode_t old_mask;
3186 
3187         old_mask = umask(0000);
3188         dprint("Old umask 0%o, new umask 0000\n", old_mask);
3189 
3190         dprint("Call to parse_args()\n");
3191         Testname = argv[0];
3192 
3193         if ((buf = getenv("SYNCWRITE")) != NULL) {
3194                 if (strcasecmp(buf, "ON") == 0)
3195                         SYNCWRITE = 1;
3196                 if (strcasecmp(buf, "OFF") == 0)
3197                         SYNCWRITE = 0;
3198         }
3199 
3200         if ((buf = getenv("SHOWERROR")) != NULL) {
3201                 if (strcasecmp(buf, "ON") == 0)
3202                         showerror = 1;
3203                 if (strcasecmp(buf, "OFF") == 0)
3204                         showerror = 0;
3205         }
3206 
3207 
3208         /* allocate mem for vars */
3209         while ((c = getopt(argc, argv, "u:g:U:G:d:l:t:p:hseSDEWmn")) != -1) {
3210                 switch (c) {
3211                 case 'u':
3212                         (void) sscanf(optarg, "%d", &i);
3213                         uid = i;
3214                         break;
3215                 case 'g':
3216                         (void) sscanf(optarg, "%d", &i);
3217                         gid = i;
3218                         break;
3219                 case 'U':
3220                         (void) sscanf(optarg, "%d", &i);
3221                         uid2 = i;
3222                         break;
3223                 case 'G':
3224                         (void) sscanf(optarg, "%d", &i);
3225                         gid2 = i;
3226                         break;
3227                 case 'd':
3228                         (void) sscanf(optarg, "%d", &debug);
3229                         switch (debug) {
3230                         case 0:
3231                                 debug = 0;
3232                                 showerror = 0;
3233                                 break;
3234                         case 1:
3235                                 debug = 0;
3236                                 showerror = 1;
3237                                 break;
3238                         case 2:
3239                                 debug = 1;
3240                                 showerror = 1;
3241                                 break;
3242                         default:
3243                                 errflg++;
3244                                 Usage();
3245                                 exit(-1);
3246                         }
3247                         break;
3248                 case 'l':       /* local path and filename for testfile */
3249                         (void) strcpy(lfilename, optarg);
3250                         break;
3251                 case 't':       /* permission for testfile */
3252                         (void) sscanf(optarg, "%o", &x);
3253                         delay = x;
3254                         break;
3255                 case 'p':       /* permission for testfile */
3256                         (void) sscanf(optarg, "%o", &x);
3257                         lperms = x;
3258                         break;
3259                 case 'f':       /* flags for testfile */
3260                         (void) sscanf(optarg, "%o", &x);
3261                         lflags = x;
3262                         break;
3263                 case 'h':
3264                         Usage();
3265                         exit(0);
3266                         break;  /* unreachable, used to quiet lint */
3267                 case 's':
3268                         srv_local = 1;
3269                         break;
3270                 case 'e':
3271                         errtoout = 1;
3272                         break;
3273                 case 'S':
3274                         SYNCWRITE = 1;
3275                         break;
3276                 case 'D':
3277                         debug = 1;
3278                         break;
3279                 case 'E':
3280                         showerror = 1;
3281                         break;
3282                 case 'W':
3283                         NBlocks = 1;
3284                         break;
3285                 case 'm':
3286                         mmflag = 1;
3287                         break;
3288                 case 'n':
3289                         skip_getdeleg = 1;
3290                         break;
3291                 default:
3292                         errflg++;
3293                         Usage();
3294                         exit(-1);
3295                 }
3296         }
3297 
3298         /* check for  mandatory flags */
3299         if (uid < 0 || gid < 0 || uid2 < 0 || gid2 < 0) {
3300                 errflg++;
3301         }
3302 
3303         if (optind < argc) { /* get test dir and cd to it */
3304                 char *dirtmp;
3305 
3306                 if (getcwd(odir, 512) == NULL) {
3307                         (void) fprintf(stderr,
3308                             "Warning: Cannot get original CDW\n");
3309                         (void) strcpy(odir, ".");
3310                 }
3311                 (void) strcpy(cwd, argv[optind]);
3312                 (void) chdir(cwd);
3313                 dirtmp = getcwd(NULL, 512);
3314                 if (dirtmp != NULL) {
3315                         if (strcmp(cwd, dirtmp) != 0) {
3316                                 (void) fprintf(stderr,
3317                                     "ERROR: cd %s failed, cwd %s\n",\
3318                                     cwd, dirtmp);
3319                                 errflg++;
3320                         } else { /* register func to cd to original dir */
3321                                 if (atexit(cd_to_odir) != 0) {
3322                                         (void) fprintf(stderr,
3323                                             "Wanrning: atexit() "\
3324                                             "failed, cd to original dir "\
3325                                             " won't be possible\n");
3326                                 }
3327                         }
3328                 free(dirtmp);
3329                 }
3330         }
3331 
3332         if (errflg) {
3333                 Usage();
3334                 exit(-1);
3335         }
3336 
3337         insert_bye();
3338 
3339         /* sync stderr to stdout, by making them the same */
3340         if (errtoout != 0) {
3341                 dprint("Synchronicing stderr to stdout ...\n");
3342                 dprint("dup2(stdout, stderr) result %d.\n", dup2(1, 2));
3343         }
3344 
3345         if ((buf = getenv("LEASE_TIME")) != NULL) {
3346                 renew = atoi(buf);
3347                 /* default value */
3348                 if (renew > 1800) {
3349                         (void) printf("lease renewal period too long (%d), "\
3350                             "180 seconds will be used in test.\n", renew);
3351                 }
3352                 if (renew < 0 || renew > 1800)
3353                         renew = 180;
3354         }
3355 
3356         if ((GLOBdata = malloc(256)) == NULL) {
3357                 perror("main()- malloc() for GLOBdata");
3358                 Glob_status = NOOK;
3359                 exit(NOOK);
3360         }
3361 
3362 
3363         if (getuid() != 0 && geteuid() != 0) {
3364                 (void) print("This program must be run as root. "\
3365                     "Quitting ...\n");
3366                 Glob_status = 1;
3367                 exit(1);
3368         }
3369 
3370         if (Setegid(gid) < 0) {
3371                 (void) print("Main, setegid(%d) failed quitting ...\n", gid);
3372                 Glob_status = 1;
3373                 exit(1);
3374         }
3375 
3376         if (Seteuid(uid) < 0) {
3377                 (void) print("Main, seteuid(%d) failed quitting ...\n", uid);
3378                 Glob_status = 1;
3379                 exit(1);
3380         }
3381 }