]>
Commit | Line | Data |
---|---|---|
2bd0ea18 NS |
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 | ||
f91dde66 NS |
37 | #include <libxfs.h> |
38 | #include <malloc.h> | |
2bd0ea18 | 39 | #include <sys/stat.h> |
f91dde66 | 40 | #include <sys/ioctl.h> |
14290264 | 41 | #include <sys/vfs.h> |
2bd0ea18 | 42 | #include <ctype.h> |
2bd0ea18 | 43 | |
2bd0ea18 NS |
44 | #define MAXBUFFERSIZE (256 * 1024) |
45 | ||
37cb1ae1 | 46 | static char *progname; |
2bd0ea18 | 47 | |
14290264 NS |
48 | static void |
49 | usage(void) | |
50 | { | |
51 | fprintf(stderr, "%s: [-npv] <size> <name1> [<name2>] ...\n", progname); | |
52 | exit(2); | |
53 | } | |
54 | ||
55 | static int | |
56 | openfd(char *name, int oflags) | |
57 | { | |
58 | struct statfs buf; | |
59 | int fd; | |
60 | ||
61 | fd = open(name, oflags, 0600); | |
62 | if (fd < 0) { | |
63 | perror(name); | |
64 | return -1; | |
65 | } | |
66 | ||
67 | fstatfs(fd, &buf); | |
68 | if (buf.f_type != XFS_SUPER_MAGIC) { | |
69 | fprintf(stderr, "%s: " | |
70 | "file [\"%s\"] is not on an XFS filesystem\n", | |
71 | progname, name); | |
72 | return -1; | |
73 | } | |
74 | return fd; | |
75 | } | |
76 | ||
2bd0ea18 NS |
77 | int |
78 | main(int argc, char **argv) | |
79 | { | |
80 | int fd; | |
81 | loff_t result; | |
82 | loff_t size = 0; | |
83 | loff_t mult = 0; | |
84 | int bytes = 0; | |
85 | loff_t wrote = 0; | |
86 | int len = 0; | |
87 | int c; | |
88 | int errflg = 0; | |
89 | int errs = 0; | |
90 | int nobytes = 0; | |
91 | int prealloc = 0; | |
92 | int verbose = 0; | |
93 | struct dioattr da; | |
2bd0ea18 NS |
94 | void *buf = NULL; |
95 | int buflen = 0, nbuflen; | |
96 | int bufalign = 0, nbufalign, bufmin; | |
97 | int oflags; | |
98 | xfs_flock64_t flck; | |
99 | ||
100 | progname = basename(argv[0]); | |
101 | while ((c = getopt(argc, argv, "npvV")) != EOF) { | |
102 | switch(c) { | |
103 | case 'n': | |
104 | nobytes++; | |
105 | break; | |
106 | case 'p': | |
107 | prealloc++; | |
108 | break; | |
109 | case 'v': | |
110 | verbose++; | |
111 | break; | |
112 | case 'V': | |
113 | printf("%s version %s\n", progname, VERSION); | |
114 | break; | |
115 | default: | |
116 | errflg++; | |
117 | break; | |
118 | } | |
119 | } | |
120 | ||
121 | if (argc < optind + 2 || errflg) | |
122 | usage(); | |
123 | ||
124 | mult = 1; | |
125 | ||
126 | len = strlen(argv[optind]); | |
127 | ||
128 | if (isalpha(argv[optind][len-1])) { | |
129 | switch (argv[optind][len-1]) { | |
130 | case 'k': | |
131 | case 'K': | |
132 | mult = 1024; | |
133 | break; | |
134 | case 'b': | |
135 | case 'B': | |
136 | mult = 512; | |
137 | break; | |
138 | case 'm': | |
139 | case 'M': | |
140 | mult = 1024; | |
141 | mult *= 1024; | |
142 | break; | |
143 | case 'g': | |
144 | case 'G': | |
145 | mult = 1024; | |
146 | mult *= 1024; | |
147 | mult *= 1024; | |
148 | break; | |
149 | default: | |
150 | fprintf(stderr, "unknown size %s\n", argv[optind]); | |
151 | usage(); | |
152 | } | |
153 | ||
154 | argv[optind][len-1] = '\0'; | |
155 | } | |
156 | ||
157 | size = atoll(argv[optind]) * mult; | |
158 | ||
159 | optind++; | |
160 | ||
161 | while (optind < argc) { | |
162 | if (verbose) | |
163 | fprintf(stdout, "%s %lld bytes %s\n", | |
5b64e00a | 164 | argv[optind], (long long)size, |
2bd0ea18 NS |
165 | prealloc |
166 | ? "(pre-allocated)" | |
167 | : ""); | |
168 | ||
169 | oflags = O_CREAT|O_TRUNC|O_WRONLY|(nobytes ? 0 : O_DIRECT); | |
170 | ||
14290264 NS |
171 | if ((fd = openfd(argv[optind], oflags)) == -1) { |
172 | optind++; | |
173 | errs++; | |
174 | continue; | |
175 | } | |
2bd0ea18 NS |
176 | |
177 | if ( (oflags & O_DIRECT) | |
178 | && ( (fd < 0 && errno == EINVAL) | |
179 | || ioctl(fd, XFS_IOC_DIOINFO, &da) < 0)) { | |
180 | ||
181 | close(fd); | |
182 | ||
183 | oflags &= ~O_DIRECT; | |
184 | ||
14290264 NS |
185 | if ((fd = openfd(argv[optind], oflags)) == -1) { |
186 | optind++; | |
187 | errs++; | |
188 | continue; | |
189 | } | |
2bd0ea18 NS |
190 | } |
191 | ||
192 | if (size == 0) { | |
193 | close(fd); | |
194 | optind++; | |
195 | continue; | |
196 | } | |
197 | ||
198 | if ((result = lseek64(fd, size - 1, SEEK_SET)) < 0LL) { | |
199 | /* | |
200 | * This check doesn't actually work for 6.2 | |
201 | * efs and nfs2, although it should. | |
202 | */ | |
5b64e00a NS |
203 | fprintf(stderr, "lseek64 error, result = %lld\n", |
204 | (long long)result); | |
2bd0ea18 NS |
205 | if (errno) |
206 | perror(argv[optind]); | |
207 | errs++; | |
208 | } else if (nobytes) { | |
209 | if (write(fd, "", 1) < 0) { | |
210 | perror(argv[optind]); | |
211 | errs++; | |
212 | } | |
213 | } else { | |
214 | flck.l_whence = SEEK_SET; | |
215 | flck.l_start = 0LL; | |
216 | flck.l_len = size; | |
30b0c726 NS |
217 | if (prealloc) |
218 | (void)ioctl(fd, XFS_IOC_RESVSP64, &flck); | |
2bd0ea18 NS |
219 | if (oflags & O_DIRECT) { |
220 | nbufalign = da.d_mem; | |
221 | ||
222 | if ( da.d_miniosz <= MAXBUFFERSIZE | |
223 | && MAXBUFFERSIZE <= da.d_maxiosz) | |
224 | nbuflen = MAXBUFFERSIZE; | |
225 | else if (da.d_maxiosz < MAXBUFFERSIZE) | |
226 | nbuflen = da.d_maxiosz; | |
227 | else | |
228 | nbuflen = da.d_miniosz; | |
229 | ||
230 | bufmin = da.d_miniosz; | |
231 | } else { | |
232 | nbuflen = MAXBUFFERSIZE; | |
233 | nbufalign = sizeof(long); | |
234 | bufmin = 0; | |
235 | } | |
236 | ||
237 | if (nbuflen > buflen || nbufalign > bufalign) { | |
238 | if (buf) | |
239 | free(buf); | |
240 | buf = memalign(nbufalign, nbuflen); | |
241 | buflen = nbuflen; | |
242 | bzero(buf, nbuflen); | |
243 | nbufalign = bufalign; | |
244 | } | |
245 | ||
246 | wrote = 0; | |
247 | ||
248 | lseek64(fd, 0LL, SEEK_SET); | |
249 | ||
250 | while (wrote < size) { | |
251 | if (size - wrote >= buflen) | |
252 | bytes = buflen; | |
253 | else if (bufmin) | |
254 | bytes = roundup(size - wrote, bufmin); | |
255 | else | |
256 | bytes = size - wrote; | |
257 | ||
258 | len = write(fd, buf, bytes); | |
259 | ||
260 | if (len < 0) { | |
261 | perror(argv[optind]); | |
262 | unlink(argv[optind]); | |
263 | errs++; | |
264 | break; | |
265 | } | |
266 | ||
267 | wrote += len; | |
268 | } | |
269 | ||
270 | if (wrote > size && ftruncate64(fd, size) < 0) { | |
271 | perror(argv[optind]); | |
272 | unlink(argv[optind]); | |
273 | errs++; | |
274 | } | |
275 | } | |
276 | ||
277 | if ( close(fd) < 0 ) { | |
278 | perror(argv[optind]); | |
279 | unlink(argv[optind]); | |
280 | errs++; | |
281 | } | |
282 | ||
283 | optind++; | |
284 | } | |
285 | ||
286 | return errs != 0; | |
287 | } |