]> xenbits.xensource.com Git - people/julieng/freebsd.git/commitdiff
newfs_msdos: rework option parsing to match NetBSD
authoremaste <emaste@FreeBSD.org>
Thu, 15 Oct 2015 16:19:00 +0000 (16:19 +0000)
committeremaste <emaste@FreeBSD.org>
Thu, 15 Oct 2015 16:19:00 +0000 (16:19 +0000)
NetBSD split newfs_msdos in two so that they can reuse the file system
creation part in makefs. This change is a step on the path of bringing
that support to FreeBSD.

Reviewed by: kib, pfg
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D3905

sbin/newfs_msdos/newfs_msdos.c

index 468578287671c8c786ea02d810dedd4527338dfe..a3994257ea0602fb93e10ff43a9a66ec3ed01417 100644 (file)
@@ -214,6 +214,35 @@ static const u_int8_t bootcode[] = {
     0
 };
 
+struct msdos_options {
+    const char *bootstrap;
+    const char *volume_label;
+    const char *OEM_string;
+    const char *floppy;
+    u_int fat_type;
+    u_int volume_id;
+    u_int bytes_per_sector;
+    u_int sectors_per_fat;
+    u_int block_size;
+    u_int sectors_per_cluster;
+    u_int directory_entries;
+    u_int drive_heads;
+    u_int info_sector;
+    u_int backup_sector;
+    u_int media_descriptor;
+    u_int num_FAT;
+    u_int hidden_sectors;
+    u_int reserved_sectors;
+    u_int size;
+    u_int sectors_per_track;
+    int no_create;
+    off_t create_size;
+    off_t offset;
+    int volume_id_set;
+    int media_descriptor_set;
+    int hidden_sectors_set;
+};
+
 static volatile sig_atomic_t got_siginfo;
 static void infohandler(int);
 
@@ -226,6 +255,7 @@ static u_int ckgeom(const char *, u_int, const char *);
 static u_int argtou(const char *, u_int, u_int, const char *);
 static off_t argtooff(const char *, const char *);
 static int oklabel(const char *);
+static int mkfs_msdos(const char *, const char *, const struct msdos_options *);
 static void mklabel(u_int8_t *, const char *);
 static void setstr(u_int8_t *, const char *, size_t);
 static void usage(void);
