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