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