Home | History | Annotate | Line # | Download | only in newfs_msdos
newfs_msdos.c revision 1.36.2.3
      1 /*	$NetBSD: newfs_msdos.c,v 1.36.2.3 2013/01/23 00:05:32 yamt Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1998 Robert Nordier
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in
     14  *    the documentation and/or other materials provided with the
     15  *    distribution.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
     18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
     21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     23  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
     25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 #include <sys/cdefs.h>
     31 #ifndef lint
     32 #if 0
     33 static const char rcsid[] =
     34   "$FreeBSD: src/sbin/newfs_msdos/newfs_msdos.c,v 1.15 2000/10/10 01:49:37 wollman Exp $";
     35 #else
     36 __RCSID("$NetBSD: newfs_msdos.c,v 1.36.2.3 2013/01/23 00:05:32 yamt Exp $");
     37 #endif
     38 #endif /* not lint */
     39 
     40 #include <sys/param.h>
     41 #include <stdio.h>
     42 #include <string.h>
     43 #include <err.h>
     44 #include <stdlib.h>
     45 #include <unistd.h>
     46 #include <paths.h>
     47 #include <errno.h>
     48 
     49 #include "mkfs_msdos.h"
     50 
     51 #define argto1(arg, lo, msg)  argtou(arg, lo, 0xff, msg)
     52 #define argto2(arg, lo, msg)  argtou(arg, lo, 0xffff, msg)
     53 #define argto4(arg, lo, msg)  argtou(arg, lo, 0xffffffff, msg)
     54 #define argtox(arg, lo, msg)  argtou(arg, lo, UINT_MAX, msg)
     55 
     56 __dead static void usage(void);
     57 static u_int argtou(const char *, u_int, u_int, const char *);
     58 static off_t argtooff(const char *, const char *);
     59 
     60 /*
     61  * Construct a FAT12, FAT16, or FAT32 file system.
     62  */
     63 int
     64 main(int argc, char *argv[])
     65 {
     66     static const char opts[] = "@:NB:C:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:u:";
     67     struct msdos_options o;
     68     char *fname, *dtype;
     69     char buf[MAXPATHLEN];
     70     int ch;
     71 
     72     memset(&o, 0, sizeof(o));
     73 
     74     while ((ch = getopt(argc, argv, opts)) != -1)
     75 	switch (ch) {
     76 	case '@':
     77 	    o.offset = argtooff(optarg, "offset");
     78 	    break;
     79 	case 'N':
     80 	    o.no_create = 1;
     81 	    break;
     82 	case 'B':
     83 	    o.bootstrap = optarg;
     84 	    break;
     85 	case 'C':
     86 	    o.create_size = argtooff(optarg, "create size");
     87 	    break;
     88 	case 'F':
     89 	    o.fat_type = atoi(optarg);
     90 	    break;
     91 	case 'I':
     92 	    o.volume_id = argto4(optarg, 0, "volume ID");
     93 	    o.volume_id_set = 1;
     94 	    break;
     95 	case 'L':
     96 	    o.volume_label = optarg;
     97 	    break;
     98 	case 'O':
     99 	    o.OEM_string = optarg;
    100 	    break;
    101 	case 'S':
    102 	    o.bytes_per_sector = argto2(optarg, 1, "bytes/sector");
    103 	    break;
    104 	case 'a':
    105 	    o.sectors_per_fat = argto4(optarg, 1, "sectors/FAT");
    106 	    break;
    107 	case 'b':
    108 	    o.block_size = argtox(optarg, 1, "block size");
    109 	    break;
    110 	case 'c':
    111 	    o.sectors_per_cluster = argto1(optarg, 1, "sectors/cluster");
    112 	    break;
    113 	case 'e':
    114 	    o.directory_entries = argto2(optarg, 1, "directory entries");
    115 	    break;
    116 	case 'f':
    117 	    o.floppy = optarg;
    118 	    break;
    119 	case 'h':
    120 	    o.drive_heads = argto2(optarg, 1, "drive heads");
    121 	    break;
    122 	case 'i':
    123 	    o.info_sector = argto2(optarg, 1, "info sector");
    124 	    break;
    125 	case 'k':
    126 	    o.backup_sector = argto2(optarg, 1, "backup sector");
    127 	    break;
    128 	case 'm':
    129 	    o.media_descriptor = argto1(optarg, 0, "media descriptor");
    130 	    o.media_descriptor_set = 1;
    131 	    break;
    132 	case 'n':
    133 	    o.num_FAT = argto1(optarg, 1, "number of FATs");
    134 	    break;
    135 	case 'o':
    136 	    o.hidden_sectors = argto4(optarg, 0, "hidden sectors");
    137 	    o.hidden_sectors_set = 1;
    138 	    break;
    139 	case 'r':
    140 	    o.reserved_sectors = argto2(optarg, 1, "reserved sectors");
    141 	    break;
    142 	case 's':
    143 	    o.size = argto4(optarg, 1, "file system size");
    144 	    break;
    145 	case 'u':
    146 	    o.sectors_per_track = argto2(optarg, 1, "sectors/track");
    147 	    break;
    148 	default:
    149 	    usage();
    150 	}
    151     argc -= optind;
    152     argv += optind;
    153     if (argc < 1 || argc > 2)
    154 	usage();
    155     fname = *argv++;
    156     if (!strchr(fname, '/') && !o.create_size) {
    157 	snprintf(buf, sizeof(buf), "%sr%s", _PATH_DEV, fname);
    158 	if (!(fname = strdup(buf)))
    159 	    err(1, NULL);
    160     }
    161     dtype = *argv;
    162     return mkfs_msdos(fname, dtype, &o);
    163 }
    164 
    165 /*
    166  * Convert and check a numeric option argument.
    167  */
    168 static u_int
    169 argtou(const char *arg, u_int lo, u_int hi, const char *msg)
    170 {
    171     char *s;
    172     u_long x;
    173 
    174     errno = 0;
    175     x = strtoul(arg, &s, 0);
    176     if (errno || !*arg || *s || x < lo || x > hi)
    177 	errx(1, "%s: bad %s", arg, msg);
    178     return x;
    179 }
    180 
    181 /*
    182  * Same for off_t, with optional skmgpP suffix
    183  */
    184 static off_t
    185 argtooff(const char *arg, const char *msg)
    186 {
    187     char *s;
    188     off_t x;
    189 
    190     errno = 0;
    191     x = strtoll(arg, &s, 0);
    192     /* allow at most one extra char */
    193     if (errno || x < 0 || (s[0] && s[1]) )
    194 	errx(1, "%s: bad %s", arg, msg);
    195     if (*s) {	/* the extra char is the multiplier */
    196 	switch (*s) {
    197 	default:
    198 	    errx(1, "%s: bad %s", arg, msg);
    199 	    /* notreached */
    200 
    201 	case 's':	/* sector */
    202 	case 'S':
    203 	    x <<= 9;	/* times 512 */
    204 	    break;
    205 
    206 	case 'k':	/* kilobyte */
    207 	case 'K':
    208 	    x <<= 10;	/* times 1024 */
    209 	    break;
    210 
    211 	case 'm':	/* megabyte */
    212 	case 'M':
    213 	    x <<= 20;	/* times 1024*1024 */
    214 	    break;
    215 
    216 	case 'g':	/* gigabyte */
    217 	case 'G':
    218 	    x <<= 30;	/* times 1024*1024*1024 */
    219 	    break;
    220 
    221 	case 'p':	/* partition start */
    222 	case 'P':	/* partition start */
    223 	case 'l':	/* partition length */
    224 	case 'L':	/* partition length */
    225 	    errx(1, "%s: not supported yet %s", arg, msg);
    226 	    return -1;
    227 	    /* notreached */
    228 	}
    229     }
    230     return x;
    231 }
    232 
    233 /*
    234  * Print usage message.
    235  */
    236 static void
    237 usage(void)
    238 {
    239     fprintf(stderr,
    240 	    "usage: %s [ -options ] special [disktype]\n", getprogname());
    241     fprintf(stderr, "where the options are:\n");
    242 static struct {
    243 	char o;
    244 	const char *h;
    245 } opts[] = {
    246 #define AOPT(a, b, c, d) { a, d },
    247 ALLOPTS
    248 #undef AOPT
    249 };
    250     for (size_t i = 0; i < __arraycount(opts); i++)
    251 	fprintf(stderr, "\t-%c %s\n", opts[i].o, opts[i].h);
    252     exit(1);
    253 }
    254