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