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