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