fsstress: Include stddef.h for ptrdiff_t
[xfstests-dev.git] / src / makeextents.c
1 /*
2  * Copyright (c) 2000-2004 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would 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, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 /*
20  * Write a bunch of holes to create a bunch of extents.
21  */
22  
23 #include "global.h"
24
25 char *progname;
26 __uint64_t num_holes = 1000;
27 __uint64_t curr_holes;
28 int verbose_opt = 0;
29 char *filename;
30 int status_num = 100;
31 int wsync;
32 int preserve;
33 unsigned int blocksize;
34 __uint64_t fileoffset;
35
36 #define JUMP_SIZE (128 * 1024)
37 #define NUMHOLES_TO_SIZE(i) (i * JUMP_SIZE)
38 #define SIZE_TO_NUMHOLES(s) (s / JUMP_SIZE)
39
40 void
41 usage(void)
42 {
43         fprintf(stderr, "%s [-b blocksize] [-n num-holes] [-s status-num]"
44                         " [-o start-offset] [-vwp] file\n", progname);
45         exit(1);
46 }
47
48 int
49 main(int argc, char *argv[])
50 {
51         int c;
52         int fd;
53         int oflags;
54         __uint64_t i;
55         __uint64_t offset;
56         int blocksize = 512;
57         unsigned char *buffer = NULL;
58         struct stat stat;
59
60         progname = argv[0];
61
62         while ((c = getopt(argc, argv, "b:n:o:ps:vw")) != -1) {
63                 switch (c) {
64                 case 'b':
65                         blocksize = atoi(optarg);
66                         break;
67                 case 'n':
68                         num_holes = atoll(optarg);
69                         break;
70                 case 'v':
71                         verbose_opt = 1;
72                         break;
73                 case 'w':
74                         wsync = 1;
75                         break;
76                 case 'p':
77                         preserve = 1;
78                         break;
79                 case 's':
80                         status_num = atoi(optarg);
81                         break;
82                 case 'o':
83                         fileoffset = strtoull(optarg, NULL, 16);
84                         break;
85                 case '?':
86                         usage();
87                 }
88         }
89         if (optind == argc-1)
90                 filename = argv[optind];
91         else
92                 usage();
93
94         buffer = malloc(blocksize);
95         if (buffer == NULL) {
96             fprintf(stderr, "%s: blocksize to big to allocate buffer\n", progname);
97             return 1;
98         }
99
100         oflags = O_RDWR | O_CREAT;
101         oflags |=   (preserve ? 0 : O_TRUNC) |
102                     (wsync ? O_SYNC : 0);
103         
104         if ((fd = open(filename, oflags, 0666)) < 0) {
105                 perror("open");
106                 return 1;
107         }
108
109         if (fstat(fd, &stat) < 0) {
110                 perror("stat");
111                 return 1;
112         }
113         if (preserve) {
114                 curr_holes = SIZE_TO_NUMHOLES(stat.st_size);
115                 if (num_holes < curr_holes) {
116                         /* we need to truncate back */
117                         if (ftruncate(fd, NUMHOLES_TO_SIZE(num_holes)) < 0) {
118                                 perror("ftruncate");
119                                 return 1;
120                         }
121                         if (verbose_opt) {
122                                 printf("truncating back to %llu\n",
123                                        (unsigned long long)
124                                         NUMHOLES_TO_SIZE(num_holes));
125                         }
126                         return 0;
127                 }
128         }
129         else {
130                 curr_holes = 0;
131         }
132         if (curr_holes != 0 && verbose_opt) {
133                 printf("creating %llu more holes\n",
134                         (unsigned long long)num_holes - curr_holes);
135         }
136                 
137         /* create holes by seeking and writing */
138         for (i = curr_holes; i < num_holes; i++) {
139
140                 offset = NUMHOLES_TO_SIZE(i) + fileoffset;
141
142                 if (lseek64(fd, offset, SEEK_SET) < 0) {
143                         perror("lseek");
144                         return 1;
145                 }
146
147                 if (write(fd, buffer, blocksize) < blocksize) {
148                         perror("write");
149                         return 1;
150                 }
151
152                 if (verbose_opt && ((i+1) % status_num == 0)) {
153                         printf("seeked and wrote %llu times\n",
154                                 (unsigned long long)i + 1);
155                 }
156         }
157
158         close(fd);
159
160         return 0;
161 }