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