15978408cSSascha Wildner /* $NetBSD: makefs.c,v 1.26 2006/10/22 21:11:56 christos Exp $ */
25978408cSSascha Wildner
35978408cSSascha Wildner /*-
45978408cSSascha Wildner * SPDX-License-Identifier: BSD-4-Clause
55978408cSSascha Wildner *
65978408cSSascha Wildner * Copyright (c) 2001-2003 Wasabi Systems, Inc.
75978408cSSascha Wildner * All rights reserved.
85978408cSSascha Wildner *
95978408cSSascha Wildner * Written by Luke Mewburn for Wasabi Systems, Inc.
105978408cSSascha Wildner *
115978408cSSascha Wildner * Redistribution and use in source and binary forms, with or without
125978408cSSascha Wildner * modification, are permitted provided that the following conditions
135978408cSSascha Wildner * are met:
145978408cSSascha Wildner * 1. Redistributions of source code must retain the above copyright
155978408cSSascha Wildner * notice, this list of conditions and the following disclaimer.
165978408cSSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright
175978408cSSascha Wildner * notice, this list of conditions and the following disclaimer in the
185978408cSSascha Wildner * documentation and/or other materials provided with the distribution.
195978408cSSascha Wildner * 3. All advertising materials mentioning features or use of this software
205978408cSSascha Wildner * must display the following acknowledgement:
215978408cSSascha Wildner * This product includes software developed for the NetBSD Project by
225978408cSSascha Wildner * Wasabi Systems, Inc.
235978408cSSascha Wildner * 4. The name of Wasabi Systems, Inc. may not be used to endorse
245978408cSSascha Wildner * or promote products derived from this software without specific prior
255978408cSSascha Wildner * written permission.
265978408cSSascha Wildner *
275978408cSSascha Wildner * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
285978408cSSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
295978408cSSascha Wildner * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
305978408cSSascha Wildner * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
315978408cSSascha Wildner * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
325978408cSSascha Wildner * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
335978408cSSascha Wildner * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
345978408cSSascha Wildner * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
355978408cSSascha Wildner * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
365978408cSSascha Wildner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
375978408cSSascha Wildner * POSSIBILITY OF SUCH DAMAGE.
38811c2036SSascha Wildner *
39811c2036SSascha Wildner * $FreeBSD: head/usr.sbin/makefs/makefs.c 326276 2017-11-27 15:37:16Z pfg $
405978408cSSascha Wildner */
415978408cSSascha Wildner
425978408cSSascha Wildner #include <sys/types.h>
435978408cSSascha Wildner #include <sys/stat.h>
445978408cSSascha Wildner #include <assert.h>
455978408cSSascha Wildner #include <ctype.h>
465978408cSSascha Wildner #include <errno.h>
475978408cSSascha Wildner #include <limits.h>
485978408cSSascha Wildner #include <stdio.h>
495978408cSSascha Wildner #include <stdlib.h>
505978408cSSascha Wildner #include <string.h>
515978408cSSascha Wildner #include <time.h>
525978408cSSascha Wildner #include <unistd.h>
535978408cSSascha Wildner #include <stdbool.h>
545978408cSSascha Wildner #include <util.h>
555978408cSSascha Wildner
565978408cSSascha Wildner #include "makefs.h"
575978408cSSascha Wildner #include "mtree.h"
585978408cSSascha Wildner
595978408cSSascha Wildner /*
605978408cSSascha Wildner * list of supported file systems and dispatch functions
615978408cSSascha Wildner */
625978408cSSascha Wildner typedef struct {
635978408cSSascha Wildner const char *type;
645978408cSSascha Wildner void (*prepare_options)(fsinfo_t *);
655978408cSSascha Wildner int (*parse_options)(const char *, fsinfo_t *);
665978408cSSascha Wildner void (*cleanup_options)(fsinfo_t *);
675978408cSSascha Wildner void (*make_fs)(const char *, const char *, fsnode *,
685978408cSSascha Wildner fsinfo_t *);
695978408cSSascha Wildner } fstype_t;
705978408cSSascha Wildner
715978408cSSascha Wildner static fstype_t fstypes[] = {
725978408cSSascha Wildner #define ENTRY(name) { \
735978408cSSascha Wildner # name, name ## _prep_opts, name ## _parse_opts, \
745978408cSSascha Wildner name ## _cleanup_opts, name ## _makefs \
755978408cSSascha Wildner }
765978408cSSascha Wildner ENTRY(ffs),
775978408cSSascha Wildner ENTRY(cd9660),
7820f6ddd0STomohiro Kusumi ENTRY(msdos),
792d60b848STomohiro Kusumi ENTRY(hammer2),
805978408cSSascha Wildner { .type = NULL },
815978408cSSascha Wildner };
825978408cSSascha Wildner
835978408cSSascha Wildner u_int debug;
845978408cSSascha Wildner int dupsok;
855978408cSSascha Wildner struct timespec start_time;
865978408cSSascha Wildner struct stat stampst;
875978408cSSascha Wildner
885978408cSSascha Wildner static fstype_t *get_fstype(const char *);
895978408cSSascha Wildner static int get_tstamp(const char *, struct stat *);
905978408cSSascha Wildner static void usage(fstype_t *, fsinfo_t *);
915978408cSSascha Wildner
925978408cSSascha Wildner int
main(int argc,char * argv[])935978408cSSascha Wildner main(int argc, char *argv[])
945978408cSSascha Wildner {
955978408cSSascha Wildner struct stat sb;
965978408cSSascha Wildner struct timeval start;
975978408cSSascha Wildner fstype_t *fstype;
985978408cSSascha Wildner fsinfo_t fsoptions;
99a63188c8STomohiro Kusumi fsnode *root = NULL;
1005978408cSSascha Wildner int ch, i, len;
101*70e962f7STomohiro Kusumi const char *subtree = NULL;
1025978408cSSascha Wildner const char *specfile;
1035978408cSSascha Wildner
1045978408cSSascha Wildner setprogname(argv[0]);
1055978408cSSascha Wildner
1065978408cSSascha Wildner debug = 0;
1075978408cSSascha Wildner if ((fstype = get_fstype(DEFAULT_FSTYPE)) == NULL)
1085978408cSSascha Wildner errx(1, "Unknown default fs type `%s'.", DEFAULT_FSTYPE);
1095978408cSSascha Wildner
1105978408cSSascha Wildner /* set default fsoptions */
1115978408cSSascha Wildner (void)memset(&fsoptions, 0, sizeof(fsoptions));
1125978408cSSascha Wildner fsoptions.fd = -1;
1135978408cSSascha Wildner fsoptions.sectorsize = -1;
1145978408cSSascha Wildner
1155978408cSSascha Wildner if (fstype->prepare_options)
1165978408cSSascha Wildner fstype->prepare_options(&fsoptions);
1175978408cSSascha Wildner
1185978408cSSascha Wildner specfile = NULL;
1195978408cSSascha Wildner #ifdef CLOCK_REALTIME
1205978408cSSascha Wildner ch = clock_gettime(CLOCK_REALTIME, &start_time);
1215978408cSSascha Wildner #else
1225978408cSSascha Wildner ch = gettimeofday(&start, NULL);
1235978408cSSascha Wildner start_time.tv_sec = start.tv_sec;
1245978408cSSascha Wildner start_time.tv_nsec = start.tv_usec * 1000;
1255978408cSSascha Wildner #endif
1265978408cSSascha Wildner if (ch == -1)
1275978408cSSascha Wildner err(1, "Unable to get system time");
1285978408cSSascha Wildner
1295978408cSSascha Wildner
1305978408cSSascha Wildner while ((ch = getopt(argc, argv, "B:b:Dd:f:F:M:m:N:O:o:pR:s:S:t:T:xZ")) != -1) {
1315978408cSSascha Wildner switch (ch) {
1325978408cSSascha Wildner
1335978408cSSascha Wildner case 'B':
1345978408cSSascha Wildner if (strcmp(optarg, "be") == 0 ||
1355978408cSSascha Wildner strcmp(optarg, "4321") == 0 ||
1365978408cSSascha Wildner strcmp(optarg, "big") == 0) {
1375978408cSSascha Wildner #if BYTE_ORDER == LITTLE_ENDIAN
1385978408cSSascha Wildner fsoptions.needswap = 1;
1395978408cSSascha Wildner #endif
1405978408cSSascha Wildner } else if (strcmp(optarg, "le") == 0 ||
1415978408cSSascha Wildner strcmp(optarg, "1234") == 0 ||
1425978408cSSascha Wildner strcmp(optarg, "little") == 0) {
1435978408cSSascha Wildner #if BYTE_ORDER == BIG_ENDIAN
1445978408cSSascha Wildner fsoptions.needswap = 1;
1455978408cSSascha Wildner #endif
1465978408cSSascha Wildner } else {
1475978408cSSascha Wildner warnx("Invalid endian `%s'.", optarg);
1485978408cSSascha Wildner usage(fstype, &fsoptions);
1495978408cSSascha Wildner }
1505978408cSSascha Wildner break;
1515978408cSSascha Wildner
1525978408cSSascha Wildner case 'b':
1535978408cSSascha Wildner len = strlen(optarg) - 1;
1545978408cSSascha Wildner if (optarg[len] == '%') {
1555978408cSSascha Wildner optarg[len] = '\0';
1565978408cSSascha Wildner fsoptions.freeblockpc =
1575978408cSSascha Wildner strsuftoll("free block percentage",
1585978408cSSascha Wildner optarg, 0, 99);
1595978408cSSascha Wildner } else {
1605978408cSSascha Wildner fsoptions.freeblocks =
1615978408cSSascha Wildner strsuftoll("free blocks",
1625978408cSSascha Wildner optarg, 0, LLONG_MAX);
1635978408cSSascha Wildner }
1645978408cSSascha Wildner break;
1655978408cSSascha Wildner
1665978408cSSascha Wildner case 'D':
1675978408cSSascha Wildner dupsok = 1;
1685978408cSSascha Wildner break;
1695978408cSSascha Wildner
1705978408cSSascha Wildner case 'd':
1715978408cSSascha Wildner debug = strtoll(optarg, NULL, 0);
1725978408cSSascha Wildner break;
1735978408cSSascha Wildner
1745978408cSSascha Wildner case 'f':
1755978408cSSascha Wildner len = strlen(optarg) - 1;
1765978408cSSascha Wildner if (optarg[len] == '%') {
1775978408cSSascha Wildner optarg[len] = '\0';
1785978408cSSascha Wildner fsoptions.freefilepc =
1795978408cSSascha Wildner strsuftoll("free file percentage",
1805978408cSSascha Wildner optarg, 0, 99);
1815978408cSSascha Wildner } else {
1825978408cSSascha Wildner fsoptions.freefiles =
1835978408cSSascha Wildner strsuftoll("free files",
1845978408cSSascha Wildner optarg, 0, LLONG_MAX);
1855978408cSSascha Wildner }
1865978408cSSascha Wildner break;
1875978408cSSascha Wildner
1885978408cSSascha Wildner case 'F':
1895978408cSSascha Wildner specfile = optarg;
1905978408cSSascha Wildner break;
1915978408cSSascha Wildner
1925978408cSSascha Wildner case 'M':
1935978408cSSascha Wildner fsoptions.minsize =
1945978408cSSascha Wildner strsuftoll("minimum size", optarg, 1LL, LLONG_MAX);
1955978408cSSascha Wildner break;
1965978408cSSascha Wildner
1975978408cSSascha Wildner case 'N':
1985978408cSSascha Wildner if (! setup_getid(optarg))
1995978408cSSascha Wildner errx(1,
2005978408cSSascha Wildner "Unable to use user and group databases in `%s'",
2015978408cSSascha Wildner optarg);
2025978408cSSascha Wildner break;
2035978408cSSascha Wildner
2045978408cSSascha Wildner case 'm':
2055978408cSSascha Wildner fsoptions.maxsize =
2065978408cSSascha Wildner strsuftoll("maximum size", optarg, 1LL, LLONG_MAX);
2075978408cSSascha Wildner break;
2085978408cSSascha Wildner
2095978408cSSascha Wildner case 'O':
2105978408cSSascha Wildner fsoptions.offset =
2115978408cSSascha Wildner strsuftoll("offset", optarg, 0LL, LLONG_MAX);
2125978408cSSascha Wildner break;
2135978408cSSascha Wildner
2145978408cSSascha Wildner case 'o':
2155978408cSSascha Wildner {
2165978408cSSascha Wildner char *p;
2175978408cSSascha Wildner
2185978408cSSascha Wildner while ((p = strsep(&optarg, ",")) != NULL) {
2195978408cSSascha Wildner if (*p == '\0')
2205978408cSSascha Wildner errx(1, "Empty option");
2215978408cSSascha Wildner if (! fstype->parse_options(p, &fsoptions))
2225978408cSSascha Wildner usage(fstype, &fsoptions);
2235978408cSSascha Wildner }
2245978408cSSascha Wildner break;
2255978408cSSascha Wildner }
2265978408cSSascha Wildner case 'p':
2275978408cSSascha Wildner /* Deprecated in favor of 'Z' */
2285978408cSSascha Wildner fsoptions.sparse = 1;
2295978408cSSascha Wildner break;
2305978408cSSascha Wildner
2315978408cSSascha Wildner case 'R':
2325978408cSSascha Wildner /* Round image size up to specified block size */
2335978408cSSascha Wildner fsoptions.roundup =
2345978408cSSascha Wildner strsuftoll("roundup-size", optarg, 0, LLONG_MAX);
2355978408cSSascha Wildner break;
2365978408cSSascha Wildner
2375978408cSSascha Wildner case 's':
2385978408cSSascha Wildner fsoptions.minsize = fsoptions.maxsize =
2395978408cSSascha Wildner strsuftoll("size", optarg, 1LL, LLONG_MAX);
2405978408cSSascha Wildner break;
2415978408cSSascha Wildner
2425978408cSSascha Wildner case 'S':
2435978408cSSascha Wildner fsoptions.sectorsize =
2445978408cSSascha Wildner (int)strsuftoll("sector size", optarg,
2455978408cSSascha Wildner 1LL, INT_MAX);
2465978408cSSascha Wildner break;
2475978408cSSascha Wildner
2485978408cSSascha Wildner case 't':
2495978408cSSascha Wildner /* Check current one and cleanup if necessary. */
2505978408cSSascha Wildner if (fstype->cleanup_options)
2515978408cSSascha Wildner fstype->cleanup_options(&fsoptions);
2525978408cSSascha Wildner fsoptions.fs_specific = NULL;
2535978408cSSascha Wildner if ((fstype = get_fstype(optarg)) == NULL)
2545978408cSSascha Wildner errx(1, "Unknown fs type `%s'.", optarg);
2555978408cSSascha Wildner fstype->prepare_options(&fsoptions);
2565978408cSSascha Wildner break;
2575978408cSSascha Wildner
2585978408cSSascha Wildner case 'T':
2595978408cSSascha Wildner if (get_tstamp(optarg, &stampst) == -1)
2605978408cSSascha Wildner errx(1, "Cannot get timestamp from `%s'",
2615978408cSSascha Wildner optarg);
2625978408cSSascha Wildner break;
2635978408cSSascha Wildner
2645978408cSSascha Wildner case 'x':
2655978408cSSascha Wildner fsoptions.onlyspec = 1;
2665978408cSSascha Wildner break;
2675978408cSSascha Wildner
2685978408cSSascha Wildner case 'Z':
2695978408cSSascha Wildner /* Superscedes 'p' for compatibility with NetBSD makefs(8) */
2705978408cSSascha Wildner fsoptions.sparse = 1;
2715978408cSSascha Wildner break;
2725978408cSSascha Wildner
2735978408cSSascha Wildner case '?':
2745978408cSSascha Wildner default:
2755978408cSSascha Wildner usage(fstype, &fsoptions);
2765978408cSSascha Wildner /* NOTREACHED */
2775978408cSSascha Wildner
2785978408cSSascha Wildner }
2795978408cSSascha Wildner }
2805978408cSSascha Wildner if (debug) {
2815978408cSSascha Wildner printf("debug mask: 0x%08x\n", debug);
2825978408cSSascha Wildner printf("start time: %ld.%ld, %s",
2835978408cSSascha Wildner (long)start_time.tv_sec, (long)start_time.tv_nsec,
2845978408cSSascha Wildner ctime(&start_time.tv_sec));
2855978408cSSascha Wildner }
2865978408cSSascha Wildner argc -= optind;
2875978408cSSascha Wildner argv += optind;
2885978408cSSascha Wildner
2895978408cSSascha Wildner if (argc < 2)
2905978408cSSascha Wildner usage(fstype, &fsoptions);
2915978408cSSascha Wildner
2925978408cSSascha Wildner /* -x must be accompanied by -F */
2935978408cSSascha Wildner if (fsoptions.onlyspec != 0 && specfile == NULL)
2945978408cSSascha Wildner errx(1, "-x requires -F mtree-specfile.");
2955978408cSSascha Wildner
2965978408cSSascha Wildner /* Accept '-' as meaning "read from standard input". */
297917508cdSTomohiro Kusumi /* DragonFly: Accept '--' as meaning none for HAMMER2 ioctl commands. */
298a63188c8STomohiro Kusumi if (strcmp(argv[1], "--") == 0) {
299a63188c8STomohiro Kusumi if (!strcmp(fstype->type, "hammer2"))
300a63188c8STomohiro Kusumi goto ignore_walk_dir;
301a63188c8STomohiro Kusumi else
302a63188c8STomohiro Kusumi errx(1, "%s: invalid argument", argv[1]);
303a63188c8STomohiro Kusumi } else if (strcmp(argv[1], "-") == 0) {
3045978408cSSascha Wildner sb.st_mode = S_IFREG;
305a63188c8STomohiro Kusumi } else {
3065978408cSSascha Wildner if (stat(argv[1], &sb) == -1)
3075978408cSSascha Wildner err(1, "Can't stat `%s'", argv[1]);
3085978408cSSascha Wildner }
3095978408cSSascha Wildner
3105978408cSSascha Wildner switch (sb.st_mode & S_IFMT) {
3115978408cSSascha Wildner case S_IFDIR: /* walk the tree */
3125978408cSSascha Wildner subtree = argv[1];
3135978408cSSascha Wildner TIMER_START(start);
3145978408cSSascha Wildner root = walk_dir(subtree, ".", NULL, NULL);
3155978408cSSascha Wildner TIMER_RESULTS(start, "walk_dir");
3165978408cSSascha Wildner break;
3175978408cSSascha Wildner case S_IFREG: /* read the manifest file */
3185978408cSSascha Wildner subtree = ".";
3195978408cSSascha Wildner TIMER_START(start);
3205978408cSSascha Wildner root = read_mtree(argv[1], NULL);
3215978408cSSascha Wildner TIMER_RESULTS(start, "manifest");
3225978408cSSascha Wildner break;
3235978408cSSascha Wildner default:
3245978408cSSascha Wildner errx(1, "%s: not a file or directory", argv[1]);
3255978408cSSascha Wildner /* NOTREACHED */
3265978408cSSascha Wildner }
3275978408cSSascha Wildner
3285978408cSSascha Wildner /* append extra directory */
3295978408cSSascha Wildner for (i = 2; i < argc; i++) {
3305978408cSSascha Wildner if (stat(argv[i], &sb) == -1)
3315978408cSSascha Wildner err(1, "Can't stat `%s'", argv[i]);
3325978408cSSascha Wildner if (!S_ISDIR(sb.st_mode))
3335978408cSSascha Wildner errx(1, "%s: not a directory", argv[i]);
3345978408cSSascha Wildner TIMER_START(start);
3355978408cSSascha Wildner root = walk_dir(argv[i], ".", NULL, root);
3365978408cSSascha Wildner TIMER_RESULTS(start, "walk_dir2");
3375978408cSSascha Wildner }
3385978408cSSascha Wildner
3395978408cSSascha Wildner if (specfile) { /* apply a specfile */
3405978408cSSascha Wildner TIMER_START(start);
3415978408cSSascha Wildner apply_specfile(specfile, subtree, root, fsoptions.onlyspec);
3425978408cSSascha Wildner TIMER_RESULTS(start, "apply_specfile");
3435978408cSSascha Wildner }
3445978408cSSascha Wildner
3455978408cSSascha Wildner if (debug & DEBUG_DUMP_FSNODES) {
3465978408cSSascha Wildner printf("\nparent: %s\n", subtree);
3475978408cSSascha Wildner dump_fsnodes(root);
3485978408cSSascha Wildner putchar('\n');
3495978408cSSascha Wildner }
350a63188c8STomohiro Kusumi ignore_walk_dir:
3515978408cSSascha Wildner /* build the file system */
3525978408cSSascha Wildner TIMER_START(start);
3535978408cSSascha Wildner fstype->make_fs(argv[0], subtree, root, &fsoptions);
3545978408cSSascha Wildner TIMER_RESULTS(start, "make_fs");
3555978408cSSascha Wildner
3565978408cSSascha Wildner free_fsnodes(root);
3575978408cSSascha Wildner
3585978408cSSascha Wildner exit(0);
3595978408cSSascha Wildner /* NOTREACHED */
3605978408cSSascha Wildner }
3615978408cSSascha Wildner
3625978408cSSascha Wildner int
set_option(const option_t * options,const char * option,char * buf,size_t len)3635978408cSSascha Wildner set_option(const option_t *options, const char *option, char *buf, size_t len)
3645978408cSSascha Wildner {
3655978408cSSascha Wildner char *var, *val;
3665978408cSSascha Wildner int retval;
3675978408cSSascha Wildner
3685978408cSSascha Wildner assert(option != NULL);
3695978408cSSascha Wildner
3705978408cSSascha Wildner var = estrdup(option);
3715978408cSSascha Wildner for (val = var; *val; val++)
3725978408cSSascha Wildner if (*val == '=') {
3735978408cSSascha Wildner *val++ = '\0';
3745978408cSSascha Wildner break;
3755978408cSSascha Wildner }
3765978408cSSascha Wildner retval = set_option_var(options, var, val, buf, len);
3775978408cSSascha Wildner free(var);
3785978408cSSascha Wildner return retval;
3795978408cSSascha Wildner }
3805978408cSSascha Wildner
3815978408cSSascha Wildner int
set_option_var(const option_t * options,const char * var,const char * val,char * buf,size_t len)3825978408cSSascha Wildner set_option_var(const option_t *options, const char *var, const char *val,
3835978408cSSascha Wildner char *buf, size_t len)
3845978408cSSascha Wildner {
3855978408cSSascha Wildner char *s;
3865978408cSSascha Wildner size_t i;
3875978408cSSascha Wildner
3885978408cSSascha Wildner #define NUM(type) \
3895978408cSSascha Wildner if (!*val) { \
3905978408cSSascha Wildner *(type *)options[i].value = 1; \
3915978408cSSascha Wildner break; \
3925978408cSSascha Wildner } \
3935978408cSSascha Wildner *(type *)options[i].value = (type)strsuftoll(options[i].desc, val, \
3945978408cSSascha Wildner options[i].minimum, options[i].maximum); break
3955978408cSSascha Wildner
3965978408cSSascha Wildner for (i = 0; options[i].name != NULL; i++) {
3975978408cSSascha Wildner if (var[1] == '\0') {
3985978408cSSascha Wildner if (options[i].letter != var[0])
3995978408cSSascha Wildner continue;
4005978408cSSascha Wildner } else if (strcmp(options[i].name, var) != 0)
4015978408cSSascha Wildner continue;
4025978408cSSascha Wildner switch (options[i].type) {
4035978408cSSascha Wildner case OPT_BOOL:
4045978408cSSascha Wildner *(bool *)options[i].value = 1;
4055978408cSSascha Wildner break;
4065978408cSSascha Wildner case OPT_STRARRAY:
4075978408cSSascha Wildner strlcpy((void *)options[i].value, val, (size_t)
4085978408cSSascha Wildner options[i].maximum);
4095978408cSSascha Wildner break;
4105978408cSSascha Wildner case OPT_STRPTR:
4115978408cSSascha Wildner s = estrdup(val);
4125978408cSSascha Wildner *(char **)options[i].value = s;
4135978408cSSascha Wildner break;
4145978408cSSascha Wildner case OPT_STRBUF:
4155978408cSSascha Wildner if (buf == NULL)
4165978408cSSascha Wildner abort();
4175978408cSSascha Wildner strlcpy(buf, val, len);
4185978408cSSascha Wildner break;
4195978408cSSascha Wildner case OPT_INT64:
4205978408cSSascha Wildner NUM(uint64_t);
4215978408cSSascha Wildner case OPT_INT32:
4225978408cSSascha Wildner NUM(uint32_t);
4235978408cSSascha Wildner case OPT_INT16:
4245978408cSSascha Wildner NUM(uint16_t);
4255978408cSSascha Wildner case OPT_INT8:
4265978408cSSascha Wildner NUM(uint8_t);
4275978408cSSascha Wildner default:
4285978408cSSascha Wildner warnx("Unknown type %d in option %s", options[i].type,
4295978408cSSascha Wildner val);
4305978408cSSascha Wildner return 0;
4315978408cSSascha Wildner }
4325978408cSSascha Wildner return i;
4335978408cSSascha Wildner }
4345978408cSSascha Wildner warnx("Unknown option `%s'", var);
4355978408cSSascha Wildner return -1;
4365978408cSSascha Wildner }
4375978408cSSascha Wildner
4385978408cSSascha Wildner
4395978408cSSascha Wildner static fstype_t *
get_fstype(const char * type)4405978408cSSascha Wildner get_fstype(const char *type)
4415978408cSSascha Wildner {
4425978408cSSascha Wildner int i;
4435978408cSSascha Wildner
4445978408cSSascha Wildner for (i = 0; fstypes[i].type != NULL; i++)
4455978408cSSascha Wildner if (strcmp(fstypes[i].type, type) == 0)
4465978408cSSascha Wildner return (&fstypes[i]);
4475978408cSSascha Wildner return (NULL);
4485978408cSSascha Wildner }
4495978408cSSascha Wildner
4505978408cSSascha Wildner option_t *
copy_opts(const option_t * o)4515978408cSSascha Wildner copy_opts(const option_t *o)
4525978408cSSascha Wildner {
4535978408cSSascha Wildner size_t i;
4545978408cSSascha Wildner
4555978408cSSascha Wildner for (i = 0; o[i].name; i++)
4565978408cSSascha Wildner continue;
4575978408cSSascha Wildner i++;
4585978408cSSascha Wildner return memcpy(ecalloc(i, sizeof(*o)), o, i * sizeof(*o));
4595978408cSSascha Wildner }
4605978408cSSascha Wildner
4615978408cSSascha Wildner static int
get_tstamp(const char * b,struct stat * st)4625978408cSSascha Wildner get_tstamp(const char *b, struct stat *st)
4635978408cSSascha Wildner {
4645978408cSSascha Wildner time_t when;
4655978408cSSascha Wildner char *eb;
4665978408cSSascha Wildner long long l;
4675978408cSSascha Wildner
4685978408cSSascha Wildner if (stat(b, st) != -1)
4695978408cSSascha Wildner return 0;
4705978408cSSascha Wildner
4715978408cSSascha Wildner {
4725978408cSSascha Wildner errno = 0;
4735978408cSSascha Wildner l = strtoll(b, &eb, 0);
4745978408cSSascha Wildner if (b == eb || *eb || errno)
4755978408cSSascha Wildner return -1;
4765978408cSSascha Wildner when = (time_t)l;
4775978408cSSascha Wildner }
4785978408cSSascha Wildner
4795978408cSSascha Wildner st->st_ino = 1;
480cdfb6d44SSascha Wildner #if HAVE_STRUCT_STAT_BIRTHTIME
4815978408cSSascha Wildner st->st_birthtime =
4825978408cSSascha Wildner #endif
4835978408cSSascha Wildner st->st_mtime = st->st_ctime = st->st_atime = when;
4845978408cSSascha Wildner return 0;
4855978408cSSascha Wildner }
4865978408cSSascha Wildner
4875978408cSSascha Wildner static void
usage(fstype_t * fstype,fsinfo_t * fsoptions)4885978408cSSascha Wildner usage(fstype_t *fstype, fsinfo_t *fsoptions)
4895978408cSSascha Wildner {
4905978408cSSascha Wildner const char *prog;
4915978408cSSascha Wildner
4925978408cSSascha Wildner prog = getprogname();
4935978408cSSascha Wildner fprintf(stderr,
4945978408cSSascha Wildner "Usage: %s [-xZ] [-B endian] [-b free-blocks] [-d debug-mask]\n"
4955978408cSSascha Wildner "\t[-F mtree-specfile] [-f free-files] [-M minimum-size] [-m maximum-size]\n"
4965978408cSSascha Wildner "\t[-N userdb-dir] [-O offset] [-o fs-options] [-R roundup-size]\n"
4975978408cSSascha Wildner "\t[-S sector-size] [-s image-size] [-T <timestamp/file>] [-t fs-type]\n"
4985978408cSSascha Wildner "\timage-file directory | manifest [extra-directory ...]\n",
4995978408cSSascha Wildner prog);
5005978408cSSascha Wildner
5015978408cSSascha Wildner if (fstype) {
5025978408cSSascha Wildner size_t i;
5035978408cSSascha Wildner option_t *o = fsoptions->fs_options;
5045978408cSSascha Wildner
5055978408cSSascha Wildner fprintf(stderr, "\n%s specific options:\n", fstype->type);
5065978408cSSascha Wildner for (i = 0; o[i].name != NULL; i++)
5075978408cSSascha Wildner fprintf(stderr, "\t%c%c%20.20s\t%s\n",
5085978408cSSascha Wildner o[i].letter ? o[i].letter : ' ',
5095978408cSSascha Wildner o[i].letter ? ',' : ' ',
5105978408cSSascha Wildner o[i].name, o[i].desc);
5115978408cSSascha Wildner }
5125978408cSSascha Wildner exit(1);
5135978408cSSascha Wildner }
514