xref: /minix3/usr.sbin/makefs/makefs.c (revision 9f988b79349f9b89ecc822458c30ec8897558560)
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