1*9f988b79SJean-Baptiste Boric /* $NetBSD: makefs.c,v 1.50 2013/08/05 14:41:57 reinoud Exp $ */
2*9f988b79SJean-Baptiste Boric
3*9f988b79SJean-Baptiste Boric /*
4*9f988b79SJean-Baptiste Boric * Copyright (c) 2001-2003 Wasabi Systems, Inc.
5*9f988b79SJean-Baptiste Boric * All rights reserved.
6*9f988b79SJean-Baptiste Boric *
7*9f988b79SJean-Baptiste Boric * Written by Luke Mewburn for Wasabi Systems, Inc.
8*9f988b79SJean-Baptiste Boric *
9*9f988b79SJean-Baptiste Boric * Redistribution and use in source and binary forms, with or without
10*9f988b79SJean-Baptiste Boric * modification, are permitted provided that the following conditions
11*9f988b79SJean-Baptiste Boric * are met:
12*9f988b79SJean-Baptiste Boric * 1. Redistributions of source code must retain the above copyright
13*9f988b79SJean-Baptiste Boric * notice, this list of conditions and the following disclaimer.
14*9f988b79SJean-Baptiste Boric * 2. Redistributions in binary form must reproduce the above copyright
15*9f988b79SJean-Baptiste Boric * notice, this list of conditions and the following disclaimer in the
16*9f988b79SJean-Baptiste Boric * documentation and/or other materials provided with the distribution.
17*9f988b79SJean-Baptiste Boric * 3. All advertising materials mentioning features or use of this software
18*9f988b79SJean-Baptiste Boric * must display the following acknowledgement:
19*9f988b79SJean-Baptiste Boric * This product includes software developed for the NetBSD Project by
20*9f988b79SJean-Baptiste Boric * Wasabi Systems, Inc.
21*9f988b79SJean-Baptiste Boric * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22*9f988b79SJean-Baptiste Boric * or promote products derived from this software without specific prior
23*9f988b79SJean-Baptiste Boric * written permission.
24*9f988b79SJean-Baptiste Boric *
25*9f988b79SJean-Baptiste Boric * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26*9f988b79SJean-Baptiste Boric * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27*9f988b79SJean-Baptiste Boric * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28*9f988b79SJean-Baptiste Boric * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29*9f988b79SJean-Baptiste Boric * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30*9f988b79SJean-Baptiste Boric * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31*9f988b79SJean-Baptiste Boric * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32*9f988b79SJean-Baptiste Boric * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33*9f988b79SJean-Baptiste Boric * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34*9f988b79SJean-Baptiste Boric * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35*9f988b79SJean-Baptiste Boric * POSSIBILITY OF SUCH DAMAGE.
36*9f988b79SJean-Baptiste Boric */
37*9f988b79SJean-Baptiste Boric
38*9f988b79SJean-Baptiste Boric #if HAVE_NBTOOL_CONFIG_H
39*9f988b79SJean-Baptiste Boric #include "nbtool_config.h"
40*9f988b79SJean-Baptiste Boric #endif
41*9f988b79SJean-Baptiste Boric
42*9f988b79SJean-Baptiste Boric #include <sys/cdefs.h>
43*9f988b79SJean-Baptiste Boric #if defined(__RCSID) && !defined(__lint)
44*9f988b79SJean-Baptiste Boric __RCSID("$NetBSD: makefs.c,v 1.50 2013/08/05 14:41:57 reinoud Exp $");
45*9f988b79SJean-Baptiste Boric #endif /* !__lint */
46*9f988b79SJean-Baptiste Boric
47*9f988b79SJean-Baptiste Boric #include <assert.h>
48*9f988b79SJean-Baptiste Boric #include <ctype.h>
49*9f988b79SJean-Baptiste Boric #include <errno.h>
50*9f988b79SJean-Baptiste Boric #include <limits.h>
51*9f988b79SJean-Baptiste Boric #include <stdio.h>
52*9f988b79SJean-Baptiste Boric #include <stdlib.h>
53*9f988b79SJean-Baptiste Boric #include <string.h>
54*9f988b79SJean-Baptiste Boric #include <unistd.h>
55*9f988b79SJean-Baptiste Boric #include <stdbool.h>
56*9f988b79SJean-Baptiste Boric #include <util.h>
57*9f988b79SJean-Baptiste Boric
58*9f988b79SJean-Baptiste Boric #include "makefs.h"
59*9f988b79SJean-Baptiste Boric #include "mtree.h"
60*9f988b79SJean-Baptiste Boric #include "cd9660.h"
61*9f988b79SJean-Baptiste Boric
62*9f988b79SJean-Baptiste Boric /*
63*9f988b79SJean-Baptiste Boric * list of supported file systems and dispatch functions
64*9f988b79SJean-Baptiste Boric */
65*9f988b79SJean-Baptiste Boric typedef struct {
66*9f988b79SJean-Baptiste Boric const char *type;
67*9f988b79SJean-Baptiste Boric void (*prepare_options)(fsinfo_t *);
68*9f988b79SJean-Baptiste Boric int (*parse_options)(const char *, fsinfo_t *);
69*9f988b79SJean-Baptiste Boric void (*cleanup_options)(fsinfo_t *);
70*9f988b79SJean-Baptiste Boric void (*make_fs)(const char *, const char *, fsnode *,
71*9f988b79SJean-Baptiste Boric fsinfo_t *);
72*9f988b79SJean-Baptiste Boric } fstype_t;
73*9f988b79SJean-Baptiste Boric
74*9f988b79SJean-Baptiste Boric static fstype_t fstypes[] = {
75*9f988b79SJean-Baptiste Boric #define ENTRY(name) { \
76*9f988b79SJean-Baptiste Boric # name, name ## _prep_opts, name ## _parse_opts, \
77*9f988b79SJean-Baptiste Boric name ## _cleanup_opts, name ## _makefs \
78*9f988b79SJean-Baptiste Boric }
79*9f988b79SJean-Baptiste Boric ENTRY(ffs),
80*9f988b79SJean-Baptiste Boric ENTRY(cd9660),
81*9f988b79SJean-Baptiste Boric ENTRY(chfs),
82*9f988b79SJean-Baptiste Boric ENTRY(v7fs),
83*9f988b79SJean-Baptiste Boric ENTRY(msdos),
84*9f988b79SJean-Baptiste Boric ENTRY(udf),
85*9f988b79SJean-Baptiste Boric { .type = NULL },
86*9f988b79SJean-Baptiste Boric };
87*9f988b79SJean-Baptiste Boric
88*9f988b79SJean-Baptiste Boric u_int debug;
89*9f988b79SJean-Baptiste Boric struct timespec start_time;
90*9f988b79SJean-Baptiste Boric
91*9f988b79SJean-Baptiste Boric static fstype_t *get_fstype(const char *);
92*9f988b79SJean-Baptiste Boric static void usage(fstype_t *, fsinfo_t *) __dead;
93*9f988b79SJean-Baptiste Boric
94*9f988b79SJean-Baptiste Boric int
main(int argc,char * argv[])95*9f988b79SJean-Baptiste Boric main(int argc, char *argv[])
96*9f988b79SJean-Baptiste Boric {
97*9f988b79SJean-Baptiste Boric struct timeval start;
98*9f988b79SJean-Baptiste Boric fstype_t *fstype;
99*9f988b79SJean-Baptiste Boric fsinfo_t fsoptions;
100*9f988b79SJean-Baptiste Boric fsnode *root;
101*9f988b79SJean-Baptiste Boric int ch, i, len;
102*9f988b79SJean-Baptiste Boric char *specfile;
103*9f988b79SJean-Baptiste Boric
104*9f988b79SJean-Baptiste Boric setprogname(argv[0]);
105*9f988b79SJean-Baptiste Boric
106*9f988b79SJean-Baptiste Boric debug = 0;
107*9f988b79SJean-Baptiste Boric if ((fstype = get_fstype(DEFAULT_FSTYPE)) == NULL)
108*9f988b79SJean-Baptiste Boric errx(1, "Unknown default fs type `%s'.", DEFAULT_FSTYPE);
109*9f988b79SJean-Baptiste Boric
110*9f988b79SJean-Baptiste Boric /* set default fsoptions */
111*9f988b79SJean-Baptiste Boric (void)memset(&fsoptions, 0, sizeof(fsoptions));
112*9f988b79SJean-Baptiste Boric fsoptions.fd = -1;
113*9f988b79SJean-Baptiste Boric fsoptions.sectorsize = -1;
114*9f988b79SJean-Baptiste Boric
115*9f988b79SJean-Baptiste Boric if (fstype->prepare_options)
116*9f988b79SJean-Baptiste Boric fstype->prepare_options(&fsoptions);
117*9f988b79SJean-Baptiste Boric
118*9f988b79SJean-Baptiste Boric specfile = NULL;
119*9f988b79SJean-Baptiste Boric if (gettimeofday(&start, NULL) == -1)
120*9f988b79SJean-Baptiste Boric err(1, "Unable to get system time");
121*9f988b79SJean-Baptiste Boric
122*9f988b79SJean-Baptiste Boric start_time.tv_sec = start.tv_sec;
123*9f988b79SJean-Baptiste Boric start_time.tv_nsec = start.tv_usec * 1000;
124*9f988b79SJean-Baptiste Boric
125*9f988b79SJean-Baptiste Boric while ((ch = getopt(argc, argv, "B:b:d:f:F:M:m:N:O:o:rs:S:t:xZ")) != -1) {
126*9f988b79SJean-Baptiste Boric switch (ch) {
127*9f988b79SJean-Baptiste Boric
128*9f988b79SJean-Baptiste Boric case 'B':
129*9f988b79SJean-Baptiste Boric if (strcmp(optarg, "be") == 0 ||
130*9f988b79SJean-Baptiste Boric strcmp(optarg, "4321") == 0 ||
131*9f988b79SJean-Baptiste Boric strcmp(optarg, "big") == 0) {
132*9f988b79SJean-Baptiste Boric #if BYTE_ORDER == LITTLE_ENDIAN
133*9f988b79SJean-Baptiste Boric fsoptions.needswap = 1;
134*9f988b79SJean-Baptiste Boric #endif
135*9f988b79SJean-Baptiste Boric } else if (strcmp(optarg, "le") == 0 ||
136*9f988b79SJean-Baptiste Boric strcmp(optarg, "1234") == 0 ||
137*9f988b79SJean-Baptiste Boric strcmp(optarg, "little") == 0) {
138*9f988b79SJean-Baptiste Boric #if BYTE_ORDER == BIG_ENDIAN
139*9f988b79SJean-Baptiste Boric fsoptions.needswap = 1;
140*9f988b79SJean-Baptiste Boric #endif
141*9f988b79SJean-Baptiste Boric } else {
142*9f988b79SJean-Baptiste Boric warnx("Invalid endian `%s'.", optarg);
143*9f988b79SJean-Baptiste Boric usage(fstype, &fsoptions);
144*9f988b79SJean-Baptiste Boric }
145*9f988b79SJean-Baptiste Boric break;
146*9f988b79SJean-Baptiste Boric
147*9f988b79SJean-Baptiste Boric case 'b':
148*9f988b79SJean-Baptiste Boric len = strlen(optarg) - 1;
149*9f988b79SJean-Baptiste Boric if (optarg[len] == '%') {
150*9f988b79SJean-Baptiste Boric optarg[len] = '\0';
151*9f988b79SJean-Baptiste Boric fsoptions.freeblockpc =
152*9f988b79SJean-Baptiste Boric strsuftoll("free block percentage",
153*9f988b79SJean-Baptiste Boric optarg, 0, 99);
154*9f988b79SJean-Baptiste Boric } else {
155*9f988b79SJean-Baptiste Boric fsoptions.freeblocks =
156*9f988b79SJean-Baptiste Boric strsuftoll("free blocks",
157*9f988b79SJean-Baptiste Boric optarg, 0, LLONG_MAX);
158*9f988b79SJean-Baptiste Boric }
159*9f988b79SJean-Baptiste Boric break;
160*9f988b79SJean-Baptiste Boric
161*9f988b79SJean-Baptiste Boric case 'd':
162*9f988b79SJean-Baptiste Boric debug = strtoll(optarg, NULL, 0);
163*9f988b79SJean-Baptiste Boric break;
164*9f988b79SJean-Baptiste Boric
165*9f988b79SJean-Baptiste Boric case 'f':
166*9f988b79SJean-Baptiste Boric len = strlen(optarg) - 1;
167*9f988b79SJean-Baptiste Boric if (optarg[len] == '%') {
168*9f988b79SJean-Baptiste Boric optarg[len] = '\0';
169*9f988b79SJean-Baptiste Boric fsoptions.freefilepc =
170*9f988b79SJean-Baptiste Boric strsuftoll("free file percentage",
171*9f988b79SJean-Baptiste Boric optarg, 0, 99);
172*9f988b79SJean-Baptiste Boric } else {
173*9f988b79SJean-Baptiste Boric fsoptions.freefiles =
174*9f988b79SJean-Baptiste Boric strsuftoll("free files",
175*9f988b79SJean-Baptiste Boric optarg, 0, LLONG_MAX);
176*9f988b79SJean-Baptiste Boric }
177*9f988b79SJean-Baptiste Boric break;
178*9f988b79SJean-Baptiste Boric
179*9f988b79SJean-Baptiste Boric case 'F':
180*9f988b79SJean-Baptiste Boric specfile = optarg;
181*9f988b79SJean-Baptiste Boric break;
182*9f988b79SJean-Baptiste Boric
183*9f988b79SJean-Baptiste Boric case 'M':
184*9f988b79SJean-Baptiste Boric fsoptions.minsize =
185*9f988b79SJean-Baptiste Boric strsuftoll("minimum size", optarg, 1LL, LLONG_MAX);
186*9f988b79SJean-Baptiste Boric break;
187*9f988b79SJean-Baptiste Boric
188*9f988b79SJean-Baptiste Boric case 'N':
189*9f988b79SJean-Baptiste Boric if (! setup_getid(optarg))
190*9f988b79SJean-Baptiste Boric errx(1,
191*9f988b79SJean-Baptiste Boric "Unable to use user and group databases in `%s'",
192*9f988b79SJean-Baptiste Boric optarg);
193*9f988b79SJean-Baptiste Boric break;
194*9f988b79SJean-Baptiste Boric
195*9f988b79SJean-Baptiste Boric case 'm':
196*9f988b79SJean-Baptiste Boric fsoptions.maxsize =
197*9f988b79SJean-Baptiste Boric strsuftoll("maximum size", optarg, 1LL, LLONG_MAX);
198*9f988b79SJean-Baptiste Boric break;
199*9f988b79SJean-Baptiste Boric
200*9f988b79SJean-Baptiste Boric case 'O':
201*9f988b79SJean-Baptiste Boric fsoptions.offset =
202*9f988b79SJean-Baptiste Boric strsuftoll("offset", optarg, 0LL, LLONG_MAX);
203*9f988b79SJean-Baptiste Boric break;
204*9f988b79SJean-Baptiste Boric
205*9f988b79SJean-Baptiste Boric case 'o':
206*9f988b79SJean-Baptiste Boric {
207*9f988b79SJean-Baptiste Boric char *p;
208*9f988b79SJean-Baptiste Boric
209*9f988b79SJean-Baptiste Boric while ((p = strsep(&optarg, ",")) != NULL) {
210*9f988b79SJean-Baptiste Boric if (*p == '\0')
211*9f988b79SJean-Baptiste Boric errx(1, "Empty option");
212*9f988b79SJean-Baptiste Boric if (! fstype->parse_options(p, &fsoptions))
213*9f988b79SJean-Baptiste Boric usage(fstype, &fsoptions);
214*9f988b79SJean-Baptiste Boric }
215*9f988b79SJean-Baptiste Boric break;
216*9f988b79SJean-Baptiste Boric }
217*9f988b79SJean-Baptiste Boric
218*9f988b79SJean-Baptiste Boric case 'r':
219*9f988b79SJean-Baptiste Boric fsoptions.replace = 1;
220*9f988b79SJean-Baptiste Boric break;
221*9f988b79SJean-Baptiste Boric
222*9f988b79SJean-Baptiste Boric case 's':
223*9f988b79SJean-Baptiste Boric fsoptions.minsize = fsoptions.maxsize =
224*9f988b79SJean-Baptiste Boric strsuftoll("size", optarg, 1LL, LLONG_MAX);
225*9f988b79SJean-Baptiste Boric break;
226*9f988b79SJean-Baptiste Boric
227*9f988b79SJean-Baptiste Boric case 'S':
228*9f988b79SJean-Baptiste Boric fsoptions.sectorsize =
229*9f988b79SJean-Baptiste Boric (int)strsuftoll("sector size", optarg,
230*9f988b79SJean-Baptiste Boric 1LL, INT_MAX);
231*9f988b79SJean-Baptiste Boric break;
232*9f988b79SJean-Baptiste Boric
233*9f988b79SJean-Baptiste Boric case 't':
234*9f988b79SJean-Baptiste Boric /* Check current one and cleanup if necessary. */
235*9f988b79SJean-Baptiste Boric if (fstype->cleanup_options)
236*9f988b79SJean-Baptiste Boric fstype->cleanup_options(&fsoptions);
237*9f988b79SJean-Baptiste Boric fsoptions.fs_specific = NULL;
238*9f988b79SJean-Baptiste Boric if ((fstype = get_fstype(optarg)) == NULL)
239*9f988b79SJean-Baptiste Boric errx(1, "Unknown fs type `%s'.", optarg);
240*9f988b79SJean-Baptiste Boric fstype->prepare_options(&fsoptions);
241*9f988b79SJean-Baptiste Boric break;
242*9f988b79SJean-Baptiste Boric
243*9f988b79SJean-Baptiste Boric case 'x':
244*9f988b79SJean-Baptiste Boric fsoptions.onlyspec = 1;
245*9f988b79SJean-Baptiste Boric break;
246*9f988b79SJean-Baptiste Boric
247*9f988b79SJean-Baptiste Boric case 'Z':
248*9f988b79SJean-Baptiste Boric fsoptions.sparse = 1;
249*9f988b79SJean-Baptiste Boric break;
250*9f988b79SJean-Baptiste Boric
251*9f988b79SJean-Baptiste Boric case '?':
252*9f988b79SJean-Baptiste Boric default:
253*9f988b79SJean-Baptiste Boric usage(fstype, &fsoptions);
254*9f988b79SJean-Baptiste Boric /* NOTREACHED */
255*9f988b79SJean-Baptiste Boric
256*9f988b79SJean-Baptiste Boric }
257*9f988b79SJean-Baptiste Boric }
258*9f988b79SJean-Baptiste Boric if (debug) {
259*9f988b79SJean-Baptiste Boric printf("debug mask: 0x%08x\n", debug);
260*9f988b79SJean-Baptiste Boric printf("start time: %ld.%ld, %s",
261*9f988b79SJean-Baptiste Boric (long)start_time.tv_sec, (long)start_time.tv_nsec,
262*9f988b79SJean-Baptiste Boric ctime(&start_time.tv_sec));
263*9f988b79SJean-Baptiste Boric }
264*9f988b79SJean-Baptiste Boric argc -= optind;
265*9f988b79SJean-Baptiste Boric argv += optind;
266*9f988b79SJean-Baptiste Boric
267*9f988b79SJean-Baptiste Boric if (argc < 2)
268*9f988b79SJean-Baptiste Boric usage(fstype, &fsoptions);
269*9f988b79SJean-Baptiste Boric
270*9f988b79SJean-Baptiste Boric /* -x must be accompanied by -F */
271*9f988b79SJean-Baptiste Boric if (fsoptions.onlyspec != 0 && specfile == NULL)
272*9f988b79SJean-Baptiste Boric errx(1, "-x requires -F mtree-specfile.");
273*9f988b79SJean-Baptiste Boric
274*9f988b79SJean-Baptiste Boric /* walk the tree */
275*9f988b79SJean-Baptiste Boric TIMER_START(start);
276*9f988b79SJean-Baptiste Boric root = walk_dir(argv[1], ".", NULL, NULL, fsoptions.replace);
277*9f988b79SJean-Baptiste Boric TIMER_RESULTS(start, "walk_dir");
278*9f988b79SJean-Baptiste Boric
279*9f988b79SJean-Baptiste Boric /* append extra directory */
280*9f988b79SJean-Baptiste Boric for (i = 2; i < argc; i++) {
281*9f988b79SJean-Baptiste Boric struct stat sb;
282*9f988b79SJean-Baptiste Boric if (stat(argv[i], &sb) == -1)
283*9f988b79SJean-Baptiste Boric err(1, "Can't stat `%s'", argv[i]);
284*9f988b79SJean-Baptiste Boric if (!S_ISDIR(sb.st_mode))
285*9f988b79SJean-Baptiste Boric errx(1, "%s: not a directory", argv[i]);
286*9f988b79SJean-Baptiste Boric TIMER_START(start);
287*9f988b79SJean-Baptiste Boric root = walk_dir(argv[i], ".", NULL, root, fsoptions.replace);
288*9f988b79SJean-Baptiste Boric TIMER_RESULTS(start, "walk_dir2");
289*9f988b79SJean-Baptiste Boric }
290*9f988b79SJean-Baptiste Boric
291*9f988b79SJean-Baptiste Boric if (specfile) { /* apply a specfile */
292*9f988b79SJean-Baptiste Boric TIMER_START(start);
293*9f988b79SJean-Baptiste Boric apply_specfile(specfile, argv[1], root, fsoptions.onlyspec);
294*9f988b79SJean-Baptiste Boric TIMER_RESULTS(start, "apply_specfile");
295*9f988b79SJean-Baptiste Boric }
296*9f988b79SJean-Baptiste Boric
297*9f988b79SJean-Baptiste Boric if (debug & DEBUG_DUMP_FSNODES) {
298*9f988b79SJean-Baptiste Boric printf("\nparent: %s\n", argv[1]);
299*9f988b79SJean-Baptiste Boric dump_fsnodes(root);
300*9f988b79SJean-Baptiste Boric putchar('\n');
301*9f988b79SJean-Baptiste Boric }
302*9f988b79SJean-Baptiste Boric
303*9f988b79SJean-Baptiste Boric /* build the file system */
304*9f988b79SJean-Baptiste Boric TIMER_START(start);
305*9f988b79SJean-Baptiste Boric fstype->make_fs(argv[0], argv[1], root, &fsoptions);
306*9f988b79SJean-Baptiste Boric TIMER_RESULTS(start, "make_fs");
307*9f988b79SJean-Baptiste Boric
308*9f988b79SJean-Baptiste Boric free_fsnodes(root);
309*9f988b79SJean-Baptiste Boric
310*9f988b79SJean-Baptiste Boric exit(0);
311*9f988b79SJean-Baptiste Boric /* NOTREACHED */
312*9f988b79SJean-Baptiste Boric }
313*9f988b79SJean-Baptiste Boric
314*9f988b79SJean-Baptiste Boric int
set_option(const option_t * options,const char * option,char * buf,size_t len)315*9f988b79SJean-Baptiste Boric set_option(const option_t *options, const char *option, char *buf, size_t len)
316*9f988b79SJean-Baptiste Boric {
317*9f988b79SJean-Baptiste Boric char *var, *val;
318*9f988b79SJean-Baptiste Boric int retval;
319*9f988b79SJean-Baptiste Boric
320*9f988b79SJean-Baptiste Boric assert(option != NULL);
321*9f988b79SJean-Baptiste Boric
322*9f988b79SJean-Baptiste Boric var = estrdup(option);
323*9f988b79SJean-Baptiste Boric for (val = var; *val; val++)
324*9f988b79SJean-Baptiste Boric if (*val == '=') {
325*9f988b79SJean-Baptiste Boric *val++ = '\0';
326*9f988b79SJean-Baptiste Boric break;
327*9f988b79SJean-Baptiste Boric }
328*9f988b79SJean-Baptiste Boric retval = set_option_var(options, var, val, buf, len);
329*9f988b79SJean-Baptiste Boric free(var);
330*9f988b79SJean-Baptiste Boric return retval;
331*9f988b79SJean-Baptiste Boric }
332*9f988b79SJean-Baptiste Boric
333*9f988b79SJean-Baptiste Boric int
set_option_var(const option_t * options,const char * var,const char * val,char * buf,size_t len)334*9f988b79SJean-Baptiste Boric set_option_var(const option_t *options, const char *var, const char *val,
335*9f988b79SJean-Baptiste Boric char *buf, size_t len)
336*9f988b79SJean-Baptiste Boric {
337*9f988b79SJean-Baptiste Boric char *s;
338*9f988b79SJean-Baptiste Boric size_t i;
339*9f988b79SJean-Baptiste Boric
340*9f988b79SJean-Baptiste Boric #define NUM(type) \
341*9f988b79SJean-Baptiste Boric if (!*val) { \
342*9f988b79SJean-Baptiste Boric *(type *)options[i].value = 1; \
343*9f988b79SJean-Baptiste Boric break; \
344*9f988b79SJean-Baptiste Boric } \
345*9f988b79SJean-Baptiste Boric *(type *)options[i].value = (type)strsuftoll(options[i].desc, val, \
346*9f988b79SJean-Baptiste Boric options[i].minimum, options[i].maximum); break
347*9f988b79SJean-Baptiste Boric
348*9f988b79SJean-Baptiste Boric for (i = 0; options[i].name != NULL; i++) {
349*9f988b79SJean-Baptiste Boric if (var[1] == '\0') {
350*9f988b79SJean-Baptiste Boric if (options[i].letter != var[0])
351*9f988b79SJean-Baptiste Boric continue;
352*9f988b79SJean-Baptiste Boric } else if (strcmp(options[i].name, var) != 0)
353*9f988b79SJean-Baptiste Boric continue;
354*9f988b79SJean-Baptiste Boric switch (options[i].type) {
355*9f988b79SJean-Baptiste Boric case OPT_BOOL:
356*9f988b79SJean-Baptiste Boric *(bool *)options[i].value = 1;
357*9f988b79SJean-Baptiste Boric break;
358*9f988b79SJean-Baptiste Boric case OPT_STRARRAY:
359*9f988b79SJean-Baptiste Boric strlcpy((void *)options[i].value, val, (size_t)
360*9f988b79SJean-Baptiste Boric options[i].maximum);
361*9f988b79SJean-Baptiste Boric break;
362*9f988b79SJean-Baptiste Boric case OPT_STRPTR:
363*9f988b79SJean-Baptiste Boric s = estrdup(val);
364*9f988b79SJean-Baptiste Boric *(char **)options[i].value = s;
365*9f988b79SJean-Baptiste Boric break;
366*9f988b79SJean-Baptiste Boric case OPT_STRBUF:
367*9f988b79SJean-Baptiste Boric if (buf == NULL)
368*9f988b79SJean-Baptiste Boric abort();
369*9f988b79SJean-Baptiste Boric strlcpy(buf, val, len);
370*9f988b79SJean-Baptiste Boric break;
371*9f988b79SJean-Baptiste Boric case OPT_INT64:
372*9f988b79SJean-Baptiste Boric NUM(uint64_t);
373*9f988b79SJean-Baptiste Boric case OPT_INT32:
374*9f988b79SJean-Baptiste Boric NUM(uint32_t);
375*9f988b79SJean-Baptiste Boric case OPT_INT16:
376*9f988b79SJean-Baptiste Boric NUM(uint16_t);
377*9f988b79SJean-Baptiste Boric case OPT_INT8:
378*9f988b79SJean-Baptiste Boric NUM(uint8_t);
379*9f988b79SJean-Baptiste Boric default:
380*9f988b79SJean-Baptiste Boric warnx("Unknown type %d in option %s", options[i].type,
381*9f988b79SJean-Baptiste Boric val);
382*9f988b79SJean-Baptiste Boric return 0;
383*9f988b79SJean-Baptiste Boric }
384*9f988b79SJean-Baptiste Boric return i;
385*9f988b79SJean-Baptiste Boric }
386*9f988b79SJean-Baptiste Boric warnx("Unknown option `%s'", var);
387*9f988b79SJean-Baptiste Boric return -1;
388*9f988b79SJean-Baptiste Boric }
389*9f988b79SJean-Baptiste Boric
390*9f988b79SJean-Baptiste Boric
391*9f988b79SJean-Baptiste Boric static fstype_t *
get_fstype(const char * type)392*9f988b79SJean-Baptiste Boric get_fstype(const char *type)
393*9f988b79SJean-Baptiste Boric {
394*9f988b79SJean-Baptiste Boric int i;
395*9f988b79SJean-Baptiste Boric
396*9f988b79SJean-Baptiste Boric for (i = 0; fstypes[i].type != NULL; i++)
397*9f988b79SJean-Baptiste Boric if (strcmp(fstypes[i].type, type) == 0)
398*9f988b79SJean-Baptiste Boric return (&fstypes[i]);
399*9f988b79SJean-Baptiste Boric return (NULL);
400*9f988b79SJean-Baptiste Boric }
401*9f988b79SJean-Baptiste Boric
402*9f988b79SJean-Baptiste Boric option_t *
copy_opts(const option_t * o)403*9f988b79SJean-Baptiste Boric copy_opts(const option_t *o)
404*9f988b79SJean-Baptiste Boric {
405*9f988b79SJean-Baptiste Boric size_t i;
406*9f988b79SJean-Baptiste Boric for (i = 0; o[i].name; i++)
407*9f988b79SJean-Baptiste Boric continue;
408*9f988b79SJean-Baptiste Boric i++;
409*9f988b79SJean-Baptiste Boric return memcpy(ecalloc(i, sizeof(*o)), o, i * sizeof(*o));
410*9f988b79SJean-Baptiste Boric }
411*9f988b79SJean-Baptiste Boric
412*9f988b79SJean-Baptiste Boric static void
usage(fstype_t * fstype,fsinfo_t * fsoptions)413*9f988b79SJean-Baptiste Boric usage(fstype_t *fstype, fsinfo_t *fsoptions)
414*9f988b79SJean-Baptiste Boric {
415*9f988b79SJean-Baptiste Boric const char *prog;
416*9f988b79SJean-Baptiste Boric
417*9f988b79SJean-Baptiste Boric prog = getprogname();
418*9f988b79SJean-Baptiste Boric fprintf(stderr,
419*9f988b79SJean-Baptiste Boric "Usage: %s [-rxZ] [-B endian] [-b free-blocks] [-d debug-mask]\n"
420*9f988b79SJean-Baptiste Boric "\t[-F mtree-specfile] [-f free-files] [-M minimum-size] [-m maximum-size]\n"
421*9f988b79SJean-Baptiste Boric "\t[-N userdb-dir] [-O offset] [-o fs-options] [-S sector-size]\n"
422*9f988b79SJean-Baptiste Boric "\t[-s image-size] [-t fs-type] image-file directory [extra-directory ...]\n",
423*9f988b79SJean-Baptiste Boric prog);
424*9f988b79SJean-Baptiste Boric
425*9f988b79SJean-Baptiste Boric if (fstype) {
426*9f988b79SJean-Baptiste Boric size_t i;
427*9f988b79SJean-Baptiste Boric option_t *o = fsoptions->fs_options;
428*9f988b79SJean-Baptiste Boric
429*9f988b79SJean-Baptiste Boric fprintf(stderr, "\n%s specific options:\n", fstype->type);
430*9f988b79SJean-Baptiste Boric for (i = 0; o[i].name != NULL; i++)
431*9f988b79SJean-Baptiste Boric fprintf(stderr, "\t%c%c%20.20s\t%s\n",
432*9f988b79SJean-Baptiste Boric o[i].letter ? o[i].letter : ' ',
433*9f988b79SJean-Baptiste Boric o[i].letter ? ',' : ' ',
434*9f988b79SJean-Baptiste Boric o[i].name, o[i].desc);
435*9f988b79SJean-Baptiste Boric }
436*9f988b79SJean-Baptiste Boric exit(1);
437*9f988b79SJean-Baptiste Boric }
438