Line data Source code
1 : /*
2 : * Copyright (C) 2011 Andrea Mazzoleni
3 : *
4 : * This program is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 3 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * This program is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "portable.h"
19 :
20 : #include "support.h"
21 :
22 : volatile int global_interrupt = 0;
23 :
24 : /****************************************************************************/
25 : /* random */
26 :
27 : /**
28 : * Pseudo random number generator.
29 : */
30 : unsigned long long seed = 0;
31 :
32 56065885 : unsigned rnd(unsigned max)
33 : {
34 56065885 : seed = seed * 6364136223846793005LL + 1442695040888963407LL;
35 :
36 56065885 : return (seed >> 32) % max;
37 : }
38 :
39 55654613 : unsigned rndnz(unsigned max)
40 : {
41 55654613 : if (max <= 1)
42 2831 : return 1;
43 : else
44 55651782 : return rnd(max - 1) + 1;
45 : }
46 :
47 32703 : void rndnz_range(unsigned char* data, int size)
48 : {
49 : int i;
50 :
51 55680550 : for (i = 0; i < size; ++i)
52 55647847 : data[i] = rndnz(256);
53 32703 : }
54 :
55 1821 : void rndnz_damage(unsigned char* data, int size)
56 : {
57 : int i;
58 :
59 : /* corrupt ensuring always different data */
60 3642 : for (i = 0; i < size; ++i) {
61 : unsigned char c;
62 :
63 : do {
64 1835 : c = rndnz(256);
65 1835 : } while (c == data[i]);
66 :
67 1821 : data[i] = c;
68 : }
69 1821 : }
70 :
71 : char CHARSET[] = "qwertyuiopasdfghjklzxcvbnm1234567890 .-+";
72 : #define CHARSET_LEN (sizeof(CHARSET) - 1)
73 :
74 26839 : void rnd_name(char* file)
75 : {
76 26839 : int l = 1 + rnd(20);
77 :
78 308569 : while (l) {
79 281730 : *file++ = CHARSET[rnd(CHARSET_LEN)];
80 281730 : --l;
81 : }
82 26839 : *file = 0;
83 26839 : }
84 :
85 : /****************************************************************************/
86 : /* file */
87 :
88 146710 : int file_cmp(const void* a, const void* b)
89 : {
90 146710 : return strcmp(a, b);
91 : }
92 :
93 1821 : int fallback(int f, struct stat* st)
94 : {
95 : #if HAVE_FUTIMENS
96 : struct timespec tv[2];
97 : #else
98 : struct timeval tv[2];
99 : #endif
100 : int ret;
101 :
102 : #if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */
103 1821 : tv[0].tv_sec = st->st_mtime;
104 1821 : if (STAT_NSEC(st) != STAT_NSEC_INVALID)
105 1821 : tv[0].tv_nsec = STAT_NSEC(st);
106 : else
107 0 : tv[0].tv_nsec = 0;
108 1821 : tv[1].tv_sec = tv[0].tv_sec;
109 1821 : tv[1].tv_nsec = tv[0].tv_nsec;
110 :
111 1821 : ret = futimens(f, tv);
112 : #elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */
113 : tv[0].tv_sec = st->st_mtime;
114 : if (STAT_NSEC(st) != STAT_NSEC_INVALID)
115 : tv[0].tv_usec = STAT_NSEC(st) / 1000;
116 : else
117 : tv[0].tv_usec = 0;
118 : tv[1].tv_sec = tv[0].tv_sec;
119 : tv[1].tv_usec = tv[0].tv_usec;
120 :
121 : ret = futimes(f, tv);
122 : #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */
123 : tv[0].tv_sec = st->st_mtime;
124 : if (STAT_NSEC(st) != STAT_NSEC_INVALID)
125 : tv[0].tv_usec = STAT_NSEC(st) / 1000;
126 : else
127 : tv[0].tv_usec = 0;
128 : tv[1].tv_sec = tv[0].tv_sec;
129 : tv[1].tv_usec = tv[0].tv_usec;
130 :
131 : ret = futimesat(f, 0, tv);
132 : #else
133 : #error No function available to set file timestamps
134 : #endif
135 1821 : return ret;
136 : }
137 :
138 : /****************************************************************************/
139 : /* cmd */
140 :
141 : /**
142 : * Create a file with random content.
143 : * - If the file exists it's rewritten, but avoiding to truncating it to 0.
144 : */
145 23267 : void cmd_generate_file(const char* path, int size)
146 : {
147 : unsigned char* data;
148 : int f;
149 :
150 : /* remove the existing file/symlink if any */
151 23267 : if (remove(path) != 0) {
152 22446 : if (errno != ENOENT) {
153 : /* LCOV_EXCL_START */
154 : log_fatal("Error removing file %s\n", path);
155 : exit(EXIT_FAILURE);
156 : /* LCOV_EXCL_STOP */
157 : }
158 : } else {
159 : /* don't truncate files to 0 size to avoid ZERO file size protection */
160 821 : ++size;
161 : }
162 :
163 23267 : data = malloc(size);
164 :
165 : /* We don't write zero bytes because we want to test */
166 : /* the recovering of new files, after an aborted sync */
167 : /* If the files contains full blocks at zero */
168 : /* this is an impossible condition to recover */
169 : /* because we cannot differentiate between an unused block */
170 : /* and a file filled with 0 */
171 23267 : rndnz_range(data, size);
172 :
173 23267 : f = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_NOFOLLOW, 0600);
174 23267 : if (f < 0) {
175 : /* LCOV_EXCL_START */
176 : log_fatal("Error creating file %s\n", path);
177 : exit(EXIT_FAILURE);
178 : /* LCOV_EXCL_STOP */
179 : }
180 :
181 23267 : if (write(f, data, size) != size) {
182 : /* LCOV_EXCL_START */
183 : log_fatal("Error writing file %s\n", path);
184 : exit(EXIT_FAILURE);
185 : /* LCOV_EXCL_STOP */
186 : }
187 :
188 23267 : if (close(f) != 0) {
189 : /* LCOV_EXCL_START */
190 : log_fatal("Error closing file %s\n", path);
191 : exit(EXIT_FAILURE);
192 : /* LCOV_EXCL_STOP */
193 : }
194 :
195 23267 : free(data);
196 23267 : }
197 :
198 : /**
199 : * Create a symlink.
200 : * - If the file already exists, it's removed.
201 : */
202 930 : void cmd_generate_symlink(const char* path, const char* linkto)
203 : {
204 : /* remove the existing file/symlink if any */
205 930 : if (remove(path) != 0) {
206 909 : if (errno != ENOENT) {
207 : /* LCOV_EXCL_START */
208 : log_fatal("Error removing file %s\n", path);
209 : exit(EXIT_FAILURE);
210 : /* LCOV_EXCL_STOP */
211 : }
212 : }
213 :
214 930 : if (symlink(linkto, path) != 0) {
215 : /* LCOV_EXCL_START */
216 : log_fatal("Error writing symlink %s\n", path);
217 : exit(EXIT_FAILURE);
218 : /* LCOV_EXCL_STOP */
219 : }
220 930 : }
221 :
222 : /**
223 : * Create a file or a symlink with a random name.
224 : */
225 24000 : void cmd_generate(int disk, int size)
226 : {
227 : char path[PATH_MAX];
228 : char* file;
229 :
230 24000 : snprintf(path, sizeof(path), "bench/disk%d/", disk);
231 24000 : file = path + strlen(path);
232 :
233 : /* add a directory */
234 24000 : *file++ = 'a' + rnd(2);
235 24000 : *file = 0;
236 :
237 : /* create it */
238 24000 : if (mkdir(path, 0777) != 0) {
239 23988 : if (errno != EEXIST) {
240 : /* LCOV_EXCL_START */
241 : log_fatal("Error creating directory %s\n", path);
242 : exit(EXIT_FAILURE);
243 : /* LCOV_EXCL_STOP */
244 : }
245 : }
246 :
247 24000 : *file++ = '/';
248 :
249 : while (1) {
250 : /* add a random file */
251 25909 : rnd_name(file);
252 :
253 : /* skip some invalid file name, see http://en.wikipedia.org/wiki/Filename */
254 25909 : if (strcmp(file, ".") == 0
255 25874 : || strcmp(file, "..") == 0
256 25874 : || strcmp(file, "prn") == 0
257 25874 : || strcmp(file, "con") == 0
258 25873 : || strcmp(file, "nul") == 0
259 25873 : || strcmp(file, "aux") == 0
260 25873 : || file[0] == ' '
261 25199 : || file[strlen(file) - 1] == ' '
262 24608 : || file[strlen(file) - 1] == '.'
263 : ) {
264 1909 : continue;
265 : }
266 :
267 24000 : break;
268 : }
269 :
270 : #ifndef WIN32 /* Windows XP doesn't support symlinks */
271 24000 : if (rnd(32) == 0) {
272 : /* symlink */
273 : char linkto[PATH_MAX];
274 :
275 733 : rnd_name(linkto);
276 :
277 733 : cmd_generate_symlink(path, linkto);
278 : } else
279 : #endif
280 : {
281 : /* file */
282 23267 : cmd_generate_file(path, size);
283 : }
284 24000 : }
285 :
286 : /**
287 : * Write a partially a file.
288 : * - The file must exist.
289 : * - The file size is not changed.
290 : * - The written data may be equal or not at the already existing one.
291 : * - If it's a symlink nothing is done.
292 : */
293 6264 : void cmd_write(const char* path, int size)
294 : {
295 : struct stat st;
296 :
297 6264 : if (lstat(path, &st) != 0) {
298 : /* LCOV_EXCL_START */
299 : log_fatal("Error accessing %s\n", path);
300 : exit(EXIT_FAILURE);
301 : /* LCOV_EXCL_STOP */
302 : }
303 :
304 6264 : if (S_ISREG(st.st_mode)) {
305 : unsigned char* data;
306 : off_t off;
307 : int f;
308 :
309 : /* not over the end */
310 6237 : if (size > st.st_size)
311 704 : size = st.st_size;
312 :
313 : /* start at random position inside the file */
314 6237 : if (size < st.st_size)
315 5532 : off = rnd(st.st_size - size);
316 : else
317 705 : off = 0;
318 :
319 6237 : data = malloc(size);
320 :
321 6237 : rndnz_range(data, size);
322 :
323 6237 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW);
324 6237 : if (f < 0) {
325 : /* LCOV_EXCL_START */
326 : log_fatal("Error creating file %s\n", path);
327 : exit(EXIT_FAILURE);
328 : /* LCOV_EXCL_STOP */
329 : }
330 :
331 6237 : if (lseek(f, off, SEEK_SET) != off) {
332 : /* LCOV_EXCL_START */
333 : log_fatal("Error seeking file %s\n", path);
334 : exit(EXIT_FAILURE);
335 : /* LCOV_EXCL_STOP */
336 : }
337 :
338 6237 : if (write(f, data, size) != size) {
339 : /* LCOV_EXCL_START */
340 : log_fatal("Error writing file %s\n", path);
341 : exit(EXIT_FAILURE);
342 : /* LCOV_EXCL_STOP */
343 : }
344 :
345 6237 : if (close(f) != 0) {
346 : /* LCOV_EXCL_START */
347 : log_fatal("Error closing file %s\n", path);
348 : exit(EXIT_FAILURE);
349 : /* LCOV_EXCL_STOP */
350 : }
351 :
352 6237 : free(data);
353 : }
354 6264 : }
355 :
356 : /**
357 : * Damage a file.
358 : * - The file must exist.
359 : * - The file size is not changed.
360 : * - The written data is SURELY different than the already existing one.
361 : * - The file timestamp is NOT modified.
362 : * - If it's a symlink nothing is done.
363 : */
364 1882 : void cmd_damage(const char* path, int size)
365 : {
366 : struct stat st;
367 :
368 : /* here a 0 size means to change nothing */
369 : /* as also the timestamp should not be changed */
370 1882 : if (!size)
371 3 : return;
372 :
373 1882 : if (lstat(path, &st) != 0) {
374 : /* LCOV_EXCL_START */
375 : log_fatal("Error accessing %s\n", path);
376 : exit(EXIT_FAILURE);
377 : /* LCOV_EXCL_STOP */
378 : }
379 :
380 1882 : if (st.st_size == 0)
381 3 : return;
382 :
383 1879 : if (S_ISREG(st.st_mode)) {
384 : off_t off;
385 : unsigned char* data;
386 : int f;
387 :
388 : /* not over the end */
389 1821 : if (size > st.st_size)
390 0 : size = st.st_size;
391 :
392 : /* start at random position inside the file */
393 1821 : if (size < st.st_size)
394 1820 : off = rnd(st.st_size - size);
395 : else
396 1 : off = 0;
397 :
398 1821 : data = malloc(size);
399 :
400 1821 : f = open(path, O_RDWR | O_BINARY | O_NOFOLLOW);
401 1821 : if (f < 0) {
402 : /* LCOV_EXCL_START */
403 : log_fatal("Error creating file %s\n", path);
404 : exit(EXIT_FAILURE);
405 : /* LCOV_EXCL_STOP */
406 : }
407 :
408 1821 : if (lseek(f, off, SEEK_SET) != off) {
409 : /* LCOV_EXCL_START */
410 : log_fatal("Error seeking file %s\n", path);
411 : exit(EXIT_FAILURE);
412 : /* LCOV_EXCL_STOP */
413 : }
414 :
415 1821 : if (read(f, data, size) != size) {
416 : /* LCOV_EXCL_START */
417 : log_fatal("Error writing file %s\n", path);
418 : exit(EXIT_FAILURE);
419 : /* LCOV_EXCL_STOP */
420 : }
421 :
422 1821 : rndnz_damage(data, size);
423 :
424 1821 : if (lseek(f, off, SEEK_SET) != off) {
425 : /* LCOV_EXCL_START */
426 : log_fatal("Error seeking file %s\n", path);
427 : exit(EXIT_FAILURE);
428 : /* LCOV_EXCL_STOP */
429 : }
430 :
431 1821 : if (write(f, data, size) != size) {
432 : /* LCOV_EXCL_START */
433 : log_fatal("Error writing file %s\n", path);
434 : exit(EXIT_FAILURE);
435 : /* LCOV_EXCL_STOP */
436 : }
437 :
438 1821 : if (fallback(f, &st) != 0) {
439 : /* LCOV_EXCL_START */
440 : log_fatal("Error setting time for file %s\n", path);
441 : exit(EXIT_FAILURE);
442 : /* LCOV_EXCL_STOP */
443 : }
444 :
445 1821 : if (close(f) != 0) {
446 : /* LCOV_EXCL_START */
447 : log_fatal("Error closing file %s\n", path);
448 : exit(EXIT_FAILURE);
449 : /* LCOV_EXCL_STOP */
450 : }
451 :
452 1821 : free(data);
453 : }
454 : }
455 :
456 : /**
457 : * Append to a file.
458 : * - The file must exist.
459 : * - If it's a symlink nothing is done.
460 : */
461 3199 : void cmd_append(const char* path, int size)
462 : {
463 : struct stat st;
464 :
465 3199 : if (lstat(path, &st) != 0) {
466 : /* LCOV_EXCL_START */
467 : log_fatal("Error accessing %s\n", path);
468 : exit(EXIT_FAILURE);
469 : /* LCOV_EXCL_STOP */
470 : }
471 :
472 3199 : if (S_ISREG(st.st_mode)) {
473 : unsigned char* data;
474 : int f;
475 :
476 3199 : data = malloc(size);
477 :
478 3199 : rndnz_range(data, size);
479 :
480 3199 : f = open(path, O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW);
481 3199 : if (f < 0) {
482 : /* LCOV_EXCL_START */
483 : log_fatal("Error opening file %s\n", path);
484 : exit(EXIT_FAILURE);
485 : /* LCOV_EXCL_STOP */
486 : }
487 :
488 3199 : if (write(f, data, size) != size) {
489 : /* LCOV_EXCL_START */
490 : log_fatal("Error writing file %s\n", path);
491 : exit(EXIT_FAILURE);
492 : /* LCOV_EXCL_STOP */
493 : }
494 :
495 3199 : if (close(f) != 0) {
496 : /* LCOV_EXCL_START */
497 : log_fatal("Error closing file %s\n", path);
498 : exit(EXIT_FAILURE);
499 : /* LCOV_EXCL_STOP */
500 : }
501 :
502 3199 : free(data);
503 : }
504 3199 : }
505 :
506 : /**
507 : * Truncate a file.
508 : * - The file must exist.
509 : * - The file is NEVER truncated to 0.
510 : * - If it's a symlink nothing is done.
511 : */
512 3153 : void cmd_truncate(const char* path, int size)
513 : {
514 : struct stat st;
515 :
516 3153 : if (lstat(path, &st) != 0) {
517 : /* LCOV_EXCL_START */
518 : log_fatal("Error accessing %s\n", path);
519 : exit(EXIT_FAILURE);
520 : /* LCOV_EXCL_STOP */
521 : }
522 :
523 3153 : if (S_ISREG(st.st_mode)) {
524 : off_t off;
525 : int f;
526 :
527 : /* if file is empty, just rewrite it */
528 3153 : if (st.st_size == 0) {
529 3 : size = 0;
530 : } else {
531 : /* don't truncate files to 0 size to avoid ZERO file size protection */
532 3150 : if (size >= st.st_size)
533 193 : size = st.st_size - 1;
534 : }
535 :
536 3153 : off = st.st_size - size;
537 :
538 3153 : f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW);
539 3153 : if (f < 0) {
540 : /* LCOV_EXCL_START */
541 : log_fatal("Error opening file %s\n", path);
542 : exit(EXIT_FAILURE);
543 : /* LCOV_EXCL_STOP */
544 : }
545 :
546 3153 : if (ftruncate(f, off) != 0) {
547 : /* LCOV_EXCL_START */
548 : log_fatal("Error truncating file %s\n", path);
549 : exit(EXIT_FAILURE);
550 : /* LCOV_EXCL_STOP */
551 : }
552 :
553 3153 : if (close(f) != 0) {
554 : /* LCOV_EXCL_START */
555 : log_fatal("Error closing file %s\n", path);
556 : exit(EXIT_FAILURE);
557 : /* LCOV_EXCL_STOP */
558 : }
559 : }
560 3153 : }
561 :
562 : /**
563 : * Delete a file.
564 : * - The file must exist.
565 : */
566 3141 : void cmd_delete(const char* path)
567 : {
568 3141 : if (remove(path) != 0) {
569 : /* LCOV_EXCL_START */
570 : log_fatal("Error removing %s\n", path);
571 : exit(EXIT_FAILURE);
572 : /* LCOV_EXCL_STOP */
573 : }
574 3141 : }
575 :
576 : /**
577 : * Change a file. Or deleted/truncated/append/created.
578 : * - The file must exist.
579 : */
580 13128 : void cmd_change(const char* path, int size)
581 : {
582 : struct stat st;
583 :
584 13128 : if (!size)
585 26 : return;
586 :
587 13102 : if (lstat(path, &st) != 0) {
588 : /* LCOV_EXCL_START */
589 : log_fatal("Error accessing %s\n", path);
590 : exit(EXIT_FAILURE);
591 : /* LCOV_EXCL_STOP */
592 : }
593 :
594 13102 : if (S_ISLNK(st.st_mode)) {
595 : /* symlink */
596 394 : if (rnd(2) == 0) {
597 : /* delete */
598 197 : if (remove(path) != 0) {
599 : /* LCOV_EXCL_START */
600 : log_fatal("Error removing %s\n", path);
601 : exit(EXIT_FAILURE);
602 : /* LCOV_EXCL_STOP */
603 : }
604 : } else {
605 : /* recreate */
606 : char linkto[PATH_MAX];
607 :
608 197 : if (remove(path) != 0) {
609 : /* LCOV_EXCL_START */
610 : log_fatal("Error removing %s\n", path);
611 : exit(EXIT_FAILURE);
612 : /* LCOV_EXCL_STOP */
613 : }
614 :
615 197 : rnd_name(linkto);
616 :
617 197 : cmd_generate_symlink(path, linkto);
618 : }
619 12708 : } else if (S_ISREG(st.st_mode)) {
620 : int r;
621 :
622 12708 : r = rnd(4);
623 :
624 12708 : if (r == 0) {
625 3215 : cmd_write(path, size);
626 9493 : } else if (r == 1) {
627 3199 : cmd_append(path, size);
628 6294 : } else if (r == 2) {
629 3153 : cmd_truncate(path, size);
630 : } else {
631 3141 : cmd_delete(path);
632 : }
633 : }
634 : }
635 :
636 1 : void help(void)
637 : {
638 1 : printf("Test for " PACKAGE " v" VERSION " by Andrea Mazzoleni, " PACKAGE_URL "\n");
639 1 : printf("Usage:\n");
640 1 : printf("\tmktest generate SEED DISK_NUM FILE_NUM FILE_SIZE\n");
641 1 : printf("\tmktest damage SEED NUM SIZE FILE\n");
642 1 : printf("\tmktest write SEED NUM SIZE FILE\n");
643 1 : printf("\tmktest change SEED SIZE FILE\n");
644 1 : printf("\tmktest append SEED SIZE FILE\n");
645 1 : printf("\tmktest truncate SEED SIZE FILE\n");
646 1 : }
647 :
648 22 : int main(int argc, char* argv[])
649 : {
650 : int i, j, b;
651 :
652 22 : lock_init();
653 :
654 22 : if (argc < 2) {
655 1 : help();
656 1 : exit(EXIT_SUCCESS);
657 : }
658 :
659 21 : if (strcmp(argv[1], "generate") == 0) {
660 : int disk, file, size;
661 :
662 4 : if (argc != 6) {
663 : /* LCOV_EXCL_START */
664 : help();
665 : exit(EXIT_FAILURE);
666 : /* LCOV_EXCL_STOP */
667 : }
668 :
669 4 : seed = atoi(argv[2]);
670 4 : disk = atoi(argv[3]);
671 4 : file = atoi(argv[4]);
672 4 : size = atoi(argv[5]);
673 :
674 28 : for (i = 0; i < disk; ++i) {
675 24024 : for (j = 0; j < file; ++j) {
676 24000 : if (j == 0)
677 : /* create at least a big one */
678 24 : cmd_generate(i + 1, size);
679 23976 : else if (j == 1)
680 : /* create at least an empty one */
681 24 : cmd_generate(i + 1, 0);
682 : else
683 23952 : cmd_generate(i + 1, rnd(size));
684 : }
685 : }
686 17 : } else if (strcmp(argv[1], "write") == 0) {
687 : int fail, size;
688 :
689 7 : if (argc < 6) {
690 : /* LCOV_EXCL_START */
691 : help();
692 : exit(EXIT_FAILURE);
693 : /* LCOV_EXCL_STOP */
694 : }
695 :
696 7 : seed = atoi(argv[2]);
697 7 : fail = atoi(argv[3]);
698 7 : size = atoi(argv[4]);
699 7 : b = 5;
700 :
701 : /* sort the file names */
702 7 : qsort(&argv[b], argc - b, sizeof(argv[b]), file_cmp);
703 :
704 977 : for (i = b; i < argc; ++i)
705 4019 : for (j = 0; j < fail; ++j)
706 3049 : cmd_write(argv[i], rndnz(size));
707 10 : } else if (strcmp(argv[1], "damage") == 0) {
708 : int fail, size;
709 :
710 3 : if (argc < 6) {
711 : /* LCOV_EXCL_START */
712 : help();
713 : exit(EXIT_FAILURE);
714 : /* LCOV_EXCL_STOP */
715 : }
716 :
717 3 : seed = atoi(argv[2]);
718 3 : fail = atoi(argv[3]);
719 3 : size = atoi(argv[4]);
720 3 : b = 5;
721 :
722 : /* sort the file names */
723 3 : qsort(&argv[b], argc - b, sizeof(argv[b]), file_cmp);
724 :
725 1885 : for (i = b; i < argc; ++i)
726 3764 : for (j = 0; j < fail; ++j)
727 1882 : cmd_damage(argv[i], rndnz(size)); /* at least one byte */
728 7 : } else if (strcmp(argv[1], "append") == 0) {
729 : int size;
730 :
731 0 : if (argc < 5) {
732 : /* LCOV_EXCL_START */
733 : help();
734 : exit(EXIT_FAILURE);
735 : /* LCOV_EXCL_STOP */
736 : }
737 :
738 0 : seed = atoi(argv[2]);
739 0 : size = atoi(argv[3]);
740 0 : b = 4;
741 :
742 : /* sort the file names */
743 0 : qsort(&argv[b], argc - b, sizeof(argv[b]), file_cmp);
744 :
745 0 : for (i = b; i < argc; ++i)
746 0 : cmd_append(argv[i], rndnz(size)); /* at least one byte */
747 7 : } else if (strcmp(argv[1], "truncate") == 0) {
748 : int size;
749 :
750 0 : if (argc < 5) {
751 : /* LCOV_EXCL_START */
752 : help();
753 : exit(EXIT_FAILURE);
754 : /* LCOV_EXCL_STOP */
755 : }
756 :
757 0 : seed = atoi(argv[2]);
758 0 : size = atoi(argv[3]);
759 0 : b = 4;
760 :
761 : /* sort the file names */
762 0 : qsort(&argv[b], argc - b, sizeof(argv[b]), file_cmp);
763 :
764 0 : for (i = b; i < argc; ++i)
765 0 : cmd_truncate(argv[i], rnd(size));
766 7 : } else if (strcmp(argv[1], "change") == 0) {
767 : int size;
768 :
769 7 : if (argc < 5) {
770 : /* LCOV_EXCL_START */
771 : help();
772 : exit(EXIT_FAILURE);
773 : /* LCOV_EXCL_STOP */
774 : }
775 :
776 7 : seed = atoi(argv[2]);
777 7 : size = atoi(argv[3]);
778 7 : b = 4;
779 :
780 : /* sort the file names */
781 7 : qsort(&argv[b], argc - b, sizeof(argv[b]), file_cmp);
782 :
783 13135 : for (i = b; i < argc; ++i)
784 13128 : cmd_change(argv[i], rnd(size));
785 : } else {
786 : /* LCOV_EXCL_START */
787 : help();
788 : exit(EXIT_FAILURE);
789 : /* LCOV_EXCL_STOP */
790 : }
791 :
792 21 : lock_done();
793 :
794 21 : return 0;
795 : }
796 :
|