1d347a0daSSam Leffler /* $NetBSD: makefs.c,v 1.20 2004/06/20 22:20:18 jmc Exp $ */ 2d347a0daSSam Leffler 3d347a0daSSam Leffler /* 4d347a0daSSam Leffler * Copyright (c) 2001-2003 Wasabi Systems, Inc. 5d347a0daSSam Leffler * All rights reserved. 6d347a0daSSam Leffler * 7d347a0daSSam Leffler * Written by Luke Mewburn for Wasabi Systems, Inc. 8d347a0daSSam Leffler * 9d347a0daSSam Leffler * Redistribution and use in source and binary forms, with or without 10d347a0daSSam Leffler * modification, are permitted provided that the following conditions 11d347a0daSSam Leffler * are met: 12d347a0daSSam Leffler * 1. Redistributions of source code must retain the above copyright 13d347a0daSSam Leffler * notice, this list of conditions and the following disclaimer. 14d347a0daSSam Leffler * 2. Redistributions in binary form must reproduce the above copyright 15d347a0daSSam Leffler * notice, this list of conditions and the following disclaimer in the 16d347a0daSSam Leffler * documentation and/or other materials provided with the distribution. 17d347a0daSSam Leffler * 3. All advertising materials mentioning features or use of this software 18d347a0daSSam Leffler * must display the following acknowledgement: 19d347a0daSSam Leffler * This product includes software developed for the NetBSD Project by 20d347a0daSSam Leffler * Wasabi Systems, Inc. 21d347a0daSSam Leffler * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22d347a0daSSam Leffler * or promote products derived from this software without specific prior 23d347a0daSSam Leffler * written permission. 24d347a0daSSam Leffler * 25d347a0daSSam Leffler * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26d347a0daSSam Leffler * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27d347a0daSSam Leffler * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28d347a0daSSam Leffler * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29d347a0daSSam Leffler * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30d347a0daSSam Leffler * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31d347a0daSSam Leffler * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32d347a0daSSam Leffler * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33d347a0daSSam Leffler * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34d347a0daSSam Leffler * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35d347a0daSSam Leffler * POSSIBILITY OF SUCH DAMAGE. 36d347a0daSSam Leffler */ 37d347a0daSSam Leffler 38d347a0daSSam Leffler #include <sys/cdefs.h> 39d347a0daSSam Leffler __FBSDID("$FreeBSD$"); 40d347a0daSSam Leffler 41d347a0daSSam Leffler #include <assert.h> 42d347a0daSSam Leffler #include <ctype.h> 43d347a0daSSam Leffler #include <errno.h> 44d347a0daSSam Leffler #include <limits.h> 45d347a0daSSam Leffler #include <stdio.h> 46d347a0daSSam Leffler #include <stdlib.h> 47d347a0daSSam Leffler #include <string.h> 48d347a0daSSam Leffler #include <unistd.h> 49d347a0daSSam Leffler 50d347a0daSSam Leffler #include "makefs.h" 51d347a0daSSam Leffler #include "mtree.h" 52d347a0daSSam Leffler 53d347a0daSSam Leffler /* 54d347a0daSSam Leffler * list of supported file systems and dispatch functions 55d347a0daSSam Leffler */ 56d347a0daSSam Leffler typedef struct { 57d347a0daSSam Leffler const char *type; 58d347a0daSSam Leffler int (*parse_options)(const char *, fsinfo_t *); 59d347a0daSSam Leffler void (*make_fs)(const char *, const char *, fsnode *, 60d347a0daSSam Leffler fsinfo_t *); 61d347a0daSSam Leffler } fstype_t; 62d347a0daSSam Leffler 63d347a0daSSam Leffler static fstype_t fstypes[] = { 64d347a0daSSam Leffler { "ffs", ffs_parse_opts, ffs_makefs }, 65d347a0daSSam Leffler { NULL }, 66d347a0daSSam Leffler }; 67d347a0daSSam Leffler 68d347a0daSSam Leffler u_int debug; 69d347a0daSSam Leffler struct timespec start_time; 70d347a0daSSam Leffler 71d347a0daSSam Leffler static fstype_t *get_fstype(const char *); 72d347a0daSSam Leffler static void usage(void); 73d347a0daSSam Leffler int main(int, char *[]); 74d347a0daSSam Leffler 75d347a0daSSam Leffler int 76d347a0daSSam Leffler main(int argc, char *argv[]) 77d347a0daSSam Leffler { 78d347a0daSSam Leffler struct timeval start; 79d347a0daSSam Leffler fstype_t *fstype; 80d347a0daSSam Leffler fsinfo_t fsoptions; 81d347a0daSSam Leffler fsnode *root; 82d347a0daSSam Leffler int ch, len; 83d347a0daSSam Leffler char *specfile; 84d347a0daSSam Leffler 85d347a0daSSam Leffler setprogname(argv[0]); 86d347a0daSSam Leffler 87d347a0daSSam Leffler debug = 0; 88d347a0daSSam Leffler if ((fstype = get_fstype(DEFAULT_FSTYPE)) == NULL) 89d347a0daSSam Leffler errx(1, "Unknown default fs type `%s'.", DEFAULT_FSTYPE); 90d347a0daSSam Leffler 91d347a0daSSam Leffler /* set default fsoptions */ 92d347a0daSSam Leffler (void)memset(&fsoptions, 0, sizeof(fsoptions)); 93d347a0daSSam Leffler fsoptions.fd = -1; 94d347a0daSSam Leffler fsoptions.sectorsize = -1; 95d347a0daSSam Leffler fsoptions.bsize= -1; 96d347a0daSSam Leffler fsoptions.fsize= -1; 97d347a0daSSam Leffler fsoptions.cpg= -1; 98d347a0daSSam Leffler fsoptions.density= -1; 99d347a0daSSam Leffler fsoptions.minfree= -1; 100d347a0daSSam Leffler fsoptions.optimization= -1; 101d347a0daSSam Leffler fsoptions.maxcontig= -1; 102d347a0daSSam Leffler fsoptions.maxbpg= -1; 103d347a0daSSam Leffler fsoptions.avgfilesize= -1; 104d347a0daSSam Leffler fsoptions.avgfpdir= -1; 105d347a0daSSam Leffler fsoptions.version = 1; 106d347a0daSSam Leffler 107d347a0daSSam Leffler specfile = NULL; 108d347a0daSSam Leffler if (gettimeofday(&start, NULL) == -1) 109d347a0daSSam Leffler err(1, "Unable to get system time"); 110d347a0daSSam Leffler 111d347a0daSSam Leffler start_time.tv_sec = start.tv_sec; 112d347a0daSSam Leffler start_time.tv_nsec = start.tv_usec * 1000; 113d347a0daSSam Leffler 114d347a0daSSam Leffler while ((ch = getopt(argc, argv, "B:b:d:f:F:M:m:N:o:s:S:t:x")) != -1) { 115d347a0daSSam Leffler switch (ch) { 116d347a0daSSam Leffler 117d347a0daSSam Leffler case 'B': 118d347a0daSSam Leffler if (strcmp(optarg, "be") == 0 || 119d347a0daSSam Leffler strcmp(optarg, "4321") == 0 || 120d347a0daSSam Leffler strcmp(optarg, "big") == 0) { 121d347a0daSSam Leffler #if BYTE_ORDER == LITTLE_ENDIAN 122d347a0daSSam Leffler fsoptions.needswap = 1; 123d347a0daSSam Leffler #endif 124d347a0daSSam Leffler } else if (strcmp(optarg, "le") == 0 || 125d347a0daSSam Leffler strcmp(optarg, "1234") == 0 || 126d347a0daSSam Leffler strcmp(optarg, "little") == 0) { 127d347a0daSSam Leffler #if BYTE_ORDER == BIG_ENDIAN 128d347a0daSSam Leffler fsoptions.needswap = 1; 129d347a0daSSam Leffler #endif 130d347a0daSSam Leffler } else { 131d347a0daSSam Leffler warnx("Invalid endian `%s'.", optarg); 132d347a0daSSam Leffler usage(); 133d347a0daSSam Leffler } 134d347a0daSSam Leffler break; 135d347a0daSSam Leffler 136d347a0daSSam Leffler case 'b': 137d347a0daSSam Leffler len = strlen(optarg) - 1; 138d347a0daSSam Leffler if (optarg[len] == '%') { 139d347a0daSSam Leffler optarg[len] = '\0'; 140d347a0daSSam Leffler fsoptions.freeblockpc = 141d347a0daSSam Leffler strsuftoll("free block percentage", 142d347a0daSSam Leffler optarg, 0, 99); 143d347a0daSSam Leffler } else { 144d347a0daSSam Leffler fsoptions.freeblocks = 145d347a0daSSam Leffler strsuftoll("free blocks", 146d347a0daSSam Leffler optarg, 0, LLONG_MAX); 147d347a0daSSam Leffler } 148d347a0daSSam Leffler break; 149d347a0daSSam Leffler 150d347a0daSSam Leffler case 'd': 151d347a0daSSam Leffler debug = 152d347a0daSSam Leffler (int)strsuftoll("debug mask", optarg, 0, UINT_MAX); 153d347a0daSSam Leffler break; 154d347a0daSSam Leffler 155d347a0daSSam Leffler case 'f': 156d347a0daSSam Leffler len = strlen(optarg) - 1; 157d347a0daSSam Leffler if (optarg[len] == '%') { 158d347a0daSSam Leffler optarg[len] = '\0'; 159d347a0daSSam Leffler fsoptions.freefilepc = 160d347a0daSSam Leffler strsuftoll("free file percentage", 161d347a0daSSam Leffler optarg, 0, 99); 162d347a0daSSam Leffler } else { 163d347a0daSSam Leffler fsoptions.freefiles = 164d347a0daSSam Leffler strsuftoll("free files", 165d347a0daSSam Leffler optarg, 0, LLONG_MAX); 166d347a0daSSam Leffler } 167d347a0daSSam Leffler break; 168d347a0daSSam Leffler 169d347a0daSSam Leffler case 'F': 170d347a0daSSam Leffler specfile = optarg; 171d347a0daSSam Leffler break; 172d347a0daSSam Leffler 173d347a0daSSam Leffler case 'M': 174d347a0daSSam Leffler fsoptions.minsize = 175d347a0daSSam Leffler strsuftoll("minimum size", optarg, 1LL, LLONG_MAX); 176d347a0daSSam Leffler break; 177d347a0daSSam Leffler 178d347a0daSSam Leffler case 'N': 179d347a0daSSam Leffler if (! setup_getid(optarg)) 180d347a0daSSam Leffler errx(1, 181d347a0daSSam Leffler "Unable to use user and group databases in `%s'", 182d347a0daSSam Leffler optarg); 183d347a0daSSam Leffler break; 184d347a0daSSam Leffler 185d347a0daSSam Leffler case 'm': 186d347a0daSSam Leffler fsoptions.maxsize = 187d347a0daSSam Leffler strsuftoll("maximum size", optarg, 1LL, LLONG_MAX); 188d347a0daSSam Leffler break; 189d347a0daSSam Leffler 190d347a0daSSam Leffler case 'o': 191d347a0daSSam Leffler { 192d347a0daSSam Leffler char *p; 193d347a0daSSam Leffler 194d347a0daSSam Leffler while ((p = strsep(&optarg, ",")) != NULL) { 195d347a0daSSam Leffler if (*p == '\0') 196d347a0daSSam Leffler errx(1, "Empty option"); 197d347a0daSSam Leffler if (! fstype->parse_options(p, &fsoptions)) 198d347a0daSSam Leffler usage(); 199d347a0daSSam Leffler } 200d347a0daSSam Leffler break; 201d347a0daSSam Leffler } 202d347a0daSSam Leffler 203d347a0daSSam Leffler case 's': 204d347a0daSSam Leffler fsoptions.minsize = fsoptions.maxsize = 205d347a0daSSam Leffler strsuftoll("size", optarg, 1LL, LLONG_MAX); 206d347a0daSSam Leffler break; 207d347a0daSSam Leffler 208d347a0daSSam Leffler case 'S': 209d347a0daSSam Leffler fsoptions.sectorsize = 210d347a0daSSam Leffler (int)strsuftoll("sector size", optarg, 211d347a0daSSam Leffler 1LL, INT_MAX); 212d347a0daSSam Leffler break; 213d347a0daSSam Leffler 214d347a0daSSam Leffler case 't': 215d347a0daSSam Leffler if ((fstype = get_fstype(optarg)) == NULL) 216d347a0daSSam Leffler errx(1, "Unknown fs type `%s'.", optarg); 217d347a0daSSam Leffler break; 218d347a0daSSam Leffler 219d347a0daSSam Leffler case 'x': 220d347a0daSSam Leffler fsoptions.onlyspec = 1; 221d347a0daSSam Leffler break; 222d347a0daSSam Leffler 223d347a0daSSam Leffler case '?': 224d347a0daSSam Leffler default: 225d347a0daSSam Leffler usage(); 226d347a0daSSam Leffler /* NOTREACHED */ 227d347a0daSSam Leffler 228d347a0daSSam Leffler } 229d347a0daSSam Leffler } 230d347a0daSSam Leffler if (debug) { 231d347a0daSSam Leffler printf("debug mask: 0x%08x\n", debug); 232d347a0daSSam Leffler printf("start time: %ld.%ld, %s", 233d347a0daSSam Leffler (long)start_time.tv_sec, (long)start_time.tv_nsec, 234d347a0daSSam Leffler ctime(&start_time.tv_sec)); 235d347a0daSSam Leffler } 236d347a0daSSam Leffler argc -= optind; 237d347a0daSSam Leffler argv += optind; 238d347a0daSSam Leffler 239d347a0daSSam Leffler if (argc != 2) 240d347a0daSSam Leffler usage(); 241d347a0daSSam Leffler 242d347a0daSSam Leffler /* -x must be accompanied by -F */ 243d347a0daSSam Leffler if (fsoptions.onlyspec != 0 && specfile == NULL) 244d347a0daSSam Leffler errx(1, "-x requires -F mtree-specfile."); 245d347a0daSSam Leffler 246d347a0daSSam Leffler /* walk the tree */ 247d347a0daSSam Leffler TIMER_START(start); 248d347a0daSSam Leffler root = walk_dir(argv[1], NULL); 249d347a0daSSam Leffler TIMER_RESULTS(start, "walk_dir"); 250d347a0daSSam Leffler 251d347a0daSSam Leffler if (specfile) { /* apply a specfile */ 252d347a0daSSam Leffler TIMER_START(start); 253d347a0daSSam Leffler apply_specfile(specfile, argv[1], root); 254d347a0daSSam Leffler TIMER_RESULTS(start, "apply_specfile"); 255d347a0daSSam Leffler } 256d347a0daSSam Leffler 257d347a0daSSam Leffler if (debug & DEBUG_DUMP_FSNODES) { 258d347a0daSSam Leffler printf("\nparent: %s\n", argv[1]); 259d347a0daSSam Leffler dump_fsnodes(".", root); 260d347a0daSSam Leffler putchar('\n'); 261d347a0daSSam Leffler } 262d347a0daSSam Leffler 263d347a0daSSam Leffler /* build the file system */ 264d347a0daSSam Leffler TIMER_START(start); 265d347a0daSSam Leffler fstype->make_fs(argv[0], argv[1], root, &fsoptions); 266d347a0daSSam Leffler TIMER_RESULTS(start, "make_fs"); 267d347a0daSSam Leffler 268d347a0daSSam Leffler exit(0); 269d347a0daSSam Leffler /* NOTREACHED */ 270d347a0daSSam Leffler } 271d347a0daSSam Leffler 272d347a0daSSam Leffler 273d347a0daSSam Leffler int 274d347a0daSSam Leffler set_option(option_t *options, const char *var, const char *val) 275d347a0daSSam Leffler { 276d347a0daSSam Leffler int i; 277d347a0daSSam Leffler 278d347a0daSSam Leffler for (i = 0; options[i].name != NULL; i++) { 279d347a0daSSam Leffler if (strcmp(options[i].name, var) != 0) 280d347a0daSSam Leffler continue; 281d347a0daSSam Leffler *options[i].value = (int)strsuftoll(options[i].desc, val, 282d347a0daSSam Leffler options[i].minimum, options[i].maximum); 283d347a0daSSam Leffler return (1); 284d347a0daSSam Leffler } 285d347a0daSSam Leffler warnx("Unknown option `%s'", var); 286d347a0daSSam Leffler return (0); 287d347a0daSSam Leffler } 288d347a0daSSam Leffler 289d347a0daSSam Leffler 290d347a0daSSam Leffler static fstype_t * 291d347a0daSSam Leffler get_fstype(const char *type) 292d347a0daSSam Leffler { 293d347a0daSSam Leffler int i; 294d347a0daSSam Leffler 295d347a0daSSam Leffler for (i = 0; fstypes[i].type != NULL; i++) 296d347a0daSSam Leffler if (strcmp(fstypes[i].type, type) == 0) 297d347a0daSSam Leffler return (&fstypes[i]); 298d347a0daSSam Leffler return (NULL); 299d347a0daSSam Leffler } 300d347a0daSSam Leffler 301d347a0daSSam Leffler static void 302d347a0daSSam Leffler usage(void) 303d347a0daSSam Leffler { 304d347a0daSSam Leffler const char *prog; 305d347a0daSSam Leffler 306d347a0daSSam Leffler prog = getprogname(); 307d347a0daSSam Leffler fprintf(stderr, 308d347a0daSSam Leffler "usage: %s [-t fs-type] [-o fs-options] [-d debug-mask] [-B endian]\n" 309d347a0daSSam Leffler "\t[-S sector-size] [-M minimum-size] [-m maximum-size] [-s image-size]\n" 310d347a0daSSam Leffler "\t[-b free-blocks] [-f free-files] [-F mtree-specfile] [-x]\n" 311d347a0daSSam Leffler "\t[-N userdb-dir] image-file directory\n", 312d347a0daSSam Leffler prog); 313d347a0daSSam Leffler exit(1); 314d347a0daSSam Leffler } 315