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