xref: /minix3/sbin/newfs_msdos/newfs_msdos.c (revision 25d017aa13555ad6275f6d3aa1113d2b0b092534)
1*25d017aaSSevan Janiyan /*	$NetBSD: newfs_msdos.c,v 1.45 2017/02/16 22:42:25 christos Exp $	*/
29f988b79SJean-Baptiste Boric 
39f988b79SJean-Baptiste Boric /*
49f988b79SJean-Baptiste Boric  * Copyright (c) 1998 Robert Nordier
59f988b79SJean-Baptiste Boric  * All rights reserved.
69f988b79SJean-Baptiste Boric  *
79f988b79SJean-Baptiste Boric  * Redistribution and use in source and binary forms, with or without
89f988b79SJean-Baptiste Boric  * modification, are permitted provided that the following conditions
99f988b79SJean-Baptiste Boric  * are met:
109f988b79SJean-Baptiste Boric  * 1. Redistributions of source code must retain the above copyright
119f988b79SJean-Baptiste Boric  *    notice, this list of conditions and the following disclaimer.
129f988b79SJean-Baptiste Boric  * 2. Redistributions in binary form must reproduce the above copyright
139f988b79SJean-Baptiste Boric  *    notice, this list of conditions and the following disclaimer in
149f988b79SJean-Baptiste Boric  *    the documentation and/or other materials provided with the
159f988b79SJean-Baptiste Boric  *    distribution.
169f988b79SJean-Baptiste Boric  *
179f988b79SJean-Baptiste Boric  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
189f988b79SJean-Baptiste Boric  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
199f988b79SJean-Baptiste Boric  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
209f988b79SJean-Baptiste Boric  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
219f988b79SJean-Baptiste Boric  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
229f988b79SJean-Baptiste Boric  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
239f988b79SJean-Baptiste Boric  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
249f988b79SJean-Baptiste Boric  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
259f988b79SJean-Baptiste Boric  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
269f988b79SJean-Baptiste Boric  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
279f988b79SJean-Baptiste Boric  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
289f988b79SJean-Baptiste Boric  */
299f988b79SJean-Baptiste Boric 
309f988b79SJean-Baptiste Boric #include <sys/cdefs.h>
319f988b79SJean-Baptiste Boric #ifndef lint
329f988b79SJean-Baptiste Boric #if 0
339f988b79SJean-Baptiste Boric static const char rcsid[] =
349f988b79SJean-Baptiste Boric   "$FreeBSD: src/sbin/newfs_msdos/newfs_msdos.c,v 1.15 2000/10/10 01:49:37 wollman Exp $";
359f988b79SJean-Baptiste Boric #else
36*25d017aaSSevan Janiyan __RCSID("$NetBSD: newfs_msdos.c,v 1.45 2017/02/16 22:42:25 christos Exp $");
379f988b79SJean-Baptiste Boric #endif
389f988b79SJean-Baptiste Boric #endif /* not lint */
399f988b79SJean-Baptiste Boric 
409f988b79SJean-Baptiste Boric #include <sys/param.h>
41*25d017aaSSevan Janiyan #include <sys/stat.h>
429f988b79SJean-Baptiste Boric #include <stdio.h>
439f988b79SJean-Baptiste Boric #include <string.h>
449f988b79SJean-Baptiste Boric #include <err.h>
459f988b79SJean-Baptiste Boric #include <stdlib.h>
469f988b79SJean-Baptiste Boric #include <unistd.h>
479f988b79SJean-Baptiste Boric #include <paths.h>
489f988b79SJean-Baptiste Boric #include <errno.h>
49*25d017aaSSevan Janiyan #include <util.h>
509f988b79SJean-Baptiste Boric 
519f988b79SJean-Baptiste Boric #include "mkfs_msdos.h"
529f988b79SJean-Baptiste Boric 
539f988b79SJean-Baptiste Boric #define argto1(arg, lo, msg)  argtou(arg, lo, 0xff, msg)
549f988b79SJean-Baptiste Boric #define argto2(arg, lo, msg)  argtou(arg, lo, 0xffff, msg)
559f988b79SJean-Baptiste Boric #define argto4(arg, lo, msg)  argtou(arg, lo, 0xffffffff, msg)
569f988b79SJean-Baptiste Boric #define argtox(arg, lo, msg)  argtou(arg, lo, UINT_MAX, msg)
579f988b79SJean-Baptiste Boric 
589f988b79SJean-Baptiste Boric __dead static void usage(void);
599f988b79SJean-Baptiste Boric static u_int argtou(const char *, u_int, u_int, const char *);
609f988b79SJean-Baptiste Boric static off_t argtooff(const char *, const char *);
619f988b79SJean-Baptiste Boric 
62*25d017aaSSevan Janiyan static time_t
get_tstamp(const char * b)63*25d017aaSSevan Janiyan get_tstamp(const char *b)
64*25d017aaSSevan Janiyan {
65*25d017aaSSevan Janiyan 	struct stat st;
66*25d017aaSSevan Janiyan 	char *eb;
67*25d017aaSSevan Janiyan 	long long l;
68*25d017aaSSevan Janiyan #ifndef HAVE_NBTOOL_CONFIG_H
69*25d017aaSSevan Janiyan 	time_t when;
70*25d017aaSSevan Janiyan #endif
71*25d017aaSSevan Janiyan 
72*25d017aaSSevan Janiyan 	if (stat(b, &st) != -1)
73*25d017aaSSevan Janiyan 		return (time_t)st.st_mtime;
74*25d017aaSSevan Janiyan 
75*25d017aaSSevan Janiyan #ifndef HAVE_NBTOOL_CONFIG_H
76*25d017aaSSevan Janiyan 	errno = 0;
77*25d017aaSSevan Janiyan 	if ((when = parsedate(b, NULL, NULL)) != -1 || errno == 0)
78*25d017aaSSevan Janiyan 		return when;
79*25d017aaSSevan Janiyan #endif
80*25d017aaSSevan Janiyan 	errno = 0;
81*25d017aaSSevan Janiyan 	l = strtoll(b, &eb, 0);
82*25d017aaSSevan Janiyan 	if (b == eb || *eb || errno)
83*25d017aaSSevan Janiyan 		errx(EXIT_FAILURE, "Can't parse timestamp `%s'", b);
84*25d017aaSSevan Janiyan 	return (time_t)l;
85*25d017aaSSevan Janiyan }
86*25d017aaSSevan Janiyan 
879f988b79SJean-Baptiste Boric /*
889f988b79SJean-Baptiste Boric  * Construct a FAT12, FAT16, or FAT32 file system.
899f988b79SJean-Baptiste Boric  */
909f988b79SJean-Baptiste Boric int
main(int argc,char * argv[])919f988b79SJean-Baptiste Boric main(int argc, char *argv[])
929f988b79SJean-Baptiste Boric {
93*25d017aaSSevan Janiyan     static const char opts[] = "@:NB:C:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:T:u:";
949f988b79SJean-Baptiste Boric     struct msdos_options o;
959f988b79SJean-Baptiste Boric     char *fname, *dtype;
969f988b79SJean-Baptiste Boric     char buf[MAXPATHLEN];
979f988b79SJean-Baptiste Boric     int ch;
989f988b79SJean-Baptiste Boric 
999f988b79SJean-Baptiste Boric     memset(&o, 0, sizeof(o));
1009f988b79SJean-Baptiste Boric 
1019f988b79SJean-Baptiste Boric     while ((ch = getopt(argc, argv, opts)) != -1)
1029f988b79SJean-Baptiste Boric 	switch (ch) {
1039f988b79SJean-Baptiste Boric 	case '@':
1049f988b79SJean-Baptiste Boric 	    o.offset = argtooff(optarg, "offset");
1059f988b79SJean-Baptiste Boric 	    break;
1069f988b79SJean-Baptiste Boric 	case 'N':
1079f988b79SJean-Baptiste Boric 	    o.no_create = 1;
1089f988b79SJean-Baptiste Boric 	    break;
1099f988b79SJean-Baptiste Boric 	case 'B':
1109f988b79SJean-Baptiste Boric 	    o.bootstrap = optarg;
1119f988b79SJean-Baptiste Boric 	    break;
1129f988b79SJean-Baptiste Boric 	case 'C':
1139f988b79SJean-Baptiste Boric 	    o.create_size = argtooff(optarg, "create size");
1149f988b79SJean-Baptiste Boric 	    break;
1159f988b79SJean-Baptiste Boric 	case 'F':
1169f988b79SJean-Baptiste Boric 	    o.fat_type = atoi(optarg);
1179f988b79SJean-Baptiste Boric 	    break;
1189f988b79SJean-Baptiste Boric 	case 'I':
1199f988b79SJean-Baptiste Boric 	    o.volume_id = argto4(optarg, 0, "volume ID");
1209f988b79SJean-Baptiste Boric 	    o.volume_id_set = 1;
1219f988b79SJean-Baptiste Boric 	    break;
1229f988b79SJean-Baptiste Boric 	case 'L':
1239f988b79SJean-Baptiste Boric 	    o.volume_label = optarg;
1249f988b79SJean-Baptiste Boric 	    break;
1259f988b79SJean-Baptiste Boric 	case 'O':
1269f988b79SJean-Baptiste Boric 	    o.OEM_string = optarg;
1279f988b79SJean-Baptiste Boric 	    break;
1289f988b79SJean-Baptiste Boric 	case 'S':
1299f988b79SJean-Baptiste Boric 	    o.bytes_per_sector = argto2(optarg, 1, "bytes/sector");
1309f988b79SJean-Baptiste Boric 	    break;
1319f988b79SJean-Baptiste Boric 	case 'a':
1329f988b79SJean-Baptiste Boric 	    o.sectors_per_fat = argto4(optarg, 1, "sectors/FAT");
1339f988b79SJean-Baptiste Boric 	    break;
1349f988b79SJean-Baptiste Boric 	case 'b':
1359f988b79SJean-Baptiste Boric 	    o.block_size = argtox(optarg, 1, "block size");
1369f988b79SJean-Baptiste Boric 	    break;
1379f988b79SJean-Baptiste Boric 	case 'c':
1389f988b79SJean-Baptiste Boric 	    o.sectors_per_cluster = argto1(optarg, 1, "sectors/cluster");
1399f988b79SJean-Baptiste Boric 	    break;
1409f988b79SJean-Baptiste Boric 	case 'e':
1419f988b79SJean-Baptiste Boric 	    o.directory_entries = argto2(optarg, 1, "directory entries");
1429f988b79SJean-Baptiste Boric 	    break;
1439f988b79SJean-Baptiste Boric 	case 'f':
1449f988b79SJean-Baptiste Boric 	    o.floppy = optarg;
1459f988b79SJean-Baptiste Boric 	    break;
1469f988b79SJean-Baptiste Boric 	case 'h':
1479f988b79SJean-Baptiste Boric 	    o.drive_heads = argto2(optarg, 1, "drive heads");
1489f988b79SJean-Baptiste Boric 	    break;
1499f988b79SJean-Baptiste Boric 	case 'i':
1509f988b79SJean-Baptiste Boric 	    o.info_sector = argto2(optarg, 1, "info sector");
1519f988b79SJean-Baptiste Boric 	    break;
1529f988b79SJean-Baptiste Boric 	case 'k':
1539f988b79SJean-Baptiste Boric 	    o.backup_sector = argto2(optarg, 1, "backup sector");
1549f988b79SJean-Baptiste Boric 	    break;
1559f988b79SJean-Baptiste Boric 	case 'm':
1569f988b79SJean-Baptiste Boric 	    o.media_descriptor = argto1(optarg, 0, "media descriptor");
1579f988b79SJean-Baptiste Boric 	    o.media_descriptor_set = 1;
1589f988b79SJean-Baptiste Boric 	    break;
1599f988b79SJean-Baptiste Boric 	case 'n':
1609f988b79SJean-Baptiste Boric 	    o.num_FAT = argto1(optarg, 1, "number of FATs");
1619f988b79SJean-Baptiste Boric 	    break;
1629f988b79SJean-Baptiste Boric 	case 'o':
1639f988b79SJean-Baptiste Boric 	    o.hidden_sectors = argto4(optarg, 0, "hidden sectors");
1649f988b79SJean-Baptiste Boric 	    o.hidden_sectors_set = 1;
1659f988b79SJean-Baptiste Boric 	    break;
1669f988b79SJean-Baptiste Boric 	case 'r':
1679f988b79SJean-Baptiste Boric 	    o.reserved_sectors = argto2(optarg, 1, "reserved sectors");
1689f988b79SJean-Baptiste Boric 	    break;
1699f988b79SJean-Baptiste Boric 	case 's':
1709f988b79SJean-Baptiste Boric 	    o.size = argto4(optarg, 1, "file system size");
1719f988b79SJean-Baptiste Boric 	    break;
172*25d017aaSSevan Janiyan 	case 'T':
173*25d017aaSSevan Janiyan 	    o.timestamp_set = 1;
174*25d017aaSSevan Janiyan 	    o.timestamp = get_tstamp(optarg);
175*25d017aaSSevan Janiyan 	    break;
1769f988b79SJean-Baptiste Boric 	case 'u':
1779f988b79SJean-Baptiste Boric 	    o.sectors_per_track = argto2(optarg, 1, "sectors/track");
1789f988b79SJean-Baptiste Boric 	    break;
1799f988b79SJean-Baptiste Boric 	default:
1809f988b79SJean-Baptiste Boric 	    usage();
1819f988b79SJean-Baptiste Boric 	}
1829f988b79SJean-Baptiste Boric     argc -= optind;
1839f988b79SJean-Baptiste Boric     argv += optind;
1849f988b79SJean-Baptiste Boric     if (argc < 1 || argc > 2)
1859f988b79SJean-Baptiste Boric 	usage();
1869f988b79SJean-Baptiste Boric     fname = *argv++;
1879f988b79SJean-Baptiste Boric     if (!strchr(fname, '/') && !o.create_size) {
1889f988b79SJean-Baptiste Boric 	snprintf(buf, sizeof(buf), "%sr%s", _PATH_DEV, fname);
1899f988b79SJean-Baptiste Boric 	if (!(fname = strdup(buf)))
1909f988b79SJean-Baptiste Boric 	    err(1, NULL);
1919f988b79SJean-Baptiste Boric     }
1929f988b79SJean-Baptiste Boric     dtype = *argv;
1939f988b79SJean-Baptiste Boric     return mkfs_msdos(fname, dtype, &o);
1949f988b79SJean-Baptiste Boric }
1959f988b79SJean-Baptiste Boric 
1969f988b79SJean-Baptiste Boric /*
1979f988b79SJean-Baptiste Boric  * Convert and check a numeric option argument.
1989f988b79SJean-Baptiste Boric  */
1999f988b79SJean-Baptiste Boric static u_int
argtou(const char * arg,u_int lo,u_int hi,const char * msg)2009f988b79SJean-Baptiste Boric argtou(const char *arg, u_int lo, u_int hi, const char *msg)
2019f988b79SJean-Baptiste Boric {
2020a6a1f1dSLionel Sambuc     off_t x;
2039f988b79SJean-Baptiste Boric 
2049f988b79SJean-Baptiste Boric     errno = 0;
2050a6a1f1dSLionel Sambuc     x = argtooff(arg, msg);
2060a6a1f1dSLionel Sambuc     if (x < lo || x > hi)
2079f988b79SJean-Baptiste Boric 	errx(1, "%s: bad %s", arg, msg);
2080a6a1f1dSLionel Sambuc     return (u_int)x;
2099f988b79SJean-Baptiste Boric }
2109f988b79SJean-Baptiste Boric 
2119f988b79SJean-Baptiste Boric /*
2129f988b79SJean-Baptiste Boric  * Same for off_t, with optional skmgpP suffix
2139f988b79SJean-Baptiste Boric  */
2149f988b79SJean-Baptiste Boric static off_t
argtooff(const char * arg,const char * msg)2159f988b79SJean-Baptiste Boric argtooff(const char *arg, const char *msg)
2169f988b79SJean-Baptiste Boric {
2179f988b79SJean-Baptiste Boric     char *s;
2189f988b79SJean-Baptiste Boric     off_t x;
2199f988b79SJean-Baptiste Boric 
2209f988b79SJean-Baptiste Boric     errno = 0;
2219f988b79SJean-Baptiste Boric     x = strtoll(arg, &s, 0);
2229f988b79SJean-Baptiste Boric     /* allow at most one extra char */
2239f988b79SJean-Baptiste Boric     if (errno || x < 0 || (s[0] && s[1]) )
2249f988b79SJean-Baptiste Boric 	errx(1, "%s: bad %s", arg, msg);
2259f988b79SJean-Baptiste Boric     if (*s) {	/* the extra char is the multiplier */
2269f988b79SJean-Baptiste Boric 	switch (*s) {
2279f988b79SJean-Baptiste Boric 	default:
2289f988b79SJean-Baptiste Boric 	    errx(1, "%s: bad %s", arg, msg);
2299f988b79SJean-Baptiste Boric 	    /* notreached */
2309f988b79SJean-Baptiste Boric 
2319f988b79SJean-Baptiste Boric 	case 's':	/* sector */
2329f988b79SJean-Baptiste Boric 	case 'S':
2339f988b79SJean-Baptiste Boric 	    x <<= 9;	/* times 512 */
2349f988b79SJean-Baptiste Boric 	    break;
2359f988b79SJean-Baptiste Boric 
2369f988b79SJean-Baptiste Boric 	case 'k':	/* kilobyte */
2379f988b79SJean-Baptiste Boric 	case 'K':
2389f988b79SJean-Baptiste Boric 	    x <<= 10;	/* times 1024 */
2399f988b79SJean-Baptiste Boric 	    break;
2409f988b79SJean-Baptiste Boric 
2419f988b79SJean-Baptiste Boric 	case 'm':	/* megabyte */
2429f988b79SJean-Baptiste Boric 	case 'M':
2439f988b79SJean-Baptiste Boric 	    x <<= 20;	/* times 1024*1024 */
2449f988b79SJean-Baptiste Boric 	    break;
2459f988b79SJean-Baptiste Boric 
2469f988b79SJean-Baptiste Boric 	case 'g':	/* gigabyte */
2479f988b79SJean-Baptiste Boric 	case 'G':
2489f988b79SJean-Baptiste Boric 	    x <<= 30;	/* times 1024*1024*1024 */
2499f988b79SJean-Baptiste Boric 	    break;
2509f988b79SJean-Baptiste Boric 
2519f988b79SJean-Baptiste Boric 	case 'p':	/* partition start */
2529f988b79SJean-Baptiste Boric 	case 'P':	/* partition start */
2539f988b79SJean-Baptiste Boric 	case 'l':	/* partition length */
2549f988b79SJean-Baptiste Boric 	case 'L':	/* partition length */
2559f988b79SJean-Baptiste Boric 	    errx(1, "%s: not supported yet %s", arg, msg);
2569f988b79SJean-Baptiste Boric 	    return -1;
2579f988b79SJean-Baptiste Boric 	    /* notreached */
2589f988b79SJean-Baptiste Boric 	}
2599f988b79SJean-Baptiste Boric     }
2609f988b79SJean-Baptiste Boric     return x;
2619f988b79SJean-Baptiste Boric }
2629f988b79SJean-Baptiste Boric 
2639f988b79SJean-Baptiste Boric /*
2649f988b79SJean-Baptiste Boric  * Print usage message.
2659f988b79SJean-Baptiste Boric  */
2669f988b79SJean-Baptiste Boric static void
usage(void)2679f988b79SJean-Baptiste Boric usage(void)
2689f988b79SJean-Baptiste Boric {
2699f988b79SJean-Baptiste Boric     fprintf(stderr,
2709f988b79SJean-Baptiste Boric 	    "usage: %s [ -options ] special [disktype]\n", getprogname());
2719f988b79SJean-Baptiste Boric     fprintf(stderr, "where the options are:\n");
2729f988b79SJean-Baptiste Boric static struct {
2739f988b79SJean-Baptiste Boric 	char o;
2749f988b79SJean-Baptiste Boric 	const char *h;
2759f988b79SJean-Baptiste Boric } opts[] = {
2769f988b79SJean-Baptiste Boric #define AOPT(_opt, _type, _name, _min, _desc) { _opt, _desc },
2779f988b79SJean-Baptiste Boric ALLOPTS
2789f988b79SJean-Baptiste Boric #undef AOPT
2799f988b79SJean-Baptiste Boric };
2809f988b79SJean-Baptiste Boric     for (size_t i = 0; i < __arraycount(opts); i++)
2819f988b79SJean-Baptiste Boric 	fprintf(stderr, "\t-%c %s\n", opts[i].o, opts[i].h);
2829f988b79SJean-Baptiste Boric     exit(1);
2839f988b79SJean-Baptiste Boric }
284