]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - mkfile/xfs_mkfile.c
1957b4da7f98c2bc4cad653afbcbea9e28516d34
[thirdparty/xfsprogs-dev.git] / mkfile / xfs_mkfile.c
1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33 /*
34 * Make file utility for xfs.
35 */
36
37 #include <libxfs.h>
38 #include <malloc.h>
39 #include <sys/stat.h>
40 #include <sys/ioctl.h>
41 #include <ctype.h>
42
43 #define MAXBUFFERSIZE (256 * 1024)
44
45 static void usage(void);
46 static char *progname;
47
48 int
49 main(int argc, char **argv)
50 {
51 int fd;
52 loff_t result;
53 loff_t size = 0;
54 loff_t mult = 0;
55 int bytes = 0;
56 loff_t wrote = 0;
57 int len = 0;
58 int c;
59 int errflg = 0;
60 int errs = 0;
61 int nobytes = 0;
62 int prealloc = 0;
63 int verbose = 0;
64 struct dioattr da;
65 void *buf = NULL;
66 int buflen = 0, nbuflen;
67 int bufalign = 0, nbufalign, bufmin;
68 int oflags;
69 xfs_flock64_t flck;
70
71 progname = basename(argv[0]);
72 while ((c = getopt(argc, argv, "npvV")) != EOF) {
73 switch(c) {
74 case 'n':
75 nobytes++;
76 break;
77 case 'p':
78 prealloc++;
79 break;
80 case 'v':
81 verbose++;
82 break;
83 case 'V':
84 printf("%s version %s\n", progname, VERSION);
85 break;
86 default:
87 errflg++;
88 break;
89 }
90 }
91
92 if (argc < optind + 2 || errflg)
93 usage();
94
95 mult = 1;
96
97 len = strlen(argv[optind]);
98
99 if (isalpha(argv[optind][len-1])) {
100 switch (argv[optind][len-1]) {
101 case 'k':
102 case 'K':
103 mult = 1024;
104 break;
105 case 'b':
106 case 'B':
107 mult = 512;
108 break;
109 case 'm':
110 case 'M':
111 mult = 1024;
112 mult *= 1024;
113 break;
114 case 'g':
115 case 'G':
116 mult = 1024;
117 mult *= 1024;
118 mult *= 1024;
119 break;
120 default:
121 fprintf(stderr, "unknown size %s\n", argv[optind]);
122 usage();
123 }
124
125 argv[optind][len-1] = '\0';
126 }
127
128 size = atoll(argv[optind]) * mult;
129
130 optind++;
131
132 while (optind < argc) {
133 if (verbose)
134 fprintf(stdout, "%s %lld bytes %s\n",
135 argv[optind], (long long)size,
136 prealloc
137 ? "(pre-allocated)"
138 : "");
139
140 oflags = O_CREAT|O_TRUNC|O_WRONLY|(nobytes ? 0 : O_DIRECT);
141
142 fd = open(argv[optind], oflags, 0600);
143
144 if ( (oflags & O_DIRECT)
145 && ( (fd < 0 && errno == EINVAL)
146 || ioctl(fd, XFS_IOC_DIOINFO, &da) < 0)) {
147
148 close(fd);
149
150 oflags &= ~O_DIRECT;
151
152 fd = open(argv[optind], oflags, 0600);
153 }
154
155 if (fd < 0) {
156 perror(argv[optind]);
157 optind++;
158 errs++;
159 continue;
160 }
161
162 if (size == 0) {
163 close(fd);
164 optind++;
165 continue;
166 }
167
168 if ((result = lseek64(fd, size - 1, SEEK_SET)) < 0LL) {
169 /*
170 * This check doesn't actually work for 6.2
171 * efs and nfs2, although it should.
172 */
173 fprintf(stderr, "lseek64 error, result = %lld\n",
174 (long long)result);
175 if (errno)
176 perror(argv[optind]);
177 errs++;
178 } else if (nobytes) {
179 if (write(fd, "", 1) < 0) {
180 perror(argv[optind]);
181 errs++;
182 }
183 } else {
184 flck.l_whence = SEEK_SET;
185 flck.l_start = 0LL;
186 flck.l_len = size;
187 if (prealloc)
188 (void)ioctl(fd, XFS_IOC_RESVSP64, &flck);
189 if (oflags & O_DIRECT) {
190 nbufalign = da.d_mem;
191
192 if ( da.d_miniosz <= MAXBUFFERSIZE
193 && MAXBUFFERSIZE <= da.d_maxiosz)
194 nbuflen = MAXBUFFERSIZE;
195 else if (da.d_maxiosz < MAXBUFFERSIZE)
196 nbuflen = da.d_maxiosz;
197 else
198 nbuflen = da.d_miniosz;
199
200 bufmin = da.d_miniosz;
201 } else {
202 nbuflen = MAXBUFFERSIZE;
203 nbufalign = sizeof(long);
204 bufmin = 0;
205 }
206
207 if (nbuflen > buflen || nbufalign > bufalign) {
208 if (buf)
209 free(buf);
210 buf = memalign(nbufalign, nbuflen);
211 buflen = nbuflen;
212 bzero(buf, nbuflen);
213 nbufalign = bufalign;
214 }
215
216 wrote = 0;
217
218 lseek64(fd, 0LL, SEEK_SET);
219
220 while (wrote < size) {
221 if (size - wrote >= buflen)
222 bytes = buflen;
223 else if (bufmin)
224 bytes = roundup(size - wrote, bufmin);
225 else
226 bytes = size - wrote;
227
228 len = write(fd, buf, bytes);
229
230 if (len < 0) {
231 perror(argv[optind]);
232 unlink(argv[optind]);
233 errs++;
234 break;
235 }
236
237 wrote += len;
238 }
239
240 if (wrote > size && ftruncate64(fd, size) < 0) {
241 perror(argv[optind]);
242 unlink(argv[optind]);
243 errs++;
244 }
245 }
246
247 if ( close(fd) < 0 ) {
248 perror(argv[optind]);
249 unlink(argv[optind]);
250 errs++;
251 }
252
253 optind++;
254 }
255
256 return errs != 0;
257 }
258
259 static void
260 usage(void)
261 {
262 fprintf(stderr, "%s: [-npv] <size> <name1> [<name2>] ...\n", progname);
263 exit(2);
264 }