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