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 }