]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 2000-2003 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 <ctype.h> | |
39 | ||
40 | #define MAXBUFFERSIZE (256 * 1024) | |
41 | ||
42 | static char *progname; | |
43 | ||
44 | static void | |
45 | usage(void) | |
46 | { | |
47 | fprintf(stderr, _("%s: [-npv] <size> <name1> [<name2>] ...\n"), | |
48 | progname); | |
49 | exit(2); | |
50 | } | |
51 | ||
52 | static int | |
53 | openfd(char *name, int oflags) | |
54 | { | |
55 | int fd; | |
56 | ||
57 | fd = open(name, oflags, 0600); | |
58 | if (fd < 0) { | |
59 | perror(name); | |
60 | return -1; | |
61 | } | |
62 | ||
63 | if (!platform_test_xfs_fd(fd)) { | |
64 | fprintf(stderr, _("%s: " | |
65 | "file [\"%s\"] is not on an XFS filesystem\n"), | |
66 | progname, name); | |
67 | return -1; | |
68 | } | |
69 | return fd; | |
70 | } | |
71 | ||
72 | int | |
73 | main(int argc, char **argv) | |
74 | { | |
75 | int fd; | |
76 | char *fname; | |
77 | loff_t result; | |
78 | loff_t size = 0; | |
79 | loff_t mult = 0; | |
80 | int bytes = 0; | |
81 | loff_t wrote = 0; | |
82 | int len = 0; | |
83 | int c; | |
84 | int errflg = 0; | |
85 | int errs = 0; | |
86 | int nobytes = 0; | |
87 | int prealloc = 0; | |
88 | int verbose = 0; | |
89 | struct dioattr da; | |
90 | void *buf = NULL; | |
91 | int buflen = 0, nbuflen; | |
92 | int bufalign = 0, nbufalign, bufmin; | |
93 | int oflags; | |
94 | xfs_flock64_t flck; | |
95 | ||
96 | progname = basename(argv[0]); | |
97 | setlocale(LC_ALL, ""); | |
98 | bindtextdomain(PACKAGE, LOCALEDIR); | |
99 | textdomain(PACKAGE); | |
100 | ||
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 | exit(0); | |
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((int)argv[optind][len-1])) { | |
129 | switch ((int)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 = strtoll(argv[optind], NULL, 10) * mult; | |
158 | ||
159 | optind++; | |
160 | ||
161 | while (optind < argc) { | |
162 | if (verbose) | |
163 | fprintf(stdout, _("%s %lld bytes %s\n"), | |
164 | argv[optind], (long long)size, | |
165 | prealloc | |
166 | ? _("(pre-allocated)") | |
167 | : ""); | |
168 | ||
169 | oflags = O_CREAT|O_TRUNC|O_WRONLY|(nobytes ? 0 : O_DIRECT); | |
170 | fname = argv[optind]; | |
171 | ||
172 | if ((fd = openfd(fname, oflags)) == -1) { | |
173 | optind++; | |
174 | errs++; | |
175 | continue; | |
176 | } | |
177 | ||
178 | if ( (oflags & O_DIRECT) | |
179 | && ( (fd < 0 && errno == EINVAL) | |
180 | || xfsctl(fname, fd, XFS_IOC_DIOINFO, &da) < 0)) { | |
181 | ||
182 | close(fd); | |
183 | ||
184 | oflags &= ~O_DIRECT; | |
185 | ||
186 | if ((fd = openfd(argv[optind], oflags)) == -1) { | |
187 | optind++; | |
188 | errs++; | |
189 | continue; | |
190 | } | |
191 | } | |
192 | ||
193 | if (size == 0) { | |
194 | close(fd); | |
195 | optind++; | |
196 | continue; | |
197 | } | |
198 | ||
199 | if ((result = lseek64(fd, size - 1, SEEK_SET)) < 0LL) { | |
200 | fprintf(stderr, _("lseek64 error, result = %lld\n"), | |
201 | (long long)result); | |
202 | if (errno) | |
203 | perror(argv[optind]); | |
204 | errs++; | |
205 | } else if (nobytes) { | |
206 | if (write(fd, "", 1) < 0) { | |
207 | perror(argv[optind]); | |
208 | errs++; | |
209 | } | |
210 | } else { | |
211 | flck.l_whence = SEEK_SET; | |
212 | flck.l_start = 0LL; | |
213 | flck.l_len = size; | |
214 | if (prealloc) | |
215 | xfsctl(fname, fd, XFS_IOC_RESVSP64, &flck); | |
216 | if (oflags & O_DIRECT) { | |
217 | nbufalign = da.d_mem; | |
218 | ||
219 | if ( da.d_miniosz <= MAXBUFFERSIZE | |
220 | && MAXBUFFERSIZE <= da.d_maxiosz) | |
221 | nbuflen = MAXBUFFERSIZE; | |
222 | else if (da.d_maxiosz < MAXBUFFERSIZE) | |
223 | nbuflen = da.d_maxiosz; | |
224 | else | |
225 | nbuflen = da.d_miniosz; | |
226 | ||
227 | bufmin = da.d_miniosz; | |
228 | } else { | |
229 | nbuflen = MAXBUFFERSIZE; | |
230 | nbufalign = sizeof(long); | |
231 | bufmin = 0; | |
232 | } | |
233 | ||
234 | if (nbuflen > buflen || nbufalign > bufalign) { | |
235 | if (buf) | |
236 | free(buf); | |
237 | buf = memalign(nbufalign, nbuflen); | |
238 | buflen = nbuflen; | |
239 | bzero(buf, nbuflen); | |
240 | nbufalign = bufalign; | |
241 | } | |
242 | ||
243 | wrote = 0; | |
244 | ||
245 | lseek64(fd, 0LL, SEEK_SET); | |
246 | ||
247 | while (wrote < size) { | |
248 | if (size - wrote >= buflen) | |
249 | bytes = buflen; | |
250 | else if (bufmin) | |
251 | bytes = roundup(size - wrote, bufmin); | |
252 | else | |
253 | bytes = size - wrote; | |
254 | ||
255 | len = write(fd, buf, bytes); | |
256 | ||
257 | if (len < 0) { | |
258 | perror(argv[optind]); | |
259 | unlink(argv[optind]); | |
260 | errs++; | |
261 | break; | |
262 | } | |
263 | ||
264 | wrote += len; | |
265 | } | |
266 | ||
267 | if (wrote > size && ftruncate64(fd, size) < 0) { | |
268 | perror(argv[optind]); | |
269 | unlink(argv[optind]); | |
270 | errs++; | |
271 | } | |
272 | } | |
273 | ||
274 | if ( close(fd) < 0 ) { | |
275 | perror(argv[optind]); | |
276 | unlink(argv[optind]); | |
277 | errs++; | |
278 | } | |
279 | ||
280 | optind++; | |
281 | } | |
282 | ||
283 | return errs != 0; | |
284 | } |