punch-alternating: add some options
[xfstests-dev.git] / src / punch-alternating.c
1 /*
2  * Punch out every other block in a file.
3  * Copyright (C) 2016 Oracle.
4  */
5 #include <stdio.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <unistd.h>
9 #include <fcntl.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include "global.h"
13
14 void usage(char *cmd)
15 {
16         printf("Usage: %s [-i interval] [-s size] file\n", cmd);
17         printf("Punches every other block in the file by default,\n");
18         printf("or 'size' blocks every 'interval' blocks with options.\n");
19         exit(1);
20 }
21
22 int main(int argc, char *argv[])
23 {
24         struct stat     s;
25         struct statfs   sf;
26         off_t           offset;
27         int             fd;
28         blksize_t       blksz;
29         off_t           sz;
30         int             mode;
31         int             error;
32         int             c;
33         int             size = 1;       /* punch $SIZE blocks ... */
34         int             interval = 2;   /* every $INTERVAL blocks */
35
36         while ((c = getopt(argc, argv, "i:s:")) != EOF) {
37                 switch (c) {
38                 case 'i':
39                         interval = atoi(optarg);
40                         break;
41                 case 's':
42                         size = atoi(optarg);
43                         break;
44                 default:
45                         usage(argv[0]);
46                 }
47         }
48
49         if (interval <= 0) {
50                 printf("interval must be > 0\n");
51                 usage(argv[0]);
52         }
53
54         if (size <= 0) {
55                 printf("size must be > 0\n");
56                 usage(argv[0]);
57         }
58
59         if (optind != argc - 1)
60                 usage(argv[0]);
61
62         fd = open(argv[optind], O_WRONLY);
63         if (fd < 0)
64                 goto err;
65
66         error = fstat(fd, &s);
67         if (error)
68                 goto err;
69
70         error = fstatfs(fd, &sf);
71         if (error)
72                 goto err;
73
74         sz = s.st_size;
75         blksz = sf.f_bsize;
76
77         mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
78         for (offset = 0; offset < sz; offset += blksz * interval) {
79                 error = fallocate(fd, mode, offset, blksz * size);
80                 if (error)
81                         goto err;
82         }
83
84         error = fsync(fd);
85         if (error)
86                 goto err;
87
88         error = close(fd);
89         if (error)
90                 goto err;
91         return 0;
92 err:
93         perror(argv[optind]);
94         return 2;
95 }