• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  *
26  * http://www.sgi.com
27  *
28  * For further information regarding this notice, see:
29  *
30  * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31  */
32 /*
33  * This program will grow a list of files.
34  * Each file will grow by grow_incr before the same
35  * file grows twice.  Each file is open and closed before next file is opened.
36  *
37  * To just verify file contents: growfiles -g 0 -c 1 filename
38  *
39  * See help and prt_examples functions below.
40  *
41  * Basic code layout
42  *  process cmdline
43  *  print debug message about options used
44  *  setup signal handlers
45  *  return control to user (if wanted - default action)
46  *  fork number of desired childern (if wanted)
47  *  re-exec self (if wanted)
48  *  Determine number of files
49  *  malloc space or i/o buffer
50  *  Loop until stop is set
51  *    Determine if hit iteration, time, max errors or num bytes reached
52  *    Loop through each file
53  *	open file
54  *	fstat file - to determine if file if a fifo
55  *	prealloc file space (if wanted)
56  *      growfile
57  *	check last write
58  *	check whole file
59  *	shrink file
60  *	close file
61  *	delay (if wanted)
62  *    End loop
63  *  End loop
64  *  remove all files (if wanted)
65  *
66  * Author: Richard Logan
67  *
68  */
69 #include <stdio.h>
70 #include <errno.h>
71 #include <stdlib.h>
72 #include <ctype.h>
73 #include <sys/types.h>
74 #include <time.h>
75 #include <sys/file.h>
76 #include <unistd.h>
77 #include <sys/stat.h>
78 #include <sys/time.h>
79 #include <sys/param.h>
80 #include <sys/signal.h>
81 #include <sys/statfs.h>
82 #include <sys/vfs.h>
83 #include <fcntl.h>
84 #include <errno.h>
85 #include <string.h>
86 #include <inttypes.h>
87 #include "dataascii.h"
88 #include "random_range.h"
89 #include "databin.h"
90 #include "open_flags.h"
91 #include "forker.h"
92 #include "file_lock.h"
93 
94 #ifdef CRAY
95 #include <sys/panic.h>
96 #include <sys/category.h>
97 #endif
98 
99 #include "test.h"
100 
101 int set_sig(void);
102 void sig_handler(int sig);
103 static void notify_others(void);
104 int handle_error(void);
105 int cleanup(void);
106 void usage(void);
107 void help(void);
108 void prt_examples(FILE * stream);
109 int growfile(int fd, char *file, int grow_incr, char *buf,
110 	     unsigned long *curr_size_ptr);
111 int shrinkfile(int fd, char *filename, int trunc_incr,
112 	       int trunc_inter, int just_trunc);
113 int check_write(int fd, int cf_inter, char *filename, int mode);
114 int check_file(int fd, int cf_inter, char *filename, int no_file_check);
115 int file_size(int fd);
116 int lkfile(int fd, int operation, int lklevel);
117 
118 #ifndef linux
119 int pre_alloc(int fd, long size);
120 #endif /* !linux */
121 
122 extern int datapidgen(int, char *, int, int);
123 extern int datapidchk(int, char *, int, int, char **);
124 
125 /* LTP status reporting */
126 char *TCID = "growfiles";	/* Default test program identifier.    */
127 int TST_TOTAL = 1;		/* Total number of test cases. */
128 
129 /* To avoid extensive modifications to the code, use this bodge */
130 #define exit(x) myexit(x)
myexit(int x)131 void myexit(int x)
132 {
133 	if (x)
134 		tst_resm(TFAIL, "Test failed");
135 	else
136 		tst_resm(TPASS, "Test passed");
137 	tst_exit();
138 }
139 
140 #define NEWIO	1		/* Use the tlibio.c functions */
141 
142 #ifndef NEWIO
143 #define NEWIO	0		/* specifies to use original iowrite.c */
144 			/* functions instead of tlibio.c functions */
145 			/* Once it is proven tlibio.c functions work properly, */
146 			/* only tlibio.c functions will be used */
147 #else
148 #include "tlibio.h"
149 #endif
150 
151 #ifndef PATH_MAX
152 #define PATH_MAX	1023
153 #endif
154 
155 #define DEF_DIR		"."
156 #define DEF_FILE	"gf"
157 
158 char *Progname;
159 int Debug = 0;
160 
161 int Pid = 0;
162 
163 int io_type = 0;		/* I/O type -sync */
164 
165 #ifdef O_LARGEFILE
166 int open_flags = O_RDWR | O_CREAT | O_LARGEFILE;	/* open flags */
167 #else
168 #warning O_LARGEFILE is not defined!
169 int open_flags = O_RDWR | O_CREAT;	/* open flags */
170 #endif
171 
172 #define MAX_FC_READ	196608	/* 4096 * 48 - 48 blocks */
173 
174 #define PATTERN_ASCII	1	/* repeating alphabet letter pattern */
175 				/* allows multiple writers and to be checked */
176 #define PATTERN_PID	2	/* <pid><words byte offset><pid> */
177 				/* Assumes 64 bit word. Only allows single */
178 				/* process to write and check */
179 /*
180  *	1234567890123456789012345678901234567890123456789012345678901234
181  *	________________________________________________________________
182  *	<    pid       >< offset in file of this word  ><    pid       >
183  */
184 
185 #define PATTERN_OFFSET	3	/* Like PATTERN_PID but has a fixed number */
186 				/* (STATIC_NUM) instead of pid. */
187 				/* Allows multiple processes to write/read */
188 #define PATTERN_ALT	4	/* alternating bit pattern (i.e. 0x5555555...) */
189 #define PATTERN_CHKER	5	/* checkerboard pattern (i.e. 0xff00ff00ff00...) */
190 #define PATTERN_CNTING  6	/* counting pattern (i.e. 0 - 07, 0 - 07, ...) */
191 #define PATTERN_ONES	7	/* all bits set (i.e. 0xffffffffffffff...) */
192 #define PATTERN_ZEROS	8	/* all bits cleared (i.e. 0x000000000...) */
193 #define PATTERN_RANDOM	9	/* random integers - can not be checked */
194 #define STATIC_NUM	221849	/* used instead of pid when PATTERN_OFFSET */
195 
196 #define MODE_RAND_SIZE	1	/* random write and trunc */
197 #define MODE_RAND_LSEEK	2	/* random lseek before write */
198 #define MODE_GROW_BY_LSEEK 4	/* lseek beyond end of file then write a byte */
199 #define RANDOM_OPEN	999876	/* if Open_flags set to this value, open flags */
200 				/* will be randomly choosen from Open_flags[] */
201 #define MODE_FIFO	S_IFIFO	/* defined in stat.h  0010000 */
202 
203 int num_files = 0;		/* num_auto_files + cmd line files */
204 char *filenames;		/* pointer to space containing filenames */
205 int remove_files = 0;		/* if set, cleanup default is not to cleanup */
206 int bytes_consumed = 0;		/* total bytes consumed, all files */
207 int bytes_to_consume = 0;	/* non-zero if -B was specified, total bytes */
208 int Maxerrs = 100;		/* Max number errors before forced exit */
209 int Errors = 0;			/* number of encountered errors */
210 int Upanic_on_error = 0;	/* call upanic if error and this variable set */
211 
212 /* The *_size variables are only used when random iosize option (-r) is used */
213 int max_size = 5000;
214 int min_size = 1;		/* also set in option parsing */
215 int mult_size = 1;		/* when random iosz, iosz must be mult of mult_size */
216 /* the *_lseek variables are only used when radon lseek option (-R) is used */
217 int min_lseek = 0;		/* also set in option parsing */
218 int max_lseek = -1;		/* -1 means size of file */
219 #ifdef CRAY
220 int Pattern = PATTERN_OFFSET;	/* This pattern is 64 bit word based */
221 #else
222 int Pattern = PATTERN_ASCII;
223 #endif
224 int Seed = -1;			/* random number seed, < 0 == uninitialized  */
225 int Nseeds = 0;			/* Number of seed specified by the user */
226 int *Seeds;			/* malloc'ed arrary of ints holding user spec seeds */
227 
228 int using_random = 0;		/* flag indicating randomization is being used */
229 float delaysecs = 0.0;		/* delay between iterations (in seconds) */
230 int delaytime;			/* delay between iterations in clocks/uses */
231 int lockfile = 0;		/* if set, do file locking */
232 				/* 1 = do file locking around write, trunc */
233 				/* and reads. */
234 				/* 2 = write lock around all file operations */
235 
236 off_t Woffset = 0;		/* offset before last write */
237 int Grow_incr = 4096;		/* sz of last write */
238 int Mode = 0;			/* bitmask of write/trunc mode */
239 				/* also knows if dealing with fifo */
240 char *Buffer = NULL;		/* buffer used by write and write check */
241 int Alignment = 0;		/* if non word multiple, io will not be word aligned */
242 int Opid = 0;			/* original pid */
243 
244 int Sync_with_others = 0;	/* Flag indicating to stop other if we stop before DONE */
245 int Iter_cnt = 0;		/* contains current iteration count value */
246 char TagName[40];		/* name of this growfiles (see Monster)     */
247 
248 struct fileinfo_t {
249 	char *filename;
250 	int fd;
251 	int openflags;
252 	int mode;
253 } Fileinfo;
254 
255 /*
256  * Define open flags that will be used when '-o random' option is used.
257  * Note: If there is more than one growfiles doing its thing to the same
258  * file, O_TRUNC will cause data mismatches.  How you ask?
259  * timing of events, example:
260  *   Process one		Process two
261  *   ---------------		-------------
262  *   get write lock
263  *   fstat file
264  *   lseek
265  *   generate pattern
266  *				open with O_TRUNC
267  *   write with wrong pattern
268  *	because offset is wrong
269  *
270  *  The second process truncated the file after the pattern was
271  *  determined, thus the pattern is wrong for the file location.
272  *
273  * There can also be a timing problem with open flag O_APPEND if
274  * file locks are not being used (-l option).  Things could happen
275  * between the fstat and the write. Thus, writing the wrong pattern.
276  * If all processes observe the file locks, O_APPEND should be ok
277  * to use.
278  */
279 int Open_flags[] = {
280 #ifdef CRAY
281 	O_RDWR | O_CREAT,
282 	O_RDWR | O_CREAT | O_RAW,
283 	O_RDWR | O_CREAT | O_BIG,
284 	O_RDWR | O_CREAT | O_APPEND,
285 	O_RDWR | O_CREAT | O_NDELAY,
286 	O_RDWR | O_CREAT | O_PLACE,
287 	O_RDWR | O_CREAT | O_SYNC,
288 	O_RDWR | O_CREAT | O_RAW | O_SYNC,
289 	O_RDWR | O_CREAT | O_NDELAY | O_SYNC,
290 	O_RDWR | O_CREAT | O_NDELAY | O_SYNC | O_BIG,
291 	O_RDWR | O_CREAT | O_RAW,
292 	O_RDWR | O_CREAT | O_RAW | O_APPEND,
293 	O_RDWR | O_CREAT | O_RAW | O_BIG,
294 	O_RDWR | O_CREAT | O_RAW | O_APPEND | O_BIG,
295 /***
296  * O_WELLFORMED makes -o random require well formed i/o
297  ***/
298 #if ALLOW_O_WELLFORMED
299 #if O_PARALLEL
300 	O_RDWR | O_CREAT | O_PARALLEL | O_WELLFORMED | O_RAW,
301 	O_RDWR | O_CREAT | O_PARALLEL | O_WELLFORMED | O_RAW | O_TRUNC,
302 #endif /* O_PARALLEL */
303 #endif
304 
305 #else /* CRAY */
306 	O_RDWR | O_CREAT,
307 	O_RDWR | O_CREAT | O_APPEND,
308 	O_RDWR | O_CREAT | O_NDELAY,
309 	O_RDWR | O_CREAT | O_SYNC,
310 	O_RDWR | O_CREAT | O_SYNC | O_NDELAY,
311 	O_RDWR | O_CREAT | O_APPEND | O_NDELAY,
312 
313 #endif /* CRAY */
314 };
315 
316 #define REXEC_INIT	0	/* don't do re-exec of childern */
317 #define REXEC_DOIT	1	/* Do re-exec of childern */
318 #define REXEC_DONE	2	/* We've already been re-exec'ed */
319 
320 #ifndef BSIZE
321 #ifdef CRAY
322 #define BSIZE	1024
323 #else
324 #define BSIZE	512
325 #endif /* CRAY */
326 #endif /* BSIZE */
327 
328 #define USECS_PER_SEC	1000000	/* microseconds per second */
329 
330 /*
331  * Define marcos used when dealing with file locks.
332  */
333 #define LKLVL0		1	/* file lock around write/read/trunc */
334 #define LKLVL1		2	/* file lock after open to before close */
335 
336 /*
337  * Define special max lseek values
338  */
339 #define LSK_EOF       	    -1	/* set fptr up to EOF */
340 #define LSK_EOFPLUSGROW	    -2	/* set fptr up to EOF + grow - leave whole */
341 #define LSK_EOFMINUSGROW    -3	/* set fptr up to EOF-grow - no grow */
342 
343 /***********************************************************************
344  * MAIN
345  ***********************************************************************/
main(int argc,char ** argv)346 int main(int argc, char **argv)
347 {
348 	extern char *optarg;	/* used by getopt */
349 	extern int optind;
350 
351 	int ind;
352 	int first_file_ind = 0;
353 	int num_auto_files = 0;	/* files created by tool */
354 	int seq_auto_files = 0;	/* auto files created by tool created by tool */
355 	char *auto_dir = DEF_DIR;
356 	char *auto_file = DEF_FILE;
357 	int grow_incr = 4096;
358 	int trunc_incr = 4096;
359 	int trunc_inter = 0;	/* 0 means none, */
360 	int unlink_inter = 0;	/* 0 means none, 1 means always unlink */
361 	int unlink_inter_ran = -1;	/* -1 -use unlink_inter, otherwise randomly choose */
362 	/* between unlink_inter and unlink_inter_ran */
363 	int file_check_inter = 0;	/* 0 means never, 1 means always */
364 	int write_check_inter = 1;	/* 0 means never, 1 means always */
365 	int iterations = 1;	/* number of increments to be added */
366 	int no_file_check = 0;	/* if set, no whole file checking will be done */
367 	int num;
368 	int fd;			/* file descriptor */
369 	int stop = 0;		/* loop stopper if set */
370 
371 	unsigned long curr_size = 0;	/* BUG:14136 (keep track of file size) */
372 	unsigned long fs_limit = 2147483647; /* BUG:14136 (filesystem size limit is 2G by default) */
373 	struct statfs fsbuf;
374 
375 	int tmp;
376 	char chr;
377 	int ret;
378 	int pre_alloc_space = 0;
379 #ifndef linux
380 	long total_grow_value;	/* used in pre-allocations */
381 #endif
382 	int backgrnd = 1;	/* return control to user */
383 	struct stat statbuf;
384 	int time_iterval = -1;
385 	time_t start_time = 0;
386 	char reason[128];	/* reason for loop termination */
387 	int num_procs = 1;
388 	int forker_mode = 0;
389 	int reexec = REXEC_INIT;	/* reexec info */
390 	char *exec_path = NULL;
391 
392 /*char *strrchr();*/
393 
394 	char *filename;		/* name of file specified by user */
395 	char *cptr;		/* temp char pointer */
396 	extern int Forker_npids;	/* num of forked pid, defined in forker.c */
397 	struct timeval tv1;
398 
399 	if (argv[0][0] == '-')
400 		reexec = REXEC_DONE;
401 	/*
402 	 * Determine name of file used to invoke this program
403 	 */
404 	if ((Progname = strrchr(argv[0], '/')) != NULL)
405 		Progname++;
406 	else
407 		Progname = argv[0];
408 
409 	TagName[0] = '\0';
410 
411 	/*
412 	 * Process options
413 	 */
414 	while ((ind = getopt(argc, argv,
415 			     "hB:C:c:bd:D:e:Ef:g:H:I:i:lL:n:N:O:o:pP:q:wt:r:R:s:S:T:uU:W:xy"))
416 	       != EOF) {
417 		switch (ind) {
418 
419 		case 'h':
420 			help();
421 			tst_exit();
422 
423 		case 'B':
424 			switch (sscanf(optarg, "%i%c", &bytes_to_consume, &chr)) {
425 			case 1:	/* noop */
426 				break;
427 
428 			case 2:
429 				if (chr == 'b') {
430 					bytes_to_consume *= BSIZE;
431 				} else {
432 					fprintf(stderr,
433 						"%s%s:  --B option arg invalid\n",
434 						Progname, TagName);
435 					usage();
436 					exit(1);
437 				}
438 				break;
439 
440 			default:
441 				fprintf(stderr,
442 					"%s%s: --B option arg invalid\n",
443 					Progname, TagName);
444 				usage();
445 				exit(1);
446 				break;
447 			}
448 
449 			break;
450 
451 		case 'E':
452 			prt_examples(stdout);
453 			exit(0);
454 
455 		case 'b':	/* batch */
456 			backgrnd = 0;
457 			break;
458 
459 		case 'C':
460 			if (sscanf(optarg, "%i", &write_check_inter) != 1) {
461 				fprintf(stderr,
462 					"%s%s: --c option arg invalid\n",
463 					Progname, TagName);
464 				usage();
465 				exit(1);
466 			}
467 			break;
468 
469 		case 'c':
470 			if (sscanf(optarg, "%i", &file_check_inter) != 1) {
471 				fprintf(stderr,
472 					"%s%s: --c option arg invalid\n",
473 					Progname, TagName);
474 				usage();
475 				exit(1);
476 			}
477 			break;
478 
479 		case 'd':
480 			auto_dir = optarg;
481 #ifdef CRAY
482 			unsetenv("TMPDIR");	/* force the use of auto_dir */
483 #endif
484 			if (stat(auto_dir, &statbuf) == -1) {
485 				if (mkdir(auto_dir, 0777) == -1) {
486 					if (errno != EEXIST) {
487 						fprintf(stderr,
488 							"%s%s: Unable to make dir %s\n",
489 							Progname, TagName,
490 							auto_dir);
491 						exit(1);
492 					}
493 				}
494 			} else {
495 				if (!(statbuf.st_mode & S_IFDIR)) {
496 					fprintf(stderr,
497 						"%s%s: %s already exists and is not a directory\n",
498 						Progname, TagName, auto_dir);
499 					exit(1);
500 				}
501 			}
502 			break;
503 
504 		case 'D':
505 			if (sscanf(optarg, "%i", &Debug) != 1) {
506 				fprintf(stderr,
507 					"%s%s: --D option arg invalid\n",
508 					Progname, TagName);
509 				usage();
510 				exit(1);
511 			}
512 			break;
513 
514 		case 'e':
515 			if (sscanf(optarg, "%i", &Maxerrs) != 1) {
516 				fprintf(stderr,
517 					"%s%s: --e option arg invalid\n",
518 					Progname, TagName);
519 				usage();
520 				exit(1);
521 			}
522 			break;
523 
524 		case 'f':
525 			auto_file = optarg;
526 			break;
527 
528 		case 'g':
529 			if ((ret = sscanf(optarg, "%i%c", &grow_incr, &chr)) < 1
530 			    || grow_incr < 0) {
531 
532 				fprintf(stderr,
533 					"%s%s: --g option arg invalid\n",
534 					Progname, TagName);
535 				usage();
536 				exit(1);
537 			}
538 			if (ret == 2) {
539 				if (chr == 'b' || chr == 'B')
540 					grow_incr *= 4096;
541 				else {
542 					fprintf(stderr,
543 						"%s%s: --g option arg invalid\n",
544 						Progname, TagName);
545 					usage();
546 					exit(1);
547 				}
548 			}
549 			break;
550 
551 		case 'H':
552 			if (sscanf(optarg, "%f", &delaysecs) != 1
553 			    || delaysecs < 0) {
554 
555 				fprintf(stderr,
556 					"%s%s: --H option arg invalid\n",
557 					Progname, TagName);
558 				usage();
559 				exit(1);
560 			}
561 			break;
562 
563 		case 'i':
564 			if (sscanf(optarg, "%i", &iterations) != 1 ||
565 			    iterations < 0) {
566 
567 				fprintf(stderr,
568 					"%s%s: --i option arg invalid\n",
569 					Progname, TagName);
570 				usage();
571 				exit(1);
572 			}
573 			break;
574 
575 		case 'I':
576 #if NEWIO
577 			if ((io_type = lio_parse_io_arg1(optarg)) == -1) {
578 				fprintf(stderr,
579 					"%s%s: --I arg is invalid, must be s, p, f, a, l, L or r.\n",
580 					Progname, TagName);
581 				exit(1);
582 			}
583 			if (io_type & LIO_RANDOM)
584 				using_random++;
585 #else
586 			if ((io_type = parse_io_arg(optarg)) == -1) {
587 				fprintf(stderr,
588 					"%s%s: --I arg is invalid, must be s, p, f, a, l, L or r.\n",
589 					Progname, TagName);
590 				exit(1);
591 			}
592 			if (io_type == 99)	/* hold-over until tlibio.h */
593 				using_random++;
594 #endif
595 			break;
596 
597 		case 'l':
598 			lockfile++;
599 			if (lockfile > 2)
600 				lockfile = 2;	/* lockfile can only be 1 or 2 */
601 			break;
602 
603 		case 'L':
604 			if (sscanf(optarg, "%i", &time_iterval) != 1 ||
605 			    time_iterval < 0) {
606 				fprintf(stderr,
607 					"%s%s: --L option arg invalid\n",
608 					Progname, TagName);
609 				usage();
610 				exit(1);
611 			}
612 			break;
613 
614 		case 'n':
615 			if (sscanf(optarg, "%i:%i", &num_procs, &forker_mode) <
616 			    1 || num_procs < 0) {
617 
618 				fprintf(stderr,
619 					"%s%s: --n option arg invalid\n",
620 					Progname, TagName);
621 				usage();
622 				exit(1);
623 			}
624 
625 			break;
626 
627 		case 'N':
628 			if (sscanf(optarg, "%i", &num_auto_files) != 1 ||
629 			    num_auto_files < 0) {
630 
631 				fprintf(stderr,
632 					"%s%s: --N option arg invalid\n",
633 					Progname, TagName);
634 				usage();
635 				exit(1);
636 			}
637 			break;
638 
639 		case 'O':
640 			if (sscanf(optarg, "%i", &Alignment) != 1 ||
641 			    Alignment < 0) {
642 
643 				fprintf(stderr,
644 					"%s%s: --O option arg invalid\n",
645 					Progname, TagName);
646 				usage();
647 				exit(1);
648 			}
649 			break;
650 
651 		case 'o':
652 			if (strcmp(optarg, "random") == 0) {
653 				open_flags = RANDOM_OPEN;
654 				using_random++;
655 
656 			} else if ((open_flags = parse_open_flags(optarg, NULL))
657 				   == -1) {
658 				fprintf(stderr,
659 					"%s%s: --o arg contains invalid flag\n",
660 					Progname, TagName);
661 				exit(1);
662 			}
663 			break;
664 
665 		case 'p':	/* pre allocate space */
666 #ifdef linux
667 			printf("%s%s: --p is illegal option on linux system\n",
668 			       Progname, TagName);
669 			exit(1);
670 #else
671 			pre_alloc_space++;
672 #endif
673 			break;
674 
675 		case 'P':
676 #ifdef CRAY
677 			if (strcmp(optarg, "PANIC") != 0) {
678 				fprintf(stderr, "%s%s: --P arg must be PANIC\n",
679 					Progname, TagName);
680 				exit(1);
681 			}
682 			Upanic_on_error++;
683 			printf("%s%s: Will call upanic after writes\n", Progname, TagName);
684 #else
685 			printf
686 			    ("%s%s: --P is illegal option on non-cray system\n",
687 			     Progname, TagName);
688 			exit(1);
689 #endif
690 			break;
691 
692 		case 'q':	/* file content or pattern */
693 			switch (optarg[0]) {
694 			case 'A':
695 				Pattern = PATTERN_ALT;
696 				break;
697 			case 'a':
698 				Pattern = PATTERN_ASCII;
699 				break;
700 			case 'p':
701 				Pattern = PATTERN_PID;
702 				break;
703 			case 'o':
704 				Pattern = PATTERN_OFFSET;
705 				break;
706 			case 'c':
707 				Pattern = PATTERN_CHKER;
708 				break;
709 			case 'C':
710 				Pattern = PATTERN_CNTING;
711 				break;
712 			case 'r':
713 				Pattern = PATTERN_RANDOM;
714 				using_random++;
715 				break;
716 			case 'z':
717 				Pattern = PATTERN_ZEROS;
718 				break;
719 			case 'O':
720 				Pattern = PATTERN_ONES;
721 				break;
722 			default:
723 				fprintf(stderr,
724 					"%s%s: --C option arg invalid, A, a, p, o, c, C, r, z, or 0\n",
725 					Progname, TagName);
726 				usage();
727 				exit(1);
728 			}
729 			break;
730 
731 		case 'R':	/* random lseek before write arg: [min-]max */
732 			if (sscanf(optarg, "%i-%i", &min_lseek, &max_lseek) !=
733 			    2) {
734 				min_lseek = 1;	/* same as default in define */
735 				if (sscanf(optarg, "%i%c", &max_lseek, &chr) !=
736 				    1) {
737 					fprintf(stderr,
738 						"%s%s: --R option arg invalid: [min-]max\n",
739 						Progname, TagName);
740 					exit(1);
741 				}
742 			}
743 			if (max_lseek < LSK_EOFMINUSGROW) {
744 				fprintf(stderr,
745 					"%s%s: --R option, max_lseek is invalid\n",
746 					Progname, TagName);
747 				exit(1);
748 			}
749 			Mode |= MODE_RAND_LSEEK;
750 			using_random++;
751 			break;
752 
753 		case 'r':	/* random io size arg: [min-]max[:mult] */
754 
755 			/* min-max:mult format */
756 			if (sscanf(optarg, "%i-%i:%i%c", &min_size, &max_size,
757 				   &mult_size, &chr) != 3) {
758 				min_size = 1;
759 				/* max:mult format */
760 				if (sscanf(optarg, "%i:%i%c", &max_size,
761 					   &mult_size, &chr) != 2) {
762 					/* min-max format */
763 					if (sscanf(optarg, "%i-%i%c", &min_size,
764 						   &max_size, &chr) != 2) {
765 						min_size = 1;
766 						if (sscanf
767 						    (optarg, "%i%c", &max_size,
768 						     &chr) != 1) {
769 							fprintf(stderr,
770 								"%s%s: --r option arg invalid: [min-]max[:mult]\n",
771 								Progname,
772 								TagName);
773 							exit(1);
774 						}
775 					}
776 				}
777 			}
778 
779 			if (max_size < 0) {
780 				fprintf(stderr,
781 					"%s%s: --r option, max_size is invalid\n",
782 					Progname, TagName);
783 				exit(1);
784 			}
785 			/*
786 			 * If min and max are the same, no randomness
787 			 */
788 			if (min_size != max_size) {
789 				Mode |= MODE_RAND_SIZE;
790 				using_random++;
791 			}
792 			break;
793 
794 		case 'S':
795 			if (sscanf(optarg, "%i", &seq_auto_files) != 1 ||
796 			    seq_auto_files < 0) {
797 
798 				fprintf(stderr,
799 					"%s%s: --S option arg invalid\n",
800 					Progname, TagName);
801 				usage();
802 				exit(1);
803 			}
804 			break;
805 
806 		case 's':	/* format: seed[,seed...] */
807 
808 			/* count the number of seeds */
809 			cptr = optarg;
810 			for (Nseeds = 1; *cptr; Nseeds++) {
811 				if ((filename = strchr(cptr, ',')) == NULL)
812 					break;
813 				cptr = filename;
814 				cptr++;
815 			}
816 			Seeds = malloc(Nseeds * sizeof(int));
817 
818 			/*
819 			 * check that each seed is valid and put them in
820 			 * the newly malloc'ed Seeds arrary.
821 			 */
822 			filename = cptr = optarg;
823 			for (Nseeds = 0; *cptr; Nseeds++) {
824 				if ((filename = strchr(cptr, ',')) == NULL) {
825 					if (sscanf(cptr, "%i", &Seeds[Nseeds]) <
826 					    1) {
827 						fprintf(stderr,
828 							"%s%s: --s option arg %s invalid\n",
829 							Progname, TagName,
830 							cptr);
831 						usage();
832 						exit(1);
833 					}
834 					Nseeds++;
835 					break;
836 				}
837 
838 				*filename = '\0';
839 				if (sscanf(cptr, "%i", &Seeds[Nseeds]) < 1) {
840 					fprintf(stderr,
841 						"%s%s: --s option arg %s invalid\n",
842 						Progname, TagName, cptr);
843 					usage();
844 					exit(1);
845 				}
846 				*filename = ',';	/* restore string */
847 				cptr = filename;
848 				cptr++;
849 			}
850 			break;
851 
852 		case 't':
853 			if ((ret =
854 			     sscanf(optarg, "%i%c", &trunc_incr, &chr)) < 1
855 			    || trunc_incr < 0) {
856 
857 				fprintf(stderr,
858 					"%s%s: --t option arg invalid\n",
859 					Progname, TagName);
860 				usage();
861 				exit(1);
862 			}
863 			if (ret == 2) {
864 				if (chr == 'b' || chr == 'B')
865 					trunc_incr *= 4096;
866 				else {
867 					fprintf(stderr,
868 						"%s%s: --t option arg invalid\n",
869 						Progname, TagName);
870 					usage();
871 					exit(1);
872 				}
873 			}
874 			break;
875 
876 		case 'T':	/* truncate interval */
877 			if (sscanf(optarg, "%i%c", &trunc_inter, &chr) != 1 ||
878 			    trunc_inter < 0) {
879 
880 				fprintf(stderr,
881 					"%s%s: --T option arg invalid\n",
882 					Progname, TagName);
883 				usage();
884 				exit(1);
885 			}
886 			break;
887 
888 		case 'u':
889 			remove_files++;
890 			break;
891 
892 		case 'U':	/* how often to unlink file */
893 			/*
894 			 * formats:
895 			 *      A-B  - randomly pick interval between A and B
896 			 *      X    - unlink file every X iteration
897 			 */
898 			if (sscanf(optarg, "%i-%i", &unlink_inter,
899 				   &unlink_inter_ran) == 2) {
900 
901 				if (unlink_inter < 0 || unlink_inter_ran < 0) {
902 					fprintf(stderr,
903 						"%s%s: --U option arg invalid\n",
904 						Progname, TagName);
905 					usage();
906 					exit(1);
907 				}
908 				/* ensure unlink_inter contains smaller value */
909 				if (unlink_inter > unlink_inter_ran) {
910 					tmp = unlink_inter_ran;
911 					unlink_inter_ran = unlink_inter;
912 					unlink_inter = tmp;
913 				}
914 				using_random++;
915 
916 			} else if (sscanf(optarg, "%i%c", &unlink_inter, &chr)
917 				   != 1 || unlink_inter < 0) {
918 
919 				fprintf(stderr,
920 					"%s%s: --U option arg invalid\n",
921 					Progname, TagName);
922 				usage();
923 				exit(1);
924 			}
925 			break;
926 
927 		case 'x':
928 			if (reexec != REXEC_DONE)
929 				reexec = REXEC_DOIT;
930 			break;
931 
932 		case 'w':
933 			Mode |= MODE_GROW_BY_LSEEK;
934 			break;
935 
936 		case 'W':
937 			TCID = optarg;
938 			sprintf(TagName, "(%.39s)", optarg);
939 			break;
940 
941 		case 'y':
942 			Sync_with_others = 1;
943 			break;
944 
945 		case '?':
946 			usage();
947 			exit(1);
948 			break;
949 		}
950 	}
951 
952 	if (Debug == 1) {
953 		cptr = getenv("TOUTPUT");
954 		if ((cptr != NULL) && (strcmp(cptr, "NOPASS") == 0)) {
955 			Debug = 0;
956 		}
957 	}
958 
959 	if (Pattern == PATTERN_RANDOM) {
960 		no_file_check = 1;
961 		if (write_check_inter || file_check_inter)
962 			printf
963 			    ("%s%s: %d Using random pattern - no data checking will be performed!\n",
964 			     Progname, TagName, getpid());
965 	} else if (max_lseek == LSK_EOFPLUSGROW || Mode & MODE_GROW_BY_LSEEK) {
966 		no_file_check = 1;
967 
968 		if (file_check_inter)
969 			printf("%s%s: %d Using random lseek beyond EOF or lseek grow,\n\
970 no whole file checking will be performed!\n", Progname, TagName,
971 			       getpid());
972 
973 	}
974 
975 	if (Mode & MODE_RAND_SIZE)
976 		grow_incr = max_size;
977 
978 	set_sig();
979 
980 	Opid = getpid();
981 	Pid = Opid;
982 
983 	if (backgrnd) {
984 		if (Debug > 1)
985 			printf
986 			    ("%s: %d DEBUG2 forking, returning control to the user\n",
987 			     Progname, Opid);
988 		background(Progname);	/* give user their prompt back */
989 	}
990 #if CRAY
991 	if (Sync_with_others)
992 		setpgrp();
993 #endif
994 
995 	if (Debug > 3) {
996 #if NEWIO
997 		lio_set_debug(Debug - 3);
998 #else
999 		set_iowrite_debug(Debug - 3);
1000 #endif
1001 	}
1002 
1003 	/*
1004 	 * Print some program information here if debug is turned on to
1005 	 * level 3 or higher.
1006 	 */
1007 
1008 	if (Debug > 2) {
1009 
1010 		if (Mode & MODE_GROW_BY_LSEEK)
1011 			printf
1012 			    ("%s: %d DEBUG lseeking past end of file, writting a \"w\"\n",
1013 			     Progname, Pid);
1014 		else if (Pattern == PATTERN_OFFSET)
1015 			printf
1016 			    ("%s: %d DEBUG3 %d<byteoffset>%d per word pattern multi-writers.\n",
1017 			     Progname, Pid, STATIC_NUM, STATIC_NUM);
1018 		else if (Pattern == PATTERN_PID)
1019 			printf
1020 			    ("%s: %d DEBUG3 <pid><byteoffset><pid> per word pattern - 1 writer\n",
1021 			     Progname, Pid);
1022 		else if (Pattern == PATTERN_ASCII)
1023 			printf
1024 			    ("%s: %d DEBUG3 ascii pattern (vi'able)- allows multiple writers\n",
1025 			     Progname, Pid);
1026 		else if (Pattern == PATTERN_ALT)
1027 			printf
1028 			    ("%s: %d DEBUG3 alt bit pattern - allows multiple writers\n",
1029 			     Progname, Pid);
1030 		else if (Pattern == PATTERN_CHKER)
1031 			printf
1032 			    ("%s: %d DEBUG3 checkerboard pattern - allows multiple writers\n",
1033 			     Progname, Pid);
1034 		else if (Pattern == PATTERN_CNTING)
1035 			printf
1036 			    ("%s: %d DEBUG3 counting pattern - allows multiple writers\n",
1037 			     Progname, Pid);
1038 		else if (Pattern == PATTERN_RANDOM)
1039 			printf
1040 			    ("%s: %d DEBUG3 random integer pattern - no write/file checking\n",
1041 			     Progname, Pid);
1042 		else if (Pattern == PATTERN_ONES)
1043 			printf
1044 			    ("%s: %d DEBUG3 all ones pattern - allows multiple writers\n",
1045 			     Progname, Pid);
1046 		else if (Pattern == PATTERN_ZEROS)
1047 			printf
1048 			    ("%s: %d DEBUG3 all zeros pattern - allows multiple writers\n",
1049 			     Progname, Pid);
1050 
1051 		else
1052 			printf("%s: %d DEBUG3 unknown pattern\n",
1053 			       Progname, Pid);
1054 		if (bytes_to_consume)
1055 			printf("%s: %d DEBUG3 bytes_to_consume = %d\n",
1056 			       Progname, Pid, bytes_to_consume);
1057 		printf
1058 		    ("%s: %d DEBUG3 Maxerrs = %d, pre_alloc_space = %d, filelocking = %d\n",
1059 		     Progname, Pid, Maxerrs, pre_alloc_space, lockfile);
1060 
1061 		printf
1062 		    ("%s: %d DEBUG3 Debug = %d, remove files in cleanup : %d\n",
1063 		     Progname, Pid, Debug, remove_files);
1064 
1065 		printf("%s: %d DEBUG3 Mode = %#o\n", Progname, Pid, Mode);
1066 
1067 		if (open_flags == RANDOM_OPEN)
1068 			printf
1069 			    ("%s: %d DEBUG3 open_flags = (random), io_type = %#o\n",
1070 			     Progname, Pid, io_type);
1071 		else
1072 			printf
1073 			    ("%s: %d DEBUG3 open_flags = %#o, io_type = %#o\n",
1074 			     Progname, Pid, open_flags, io_type);
1075 
1076 		if (Mode & MODE_RAND_SIZE) {
1077 			printf
1078 			    ("%s: %d DEBUG3 random write/trunc:  min=%d, max=%d, mult = %d\n",
1079 			     Progname, Pid, min_size, max_size, mult_size);
1080 		} else {
1081 			printf("%s: %d DEBUG3 grow_incr = %d\n",
1082 			       Progname, Pid, grow_incr);
1083 		}
1084 		if (Mode & MODE_RAND_LSEEK) {
1085 			if (max_lseek == LSK_EOF)
1086 				printf
1087 				    ("%s: %d DEBUG3 random lseek:  min=%d, max=<endoffile>\n",
1088 				     Progname, Pid, min_lseek);
1089 			else if (max_lseek == LSK_EOFPLUSGROW)
1090 				printf
1091 				    ("%s: %d DEBUG3 random lseek:  min=%d, max=<endoffile+iosize>\n",
1092 				     Progname, Pid, min_lseek);
1093 			else if (max_lseek == LSK_EOFMINUSGROW)
1094 				printf
1095 				    ("%s: %d DEBUG3 random lseek:  min=%d, max=<endoffile-iosize>\n",
1096 				     Progname, Pid, min_lseek);
1097 			else
1098 				printf
1099 				    ("%s: %d DEBUG3 random lseek:  min=%d, max=%d\n",
1100 				     Progname, Pid, min_lseek, max_lseek);
1101 		}
1102 
1103 		printf
1104 		    ("%s: %d DEBUG3 check write interval = %d, check file interval = %d\n",
1105 		     Progname, Pid, write_check_inter, file_check_inter);
1106 
1107 		printf("%s: %d DEBUG3 trunc interval = %d, trunc_incr = %d\n",
1108 		       Progname, Pid, trunc_inter, trunc_incr);
1109 
1110 		if (no_file_check)
1111 			printf
1112 			    ("%s: %d DEBUG3 no whole file checking will be done\n",
1113 			     Progname, Pid);
1114 
1115 		if (unlink_inter_ran == -1) {
1116 			printf("%s: %d DEBUG3 unlink_inter = %d\n",
1117 			       Progname, Pid, unlink_inter);
1118 		} else {
1119 			printf
1120 			    ("%s: %d DEBUG3 unlink_inter = %d, unlink_inter_ran = %d\n",
1121 			     Progname, Pid, unlink_inter, unlink_inter_ran);
1122 		}
1123 
1124 		if (Debug > 8) {
1125 			num = sizeof(Open_flags) / sizeof(int);
1126 			printf("%s: %d DEBUG9 random open flags values:\n",
1127 			       Progname, Pid);
1128 			for (ind = 0; ind < num; ind++) {
1129 				printf("\t%#o\n", Open_flags[ind]);
1130 			}
1131 		}
1132 	}
1133 	/* end of DEBUG > 2 */
1134 	if (Debug > 1 && num_procs > 1) {
1135 		printf("%s: %d DEBUG2 about to fork %d more copies\n", Progname,
1136 		       Opid, num_procs - 1);
1137 	}
1138 
1139 	fflush(stdout);		/* ensure pending i/o is flushed before forking */
1140 	fflush(stderr);
1141 
1142 	forker(num_procs, forker_mode, Progname);
1143 
1144 	Pid = getpid();		/* reset after the forks */
1145 	/*
1146 	 * If user specified random seed(s), get that random seed value.
1147 	 * get random seed if it was not specified by the user.
1148 	 * This is done after the forks, because pid is used to get the seed.
1149 	 */
1150 	if (Nseeds == 1) {
1151 		/*
1152 		 * If only one seed specified, all processes will get that seed.
1153 		 */
1154 		Seed = Seeds[0];
1155 	} else if (Nseeds > 1) {
1156 		/*
1157 		 * More than one seed was specified.
1158 		 * The original process gets the first seed.  Each
1159 		 * process will be get the next seed in the specified list.
1160 		 */
1161 		if (Opid == Pid) {
1162 			Seed = Seeds[0];
1163 		} else {
1164 			/*
1165 			 * If user didn't specify enough seeds, use default method.
1166 			 */
1167 			if (Forker_npids >= Nseeds) {
1168 				struct timeval ts;
1169 				gettimeofday(&ts, NULL);
1170 				Seed = ts.tv_sec + Pid;	/* default random seed */
1171 			} else {
1172 				Seed = Seeds[Forker_npids];
1173 			}
1174 		}
1175 	} else {
1176 		/*
1177 		 * Generate a random seed based on time and pid.
1178 		 * It has a good chance of being unique for each pid.
1179 		 */
1180 		struct timeval ts;
1181 		gettimeofday(&ts, NULL);
1182 		Seed = ts.tv_sec + Pid;	/* default random seed */
1183 		//Seed=time(0) + Pid;  /* default random seed */
1184 
1185 	}
1186 
1187 	random_range_seed(Seed);
1188 
1189 	if (using_random && Debug > 0)
1190 		printf("%s%s: %d DEBUG1 Using random seed of %d\n",
1191 		       Progname, TagName, Pid, Seed);
1192 
1193 	if (unlink_inter_ran > 0) {
1194 		/*
1195 		 * Find unlinking file interval.  This must be done after
1196 		 * the seed was set.   This allows multiple copies to
1197 		 * get different intervals.
1198 		 */
1199 		tmp = unlink_inter;
1200 		unlink_inter =
1201 		    (int)random_range(tmp, unlink_inter_ran, 1, NULL);
1202 
1203 		if (Debug > 2)
1204 			printf
1205 			    ("%s: %d DEBUG3 Unlink interval is %d (random %d - %d)\n",
1206 			     Progname, Pid, unlink_inter, tmp,
1207 			     unlink_inter_ran);
1208 	}
1209 
1210 	/*
1211 	 * re-exec all childern if reexec is set to REXEC_DOIT.
1212 	 * This is useful on MPP systems to get the
1213 	 * child process on another PE.
1214 	 */
1215 	if (reexec == REXEC_DOIT && Opid != Pid) {
1216 		if (exec_path == NULL) {
1217 			exec_path = argv[0];
1218 			/* Get space for cmd (2 extra, 1 for - and 1 fro NULL */
1219 			argv[0] = malloc(strlen(exec_path) + 2);
1220 			sprintf(argv[0], "-%s", exec_path);
1221 		}
1222 
1223 		if (Debug > 2)
1224 			printf("%s: %d DEBUG3 %s/%d: execvp(%s, argv)\n",
1225 			       Progname, Pid, __FILE__, __LINE__, argv[0]);
1226 
1227 		execvp(argv[0], argv);
1228 	}
1229 
1230 	/*** begin filename stuff here *****/
1231 	/*
1232 	 * Determine the number of files to be dealt with
1233 	 */
1234 	if (optind == argc) {
1235 		/*
1236 		 * no cmd line files, therfore, set
1237 		 * the default number of auto created files
1238 		 */
1239 		if (!num_auto_files && !seq_auto_files)
1240 			num_auto_files = 1;
1241 	} else {
1242 		first_file_ind = optind;
1243 		num_files += argc - optind;
1244 	}
1245 
1246 	if (num_auto_files) {
1247 		num_files += num_auto_files;
1248 	}
1249 
1250 	if (seq_auto_files) {
1251 		num_files += seq_auto_files;
1252 	}
1253 
1254 	/*
1255 	 * get space for file names
1256 	 */
1257 	if ((filenames = malloc(num_files * PATH_MAX)) == NULL) {
1258 		fprintf(stderr, "%s%s: %d %s/%d: malloc(%d) failed: %s\n",
1259 			Progname, TagName, Pid, __FILE__, __LINE__,
1260 			num_files * PATH_MAX, strerror(errno));
1261 		exit(1);
1262 	}
1263 
1264 	/*
1265 	 * fill in filename cmd files then auto files.
1266 	 */
1267 
1268 	num = 0;
1269 	if (first_file_ind) {
1270 		for (ind = first_file_ind; ind < argc; ind++, num++) {
1271 			strcpy((char *)filenames + (num * PATH_MAX), argv[ind]);
1272 		}
1273 	}
1274 
1275 	/*
1276 	 * construct auto filename and insert them into filenames space
1277 	 */
1278 
1279 	for (ind = 0; ind < num_auto_files; ind++, num++) {
1280 		gettimeofday(&tv1, NULL);
1281 		sprintf((char *)filenames + (num * PATH_MAX),
1282 			"%s/%s%ld%ld%d.%d", auto_dir, auto_file,
1283 			(long)tv1.tv_sec, (long)tv1.tv_usec, rand(), ind);
1284 	}
1285 
1286 	/*
1287 	 * construct auto seq filenames
1288 	 */
1289 	for (ind = 1; ind <= seq_auto_files; ind++, num++) {
1290 		sprintf((char *)filenames + (num * PATH_MAX), "%s/%s%d",
1291 			auto_dir, auto_file, ind);
1292 	}
1293 
1294 /**** end filename stuff ****/
1295 
1296 	if (time_iterval > 0) {
1297 		struct timeval ts;
1298 		gettimeofday(&ts, NULL);
1299 		start_time = ts.tv_sec;
1300 		//start_time=time(0);
1301 	}
1302 
1303 	/*
1304 	 * get space for I/O buffer
1305 	 */
1306 	if (grow_incr) {
1307 		if ((Buffer = malloc(grow_incr + Alignment)) == NULL) {
1308 			fprintf(stderr,
1309 				"%s%s: %d %s/%d: malloc(%d) failed: %s\n",
1310 				Progname, TagName, Pid, __FILE__, __LINE__,
1311 				grow_incr, strerror(errno));
1312 			exit(1);
1313 		}
1314 		if (Alignment)
1315 			Buffer = Buffer + Alignment;
1316 
1317 	}
1318 
1319 	if (Debug > 2) {
1320 		printf("%s: %d DEBUG3 num_files = %d\n",
1321 		       Progname, Pid, num_files);
1322 	}
1323 #ifndef linux
1324 	if (pre_alloc_space) {
1325 		if (iterations == 0) {
1326 			fprintf(stderr,
1327 				"%s%s: %d %s/%d: can NOT pre-alloc and grow forever\n",
1328 				Progname, TagName, Pid, __FILE__, __LINE__);
1329 			exit(1);
1330 		}
1331 		if (Mode & MODE_RAND_SIZE) {
1332 			fprintf(stderr,
1333 				"%s%s: %d %s/%d: can NOT pre-alloc and do random io size\n",
1334 				Progname, TagName, Pid, __FILE__, __LINE__);
1335 			exit(1);
1336 		}
1337 
1338 		total_grow_value = grow_incr * iterations;
1339 
1340 		/*
1341 		 * attempt to limit
1342 		 */
1343 		if (bytes_to_consume && bytes_to_consume < total_grow_value) {
1344 			total_grow_value = bytes_to_consume;
1345 		}
1346 	}
1347 #endif
1348 
1349 	/*
1350 	 * If delaying between iterations, get amount time to
1351 	 * delaysecs in clocks or usecs.
1352 	 * If on the CRAY, delaytime is in clocks since
1353 	 * _rtc() will be used, which does not have the overhead
1354 	 * of gettimeofday(2).
1355 	 */
1356 	if (delaysecs) {
1357 #if CRAY
1358 		int hz;
1359 		hz = sysconf(_SC_CLK_TCK);
1360 		delaytime = (int)((float)hz * delaysecs);
1361 #else
1362 		delaytime = (int)((float)USECS_PER_SEC * delaysecs);
1363 #endif
1364 	}
1365 
1366 	if (statfs(auto_dir, &fsbuf) == -1) {
1367 		fprintf(stderr, "%s%s: Unable to get the info of mounted "
1368 			"filesystem that includes dir %s\n",
1369 			Progname, TagName, auto_dir);
1370 		exit(1);
1371 	}
1372 
1373 	/* Compare two values and use the smaller one as limit */
1374 	fs_limit = MIN(fsbuf.f_bsize * fsbuf.f_bavail / num_files, fs_limit);
1375 
1376 	/*
1377 	 * This is the main iteration loop.
1378 	 * Each iteration, all files can  be opened, written to,
1379 	 * read to check the write, check the whole file,
1380 	 * truncated, and closed.
1381 	 */
1382 	for (Iter_cnt = 1; !stop; Iter_cnt++) {
1383 		struct timeval ts;
1384 		if (iterations && (Iter_cnt >= iterations + 1)) {
1385 			strcpy(reason, "Hit iteration value");
1386 			stop = 1;
1387 			continue;
1388 		}
1389 		gettimeofday(&ts, NULL);
1390 		if ((time_iterval > 0)
1391 		    && (start_time + time_iterval < ts.tv_sec)) {
1392 
1393 			sprintf(reason, "Hit time value of %d", time_iterval);
1394 			stop = 1;
1395 			continue;
1396 		}
1397 
1398 		if (bytes_to_consume && bytes_consumed >= bytes_to_consume) {
1399 			sprintf(reason, "Hit bytes consumed value of %d",
1400 				bytes_to_consume);
1401 			stop = 1;
1402 			continue;
1403 		}
1404 
1405 		/*
1406 		 * This loop will loop through all files.
1407 		 * Each iteration, a single file can  be opened, written to,
1408 		 * read to check the write, check the whole file,
1409 		 * truncated, and closed.
1410 		 */
1411 		for (ind = 0; ind < num_files; ind++) {
1412 
1413 			fflush(stdout);
1414 			fflush(stderr);
1415 
1416 			filename = (char *)filenames + (ind * PATH_MAX);
1417 			Fileinfo.filename =
1418 			    (char *)filenames + (ind * PATH_MAX);
1419 
1420 			if (open_flags == RANDOM_OPEN) {
1421 				ret =
1422 				    Open_flags[random_range
1423 					       (0,
1424 						sizeof(Open_flags) /
1425 						sizeof(int) - 1, 1, NULL)];
1426 			}
1427 
1428 			else
1429 				ret = open_flags;
1430 
1431 			Fileinfo.openflags = ret;
1432 
1433 			if (Debug > 3) {
1434 				printf
1435 				    ("%s: %d DEBUG3 %s/%d: %d Open filename = %s, open flags = %#o %s\n",
1436 				     Progname, Pid, __FILE__, __LINE__,
1437 				     Iter_cnt, filename, ret,
1438 				     openflags2symbols(ret, ",", 0));
1439 			} else if (Debug > 2) {
1440 				printf
1441 				    ("%s: %d DEBUG3 %s/%d: %d filename = %s, open flags = %#o\n",
1442 				     Progname, Pid, __FILE__, __LINE__,
1443 				     Iter_cnt, filename, ret);
1444 			}
1445 
1446 			/*
1447 			 * open file with desired flags.
1448 			 */
1449 			if ((fd = open(filename, ret, 0777)) == -1) {
1450 				fprintf(stderr,
1451 					"%s%s: %d %s/%d: open(%s, %#o, 0777) returned -1, errno:%d %s\n",
1452 					Progname, TagName, Pid, __FILE__,
1453 					__LINE__, filename, ret, errno,
1454 					strerror(errno));
1455 				handle_error();
1456 				continue;
1457 			}
1458 
1459 			Fileinfo.fd = fd;
1460 
1461 			lkfile(fd, LOCK_EX, LKLVL1);	/* lock if lockfile is LKLVL1 */
1462 
1463 #ifndef linux
1464 			/*
1465 			 * preallocation is only done once, if specified.
1466 			 */
1467 			if (pre_alloc_space) {
1468 				if (pre_alloc(fd, total_grow_value) != 0) {
1469 					cleanup();
1470 					exit(2);
1471 				}
1472 				if (Debug > 1) {
1473 					printf
1474 					    ("%s: %d DEBUG2 %s/%d: pre_allocated %ld for file %s\n",
1475 					     Progname, Pid, __FILE__, __LINE__,
1476 					     total_grow_value, filename);
1477 				}
1478 				lkfile(fd, LOCK_UN, LKLVL1);	/* release lock */
1479 				close(fd);
1480 				Iter_cnt = 0;	/* reset outside loop to restart from one */
1481 				continue;
1482 			}
1483 #endif
1484 
1485 			/*
1486 			 * grow file by desired amount.
1487 			 * growfile() will set the Grow_incr variable and
1488 			 * possiblly update the Mode variable indicating
1489 			 * if we are dealing with a FIFO file.
1490 			 */
1491 
1492 			/* BUG:14136 (don't go past filesystem size limit) */
1493 			curr_size = file_size(fd);
1494 			if (curr_size + grow_incr >= fs_limit) {
1495 				lkfile(fd, LOCK_UN, LKLVL1);	/* release lock */
1496 				close(fd);
1497 				sprintf(reason,
1498 					"Reached %ld filesize which is almost %ld limit.",
1499 					curr_size, fs_limit);
1500 				stop = 1;
1501 				continue;
1502 			}
1503 
1504 			if (growfile(fd, filename, grow_incr, Buffer, &curr_size) != 0) {	/* BUG:14136 */
1505 				handle_error();
1506 				lkfile(fd, LOCK_UN, LKLVL1);	/* release lock */
1507 				close(fd);
1508 				continue;
1509 			}
1510 
1511 			/*
1512 			 * check if last write is not corrupted
1513 			 */
1514 			if (check_write(fd, write_check_inter, filename,
1515 					Mode) != 0) {
1516 				handle_error();
1517 			}
1518 
1519 			/*
1520 			 * Check that whole file is not corrupted.
1521 			 */
1522 			if (check_file(fd, file_check_inter, filename,
1523 				       no_file_check) != 0) {
1524 				handle_error();
1525 			}
1526 
1527 			/*
1528 			 * shrink file by desired amount if it is time
1529 			 */
1530 
1531 			if (shrinkfile
1532 			    (fd, filename, trunc_incr, trunc_inter,
1533 			     Mode) != 0) {
1534 				handle_error();
1535 			}
1536 
1537 			lkfile(fd, LOCK_UN, LKLVL1);	/* release lock */
1538 
1539 			if (Debug > 4)
1540 				printf
1541 				    ("%s: %d DEBUG5 %s/%d: %d Closing file %s fd:%d \n",
1542 				     Progname, Pid, __FILE__, __LINE__,
1543 				     Iter_cnt, filename, fd);
1544 			close(fd);
1545 
1546 			/*
1547 			 * Unlink the file if that is desired
1548 			 */
1549 			if (unlink_inter && (Iter_cnt % unlink_inter == 0)) {
1550 
1551 				if (Debug > 4)
1552 					printf
1553 					    ("%s: %d DEBUG5 %s/%d: %d Unlinking file %s\n",
1554 					     Progname, Pid, __FILE__, __LINE__,
1555 					     Iter_cnt, filename);
1556 
1557 				unlink(filename);
1558 			}
1559 
1560 			/*
1561 			 * delay while staying active for "delaysecs" seconds.
1562 			 */
1563 			if (delaytime) {
1564 
1565 				int ct, end;
1566 #ifdef CRAY
1567 				ct = _rtc();
1568 				end = ct + delaytime;
1569 				while (ct < end) {
1570 					ct = _rtc();
1571 				}
1572 #else
1573 				struct timeval curtime;
1574 				gettimeofday(&curtime, NULL);
1575 				ct = curtime.tv_sec * USECS_PER_SEC +
1576 				    curtime.tv_usec;
1577 				end = ct + delaytime;
1578 				while (ct < end) {
1579 
1580 					gettimeofday(&curtime, NULL);
1581 					ct = curtime.tv_sec * USECS_PER_SEC +
1582 					    curtime.tv_usec;
1583 				}
1584 #endif
1585 			}
1586 		}
1587 #ifndef linux
1588 		/*
1589 		 * if Iter_cnt == 0, then we pre allocated space to all files
1590 		 * and we are starting outside loop over.  Set pre_alloc_space
1591 		 * to zero otherwise we get in infinite loop
1592 		 */
1593 		if (Iter_cnt == 0) {
1594 			pre_alloc_space = 0;
1595 		}
1596 #endif
1597 
1598 	}			/* end iteration for loop */
1599 
1600 	if (Debug) {
1601 		printf("%s%s: %d %s/%d: DONE %d iterations to %d files. %s\n",
1602 		       Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt,
1603 		       num_files, reason);
1604 	}
1605 	fflush(stdout);
1606 	fflush(stderr);
1607 
1608 	cleanup();
1609 
1610 	if (Errors) {
1611 		if (Debug > 2) {
1612 			printf("%s%s: %d DEBUG3 %d error(s) encountered\n",
1613 			       Progname, TagName, Pid, Errors);
1614 			printf
1615 			    ("%s%s: %d DEBUG3 %s/%d: exiting with value of 1\n",
1616 			     Progname, TagName, Pid, __FILE__, __LINE__);
1617 		}
1618 		exit(1);
1619 	}
1620 	if (Debug > 2) {
1621 		printf
1622 		    ("%s%s: %d DEBUG3 %s/%d: no errors, exiting with value of 0\n",
1623 		     Progname, TagName, Pid, __FILE__, __LINE__);
1624 	}
1625 
1626 	exit(0);
1627 	tst_exit();		/* to keep compiler happy */
1628 }
1629 
1630 /***********************************************************************
1631  *
1632  ***********************************************************************/
set_sig(void)1633 int set_sig(void)
1634 {
1635 	int sig;
1636 
1637 	/*
1638 	 * now loop through all signals and set the handlers
1639 	 */
1640 
1641 	for (sig = 1; sig < NSIG; sig++) {
1642 		switch (sig) {
1643 		case SIGKILL:
1644 		case SIGSTOP:
1645 		case SIGCONT:
1646 #ifdef CRAY
1647 		case SIGINFO:
1648 		case SIGRECOVERY:
1649 #endif /* CRAY */
1650 #ifdef SIGCKPT
1651 		case SIGCKPT:
1652 #endif /* SIGCKPT */
1653 #ifdef SIGRESTART
1654 		case SIGRESTART:
1655 #endif /* SIGRESTART */
1656 		case SIGCHLD:
1657 			break;
1658 
1659 		default:
1660 #ifdef sgi
1661 			sigset(sig, sig_handler);
1662 #else
1663 /* linux and cray */
1664 			signal(sig, sig_handler);
1665 #endif
1666 			break;
1667 		}
1668 	}			/* endfor */
1669 
1670 	return 0;
1671 }
1672 
1673 /***********************************************************************
1674  *
1675  ***********************************************************************/
sig_handler(int sig)1676 void sig_handler(int sig)
1677 {
1678 	int exit_stat = 2;
1679 
1680 	if (sig == SIGUSR2) {
1681 		fprintf(stdout,
1682 			"%s%s: %d %s/%d: received SIGUSR2 (%d) - stopping.\n",
1683 			Progname, TagName, Pid, __FILE__, __LINE__, sig);
1684 #ifndef sgi
1685 		signal(sig, sig_handler);	/* allow us to get this signal more than once */
1686 #endif
1687 
1688 	} else if (sig == SIGINT) {
1689 		/* The user has told us to cleanup, don't pretend it's an error. */
1690 		exit_stat = 0;
1691 		if (Debug != 0) {
1692 			fprintf(stderr,
1693 				"%s%s: %d %s/%d: received unexpected signal: %d\n",
1694 				Progname, TagName, Pid, __FILE__, __LINE__,
1695 				sig);
1696 		}
1697 	} else {
1698 		fprintf(stderr,
1699 			"%s%s: %d %s/%d: received unexpected signal: %d\n",
1700 			Progname, TagName, Pid, __FILE__, __LINE__, sig);
1701 	}
1702 
1703 	notify_others();
1704 	cleanup();
1705 	if (Debug > 2) {
1706 		printf("%s%s: %d DEBUG3 %s/%d: Exiting with a value of %d\n",
1707 		       Progname, TagName, Pid, __FILE__, __LINE__, exit_stat);
1708 	}
1709 	exit(exit_stat);
1710 }
1711 
1712 /***********************************************************************
1713  * this function attempts to send SIGUSR2 to other growfiles processes
1714  * telling them to stop.
1715  *
1716  ***********************************************************************/
notify_others(void)1717 static void notify_others(void)
1718 {
1719 	static int send_signals = 0;
1720 	int ind;
1721 
1722 	if (Sync_with_others && send_signals == 0) {
1723 
1724 #if CRAY
1725 		send_signals = 1;	/* only send signals once */
1726 		if (Debug > 1)
1727 			printf
1728 			    ("%s%s: %d DEBUG2 %s/%d: Sending SIGUSR2 to pgrp\n",
1729 			     Progname, TagName, Pid, __FILE__, __LINE__);
1730 		killm(C_PGRP, getpgrp(), SIGUSR2);
1731 #else
1732 		send_signals = 1;	/* only send signals once */
1733 
1734 		for (ind = 0; ind < Forker_npids; ind++) {
1735 			if (Forker_pids[ind] != Pid)
1736 				if (Debug > 1)
1737 					printf
1738 					    ("%s%s: %d DEBUG2 %s/%d: Sending SIGUSR2 to pid %d\n",
1739 					     Progname, TagName, Pid, __FILE__,
1740 					     __LINE__, Forker_pids[ind]);
1741 			kill(Forker_pids[ind], SIGUSR2);
1742 		}
1743 #endif
1744 	}
1745 
1746 }
1747 
1748 /***********************************************************************
1749  * this function will count the number of errors encountered.
1750  * This function will call upanic if wanted or cleanup and
1751  * and exit is Maxerrs were encountered.
1752  ***********************************************************************/
handle_error(void)1753 int handle_error(void)
1754 {
1755 	Errors++;
1756 
1757 #ifdef CRAY
1758 	if (Errors & Upanic_on_error) {
1759 		upanic(PA_PANIC);
1760 	}
1761 #endif
1762 
1763 	if (Maxerrs && Errors >= Maxerrs) {
1764 		printf("%s%s: %d %s/%d: %d Hit max errors value of %d\n",
1765 		       Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt,
1766 		       Maxerrs);
1767 		notify_others();
1768 		cleanup();
1769 
1770 		if (Debug > 2) {
1771 			printf("%s%s: %d DEBUG3 %d error(s) encountered\n",
1772 			       Progname, TagName, Pid, Errors);
1773 			printf
1774 			    ("%s%s: %d DEBUG3 %s/%d: exiting with value of 1\n",
1775 			     Progname, TagName, Pid, __FILE__, __LINE__);
1776 		}
1777 
1778 		exit(1);
1779 	}
1780 
1781 	return 0;
1782 }
1783 
1784 /***********************************************************************
1785  *
1786  ***********************************************************************/
cleanup(void)1787 int cleanup(void)
1788 {
1789 	int ind;
1790 
1791 	if (remove_files) {
1792 		if (Debug > 2)
1793 			printf("%s: %d DEBUG3 Removing all %d files\n",
1794 			       Progname, Pid, num_files);
1795 		for (ind = 0; ind <= num_files; ind++) {
1796 			unlink(filenames + (ind * PATH_MAX));
1797 		}
1798 	}
1799 	if (using_random && Debug > 1)
1800 		printf("%s%s: %d DEBUG2 Used random seed: %d\n",
1801 		       Progname, TagName, Pid, Seed);
1802 	return 0;
1803 }
1804 
1805 /***********************************************************************
1806  *
1807  ***********************************************************************/
usage(void)1808 void usage(void)
1809 {
1810 	fprintf(stderr,
1811 		"Usage: %s%s [-bhEluy][[-g grow_incr][-i num][-t trunc_incr][-T trunc_inter]\n",
1812 		Progname, TagName);
1813 	fprintf(stderr,
1814 		"[-d auto_dir][-e maxerrs][-f auto_file][-N num_files][-w][-c chk_inter][-D debug]\n");
1815 	fprintf(stderr,
1816 		"[-s seed][-S seq_auto_files][-p][-P PANIC][-I io_type][-o open_flags][-B maxbytes]\n");
1817 	fprintf(stderr,
1818 		"[-r iosizes][-R lseeks][-U unlk_inter][-W tagname] [files]\n");
1819 
1820 	return;
1821 
1822 }				/* end of usage */
1823 
1824 /***********************************************************************
1825  *
1826  ***********************************************************************/
help(void)1827 void help(void)
1828 {
1829 	usage();
1830 
1831 	fprintf(stdout, "\
1832   -h             Specfied to print this help and exit.\n\
1833   -b             Specfied to execute in sync mode.(def async mode)\n\
1834   -B maxbytes    Max bytes to consume by all files.  growfiles exits when more\n\
1835                  than maxbytes have been consumed. (def no chk)  If maxbytes ends\n\
1836                  with the letter 'b', maxbytes is multiplied by BSIZE\n\
1837   -C write_chk   Specifies how often to check the last write (default 1)\n\
1838   -c file_chk    Specifies how often to check whole file (default 0)\n\
1839   -d auto_dir    Specifies the directory to auto created files. (default .)\n\
1840   -D debug_lvl   Specifies the debug level (default 1)\n\
1841   -E             Print examples and exit\n\
1842   -e errs        The number errors that will terminate this program (def 100)\n\
1843   -f auto_file   Specifies the base filename files created. (default \"gf\")\n\
1844   -g grow_incr   Specfied to grow by incr for each num. (default 4096)\n\
1845                  grow_incr may end in b for blocks\n\
1846 		 If -r option is used, this option is ignored and size is random\n\
1847   -H delay       Amount of time to delay between each file (default 0.0)\n\
1848   -I io_type Specifies io type: s - sync, p - polled async, a - async (def s)\n\
1849 		 l - listio sync, L - listio async, r - random\n\
1850   -i iteration   Specfied to grow each file num times. 0 means forever (default 1)\n\
1851   -l             Specfied to do file locking around write/read/trunc\n\
1852 		 If specified twice, file locking after open to just before close\n\
1853   -L time        Specfied to exit after time secs, must be used with -i.\n\
1854   -N num_files   Specifies the number of files to be created.\n\
1855                  The default is zero if cmd line files.\n\
1856                  The default is one if no cmd line files.\n\
1857   -n num_procs   Specifies the number of copies of this cmd.\n\
1858   -o op_type     Specifies open flages: (def O_RDWR,O_CREAT) op_type can be 'random'\n\
1859   -O offset      adjust i/o buffer alignment by offset bytes\n\
1860   -P PANIC       Specifies to call upanic on error.\n\
1861   -p             Specifies to pre-allocate space\n\
1862   -q pattern     pattern can be a - ascii, p - pid with boff, o boff (def)\n\
1863 		 A - Alternating bits, r - random, O - all ones, z - all zeros,\n\
1864 		 c - checkboard, C - counting\n\
1865   -R [min-]max   random lseek before write and trunc, max of -1 means filesz,\n\
1866 		 -2 means filesz+grow, -3 filesz-grow. (min def is 0)\n\
1867   -r [min-]max   random io write size (min def is 1)\n\
1868   -S seq_auto_files Specifies the number of seqental auto files (default 0)\n\
1869   -s seed[,seed...] Specifies the random number seed (default time(0)+pid)\n\
1870   -t trunc_incr  Specfied the amount to shrink file. (default 4096)\n\
1871                  trunc_inter may end in b for blocks\n\
1872 		 If -R option is used, this option is ignored and trunc is random\n\
1873   -T trunc_inter Specfied the how many grows happen before shrink. (default 0)\n\
1874   -u             unlink files before exit\n\
1875   -U ui[-ui2]    Unlink files each ui iteration (def 0)\n\
1876   -w             Specfied to grow via lseek instead of writes.\n\
1877   -W tag-name	 Who-am-i.  My Monster tag name.  (used by Monster).\n\
1878   -x		 Re-exec children before continuing - useful on MPP systems\n\
1879   -y             Attempt to sync copies - if one fails it will send sigusr2 to others\n\
1880   Action to each file every iteration is open, write, write check\n\
1881   file check, trunc and closed.\n");
1882 
1883 	return;
1884 }
1885 
1886 /***********************************************************************
1887  *
1888  ***********************************************************************/
prt_examples(FILE * stream)1889 void prt_examples(FILE * stream)
1890 {
1891 	/* This example creates 200 files in directory dir1.  It writes */
1892 	/* 4090 bytes 100 times then truncates 408990 bytes off the file */
1893 	/* The file contents are checked every 1000 grow. */
1894 	fprintf(stream,
1895 		"# run forever: writes of 4090 bytes then on every 100 iterval\n\
1896 # truncate file by 408990 bytes.  Done to 200 files in dir1.\n\
1897 %s -i 0 -g 4090 -T 100 -t 408990 -l -C 10 -c 1000 -d dir1 -S 200\n\n",
1898 		Progname);
1899 
1900 	/* same as above with 5000 byte grow and a 499990 byte tuncate */
1901 	fprintf(stream,
1902 		"# same as above with writes of 5000 bytes and truncs of 499990\n\
1903 %s -i 0 -g 5000 -T 100 -t 499990 -l -C 10 -c 1000 -d dir2 -S 200\n\n",
1904 		Progname);
1905 
1906 	/* This example beats on opens and closes */
1907 	fprintf(stream,
1908 		"# runs forever: beats on opens and closes of file ocfile - no io\n\
1909 %s -i 0 -g 0 -c 0 -C 0 ocfile\n\n",
1910 		Progname);
1911 
1912 	fprintf(stream, "# writes 4096 to files until 50 blocks are written\n\
1913 %s -i 0 -g 4096 -B 50b file1 file2\n\n", Progname);
1914 
1915 	fprintf(stream,
1916 		"# write one byte to 750 files in gdir then unlinks them\n\
1917 %s -g 1 -C 0 -d gdir -u -S 750\n\n", Progname);
1918 
1919 	fprintf(stream, "# run 30 secs: random iosize, random lseek up to eof\n\
1920 %s -r 1-5000 -R 0--1 -i 0 -L 30 -C 1 g_rand1 g_rand2\n\n", Progname);
1921 
1922 	fprintf(stream,
1923 		"# run 30 secs: grow by lseek then write single byte, trunc every 10 itervals\n\
1924 %s -g 5000 -wlu -i 0 -L 30 -C 1 -T 10  g_sleek1 g_lseek2\n\n",
1925 		Progname);
1926 
1927 	fprintf(stream,
1928 		"# run forever: 5 copies of random iosize, random lseek to beyond eof,\n\
1929 # rand io types doing a trunc every 5 iterations, with unlinks.\n\
1930 %s -i0 -r 1-50000 -R 0--2 -I r -C1 -l -n5 -u -U 100-200 gf_rana gf_ranb\n\n",
1931 		Progname);
1932 
1933 	fprintf(stream,
1934 		"# run forever: 5 copies of random iosize, random lseek to beyond eof,\n\
1935 # random open flags, rand io types doing a trunc every 10 iterations.\n\
1936 %s -i0 -r 1-50000 -R 0--2 -o random -I r -C0 -l -T 20 -uU100-200 -n 5 gf_rand1 gf_rand2\n",
1937 		Progname);
1938 
1939 	return;
1940 }
1941 
1942 /***********************************************************************
1943  *
1944  * The file descriptor current offset is assumed to be the end of the
1945  * file.
1946  * Woffset will be set to the offset before the write.
1947  * Grow_incr will be set to the size of the write or lseek write.
1948  ***********************************************************************/
growfile(int fd,char * file,int grow_incr,char * buf,unsigned long * curr_size_ptr)1949 int /* BUG:14136 */ growfile(int fd, char *file, int grow_incr, char *buf,
1950 			     unsigned long *curr_size_ptr)
1951 {
1952 	off_t noffset;
1953 	int ret;
1954 	int cur_offset;
1955 	char *errmsg;
1956 	off_t fsize;		/* current size of file */
1957 	int size_grew;		/* size the file grew */
1958 	struct stat stbuf;
1959 	off_t off_tmp = 0;
1960 
1961 	/*
1962 	 * Do a stat on the open file.
1963 	 * If the file is a fifo, set the bit in Mode variable.
1964 	 * This fifo check must be done prior to growfile() returning.
1965 	 * Also get the current size of the file.
1966 	 */
1967 	if (fstat(fd, &stbuf) != -1) {
1968 		if (S_ISFIFO(stbuf.st_mode)) {
1969 			Fileinfo.mode |= MODE_FIFO;
1970 			Mode |= MODE_FIFO;
1971 			if (Debug > 3)
1972 				printf
1973 				    ("%s: %d DEBUG4 %s/%d: file is a fifo - no lseek or truncs,\n",
1974 				     Progname, Pid, __FILE__, __LINE__);
1975 		}
1976 		fsize = stbuf.st_size;
1977 
1978 	} else {
1979 		fprintf(stderr,
1980 			"%s%s: %d %s/%d: Unable to fstat(%d, &buf), errno:%d %s\n",
1981 			Progname, TagName, Pid, __FILE__, __LINE__, fd, errno,
1982 			strerror(errno));
1983 
1984 		return -1;
1985 	}
1986 
1987 	if (grow_incr <= 0) {	/* don't attempt i/o if grow_incr <= 0 */
1988 
1989 		Grow_incr = grow_incr;
1990 		if (Debug > 2)
1991 			printf
1992 			    ("%s: %d DEBUG3 %s/%d: Not attempting to grow, growsize == %d\n",
1993 			     Progname, Pid, __FILE__, __LINE__, grow_incr);
1994 		return grow_incr;
1995 	}
1996 
1997 	if (Mode & MODE_RAND_SIZE) {
1998 		grow_incr =
1999 		    random_range(min_size, max_size, mult_size, &errmsg);
2000 		if (errmsg != NULL) {
2001 			fprintf(stderr,
2002 				"%s%s: %d %s/%d: random_range() failed - %s\n",
2003 				Progname, TagName, Pid, __FILE__, __LINE__,
2004 				errmsg);
2005 			return -1;
2006 		}
2007 		Grow_incr = grow_incr;
2008 	} else
2009 		Grow_incr = grow_incr;
2010 
2011 	if (!(Mode & MODE_FIFO)) {
2012 		if ((cur_offset = lseek(fd, 0, SEEK_CUR)) == -1) {
2013 			fprintf(stderr, "%s%s: %d %s/%d: tell failed: %s\n",
2014 				Progname, TagName, Pid, __FILE__, __LINE__,
2015 				strerror(errno));
2016 			return -1;
2017 		}
2018 	}
2019 
2020 	if (Mode & MODE_GROW_BY_LSEEK) {
2021 		Woffset = fsize;
2022 		if (Debug > 2) {
2023 			printf
2024 			    ("%s: %d DEBUG3 %s/%d: Current size of file is %ld\n",
2025 			     Progname, Pid, __FILE__, __LINE__, (long)Woffset);
2026 			printf
2027 			    ("%s: %d DEBUG3 %s/%d: lseeking to %d byte with SEEK_END\n",
2028 			     Progname, Pid, __FILE__, __LINE__, grow_incr - 1);
2029 		}
2030 
2031 		if ((noffset = lseek(fd, grow_incr - 1, SEEK_END)) == -1) {
2032 			fprintf(stderr,
2033 				"%s%s: %s/%d: lseek(fd, %d, SEEK_END) failed: %s\n",
2034 				Progname, TagName, __FILE__, __LINE__,
2035 				grow_incr - 1, strerror(errno));
2036 			return -1;
2037 		}
2038 
2039 		lkfile(fd, LOCK_EX, LKLVL0);	/* get exclusive lock */
2040 
2041 #if NEWIO
2042 		ret =
2043 		    lio_write_buffer(fd, io_type, "w", 1, SIGUSR1, &errmsg, 0);
2044 #else
2045 		ret = write_buffer(fd, io_type, "w", 1, 0, &errmsg);
2046 #endif
2047 
2048 		if (ret != 1) {
2049 			fprintf(stderr, "%s%s: %d %s/%d: %d %s\n",
2050 				Progname, TagName, Pid, __FILE__, __LINE__,
2051 				Iter_cnt, errmsg);
2052 			if (ret == -ENOSPC) {
2053 				cleanup();
2054 				exit(2);
2055 			}
2056 		}
2057 /***
2058 		write(fd, "w", 1);
2059 ****/
2060 
2061 		lkfile(fd, LOCK_UN, LKLVL0);
2062 
2063 		if (Debug > 2)
2064 			printf("%s: %d DEBUG3 %s/%d: %d wrote 1 byte to file\n",
2065 			       Progname, Pid, __FILE__, __LINE__, Iter_cnt);
2066 
2067 	} else {		/* end of grow by lseek */
2068 
2069 		if (Fileinfo.openflags & O_APPEND) {
2070 			/*
2071 			 * Deal with special case of the open flag containing O_APPEND.
2072 			 * If it does, the current offset does not matter since the write
2073 			 * will be done end of the file.
2074 			 */
2075 			if (Debug > 4)
2076 				printf
2077 				    ("%s: %d DEBUG5 %s/%d: dealing with O_APPEND condition\n",
2078 				     Progname, Pid, __FILE__, __LINE__);
2079 			lkfile(fd, LOCK_EX, LKLVL0);	/* get exclusive lock */
2080 
2081 			/*
2082 			 * do fstat again to get size of the file.
2083 			 * This is done inside a file lock (if locks are being used).
2084 			 */
2085 			if (fstat(fd, &stbuf) != -1) {
2086 				Woffset = stbuf.st_size;
2087 			} else {
2088 				fprintf(stderr,
2089 					"%s%s: %d %s/%d: Unable to fstat(%d, &buf), errno:%d %s\n",
2090 					Progname, TagName, Pid, __FILE__,
2091 					__LINE__, fd, errno, strerror(errno));
2092 
2093 				lkfile(fd, LOCK_UN, LKLVL0);	/* release lock */
2094 				return -1;
2095 			}
2096 			if (Debug > 2)
2097 				printf
2098 				    ("%s: %d DEBUG3 %s/%d: dealing with O_APPEND condition (offset:fsz:%d)\n",
2099 				     Progname, Pid, __FILE__, __LINE__,
2100 				     (int)stbuf.st_size);
2101 
2102 		} else if (Mode & MODE_RAND_LSEEK) {
2103 			if (max_lseek == LSK_EOF) {	/* within file size */
2104 				noffset =
2105 				    random_range(min_lseek, fsize, 1, NULL);
2106 			} else if (max_lseek == LSK_EOFPLUSGROW) {
2107 				/* max to beyond file size */
2108 				noffset =
2109 				    random_range(min_lseek, fsize + grow_incr,
2110 						 1, NULL);
2111 			} else if (max_lseek == LSK_EOFMINUSGROW) {
2112 				/*
2113 				 * Attempt to not grow the file.
2114 				 * If the i/o will fit from min_lseek to EOF,
2115 				 * pick offset to allow it to fit.
2116 				 * Otherwise, pick the min_lseek offset and grow
2117 				 * file by smallest amount.
2118 				 * If min_lseek is != 0, there will be a problem
2119 				 * with whole file checking if file is ever smaller
2120 				 * than min_lseek.
2121 				 */
2122 				if (fsize <= min_lseek + grow_incr)
2123 					noffset = min_lseek;	/* file will still grow */
2124 				else
2125 					noffset =
2126 					    random_range(min_lseek,
2127 							 fsize - grow_incr, 1,
2128 							 NULL);
2129 			} else {
2130 				noffset =
2131 				    random_range(min_lseek, max_lseek, 1, NULL);
2132 			}
2133 
2134 			if ((Woffset = lseek(fd, noffset, SEEK_SET)) == -1) {
2135 				fprintf(stderr,
2136 					"%s%s: %d %s/%d: lseek(%d, %ld, "
2137 					"SEEK_SET) l2 failed: %s\n", Progname,
2138 					TagName, Pid, __FILE__, __LINE__, fd,
2139 					(long)noffset, strerror(errno));
2140 				return -1;
2141 			} else if (Debug > 2)
2142 				printf("%s: %d DEBUG3 %s/%d: lseeked to "
2143 				       "random offset %ld (fsz:%d)\n",
2144 				       Progname, Pid, __FILE__, __LINE__,
2145 				       (long)Woffset, (int)stbuf.st_size);
2146 
2147 		}
2148 
2149 		/*
2150 		 * lseek to end of file only if not fifo
2151 		 */
2152 		else if (!(Mode & MODE_FIFO)) {
2153 			if ((Woffset = lseek(fd, 0, SEEK_END)) == -1) {
2154 				fprintf(stderr,
2155 					"%s%s: %d %s/%d: lseek(fd, 0, SEEK_END) failed: %s\n",
2156 					Progname, TagName, Pid, __FILE__,
2157 					__LINE__, strerror(errno));
2158 				return -1;
2159 			} else if (Debug > 2)
2160 				printf("%s: %d DEBUG3 %s/%d: lseeked to "
2161 				       "end of file, offset %ld\n",
2162 				       Progname, Pid, __FILE__, __LINE__,
2163 				       (long)Woffset);
2164 		}
2165 
2166 		if (Pattern == PATTERN_OFFSET)
2167 			datapidgen(STATIC_NUM, buf, grow_incr, Woffset);
2168 		else if (Pattern == PATTERN_PID)
2169 			datapidgen(Pid, buf, grow_incr, Woffset);
2170 		else if (Pattern == PATTERN_ASCII)
2171 			dataasciigen(NULL, buf, grow_incr, Woffset);
2172 		else if (Pattern == PATTERN_RANDOM)
2173 			databingen('r', buf, grow_incr, Woffset);
2174 		else if (Pattern == PATTERN_ALT)
2175 			databingen('a', buf, grow_incr, Woffset);
2176 		else if (Pattern == PATTERN_CHKER)
2177 			databingen('c', buf, grow_incr, Woffset);
2178 		else if (Pattern == PATTERN_CNTING)
2179 			databingen('C', buf, grow_incr, Woffset);
2180 		else if (Pattern == PATTERN_ZEROS)
2181 			databingen('z', buf, grow_incr, Woffset);
2182 		else if (Pattern == PATTERN_ONES)
2183 			databingen('o', buf, grow_incr, Woffset);
2184 		else
2185 			dataasciigen(NULL, buf, grow_incr, Woffset);
2186 
2187 		if (Debug > 2)
2188 			printf
2189 			    ("%s: %d DEBUG3 %s/%d: attempting to write %d bytes\n",
2190 			     Progname, Pid, __FILE__, __LINE__, grow_incr);
2191 
2192 		lkfile(fd, LOCK_EX, LKLVL0);	/* get exclusive lock */
2193 
2194 /*****
2195 		ret=write(fd, buf, grow_incr);
2196 
2197 		off_tmp = tell(fd);
2198 
2199 		lkfile(fd, LOCK_UN, LKLVL0);
2200 
2201 		if (ret != grow_incr) {
2202 			fprintf(stderr, "%s: %s/%d: write failed: %s\n",
2203 				Progname, __FILE__, __LINE__, strerror(errno));
2204 			return -1;
2205 		}
2206 *****/
2207 
2208 #if NEWIO
2209 		ret = lio_write_buffer(fd, io_type, buf, grow_incr,
2210 				       SIGUSR1, &errmsg, 0);
2211 #else
2212 		ret = write_buffer(fd, io_type, buf, grow_incr, 0, &errmsg);
2213 #endif
2214 
2215 		if (Mode & MODE_FIFO) {
2216 			/* If it is a fifo then just pretend the file
2217 			 * offset is where we think it should be.
2218 			 */
2219 			off_tmp = Woffset + grow_incr;
2220 		} else {
2221 			if ((off_tmp = lseek(fd, 0, SEEK_CUR)) < 0) {	/* get offset after the write */
2222 				fprintf(stderr,
2223 					"%s%s: %s/%d: tell(2) failed: %d  %s\n",
2224 					Progname, TagName, __FILE__, __LINE__,
2225 					errno, strerror(errno));
2226 				return -1;
2227 			}
2228 #if NEWIO
2229 #if defined(sgi) || defined(__linux__)
2230 			/* If this is POSIX I/O and it is via aio_{read,write}
2231 			 * or lio_listio then after completion of the I/O the
2232 			 * value of the file offset for the file is
2233 			 * unspecified--which means we cannot trust what
2234 			 * tell() told us.  Fudge it here.
2235 			 */
2236 			if ((io_type & LIO_IO_ASYNC_TYPES)
2237 			    || (io_type & LIO_RANDOM)) {
2238 				if (off_tmp != Woffset + grow_incr) {
2239 					if (Debug > 5) {
2240 						printf
2241 						    ("%s: %d DEBUG6 %s/%d: posix fudge, forcing tmp (%"
2242 						     PRId64
2243 						     ") to match Woffset+grow_incr (%"
2244 						     PRId64 ")\n", Progname,
2245 						     Pid, __FILE__, __LINE__,
2246 						     (int64_t) off_tmp,
2247 						     (int64_t) Woffset +
2248 						     grow_incr);
2249 					}
2250 					off_tmp = Woffset + grow_incr;
2251 				}
2252 			}
2253 #endif /* sgi __linux__ */
2254 #endif
2255 		}
2256 		*curr_size_ptr = off_tmp;	/* BUG:14136 */
2257 
2258 		lkfile(fd, LOCK_UN, LKLVL0);
2259 
2260 		if (ret != grow_incr) {
2261 			fprintf(stderr, "%s%s: %d %s/%d: %d %s\n",
2262 				Progname, TagName, Pid, __FILE__, __LINE__,
2263 				Iter_cnt, errmsg);
2264 			if (ret == -ENOSPC) {
2265 				cleanup();
2266 				exit(2);
2267 			}
2268 			return -1;
2269 		}
2270 
2271 		/*
2272 		 * Check for a condition where the file was truncated just before
2273 		 * the write.
2274 		 */
2275 		if (off_tmp != Woffset + grow_incr) {
2276 			/*
2277 			 * The offset after the write was not as expected.
2278 			 * This could be caused by the following:
2279 			 *  - file truncated after the lseek and before the write.
2280 			 *  - the file was written to after fstat and before the write
2281 			 *    and the file was opened with O_APPEND.
2282 			 *
2283 			 * The pattern written to the file will be considered corrupted.
2284 			 */
2285 			if (Debug > 0 && lockfile) {
2286 				printf("%s%s: %d DEBUG1 %s/%d: offset after "
2287 				       "write(%ld) not as exp(%ld+%d=%ld)\n",
2288 				       Progname, TagName, Pid, __FILE__,
2289 				       __LINE__, (long)off_tmp, (long)Woffset,
2290 				       grow_incr, (long)(Woffset + grow_incr));
2291 				printf
2292 				    ("%s%s: %d DEBUG1 %s/%d: %d Assuming file "
2293 				     "changed by another process, resetting "
2294 				     "offset:%ld (expect pattern mismatch)\n",
2295 				     Progname, TagName, Pid, __FILE__, __LINE__,
2296 				     Iter_cnt, (long)(off_tmp - grow_incr));
2297 			}
2298 			if (Debug > 4) {
2299 				printf
2300 				    ("%s: %d DEBUG5 %s/%d: about to chop Woffset.  "
2301 				     "tmp=%ld, grow_incr=%d, Woffset was %ld\n",
2302 				     Progname, Pid, __FILE__, __LINE__,
2303 				     (long)off_tmp, grow_incr, (long)Woffset);
2304 			}
2305 			Woffset = off_tmp - grow_incr;
2306 			if (Woffset < 0)
2307 				Woffset = 0;
2308 		}
2309 
2310 	}			/* end of grow by write */
2311 
2312 	/*
2313 	 * Woffset - holds start of grow (start of write expect in grow by lseek)
2314 	 * Grow_incr - holds size of grow (write).
2315 	 * fsize - holds size of file before write
2316 	 */
2317 	size_grew = (Woffset + Grow_incr) - fsize;
2318 	if (Debug > 1) {
2319 		if (Mode & MODE_FIFO) {
2320 			printf
2321 			    ("%s: %d DEBUG2 %s/%d: file is fifo, %d wrote %d bytes\n",
2322 			     Progname, Pid, __FILE__, __LINE__, Grow_incr,
2323 			     Iter_cnt);
2324 		}
2325 
2326 		else if (size_grew > 0)
2327 			printf
2328 			    ("%s: %d DEBUG2 %s/%d: %d wrote %d bytes(off:%ld), "
2329 			     "grew file by %d bytes\n", Progname, Pid, __FILE__,
2330 			     __LINE__, Iter_cnt, Grow_incr, (long)Woffset,
2331 			     size_grew);
2332 		else
2333 			printf
2334 			    ("%s: %d DEBUG2 %s/%d: %d wrote %d bytes(off:%ld), "
2335 			     "did not grow file\n", Progname, Pid, __FILE__,
2336 			     __LINE__, Iter_cnt, Grow_incr, (long)Woffset);
2337 	}
2338 
2339 	bytes_consumed += size_grew;
2340 	return 0;
2341 
2342 }				/* end of growfile */
2343 
2344 /***********************************************************************
2345  * shrinkfile file by trunc_incr.  file can not be made smaller than
2346  * size zero.  Therefore, if trunc_incr is larger than file size,
2347  * file will be truncated to zero.
2348  * The file descriptor current offset is assumed to be the end of the
2349  * file.
2350  *
2351  ***********************************************************************/
2352 int
shrinkfile(int fd,char * filename,int trunc_incr,int trunc_inter,int just_trunc)2353 shrinkfile(int fd, char *filename, int trunc_incr, int trunc_inter,
2354 	   int just_trunc)
2355 {
2356 	static int shrink_cnt = 0;
2357 	int cur_offset;
2358 	int new_offset;
2359 	int ret;
2360 #ifdef CRAY
2361 	int offset;
2362 #endif
2363 
2364 	shrink_cnt++;
2365 
2366 	if (trunc_inter == 0 || (shrink_cnt % trunc_inter != 0)) {
2367 		if (Debug > 3)
2368 			printf
2369 			    ("%s: %d DEBUG4 %s/%d: Not shrinking file - not time, iter=%d, cnt=%d\n",
2370 			     Progname, Pid, __FILE__, __LINE__, trunc_inter,
2371 			     shrink_cnt);
2372 		return 0;	/* not this time */
2373 	}
2374 
2375 	if (Mode & MODE_FIFO) {
2376 		if (Debug > 5)
2377 			printf
2378 			    ("%s: %d DEBUG5 %s/%d: Not attempting to shrink a FIFO\n",
2379 			     Progname, Pid, __FILE__, __LINE__);
2380 		return 0;	/* can not truncate fifo */
2381 	}
2382 
2383 	lkfile(fd, LOCK_EX, LKLVL0);
2384 
2385 	if ((cur_offset = lseek(fd, 0, SEEK_CUR)) == -1) {
2386 		fprintf(stderr, "%s%s: %d %s/%d: tell(%d) failed: %s\n",
2387 			Progname, TagName, Pid, __FILE__, __LINE__, fd,
2388 			strerror(errno));
2389 		lkfile(fd, LOCK_UN, LKLVL0);
2390 		return -1;
2391 	}
2392 
2393 	if (Mode & MODE_RAND_LSEEK) {
2394 		if (max_lseek <= -1) {
2395 			if ((new_offset = file_size(fd)) == -1) {
2396 				lkfile(fd, LOCK_UN, LKLVL0);
2397 				return -1;
2398 			}
2399 
2400 			if (new_offset < min_lseek)
2401 				new_offset = min_lseek;
2402 			else
2403 				new_offset =
2404 				    random_range(min_lseek, new_offset, 1,
2405 						 NULL);
2406 		} else {
2407 			new_offset =
2408 			    random_range(min_lseek, max_lseek, 1, NULL);
2409 		}
2410 
2411 #ifdef CRAY
2412 		if ((offset = lseek(fd, new_offset, SEEK_SET)) == -1) {
2413 			fprintf(stderr,
2414 				"%s%s: %d %s/%d: lseek(%d, %d, SEEK_SET) l3 failed: %s\n",
2415 				Progname, TagName, Pid, __FILE__, __LINE__, fd,
2416 				new_offset, strerror(errno));
2417 			lkfile(fd, LOCK_UN, LKLVL0);
2418 			return -1;
2419 		} else if (Debug > 3)
2420 			printf
2421 			    ("%s: %d DEBUG4 %s/%d: lseeked to random offset %d\n",
2422 			     Progname, Pid, __FILE__, __LINE__, offset);
2423 
2424 #endif
2425 	}
2426 
2427 	else {			/* remove trunc_incr from file */
2428 
2429 		new_offset = cur_offset - trunc_incr;
2430 
2431 		if (new_offset < 0)
2432 			new_offset = 0;
2433 
2434 #ifdef CRAY
2435 		if (lseek(fd, new_offset, SEEK_SET) == -1) {
2436 			fprintf(stderr,
2437 				"%s%s: %d %s/%d: lseek(fd, %d, SEEK_SET) l4 failed: %s\n",
2438 				Progname, TagName, Pid, __FILE__, __LINE__,
2439 				new_offset, strerror(errno));
2440 			lkfile(fd, LOCK_UN, LKLVL0);
2441 			return -1;
2442 		} else if (Debug > 3)
2443 			printf
2444 			    ("%s: %d DEBUG4 %s/%d: lseeked to offset %d, %d bytes from end\n",
2445 			     Progname, Pid, __FILE__, __LINE__, new_offset,
2446 			     trunc_incr);
2447 #endif
2448 	}
2449 
2450 #ifdef CRAY
2451 	ret = trunc(fd);
2452 #else
2453 	ret = ftruncate(fd, new_offset);
2454 	if (ret == 0 && Debug > 3) {
2455 		printf
2456 		    ("%s: %d DEBUG4 %s/%d: ftruncated to offset %d, %d bytes from end\n",
2457 		     Progname, Pid, __FILE__, __LINE__, new_offset, trunc_incr);
2458 	}
2459 #endif
2460 
2461 	lkfile(fd, LOCK_UN, LKLVL0);
2462 
2463 	if (ret == -1) {
2464 #ifdef CRAY
2465 		fprintf(stderr, "%s%s: %d %s/%d: trunc failed: %s\n",
2466 			Progname, TagName, Pid, __FILE__, __LINE__,
2467 			strerror(errno));
2468 #else
2469 		fprintf(stderr, "%s%s: %d %s/%d: ftruncate failed: %s\n",
2470 			Progname, TagName, Pid, __FILE__, __LINE__,
2471 			strerror(errno));
2472 #endif
2473 		return -1;
2474 	}
2475 
2476 	if (Debug > 2) {
2477 		printf
2478 		    ("%s: %d DEBUG2 %s/%d: trunc file by %d bytes, to size of = %d bytes\n",
2479 		     Progname, Pid, __FILE__, __LINE__, cur_offset - new_offset,
2480 		     new_offset);
2481 	}
2482 
2483 	bytes_consumed -= (cur_offset - new_offset);
2484 	return 0;
2485 
2486 }				/* end of shrinkfile */
2487 
2488 /***********************************************************************
2489  *
2490  ***********************************************************************/
check_write(int fd,int cf_inter,char * filename,int mode)2491 int check_write(int fd, int cf_inter, char *filename, int mode)
2492 {
2493 	int fsize;
2494 	static int cf_count = 0;
2495 	int ret = 0;
2496 	int tmp;
2497 	char *errmsg;
2498 	char *ptr;
2499 
2500 	cf_count++;
2501 
2502 	if (cf_inter == 0 || (cf_count % cf_inter != 0)) {
2503 		if (Debug > 4)
2504 			printf
2505 			    ("%s: %d DEBUG5 %s/%d: no write check, not time iter=%d, cnt=%d\n",
2506 			     Progname, Pid, __FILE__, __LINE__, cf_inter,
2507 			     cf_count);
2508 		return 0;	/* no check done */
2509 	}
2510 
2511 	if (Grow_incr <= 0) {
2512 		if (Debug > 3)
2513 			printf("%s: %d DEBUG4 %s/%d: No write validation,  "
2514 			       "Grow_incr = %d, offset = %ld\n",
2515 			       Progname, Pid, __FILE__, __LINE__, Grow_incr,
2516 			       (long)Woffset);
2517 		return 0;	/* no check */
2518 	}
2519 
2520 	/*
2521 	 * Get the shared file lock.  We need to hold the lock from before
2522 	 * we do the stat until after the read.
2523 	 */
2524 	lkfile(fd, LOCK_SH, LKLVL0);
2525 
2526 	if ((fsize = file_size(fd)) == -1) {
2527 		lkfile(fd, LOCK_UN, LKLVL0);
2528 		return -1;
2529 
2530 	} else if (fsize <= Woffset) {
2531 		/*
2532 		 * The file was truncated between write and now.
2533 		 * The contents of our last write is totally gone, no check.
2534 		 */
2535 		if (Debug > 1)
2536 			printf
2537 			    ("%s%s: %d DEBUG2 %s/%d: %d File size (%d) smaller than "
2538 			     "where last wrote (%ld)- no write validation\n",
2539 			     Progname, TagName, Pid, __FILE__, __LINE__,
2540 			     Iter_cnt, fsize, (long)Woffset);
2541 		lkfile(fd, LOCK_UN, LKLVL0);
2542 		return 0;	/* no validation, but not an error */
2543 
2544 	} else if (fsize < (Woffset + Grow_incr)) {
2545 		/*
2546 		 * The file was truncated between write and now.
2547 		 * Part of our last write has been truncated, adjust our Grow_incr
2548 		 * to reflect this.
2549 		 */
2550 
2551 		tmp = Grow_incr;
2552 		Grow_incr = fsize - Woffset;
2553 
2554 		if (Debug > 1) {
2555 
2556 			printf("%s%s: %d DEBUG2 %s/%d: %d fsz:%d, lost(%d)of "
2557 			       "wrt(off:%ld, sz:%d), adj=%d\n", Progname,
2558 			       TagName, Pid, __FILE__, __LINE__, Iter_cnt,
2559 			       fsize, tmp - Grow_incr, (long)Woffset, tmp,
2560 			       Grow_incr);
2561 		}
2562 
2563 	}
2564 
2565 	if (Debug > 2)
2566 		printf("%s: %d DEBUG3 %s/%d: about to do write validation, "
2567 		       "offset = %ld, size = %d\n",
2568 		       Progname, Pid, __FILE__, __LINE__, (long)Woffset,
2569 		       Grow_incr);
2570 
2571 	if (!(mode & MODE_FIFO)) {
2572 
2573 		if (lseek(fd, Woffset, 0) == -1) {
2574 			fprintf(stderr,
2575 				"%s%s: %d %s/%d: lseek(fd, %ld, 0) failed: %s\n",
2576 				Progname, TagName, Pid, __FILE__, __LINE__,
2577 				(long)Woffset, strerror(errno));
2578 		}
2579 		if (Debug > 3)
2580 			printf("%s: %d DEBUG4 %s/%d: lseeked to offset:%ld\n",
2581 			       Progname, Pid, __FILE__, __LINE__,
2582 			       (long)Woffset);
2583 	}
2584 
2585 	/*
2586 	 * Read last writes data
2587 	 */
2588 #if NEWIO
2589 	ret =
2590 	    lio_read_buffer(fd, io_type, Buffer, Grow_incr, SIGUSR1, &errmsg,
2591 			    0);
2592 #else
2593 	ret = read_buffer(fd, io_type, Buffer, Grow_incr, 0, &errmsg);
2594 #endif
2595 
2596 	/*
2597 	 * report the error and debug information before releasing
2598 	 * the file lock
2599 	 */
2600 	if (ret != Grow_incr) {
2601 		fprintf(stderr, "%s%s: %d %s/%d: %d CW %s\n", Progname, TagName,
2602 			Pid, __FILE__, __LINE__, Iter_cnt, errmsg);
2603 		{
2604 			struct stat stbuf;
2605 			fstat(fd, &stbuf);
2606 			if (Debug > 2)
2607 				printf("%s%s: %d DEBUG3 %s/%d: fd:%d, offset:%d, fsize:%d, openflags:%#o\n", Progname, TagName, Pid, __FILE__, __LINE__, fd, (int)lseek(fd, SEEK_CUR, 0),	/* FIXME: 64bit/LFS ? */
2608 				       (int)stbuf.st_size, Fileinfo.openflags);
2609 		}
2610 
2611 		lkfile(fd, LOCK_UN, LKLVL0);
2612 		return 1;
2613 	}
2614 
2615 	lkfile(fd, LOCK_UN, LKLVL0);
2616 
2617 	if (Mode & MODE_GROW_BY_LSEEK) {
2618 		/* check that all zeros upto last character */
2619 		for (ptr = Buffer; ptr < (Buffer + Grow_incr - 1); ptr++) {
2620 			if (*ptr != '\0') {
2621 				fprintf(stderr,
2622 					"%s%s: %d %s/%d: data mismatch at offset %d, exp:%#o(zerofilled), act:%#o in file %s\n",
2623 					Progname, TagName, Pid, __FILE__,
2624 					__LINE__,
2625 					(int)(Woffset +
2626 					      (Grow_incr - (Buffer - ptr))), 0,
2627 					*ptr, filename);
2628 				fflush(stderr);
2629 				return 1;
2630 			}
2631 		}
2632 		/* check that the last char is a 'w' */
2633 		if (*ptr != 'w') {
2634 			fprintf(stderr,
2635 				"%s%s: %d %s/%d: data mismatch at offset %d, exp:%#o(zerofilled), act:%#o in file %s\n",
2636 				Progname, TagName, Pid, __FILE__, __LINE__,
2637 				(int)(Woffset + (Grow_incr - (Buffer - ptr))),
2638 				'w', *ptr, filename);
2639 			fflush(stderr);
2640 			return 1;
2641 		}
2642 		return 0;	/* all is well */
2643 
2644 	} else if (Pattern == PATTERN_OFFSET)
2645 		ret =
2646 		    datapidchk(STATIC_NUM, Buffer, Grow_incr, Woffset, &errmsg);
2647 	else if (Pattern == PATTERN_PID)
2648 		ret = datapidchk(Pid, Buffer, Grow_incr, Woffset, &errmsg);
2649 	else if (Pattern == PATTERN_ASCII)
2650 		ret = dataasciichk(NULL, Buffer, Grow_incr, Woffset, &errmsg);
2651 	else if (Pattern == PATTERN_RANDOM) ;	/* no check for random */
2652 	else if (Pattern == PATTERN_ALT)
2653 		ret = databinchk('a', Buffer, Grow_incr, Woffset, &errmsg);
2654 	else if (Pattern == PATTERN_CHKER)
2655 		ret = databinchk('c', Buffer, Grow_incr, Woffset, &errmsg);
2656 	else if (Pattern == PATTERN_CNTING)
2657 		ret = databinchk('C', Buffer, Grow_incr, Woffset, &errmsg);
2658 	else if (Pattern == PATTERN_ZEROS)
2659 		ret = databinchk('z', Buffer, Grow_incr, Woffset, &errmsg);
2660 	else if (Pattern == PATTERN_ONES)
2661 		ret = databinchk('o', Buffer, Grow_incr, Woffset, &errmsg);
2662 	else
2663 		ret = dataasciichk(NULL, Buffer, Grow_incr, Woffset, &errmsg);
2664 
2665 	if (ret >= 0) {
2666 		fprintf(stderr, "%s%s: %d %s/%d: %d CW %s in file %s\n",
2667 			Progname, TagName, Pid, __FILE__, __LINE__, Iter_cnt,
2668 			errmsg, filename);
2669 
2670 		if (Debug > 0)
2671 			printf("%s%s: %d DEBUG1 %s/%d: **fd:%d, lk:%d, "
2672 			       "offset:%ld, sz:%d open flags:%#o %s\n",
2673 			       Progname, TagName, Pid, __FILE__, __LINE__, fd,
2674 			       lockfile, (long)Woffset, Grow_incr,
2675 			       Fileinfo.openflags,
2676 			       openflags2symbols(Fileinfo.openflags, ",", 0));
2677 
2678 		fflush(stderr);
2679 		return 1;
2680 	}
2681 
2682 	if (Debug > 6)
2683 		printf("%s: %d DEBUG7 %s/%d: No corruption detected on "
2684 		       "write validation , offset = %ld, size = %d\n",
2685 		       Progname, Pid, __FILE__, __LINE__, (long)Woffset,
2686 		       Grow_incr);
2687 
2688 	return 0;		/* all is well */
2689 }
2690 
2691 /***********************************************************************
2692  *
2693  ***********************************************************************/
check_file(int fd,int cf_inter,char * filename,int no_file_check)2694 int check_file(int fd, int cf_inter, char *filename, int no_file_check)
2695 {
2696 	int fsize;
2697 	static int cf_count = 0;
2698 	char *buf;
2699 	int ret;
2700 	int ret_val = 0;
2701 	int rd_cnt;
2702 	int rd_size;
2703 	char *errmsg;
2704 
2705 	cf_count++;
2706 
2707 	if (cf_inter == 0 || (cf_count % cf_inter != 0)) {
2708 		if (Debug > 4)
2709 			printf
2710 			    ("%s: %d DEBUG5 %s/%d: No file check - not time, iter=%d, cnt=%d\n",
2711 			     Progname, Pid, __FILE__, __LINE__, cf_inter,
2712 			     cf_count);
2713 		return 0;	/* no check done */
2714 	}
2715 
2716 	/*
2717 	 * if we can't determine file content, don't bother checking
2718 	 */
2719 	if (no_file_check) {
2720 		if (Debug > 4)
2721 			printf
2722 			    ("%s: %d DEBUG5 %s/%d: No file check, lseek grow or random lseeks\n",
2723 			     Progname, Pid, __FILE__, __LINE__);
2724 		return 0;
2725 	}
2726 
2727 	/*
2728 	 * Lock the file.  We need to have the file lock before
2729 	 * the stat and until after the last read to prevent
2730 	 * a trunc/truncate from "corrupting" our data.
2731 	 */
2732 	lkfile(fd, LOCK_SH, LKLVL0);
2733 
2734 	if ((fsize = file_size(fd)) == -1) {
2735 		lkfile(fd, LOCK_UN, LKLVL0);
2736 		return -1;
2737 	}
2738 
2739 	if (fsize == 0) {
2740 		if (Debug > 2)
2741 			printf
2742 			    ("%s: %d DEBUG3 %s/%d: No file validation, file size == 0\n",
2743 			     Progname, Pid, __FILE__, __LINE__);
2744 
2745 		lkfile(fd, LOCK_UN, LKLVL0);
2746 		return 0;
2747 	}
2748 
2749 	if (Debug > 2)
2750 		printf("%s: %d DEBUG3 %s/%d: about to do file validation\n",
2751 		       Progname, Pid, __FILE__, __LINE__);
2752 
2753 	if (fsize > MAX_FC_READ) {
2754 		/*
2755 		 * read the file in MAX_FC_READ chuncks.
2756 		 */
2757 
2758 		if ((buf = malloc(MAX_FC_READ)) == NULL) {
2759 			fprintf(stderr, "%s%s: %s/%d: malloc(%d) failed: %s\n",
2760 				Progname, TagName, __FILE__, __LINE__,
2761 				MAX_FC_READ, strerror(errno));
2762 			lkfile(fd, LOCK_UN, LKLVL0);
2763 			return -1;
2764 		}
2765 
2766 		lseek(fd, 0, SEEK_SET);
2767 
2768 		lkfile(fd, LOCK_SH, LKLVL0);	/* get lock on file before getting file size */
2769 
2770 		rd_cnt = 0;
2771 		while (rd_cnt < fsize) {
2772 			rd_size = MIN(MAX_FC_READ, fsize - rd_cnt);
2773 
2774 #if NEWIO
2775 			ret = lio_read_buffer(fd, io_type, buf, rd_size,
2776 					      SIGUSR1, &errmsg, 0);
2777 #else
2778 			ret =
2779 			    read_buffer(fd, io_type, buf, rd_size, 0, &errmsg);
2780 #endif
2781 
2782 			if (ret != rd_size) {
2783 				fprintf(stderr, "%s%s: %d %s/%d: %d CFa %s\n",
2784 					Progname, TagName, Pid, __FILE__,
2785 					__LINE__, Iter_cnt, errmsg);
2786 				free(buf);
2787 				lkfile(fd, LOCK_UN, LKLVL0);
2788 				return -1;
2789 			}
2790 /**
2791 	        read(fd, buf, rd_size);
2792 ***/
2793 
2794 			if (Pattern == PATTERN_OFFSET)
2795 				ret =
2796 				    datapidchk(STATIC_NUM, buf, rd_size, rd_cnt,
2797 					       &errmsg);
2798 			else if (Pattern == PATTERN_PID)
2799 				ret =
2800 				    datapidchk(Pid, buf, rd_size, rd_cnt,
2801 					       &errmsg);
2802 			else if (Pattern == PATTERN_ASCII)
2803 				ret =
2804 				    dataasciichk(NULL, buf, rd_size, rd_cnt,
2805 						 &errmsg);
2806 			else if (Pattern == PATTERN_RANDOM) ;	/* no checks for random */
2807 			else if (Pattern == PATTERN_ALT)
2808 				ret =
2809 				    databinchk('a', buf, rd_size, rd_cnt,
2810 					       &errmsg);
2811 			else if (Pattern == PATTERN_CHKER)
2812 				ret =
2813 				    databinchk('c', buf, rd_size, rd_cnt,
2814 					       &errmsg);
2815 			else if (Pattern == PATTERN_CNTING)
2816 				ret =
2817 				    databinchk('C', buf, rd_size, rd_cnt,
2818 					       &errmsg);
2819 			else if (Pattern == PATTERN_ZEROS)
2820 				ret =
2821 				    databinchk('z', buf, rd_size, rd_cnt,
2822 					       &errmsg);
2823 			else if (Pattern == PATTERN_ONES)
2824 				ret =
2825 				    databinchk('o', buf, rd_size, rd_cnt,
2826 					       &errmsg);
2827 			else
2828 				ret =
2829 				    dataasciichk(NULL, buf, rd_size, rd_cnt,
2830 						 &errmsg);
2831 
2832 			if (ret >= 0) {
2833 				fprintf(stderr,
2834 					"%s%s: %d %s/%d: %d CFp %s in file %s\n",
2835 					Progname, TagName, Pid, __FILE__,
2836 					__LINE__, Iter_cnt, errmsg, filename);
2837 				fflush(stderr);
2838 				ret_val = 1;
2839 				lkfile(fd, LOCK_UN, LKLVL0);
2840 				break;
2841 			}
2842 			rd_cnt += rd_size;
2843 		}
2844 
2845 		lkfile(fd, LOCK_UN, LKLVL0);
2846 
2847 		free(buf);
2848 
2849 	} else {
2850 		/*
2851 		 * Read the whole file in a single read
2852 		 */
2853 		if ((buf = malloc(fsize)) == NULL) {
2854 			fprintf(stderr, "%s%s: %s/%d: malloc(%d) failed: %s\n",
2855 				Progname, TagName, __FILE__, __LINE__, fsize,
2856 				strerror(errno));
2857 			fflush(stderr);
2858 			return -1;
2859 		}
2860 
2861 		lseek(fd, 0, SEEK_SET);
2862 
2863 /****
2864 	    read(fd, buf, fsize);
2865 ****/
2866 #if NEWIO
2867 		ret =
2868 		    lio_read_buffer(fd, io_type, buf, fsize, SIGUSR1, &errmsg,
2869 				    0);
2870 #else
2871 		ret = read_buffer(fd, io_type, buf, fsize, 0, &errmsg);
2872 #endif
2873 
2874 		/* unlock the file as soon as we can */
2875 		lkfile(fd, LOCK_UN, LKLVL0);
2876 
2877 		if (ret != fsize) {
2878 			fprintf(stderr, "%s%s: %d %s/%d: %d CFw %s\n",
2879 				Progname, TagName, Pid, __FILE__, __LINE__,
2880 				Iter_cnt, errmsg);
2881 			ret_val = 1;
2882 		} else {
2883 			if (Pattern == PATTERN_OFFSET)
2884 				ret =
2885 				    datapidchk(STATIC_NUM, buf, fsize, 0,
2886 					       &errmsg);
2887 			else if (Pattern == PATTERN_PID)
2888 				ret = datapidchk(Pid, buf, fsize, 0, &errmsg);
2889 			else if (Pattern == PATTERN_ASCII)
2890 				ret =
2891 				    dataasciichk(NULL, buf, fsize, 0, &errmsg);
2892 			else if (Pattern == PATTERN_RANDOM) ;	/* no check for random */
2893 			else if (Pattern == PATTERN_ALT)
2894 				ret = databinchk('a', buf, fsize, 0, &errmsg);
2895 			else if (Pattern == PATTERN_CHKER)
2896 				ret = databinchk('c', buf, fsize, 0, &errmsg);
2897 			else if (Pattern == PATTERN_CNTING)
2898 				ret = databinchk('C', buf, fsize, 0, &errmsg);
2899 			else if (Pattern == PATTERN_ZEROS)
2900 				ret = databinchk('z', buf, fsize, 0, &errmsg);
2901 			else if (Pattern == PATTERN_ONES)
2902 				ret = databinchk('o', buf, fsize, 0, &errmsg);
2903 			else
2904 				ret =
2905 				    dataasciichk(NULL, buf, fsize, 0, &errmsg);
2906 
2907 			if (ret >= 0) {
2908 				fprintf(stderr,
2909 					"%s%s: %d %s/%d: %d CFw %s in file %s\n",
2910 					Progname, TagName, Pid, __FILE__,
2911 					__LINE__, Iter_cnt, errmsg, filename);
2912 				fflush(stderr);
2913 				ret_val = 1;
2914 			}
2915 		}
2916 		free(buf);
2917 	}
2918 
2919 	return ret_val;
2920 
2921 }				/* end of check_file */
2922 
2923 /***********************************************************************
2924  *
2925  ***********************************************************************/
file_size(int fd)2926 int file_size(int fd)
2927 {
2928 	struct stat sb;
2929 
2930 	if (fstat(fd, &sb) < 0) {
2931 		fprintf(stderr,
2932 			"%s%s: %d %s/%d: Unable to fstat(%d, &buf), errno:%d %s\n",
2933 			Progname, TagName, Pid, __FILE__, __LINE__, fd, errno,
2934 			strerror(errno));
2935 		return -1;
2936 
2937 	}
2938 
2939 	return sb.st_size;
2940 }
2941 
2942 /***********************************************************************
2943  *  do file lock/unlock action.
2944  ***********************************************************************/
lkfile(int fd,int operation,int lklevel)2945 int lkfile(int fd, int operation, int lklevel)
2946 {
2947 	char *errmsg;
2948 
2949 	if (lockfile == lklevel) {
2950 
2951 		if (Debug > 5) {
2952 			switch (operation) {
2953 			case LOCK_UN:
2954 				printf
2955 				    ("%s: %d DEBUG6 %s/%d: Attempting to release lock on fd %d\n",
2956 				     Progname, Pid, __FILE__, __LINE__, fd);
2957 				break;
2958 
2959 			case LOCK_SH:
2960 				printf
2961 				    ("%s: %d DEBUG6 %s/%d: Attempting to get read/shared lock on fd %d\n",
2962 				     Progname, Pid, __FILE__, __LINE__, fd);
2963 				break;
2964 
2965 			case LOCK_EX:
2966 				printf
2967 				    ("%s: %d DEBUG6 %s/%d: Attempting to get write/exclusive lock on fd %d\n",
2968 				     Progname, Pid, __FILE__, __LINE__, fd);
2969 				break;
2970 			}
2971 		}
2972 
2973 		/*
2974 		 * Attempt to get/release desired lock.
2975 		 * file_lock will attempt to do action over and over again until
2976 		 * either an unretryable error or the action is completed.
2977 		 */
2978 
2979 		if (file_lock(fd, operation, &errmsg) != 0) {
2980 			printf
2981 			    ("%s%s: %d %s/%d: Unable to perform lock operation. %s\n",
2982 			     Progname, TagName, Pid, __FILE__, __LINE__,
2983 			     errmsg);
2984 
2985 			/* do we count this as an error? handle_error();  */
2986 			return -1;
2987 		}
2988 
2989 		if (Debug > 2) {
2990 			switch (operation) {
2991 			case LOCK_UN:
2992 				printf
2993 				    ("%s: %d DEBUG3 %s/%d: Released lock on fd %d\n",
2994 				     Progname, Pid, __FILE__, __LINE__, fd);
2995 				break;
2996 
2997 			case LOCK_SH:
2998 				printf
2999 				    ("%s: %d DEBUG3 %s/%d: Got read/shared lock on fd %d\n",
3000 				     Progname, Pid, __FILE__, __LINE__, fd);
3001 				break;
3002 
3003 			case LOCK_EX:
3004 				printf
3005 				    ("%s: %d DEBUG3 %s/%d: Got write/exclusive lock on fd %d\n",
3006 				     Progname, Pid, __FILE__, __LINE__, fd);
3007 				break;
3008 
3009 			default:
3010 				printf
3011 				    ("%s: %d DEBUG3 %s/%d: Completed action %d on fd %d\n",
3012 				     Progname, Pid, __FILE__, __LINE__,
3013 				     operation, fd);
3014 				break;
3015 			}
3016 		}
3017 	}
3018 
3019 	return 0;
3020 }
3021 
3022 #ifndef linux
3023 /***********************************************************************
3024  *
3025  ***********************************************************************/
pre_alloc(int fd,long size)3026 int pre_alloc(int fd, long size)
3027 {
3028 
3029 #ifdef CRAY
3030 	long avl;
3031 
3032 	if (ialloc(fd, size, IA_CONT, &avl) == -1) {
3033 		fprintf(stderr,
3034 			"%s%s %s/%d: Unable to pre-alloc space: ialloc failed: %d  %s\n",
3035 			Progname, TagName, __FILE__, __LINE__, errno,
3036 			strerror(errno));
3037 		return -1;
3038 	}
3039 #endif
3040 
3041 #ifdef sgi
3042 	struct flock f;
3043 
3044 	f.l_whence = 0;
3045 	f.l_start = 0;
3046 	f.l_len = size;
3047 
3048 	/* non-zeroing reservation */
3049 	if (fcntl(fd, F_RESVSP, &f) == -1) {
3050 		fprintf(stderr,
3051 			"%s%s %s/%d: Unable to pre-alloc space: fcntl(F_RESVSP) failed: %d  %s\n",
3052 			Progname, TagName, __FILE__, __LINE__, errno,
3053 			strerror(errno));
3054 		return -1;
3055 	}
3056 #endif
3057 
3058 	return 0;
3059 }
3060 #endif
3061