forked from kdave/xfstests
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgrowfiles.c
2619 lines (2248 loc) · 76 KB
/
growfiles.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright (c) 2000 Silicon Graphics, Inc.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* This program will grow a list of files.
* Each file will grow by grow_incr before the same
* file grows twice. Each file is open and closed before next file is opened.
*
* To just verify file contents: growfiles -g 0 -c 1 filename
*
* See help and prt_examples functions below.
*
* Basic code layout
* process cmdline
* print debug message about options used
* setup signal handlers
* return control to user (if wanted - default action)
* fork number of desired childern (if wanted)
* re-exec self (if wanted)
* Determine number of files
* malloc space or i/o buffer
* Loop until stop is set
* Determine if hit iteration, time, max errors or num bytes reached
* Loop through each file
* open file
* fstat file - to determine if file is a fifo
* prealloc file space (if wanted)
* growfile
* check last write
* check whole file
* shrink file
* close file
* delay (if wanted)
* End loop
* End loop
* remove all files (if wanted)
*
* Author: Richard Logan
*
*/
#include "global.h"
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#include "dataascii.h"
#include "random_range.h"
#include "databin.h"
#include "open_flags.h"
#include "forker.h"
#include "file_lock.h"
extern int datapidgen(int pid, unsigned char *buffer, int bsize, int offset);
extern void databingen(int mode, unsigned char *buffer, int bsize, int offset);
extern int datapidchk(int pid, char *buffer, int bsize, int offset, char **errmsg);
extern int databinchk(int mode, char *buffer, int bsize, int offset, char **errmsg);
int file_size(int fd);
int check_write(int fd, int cf_inter, char *filename, int mode);
int shrinkfile(int fd, char *filename, int trunc_incr, int trunc_inter, int just_trunc);
int check_file(int fd, int cf_inter, char *filename, int no_file_check);
int growfile(int fd, char *file, int grow_incr, unsigned char *buf);
int cleanup();
int handle_error();
int lkfile(int fd, int operation, int lklevel);
void usage();
void help();
void prt_examples(FILE *stream);
int set_sig();
void sig_handler();
static void notify_others();
int pre_alloc(char *file, int fd, int size);
#define NEWIO 1 /* Use the tlibio.c functions */
#ifndef NEWIO
#define NEWIO 0 /* specifies to use original iowrite.c */
/* functions instead of tlibio.c functions */
/* Once it is proven tlibio.c functions work properly, */
/* only tlibio.c functions will be used */
#else
#include "tlibio.h"
#endif
#ifndef PATH_MAX
#define PATH_MAX 1023
#endif
#define DEF_DIR "."
#define DEF_FILE "gf"
char *Progname;
int Debug = 1;
int Pid=0;
int io_type = 0; /* I/O type -sync */
int open_flags = O_RDWR|O_CREAT; /* open flags */
#define MAX_FC_READ 196608 /* 4096 * 48 - 48 blocks */
#define PATTERN_ASCII 1 /* repeating alphabet letter pattern */
/* allows multiple writers and to be checked */
#define PATTERN_PID 2 /* <pid><words byte offset><pid> */
/* Assumes 64 bit word. Only allows single */
/* process to write and check */
/*
* 1234567890123456789012345678901234567890123456789012345678901234
* ________________________________________________________________
* < pid >< offset in file of this word >< pid >
*/
#define PATTERN_OFFSET 3 /* Like PATTERN_PID but has a fixed number */
/* (STATIC_NUM) instead of pid. */
/* Allows multiple processes to write/read */
#define PATTERN_ALT 4 /* alternating bit pattern (i.e. 0x5555555...) */
#define PATTERN_CHKER 5 /* checkerboard pattern (i.e. 0xff00ff00ff00...) */
#define PATTERN_CNTING 6 /* counting pattern (i.e. 0 - 07, 0 - 07, ...) */
#define PATTERN_ONES 7 /* all bits set (i.e. 0xffffffffffffff...) */
#define PATTERN_ZEROS 8 /* all bits cleared (i.e. 0x000000000...) */
#define PATTERN_RANDOM 9 /* random integers - can not be checked */
#define STATIC_NUM 221849 /* used instead of pid when PATTERN_OFFSET */
#define MODE_RAND_SIZE 1 /* random write and trunc */
#define MODE_RAND_LSEEK 2 /* random lseek before write */
#define MODE_GROW_BY_LSEEK 4 /* lseek beyond end of file then write a byte */
#define RANDOM_OPEN 999876 /* if Open_flags set to this value, open flags */
/* will be randomly choosen from Open_flags[] */
#define MODE_FIFO S_IFIFO /* defined in stat.h 0010000 */
int num_files = 0; /* num_auto_files + cmd line files */
char *filenames; /* pointer to space containing filenames */
int remove_files = 0; /* if set, cleanup default is not to cleanup */
int bytes_consumed = 0; /* total bytes consumed, all files */
int bytes_to_consume = 0; /* non-zero if -B was specified, total bytes */
int Maxerrs = 100; /* Max number errors before forced exit */
int Errors = 0; /* number of encountered errors */
int Upanic_on_error = 0; /* call upanic if error and this variable set */
/* The *_size variables are only used when random iosize option (-r) is used */
int max_size=5000;
int min_size=1; /* also set in option parsing */
int mult_size=1; /* when random iosz, iosz must be mult of mult_size */
/* the *_lseek variables are only used when radon lseek option (-R) is used */
int min_lseek=0; /* also set in option parsing */
int max_lseek=-1; /* -1 means size of file */
int Pattern=PATTERN_ASCII;
int Seed=-1; /* random number seed, < 0 == uninitialized */
int Nseeds=0; /* Number of seed specified by the user */
int *Seeds; /* malloc'ed arrary of ints holding user spec seeds */
int using_random=0; /* flag indicating randomization is being used */
float delaysecs=0.0; /* delay between iterations (in seconds) */
int delaytime; /* delay between iterations in clocks/uses */
int lockfile=0; /* if set, do file locking */
/* 1 = do file locking around write, trunc */
/* and reads. */
/* 2 = write lock around all file operations */
int Woffset=0; /* offset before last write */
int Grow_incr=4096; /* sz of last write */
int Mode=0; /* bitmask of write/trunc mode */
/* also knows if dealing with fifo */
char *Buffer = NULL; /* buffer used by write and write check */
int Alignment=0; /* if non word multiple, io will not be word aligned */
int Opid=0; /* original pid */
int Sync_with_others = 0; /* Flag indicating to stop other if we stop before DONE */
int Iter_cnt = 0; /* contains current iteration count value */
char TagName[40]; /* name of this growfiles (see Monster) */
struct fileinfo_t {
char *filename;
int fd;
int openflags;
int mode;
} Fileinfo;
/*
* Define open flags that will be used when '-o random' option is used.
* Note: If there is more than one growfiles doing its thing to the same
* file, O_TRUNC will cause data mismatches. How you ask?
* timing of events, example:
* Process one Process two
* --------------- -------------
* get write lock
* fstat file
* lseek
* generate pattern
* open with O_TRUNC
* write with wrong pattern
* because offset is wrong
*
* The second process truncated the file after the pattern was
* determined, thus the pattern is wrong for the file location.
*
* There can also be a timing problem with open flag O_APPEND if
* file locks are not being used (-l option). Things could happen
* between the fstat and the write. Thus, writing the wrong pattern.
* If all processes observe the file locks, O_APPEND should be ok
* to use.
*/
int Open_flags[] = {
O_RDWR|O_CREAT,
O_RDWR|O_CREAT|O_APPEND,
O_RDWR|O_CREAT|O_NDELAY,
O_RDWR|O_CREAT|O_SYNC,
O_RDWR|O_CREAT|O_SYNC|O_NDELAY,
O_RDWR|O_CREAT|O_APPEND|O_NDELAY,
};
#define REXEC_INIT 0 /* don't do re-exec of childern */
#define REXEC_DOIT 1 /* Do re-exec of childern */
#define REXEC_DONE 2 /* We've already been re-exec'ed */
#ifndef BSIZE
#define BSIZE 512
#endif /* BSIZE */
#define USECS_PER_SEC 1000000 /* microseconds per second */
/*
* Define marcos used when dealing with file locks.
*/
#define LKLVL0 1 /* file lock around write/read/trunc */
#define LKLVL1 2 /* file lock after open to before close */
/*
* Define special max lseek values
*/
#define LSK_EOF -1 /* set fptr up to EOF */
#define LSK_EOFPLUSGROW -2 /* set fptr up to EOF + grow - leave whole */
#define LSK_EOFMINUSGROW -3 /* set fptr up to EOF-grow - no grow */
/***********************************************************************
* MAIN
***********************************************************************/
int
main(argc, argv)
int argc;
char **argv;
{
extern char *optarg; /* used by getopt */
extern int optind;
extern int opterr;
int ind;
int first_file_ind = 0;
int num_auto_files = 0; /* files created by tool */
int seq_auto_files = 0; /* auto files created by tool created by tool */
char *auto_dir = DEF_DIR;
char *auto_file = DEF_FILE;
int grow_incr = 4096;
int trunc_incr = 4096;
int trunc_inter = 0; /* 0 means none, */
int unlink_inter = 0; /* 0 means none, 1 means always unlink */
int unlink_inter_ran = -1; /* -1 -use unlink_inter, otherwise randomly choose */
/* between unlink_inter and unlink_inter_ran */
int file_check_inter = 0; /* 0 means never, 1 means always */
int write_check_inter = 1; /* 0 means never, 1 means always */
int iterations = 1; /* number of increments to be added */
int no_file_check = 0; /* if set, no whole file checking will be done */
int num;
int fd; /* file descriptor */
int stop = 0; /* loop stopper if set */
int tmp;
char chr;
int ret;
int pre_alloc_space = 0;
int total_grow_value = 0; /* used in pre-allocations */
int backgrnd = 1; /* return control to user */
struct stat statbuf;
int time_iterval = -1;
time_t start_time = 0;
char reason[40]; /* reason for loop termination */
int num_procs=1;
int forker_mode=0;
int reexec=REXEC_INIT; /* reexec info */
char *exec_path=NULL;
char *strrchr();
char *filename; /* name of file specified by user */
char *cptr; /* temp char pointer */
extern int Forker_npids; /* num of forked pid, defined in forker.c */
if ( argv[0][0] == '-' )
reexec=REXEC_DONE;
/*
* Determine name of file used to invoke this program
*/
if ((Progname=strrchr(argv[0], '/')) != NULL)
Progname++;
else
Progname=argv[0];
TagName[0] = '\0';
/*
* Process options
*/
while ((ind=getopt(argc, argv,
"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) {
switch(ind) {
case 'h' :
help();
exit(0);
case 'B':
switch (sscanf(optarg, "%i%c",
&bytes_to_consume, &chr)) {
case 1: /* noop */
break;
case 2:
if (chr == 'b') {
bytes_to_consume *= BSIZE;
} else {
fprintf(stderr,
"%s%s: --B option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
break;
default:
fprintf(stderr, "%s%s: --B option arg invalid\n",
Progname, TagName);
usage();
exit(1);
break;
}
break;
case 'E' :
prt_examples(stdout);
exit(0);
case 'b' : /* batch */
backgrnd=0;
break;
case 'C':
if (sscanf(optarg, "%i", &write_check_inter) != 1 ) {
fprintf(stderr, "%s%s: --c option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
break;
case 'c':
if (sscanf(optarg, "%i", &file_check_inter) != 1 ) {
fprintf(stderr, "%s%s: --c option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
break;
case 'd':
auto_dir=optarg;
if ( stat(auto_dir, &statbuf) == -1 ) {
if ( mkdir(auto_dir, 0777) == -1 ) {
if ( errno != EEXIST ) {
fprintf(stderr,
"%s%s: Unable to make dir %s\n",
Progname, TagName, auto_dir);
exit(1);
}
}
}
else {
if ( ! (statbuf.st_mode & S_IFDIR) ) {
fprintf(stderr,
"%s%s: %s already exists and is not a directory\n",
Progname, TagName, auto_dir);
exit(1);
}
}
break;
case 'D':
if (sscanf(optarg, "%i", &Debug) != 1 ) {
fprintf(stderr, "%s%s: --D option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
break;
case 'e':
if (sscanf(optarg, "%i", &Maxerrs) != 1 ) {
fprintf(stderr, "%s%s: --e option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
break;
case 'f':
auto_file=optarg;
break;
case 'g':
if ((ret=sscanf(optarg, "%i%c", &grow_incr, &chr)) < 1 ||
grow_incr < 0 ) {
fprintf(stderr, "%s%s: --g option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
if ( ret == 2 ) {
if ( chr == 'b' || chr == 'B' )
grow_incr *= 4096;
else {
fprintf(stderr,
"%s%s: --g option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
}
break;
case 'H':
if (sscanf(optarg, "%f", &delaysecs) != 1 || delaysecs < 0 ) {
fprintf(stderr, "%s%s: --H option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
break;
case 'i':
if (sscanf(optarg, "%i", &iterations) != 1 ||
iterations < 0 ) {
fprintf(stderr, "%s%s: --i option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
break;
case 'I':
#if NEWIO
if((io_type=lio_parse_io_arg1(optarg)) == -1 ) {
fprintf(stderr,
"%s%s: --I arg is invalid, must be s, p, f, a, l, L or r.\n",
Progname, TagName);
exit(1);
}
if( io_type & LIO_RANDOM )
using_random++;
#else
if((io_type=parse_io_arg(optarg)) == -1 ) {
fprintf(stderr,
"%s%s: --I arg is invalid, must be s, p, f, a, l, L or r.\n",
Progname, TagName);
exit(1);
}
if( io_type == 99 ) /* hold-over until tlibio.h */
using_random++;
#endif
break;
case 'l':
lockfile++;
if ( lockfile > 2 )
lockfile=2; /* lockfile can only be 1 or 2 */
break;
case 'L':
if (sscanf(optarg, "%i", &time_iterval) != 1 ||
time_iterval < 0 ) {
fprintf(stderr, "%s%s: --L option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
break;
case 'n':
if (sscanf(optarg, "%i:%i", &num_procs, &forker_mode) < 1 ||
num_procs < 0 ) {
fprintf(stderr, "%s%s: --n option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
break;
case 'N':
if (sscanf(optarg, "%i", &num_auto_files) != 1 ||
num_auto_files < 0 ) {
fprintf(stderr, "%s%s: --N option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
break;
case 'O':
if (sscanf(optarg, "%i", &Alignment) != 1 ||
num_auto_files < 0 ) {
fprintf(stderr, "%s%s: --O option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
break;
case 'o':
if ( strcmp(optarg, "random") == 0 ){
open_flags=RANDOM_OPEN;
using_random++;
} else if ((open_flags=parse_open_flags(optarg, NULL)) == -1 ) {
fprintf(stderr, "%s%s: --o arg contains invalid flag\n",
Progname, TagName);
exit(1);
}
break;
case 'p' : /* pre allocate space */
printf("%s%s: --p is illegal option on this system\n",
Progname, TagName);
exit(1);
break;
case 'P':
printf("%s%s: --P is illegal option on non-cray system\n",
Progname, TagName);
exit(1);
break;
case 'q': /* file content or pattern */
switch(optarg[0]) {
case 'A':
Pattern = PATTERN_ALT;
break;
case 'a':
Pattern = PATTERN_ASCII;
break;
case 'p':
Pattern = PATTERN_PID;
break;
case 'o':
Pattern = PATTERN_OFFSET;
break;
case 'c':
Pattern = PATTERN_CHKER;
break;
case 'C':
Pattern = PATTERN_CNTING;
break;
case 'r':
Pattern = PATTERN_RANDOM;
using_random++;
break;
case 'z':
Pattern = PATTERN_ZEROS;
break;
case 'O':
Pattern = PATTERN_ONES;
break;
default:
fprintf(stderr,
"%s%s: --C option arg invalid, A, a, p, o, c, C, r, z, or 0\n",
Progname, TagName);
usage();
exit(1);
}
break;
case 'R': /* random lseek before write arg: [min-]max*/
if (sscanf(optarg, "%i-%i", &min_lseek, &max_lseek) != 2 ) {
min_lseek=1; /* same as default in define */
if (sscanf(optarg, "%i%c", &max_lseek, &chr) != 1 ) {
fprintf(stderr, "%s%s: --R option arg invalid: [min-]max\n",
Progname, TagName);
exit(1);
}
}
if ( max_lseek < LSK_EOFMINUSGROW ) {
fprintf(stderr, "%s%s: --R option, max_lseek is invalid\n",
Progname, TagName);
exit(1);
}
Mode |= MODE_RAND_LSEEK;
using_random++;
break;
case 'r': /* random io size arg: [min-]max[:mult] */
/* min-max:mult format */
if (sscanf(optarg, "%i-%i:%i%c", &min_size, &max_size,
&mult_size, &chr) != 3 ) {
min_size=1;
/* max:mult format */
if (sscanf(optarg, "%i:%i%c", &max_size,
&mult_size, &chr) != 2 ) {
/* min-max format */
if (sscanf(optarg, "%i-%i%c", &min_size,
&max_size, &chr) != 2 ) {
min_size=1;
if (sscanf(optarg, "%i%c", &max_size, &chr) != 1 ) {
fprintf(stderr,
"%s%s: --r option arg invalid: [min-]max[:mult]\n",
Progname, TagName);
exit(1);
}
}
}
}
if ( max_size < 0 ) {
fprintf(stderr, "%s%s: --r option, max_size is invalid\n",
Progname, TagName);
exit(1);
}
/*
* If min and max are the same, no randomness
*/
if ( min_size != max_size ) {
Mode |= MODE_RAND_SIZE;
using_random++;
}
break;
case 'S':
if (sscanf(optarg, "%i", &seq_auto_files) != 1 ||
seq_auto_files < 0 ) {
fprintf(stderr, "%s%s: --S option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
break;
case 's': /* format: seed[,seed...] */
/* count the number of seeds */
cptr=optarg;
for(Nseeds=1; *cptr ; Nseeds++) {
if ( (filename=strchr(cptr, ',')) == NULL )
break;
cptr=filename;
cptr++;
}
Seeds=(int *)malloc(Nseeds*sizeof(int));
/*
* check that each seed is valid and put them in
* the newly malloc'ed Seeds arrary.
*/
filename=cptr=optarg;
for(Nseeds=0; *cptr; Nseeds++) {
if ( (filename=strchr(cptr, ',')) == NULL ) {
if ( sscanf(cptr, "%i", &Seeds[Nseeds]) < 1 ) {
fprintf(stderr, "%s%s: --s option arg %s invalid\n",
Progname, TagName, cptr);
usage();
exit(1);
}
Nseeds++;
break;
}
*filename='\0';
if ( sscanf(cptr, "%i", &Seeds[Nseeds]) < 1 ) {
fprintf(stderr, "%s%s: --s option arg %s invalid\n",
Progname, TagName, cptr);
usage();
exit(1);
}
*filename=','; /* restore string */
cptr=filename;
cptr++;
}
break;
case 't':
if ((ret=sscanf(optarg, "%i%c", &trunc_incr, &chr)) < 1 ||
trunc_incr < 0 ) {
fprintf(stderr, "%s%s: --t option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
if ( ret == 2 ) {
if ( chr == 'b' || chr == 'B' )
trunc_incr *= 4096;
else {
fprintf(stderr,
"%s%s: --t option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
}
break;
case 'T': /* truncate interval */
if (sscanf(optarg, "%i%c", &trunc_inter, &chr) != 1 ||
trunc_inter < 0 ) {
fprintf(stderr, "%s%s: --T option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
break;
case 'u':
remove_files++;
break;
case 'U': /* how often to unlink file */
/*
* formats:
* A-B - randomly pick interval between A and B
* X - unlink file every X iteration
*/
if (sscanf(optarg, "%i-%i", &unlink_inter,
&unlink_inter_ran) == 2 ) {
if ( unlink_inter < 0 || unlink_inter_ran < 0 ) {
fprintf(stderr, "%s%s: --U option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
/* ensure unlink_inter contains smaller value */
if ( unlink_inter > unlink_inter_ran ) {
tmp=unlink_inter_ran;
unlink_inter_ran=unlink_inter;
unlink_inter=tmp;
}
using_random++;
} else if (sscanf(optarg, "%i%c", &unlink_inter, &chr) != 1 ||
unlink_inter < 0 ) {
fprintf(stderr, "%s%s: --U option arg invalid\n",
Progname, TagName);
usage();
exit(1);
}
break;
case 'x':
if ( reexec != REXEC_DONE )
reexec=REXEC_DOIT;
break;
case 'w':
Mode |= MODE_GROW_BY_LSEEK;
break;
case 'W':
sprintf( TagName, "(%.39s)", optarg );
break;
case 'y':
Sync_with_others=1;
break;
case '?':
usage();
exit(1);
break;
}
}
if( Debug == 1 ){
cptr = getenv("TOUTPUT");
if( (cptr != NULL) && (strcmp( cptr, "NOPASS" ) == 0) ){
Debug = 0;
}
}
if ( Pattern == PATTERN_RANDOM ) {
no_file_check=1;
if ( write_check_inter || file_check_inter )
printf("%s%s: %d Using random pattern - no data checking will be performed!\n",
Progname, TagName, (int)getpid());
}
else if ( max_lseek == LSK_EOFPLUSGROW || Mode & MODE_GROW_BY_LSEEK ) {
no_file_check=1;
if ( file_check_inter )
printf("%s%s: %d Using random lseek beyond EOF or lseek grow,\n\
no whole file checking will be performed!\n", Progname, TagName, (int)getpid());
}
if ( Mode & MODE_RAND_SIZE )
grow_incr=max_size;
set_sig();
Opid=getpid();
Pid=Opid;
if ( backgrnd ) {
if ( Debug > 1 )
printf("%s: %d DEBUG2 forking, returning control to the user\n",
Progname, Opid);
background(Progname); /* give user their prompt back */
}
if ( Debug > 3 ) {
#if NEWIO
lio_set_debug(Debug-3);
#else
set_iowrite_debug(Debug-3);
#endif
}
/*
* Print some program information here if debug is turned on to
* level 3 or higher.
*/
if ( Debug > 2 ) {
if ( Mode & MODE_GROW_BY_LSEEK )
printf("%s: %d DEBUG lseeking past end of file, writting a \"w\"\n",
Progname, Pid);
else if ( Pattern == PATTERN_OFFSET )
printf("%s: %d DEBUG3 %d<byteoffset>%d per word pattern multi-writers.\n",
Progname, Pid, STATIC_NUM, STATIC_NUM);
else if ( Pattern == PATTERN_PID )
printf("%s: %d DEBUG3 <pid><byteoffset><pid> per word pattern - 1 writer\n",
Progname, Pid);
else if ( Pattern == PATTERN_ASCII )
printf("%s: %d DEBUG3 ascii pattern (vi'able)- allows multiple writers\n",
Progname, Pid);
else if ( Pattern == PATTERN_ALT )
printf("%s: %d DEBUG3 alt bit pattern - allows multiple writers\n",
Progname, Pid);
else if ( Pattern == PATTERN_CHKER )
printf("%s: %d DEBUG3 checkerboard pattern - allows multiple writers\n",
Progname, Pid);
else if ( Pattern == PATTERN_CNTING )
printf("%s: %d DEBUG3 counting pattern - allows multiple writers\n",
Progname, Pid);
else if ( Pattern == PATTERN_RANDOM )
printf("%s: %d DEBUG3 random integer pattern - no write/file checking\n",
Progname, Pid);
else if ( Pattern == PATTERN_ONES )
printf("%s: %d DEBUG3 all ones pattern - allows multiple writers\n",
Progname, Pid);
else if ( Pattern == PATTERN_ZEROS )
printf("%s: %d DEBUG3 all zeros pattern - allows multiple writers\n",
Progname, Pid);
else
printf("%s: %d DEBUG3 unknown pattern\n",
Progname, Pid);
if ( bytes_to_consume )
printf("%s: %d DEBUG3 bytes_to_consume = %d\n",
Progname, Pid, bytes_to_consume);
printf("%s: %d DEBUG3 Maxerrs = %d, pre_alloc_space = %d, filelocking = %d\n",
Progname, Pid, Maxerrs, pre_alloc_space, lockfile);
printf("%s: %d DEBUG3 Debug = %d, remove files in cleanup : %d\n",
Progname, Pid, Debug, remove_files);
printf("%s: %d DEBUG3 Mode = %#o\n", Progname, Pid, Mode);
if ( open_flags == RANDOM_OPEN )
printf("%s: %d DEBUG3 open_flags = (random), io_type = %#o\n", Progname,
Pid, io_type);
else
printf("%s: %d DEBUG3 open_flags = %#o, io_type = %#o\n", Progname,
Pid, open_flags, io_type);
if ( Mode & MODE_RAND_SIZE ) {
printf("%s: %d DEBUG3 random write/trunc: min=%d, max=%d, mult = %d\n",
Progname, Pid, min_size, max_size, mult_size);
}
else {
printf("%s: %d DEBUG3 grow_incr = %d\n",
Progname, Pid, grow_incr);
}
if ( Mode & MODE_RAND_LSEEK ) {
if ( max_lseek == LSK_EOF )
printf("%s: %d DEBUG3 random lseek: min=%d, max=<endoffile>\n",
Progname, Pid, min_lseek);
else if ( max_lseek == LSK_EOFPLUSGROW )
printf("%s: %d DEBUG3 random lseek: min=%d, max=<endoffile+iosize>\n",
Progname, Pid, min_lseek);
else if ( max_lseek == LSK_EOFMINUSGROW )
printf("%s: %d DEBUG3 random lseek: min=%d, max=<endoffile-iosize>\n",
Progname, Pid, min_lseek);
else
printf("%s: %d DEBUG3 random lseek: min=%d, max=%d\n",
Progname, Pid, min_lseek, max_lseek);
}
printf("%s: %d DEBUG3 check write interval = %d, check file interval = %d\n",
Progname, Pid, write_check_inter, file_check_inter);
printf("%s: %d DEBUG3 trunc interval = %d, trunc_incr = %d\n",
Progname, Pid, trunc_inter, trunc_incr);
if ( no_file_check )
printf("%s: %d DEBUG3 no whole file checking will be done\n",
Progname, Pid);
if ( unlink_inter_ran == -1 ) {
printf("%s: %d DEBUG3 unlink_inter = %d\n",
Progname, Pid, unlink_inter);
} else {
printf("%s: %d DEBUG3 unlink_inter = %d, unlink_inter_ran = %d\n",
Progname, Pid, unlink_inter, unlink_inter_ran);
}
if ( Debug > 8 ) {
num=sizeof(Open_flags)/sizeof(int);
printf("%s: %d DEBUG9 random open flags values:\n", Progname, Pid);
for(ind=0; ind<num; ind++) {
printf("\t%#o\n", Open_flags[ind]);
}
}
} /* end of DEBUG > 2 */
if ( Debug > 1 && num_procs > 1 ) {
printf("%s: %d DEBUG2 about to fork %d more copies\n", Progname,
Opid, num_procs-1);
}
fflush(stdout); /* ensure pending i/o is flushed before forking */
fflush(stderr);
forker(num_procs, forker_mode, Progname);
Pid=getpid(); /* reset after the forks */
/*
* If user specified random seed(s), get that random seed value.
* get random seed if it was not specified by the user.
* This is done after the forks, because pid is used to get the seed.
*/
if ( Nseeds == 1 ) {
/*
* If only one seed specified, all processes will get that seed.
*/
Seed=Seeds[0];
} else if ( Nseeds > 1 ) {
/*
* More than one seed was specified.
* The original process gets the first seed. Each
* process will be get the next seed in the specified list.
*/
if ( Opid == Pid ) {
Seed=Seeds[0];
} else {
/*
* If user didn't specify enough seeds, use default method.
*/
if ( Forker_npids >= Nseeds )
Seed=time(0) + Pid; /* default random seed */
else {