@@ -237,114 +267,96 @@ int
 main(int argc, char *argv[])
 {
     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:";
-    const char *opt_B = NULL, *opt_L = NULL, *opt_O = NULL, *opt_f = NULL;
-    u_int opt_F = 0, opt_I = 0, opt_S = 0, opt_a = 0, opt_b = 0, opt_c = 0;
-    u_int opt_e = 0, opt_h = 0, opt_i = 0, opt_k = 0, opt_m = 0, opt_n = 0;
-    u_int opt_o = 0, opt_r = 0, opt_s = 0, opt_u = 0;
-    int opt_N = 0;
-    int Iflag = 0, mflag = 0, oflag = 0;
+    struct msdos_options o;
+    const char *fname, *dtype;
     char buf[MAXPATHLEN];
-    struct sigaction si_sa;
-    struct stat sb;
-    struct timeval tv;
-    struct bpb bpb;
-    struct tm *tm;
-    struct bs *bs;
-    struct bsbpb *bsbpb;
-    struct bsxbpb *bsxbpb;
-    struct bsx *bsx;
-    struct de *de;
-    u_int8_t *img;
-    const char *fname, *dtype, *bname;
-    ssize_t n;
-    time_t now;
-    u_int fat, bss, rds, cls, dir, lsn, x, x1, x2;
-    int ch, fd, fd1;
-    off_t opt_create = 0, opt_ofs = 0;
+    int ch;
+
+    memset(&o, 0, sizeof(o));
 
     while ((ch = getopt(argc, argv, opts)) != -1)
        switch (ch) {
        case '@':
-           opt_ofs = argtooff(optarg, "offset");
+           o.offset = argtooff(optarg, "offset");
            break;
        case 'N':
-           opt_N = 1;
+           o.no_create = 1;
            break;
        case 'B':
-           opt_B = optarg;
+           o.bootstrap = optarg;
            break;
        case 'C':
-           opt_create = argtooff(optarg, "create size");
+           o.create_size = argtooff(optarg, "create size");
            break;
        case 'F':
            if (strcmp(optarg, "12") &&
                strcmp(optarg, "16") &&
                strcmp(optarg, "32"))
                errx(1, "%s: bad FAT type", optarg);
-           opt_F = atoi(optarg);
+           o.fat_type = atoi(optarg);
            break;
        case 'I':
-           opt_I = argto4(optarg, 0, "volume ID");
-           Iflag = 1;
+           o.volume_id = argto4(optarg, 0, "volume ID");
+           o.volume_id_set = 1;
            break;
        case 'L':
            if (!oklabel(optarg))
                errx(1, "%s: bad volume label", optarg);
-           opt_L = optarg;
+           o.volume_label = optarg;
            break;
        case 'O':
            if (strlen(optarg) > 8)
                errx(1, "%s: bad OEM string", optarg);
-           opt_O = optarg;
+           o.OEM_string = optarg;
            break;
        case 'S':
-           opt_S = argto2(optarg, 1, "bytes/sector");
+           o.bytes_per_sector = argto2(optarg, 1, "bytes/sector");
            break;
        case 'a':
-           opt_a = argto4(optarg, 1, "sectors/FAT");
+           o.sectors_per_fat = argto4(optarg, 1, "sectors/FAT");
            break;
        case 'b':
-           opt_b = argtox(optarg, 1, "block size");
-           opt_c = 0;
+           o.block_size = argtox(optarg, 1, "block size");
+           o.sectors_per_cluster = 0;
            break;
        case 'c':
-           opt_c = argto1(optarg, 1, "sectors/cluster");
-           opt_b = 0;
+           o.sectors_per_cluster = argto1(optarg, 1, "sectors/cluster");
+           o.block_size = 0;
            break;
        case 'e':
-           opt_e = argto2(optarg, 1, "directory entries");
+           o.directory_entries = argto2(optarg, 1, "directory entries");
            break;
        case 'f':
-           opt_f = optarg;
+           o.floppy = optarg;
            break;
        case 'h':
-           opt_h = argto2(optarg, 1, "drive heads");
+           o.drive_heads = argto2(optarg, 1, "drive heads");
            break;
        case 'i':
-           opt_i = argto2(optarg, 1, "info sector");
+           o.info_sector = argto2(optarg, 1, "info sector");
            break;
        case 'k':
-           opt_k = argto2(optarg, 1, "backup sector");
+           o.backup_sector = argto2(optarg, 1, "backup sector");
            break;
        case 'm':
-           opt_m = argto1(optarg, 0, "media descriptor");
-           mflag = 1;
+           o.media_descriptor = argto1(optarg, 0, "media descriptor");
+           o.media_descriptor_set = 1;
            break;
        case 'n':
-           opt_n = argto1(optarg, 1, "number of FATs");
+           o.num_FAT = argto1(optarg, 1, "number of FATs");
            break;
        case 'o':
-           opt_o = argto4(optarg, 0, "hidden sectors");
-           oflag = 1;
+           o.hidden_sectors = argto4(optarg, 0, "hidden sectors");
+           o.hidden_sectors_set = 1;
            break;
        case 'r':
-           opt_r = argto2(optarg, 1, "reserved sectors");
+           o.reserved_sectors = argto2(optarg, 1, "reserved sectors");
            break;
        case 's':
-           opt_s = argto4(optarg, 1, "file system size");
+           o.size = argto4(optarg, 1, "file system size");
            break;
        case 'u':
-           opt_u = argto2(optarg, 1, "sectors/track");
+           o.sectors_per_track = argto2(optarg, 1, "sectors/track");
            break;
        default:
            usage();
@@ -354,57 +366,82 @@ main(int argc, char *argv[])
     if (argc < 1 || argc > 2)
        usage();
     fname = *argv++;
-    if (!opt_create && !strchr(fname, '/')) {
+    if (!o.create_size && !strchr(fname, '/')) {
        snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname);
        if (!(fname = strdup(buf)))
            err(1, NULL);
     }
     dtype = *argv;
-    if (opt_create) {
-       if (opt_N)
+    return mkfs_msdos(fname, dtype, &o);
+}
+
+int mkfs_msdos(const char *fname, const char *dtype,
+    const struct msdos_options *op)
+{
+    char buf[MAXPATHLEN];
+    struct sigaction si_sa;
+    struct stat sb;
+    struct timeval tv;
+    struct bpb bpb;
+    struct tm *tm;
+    struct bs *bs;
+    struct bsbpb *bsbpb;
+    struct bsxbpb *bsxbpb;
+    struct bsx *bsx;
+    struct de *de;
+    u_int8_t *img;
+    const char *bname;
+    ssize_t n;
+    time_t now;
+    u_int fat, bss, rds, cls, dir, lsn, x, x1, x2;
+    int fd, fd1;
+    struct msdos_options o = *op;
+
+    if (o.create_size) {
+       if (o.no_create)
            errx(1, "create (-C) is incompatible with -N");
        fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644);
        if (fd == -1)
            errx(1, "failed to create %s", fname);
-       if (ftruncate(fd, opt_create))
-           errx(1, "failed to initialize %jd bytes", (intmax_t)opt_create);
-    } else if ((fd = open(fname, opt_N ? O_RDONLY : O_RDWR)) == -1)
+       if (ftruncate(fd, o.create_size))
+           errx(1, "failed to initialize %jd bytes", (intmax_t)o.create_size);
+    } else if ((fd = open(fname, o.no_create ? O_RDONLY : O_RDWR)) == -1)
        err(1, "%s", fname);
     if (fstat(fd, &sb))
        err(1, "%s", fname);
-    if (opt_create) {
+    if (o.create_size) {
        if (!S_ISREG(sb.st_mode))
            warnx("warning, %s is not a regular file", fname);
     } else {
        if (!S_ISCHR(sb.st_mode))
            warnx("warning, %s is not a character device", fname);
     }
-    if (!opt_N)
+    if (!o.no_create)
        check_mounted(fname, sb.st_mode);
-    if (opt_ofs && opt_ofs != lseek(fd, opt_ofs, SEEK_SET))
-       errx(1, "cannot seek to %jd", (intmax_t)opt_ofs);
+    if (o.offset && o.offset != lseek(fd, o.offset, SEEK_SET))
+       errx(1, "cannot seek to %jd", (intmax_t)o.offset);
     memset(&bpb, 0, sizeof(bpb));
-    if (opt_f) {
-       getstdfmt(opt_f, &bpb);
+    if (o.floppy) {
+       getstdfmt(o.floppy, &bpb);
        bpb.bpbHugeSectors = bpb.bpbSectors;
        bpb.bpbSectors = 0;
        bpb.bpbBigFATsecs = bpb.bpbFATsecs;
        bpb.bpbFATsecs = 0;
     }
-    if (opt_h)
-       bpb.bpbHeads = opt_h;
-    if (opt_u)
-       bpb.bpbSecPerTrack = opt_u;
-    if (opt_S)
-       bpb.bpbBytesPerSec = opt_S;
-    if (opt_s)
-       bpb.bpbHugeSectors = opt_s;
-    if (oflag)
-       bpb.bpbHiddenSecs = opt_o;
-    if (!(opt_f || (opt_h && opt_u && opt_S && opt_s && oflag))) {
+    if (o.drive_heads)
+       bpb.bpbHeads = o.drive_heads;
+    if (o.sectors_per_track)
+       bpb.bpbSecPerTrack = o.sectors_per_track;
+    if (o.bytes_per_sector)
+       bpb.bpbBytesPerSec = o.bytes_per_sector;
+    if (o.size)
+       bpb.bpbHugeSectors = o.size;
+    if (o.hidden_sectors_set)
+       bpb.bpbHiddenSecs = o.hidden_sectors;
+    if (!(o.floppy || (o.drive_heads && o.sectors_per_track && o.bytes_per_sector && o.size && o.hidden_sectors_set))) {
        off_t delta;
-       getdiskinfo(fd, fname, dtype, oflag, &bpb);
-       bpb.bpbHugeSectors -= (opt_ofs / bpb.bpbBytesPerSec);
+       getdiskinfo(fd, fname, dtype, o.hidden_sectors_set, &bpb);
+       bpb.bpbHugeSectors -= (o.offset / bpb.bpbBytesPerSec);
        delta = bpb.bpbHugeSectors % bpb.bpbSecPerTrack;
        if (delta != 0) {
            warnx("trim %d sectors to adjust to a multiple of %d",
@@ -429,60 +466,60 @@ main(int argc, char *argv[])
     if (bpb.bpbBytesPerSec < MINBPS)
        errx(1, "bytes/sector (%u) is too small; minimum is %u",
             bpb.bpbBytesPerSec, MINBPS);
-    if (!(fat = opt_F)) {
-       if (opt_f)
+    if (!(fat = o.fat_type)) {
+       if (o.floppy)
            fat = 12;
-       else if (!opt_e && (opt_i || opt_k))
+       else if (!o.directory_entries && (o.info_sector || o.backup_sector))
            fat = 32;
     }
-    if ((fat == 32 && opt_e) || (fat != 32 && (opt_i || opt_k)))
+    if ((fat == 32 && o.directory_entries) || (fat != 32 && (o.info_sector || o.backup_sector)))
        errx(1, "-%c is not a legal FAT%s option",
-            fat == 32 ? 'e' : opt_i ? 'i' : 'k',
+            fat == 32 ? 'e' : o.info_sector ? 'i' : 'k',
             fat == 32 ? "32" : "12/16");
-    if (opt_f && fat == 32)
+    if (o.floppy && fat == 32)
        bpb.bpbRootDirEnts = 0;
-    if (opt_b) {
-       if (!powerof2(opt_b))
-           errx(1, "block size (%u) is not a power of 2", opt_b);
-       if (opt_b < bpb.bpbBytesPerSec)
+    if (o.block_size) {
+       if (!powerof2(o.block_size))
+           errx(1, "block size (%u) is not a power of 2", o.block_size);
+       if (o.block_size < bpb.bpbBytesPerSec)
            errx(1, "block size (%u) is too small; minimum is %u",
-                opt_b, bpb.bpbBytesPerSec);
-       if (opt_b > bpb.bpbBytesPerSec * MAXSPC)
+                o.block_size, bpb.bpbBytesPerSec);
+       if (o.block_size > bpb.bpbBytesPerSec * MAXSPC)
            errx(1, "block size (%u) is too large; maximum is %u",
-                opt_b, bpb.bpbBytesPerSec * MAXSPC);
-       bpb.bpbSecPerClust = opt_b / bpb.bpbBytesPerSec;
+                o.block_size, bpb.bpbBytesPerSec * MAXSPC);
+       bpb.bpbSecPerClust = o.block_size / bpb.bpbBytesPerSec;
     }
-    if (opt_c) {
-       if (!powerof2(opt_c))
-           errx(1, "sectors/cluster (%u) is not a power of 2", opt_c);
-       bpb.bpbSecPerClust = opt_c;
+    if (o.sectors_per_cluster) {
+       if (!powerof2(o.sectors_per_cluster))
+           errx(1, "sectors/cluster (%u) is not a power of 2", o.sectors_per_cluster);
+       bpb.bpbSecPerClust = o.sectors_per_cluster;
     }
-    if (opt_r)
-       bpb.bpbResSectors = opt_r;
-    if (opt_n) {
-       if (opt_n > MAXNFT)
+    if (o.reserved_sectors)
+       bpb.bpbResSectors = o.reserved_sectors;
+    if (o.num_FAT) {
+       if (o.num_FAT > MAXNFT)
            errx(1, "number of FATs (%u) is too large; maximum is %u",
-                opt_n, MAXNFT);
-       bpb.bpbFATs = opt_n;
+                o.num_FAT, MAXNFT);
+       bpb.bpbFATs = o.num_FAT;
     }
-    if (opt_e)
-       bpb.bpbRootDirEnts = opt_e;
-    if (mflag) {
-       if (opt_m < 0xf0)
-           errx(1, "illegal media descriptor (%#x)", opt_m);
-       bpb.bpbMedia = opt_m;
+    if (o.directory_entries)
+       bpb.bpbRootDirEnts = o.directory_entries;
+    if (o.media_descriptor_set) {
+       if (o.media_descriptor < 0xf0)
+           errx(1, "illegal media descriptor (%#x)", o.media_descriptor);
+       bpb.bpbMedia = o.media_descriptor;
     }
-    if (opt_a)
-       bpb.bpbBigFATsecs = opt_a;
-    if (opt_i)
-       bpb.bpbFSInfo = opt_i;
-    if (opt_k)
-       bpb.bpbBackup = opt_k;
+    if (o.sectors_per_fat)
+       bpb.bpbBigFATsecs = o.sectors_per_fat;
+    if (o.info_sector)
+       bpb.bpbFSInfo = o.info_sector;
+    if (o.backup_sector)
+       bpb.bpbBackup = o.backup_sector;
     bss = 1;
     bname = NULL;
     fd1 = -1;
-    if (opt_B) {
-       bname = opt_B;
+    if (o.bootstrap) {
+       bname = o.bootstrap;
        if (!strchr(bname, '/')) {
            snprintf(buf, sizeof(buf), "/boot/%s", bname);
            if (!(bname = strdup(buf)))
@@ -612,7 +649,7 @@ main(int argc, char *argv[])
        bpb.bpbBigFATsecs = 0;
     }
     print_bpb(&bpb);
-    if (!opt_N) {
+    if (!o.no_create) {
        gettimeofday(&tv, NULL);
        now = tv.tv_sec;
        tm = localtime(&now);
@@ -634,14 +671,14 @@ main(int argc, char *argv[])
                    got_siginfo = 0;
            }
            x = lsn;
-           if (opt_B &&
+           if (o.bootstrap &&
                fat == 32 && bpb.bpbBackup != MAXU16 &&
                bss <= bpb.bpbBackup && x >= bpb.bpbBackup) {
                x -= bpb.bpbBackup;
-               if (!x && lseek(fd1, opt_ofs, SEEK_SET))
+               if (!x && lseek(fd1, o.offset, SEEK_SET))
                    err(1, "%s", bname);
            }
-           if (opt_B && x < bss) {
+           if (o.bootstrap && x < bss) {
                if ((n = read(fd1, img, bpb.bpbBytesPerSec)) == -1)
                    err(1, "%s", bname);
                if ((unsigned)n != bpb.bpbBytesPerSec)
@@ -678,8 +715,8 @@ main(int argc, char *argv[])
                }
                bsx = (struct bsx *)(img + x1);
                mk1(bsx->exBootSignature, 0x29);
-               if (Iflag)
-                   x = opt_I;
+               if (o.volume_id_set)
+                   x = o.volume_id;
                else
                    x = (((u_int)(1 + tm->tm_mon) << 8 |
                          (u_int)tm->tm_mday) +
@@ -689,16 +726,16 @@ main(int argc, char *argv[])
                         ((u_int)tm->tm_hour << 8 |
                          (u_int)tm->tm_min));
                mk4(bsx->exVolumeID, x);
-               mklabel(bsx->exVolumeLabel, opt_L ? opt_L : "NO NAME");
+               mklabel(bsx->exVolumeLabel, o.volume_label ? o.volume_label : "NO NAME");
                sprintf(buf, "FAT%u", fat);
                setstr(bsx->exFileSysType, buf, sizeof(bsx->exFileSysType));
-               if (!opt_B) {
+               if (!o.bootstrap) {
                    x1 += sizeof(struct bsx);
                    bs = (struct bs *)img;
                    mk1(bs->bsJump[0], 0xeb);
                    mk1(bs->bsJump[1], x1 - 2);
                    mk1(bs->bsJump[2], 0x90);
-                   setstr(bs->bsOemName, opt_O ? opt_O : "BSD4.4  ",
+                   setstr(bs->bsOemName, o.OEM_string ? o.OEM_string : "BSD4.4  ",
                           sizeof(bs->bsOemName));
                    memcpy(img + x1, bootcode, sizeof(bootcode));
                    mk2(img + MINBPS - 2, DOSMAGIC);
@@ -719,9 +756,9 @@ main(int argc, char *argv[])
                mk1(img[0], bpb.bpbMedia);
                for (x = 1; x < fat * (fat == 32 ? 3 : 2) / 8; x++)
                    mk1(img[x], fat == 32 && x % 4 == 3 ? 0x0f : 0xff);
-           } else if (lsn == dir && opt_L) {
+           } else if (lsn == dir && o.volume_label) {
                de = (struct de *)img;
-               mklabel(de->deName, opt_L);
+               mklabel(de->deName, o.volume_label);
                mk1(de->deAttributes, 050);
                x = (u_int)tm->tm_hour << 11 |
                    (u_int)tm->tm_min << 5 |