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