1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (c) 1998 Robert Nordier
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * All rights reserved.
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Redistribution and use in source and binary forms, with or without
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * modification, are permitted provided that the following conditions
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * are met:
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    notice, this list of conditions and the following disclaimer in
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    the documentation and/or other materials provided with the
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    distribution.
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2872eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat#ifndef lint
2972eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehatstatic const char rcsid[] =
3033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        "$FreeBSD: src/sbin/newfs_msdos/newfs_msdos.c,v 1.33 2009/04/11 14:56:29 ed Exp $";
3172eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat#endif /* not lint */
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/param.h>
3472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
3572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat#ifndef ANDROID
3633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#include <sys/fdcio.h>
3733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#include <sys/disk.h>
3833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#include <sys/disklabel.h>
3933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#include <sys/mount.h>
4072eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat#else
4133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#include <stdarg.h>
4233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#include <linux/fs.h>
4333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#include <linux/hdreg.h>
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
4572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h>
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/time.h>
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <ctype.h>
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <err.h>
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h>
5372eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat#include <inttypes.h>
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <paths.h>
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <time.h>
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
6133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define MAXU16   0xffff     /* maximum unsigned 16-bit quantity */
6233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define BPN      4          /* bits per nibble */
6333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define NPB      2          /* nibbles per byte */
6433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg
6533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define DOSMAGIC  0xaa55    /* DOS magic number */
6633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define MINBPS    512       /* minimum bytes per sector */
6733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define MAXSPC    128       /* maximum sectors per cluster */
6833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define MAXNFT    16        /* maximum number of FATs */
6933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define DEFBLK    4096      /* default block size */
7033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define DEFBLK16  2048      /* default block size FAT16 */
7133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define DEFRDE    512       /* default root directory entries */
7233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define RESFTE    2         /* reserved FAT entries */
7333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define MINCLS12  1         /* minimum FAT12 clusters */
7433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define MINCLS16  0x1000    /* minimum FAT16 clusters */
7533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define MINCLS32  2         /* minimum FAT32 clusters */
7633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define MAXCLS12  0xfed     /* maximum FAT12 clusters */
7733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define MAXCLS16  0xfff5    /* maximum FAT16 clusters */
7833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define MAXCLS32  0xffffff5 /* maximum FAT32 clusters */
7933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg
8033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define mincls(fat)  ((fat) == 12 ? MINCLS12 :    \
8133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                      (fat) == 16 ? MINCLS16 :    \
8233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                                        MINCLS32)
8333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg
8433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define maxcls(fat)  ((fat) == 12 ? MAXCLS12 :    \
8533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                      (fat) == 16 ? MAXCLS16 :    \
8633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                                        MAXCLS32)
8733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg
8833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define mk1(p, x)                           \
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    (p) = (u_int8_t)(x)
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
9133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define mk2(p, x)                           \
9233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    (p)[0] = (u_int8_t)(x),                 \
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    (p)[1] = (u_int8_t)((x) >> 010)
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
9533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg#define mk4(p, x)                           \
9633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    (p)[0] = (u_int8_t)(x),                 \
9733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    (p)[1] = (u_int8_t)((x) >> 010),        \
9833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    (p)[2] = (u_int8_t)((x) >> 020),        \
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    (p)[3] = (u_int8_t)((x) >> 030)
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define argto1(arg, lo, msg)  argtou(arg, lo, 0xff, msg)
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define argto2(arg, lo, msg)  argtou(arg, lo, 0xffff, msg)
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define argto4(arg, lo, msg)  argtou(arg, lo, 0xffffffff, msg)
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define argtox(arg, lo, msg)  argtou(arg, lo, UINT_MAX, msg)
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct bs {
10733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t jmp[3];        /* bootstrap entry point */
10833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t oem[8];        /* OEM name and version */
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct bsbpb {
11233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t bps[2];    /* bytes per sector */
11333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t spc;       /* sectors per cluster */
11433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t res[2];    /* reserved sectors */
11533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t nft;       /* number of FATs */
11633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t rde[2];    /* root directory entries */
11733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t sec[2];    /* total sectors */
11833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t mid;       /* media descriptor */
11933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t spf[2];    /* sectors per FAT */
12033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t spt[2];    /* sectors per track */
12133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t hds[2];    /* drive heads */
12233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t hid[4];    /* hidden sectors */
12333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t bsec[4];   /* big total sectors */
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct bsxbpb {
12733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t bspf[4];       /* big sectors per FAT */
12833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t xflg[2];       /* FAT control flags */
12933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t vers[2];       /* file system version */
13033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t rdcl[4];       /* root directory start cluster */
13133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t infs[2];       /* file system info sector */
13233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t bkbs[2];       /* backup boot sector */
13333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t rsvd[12];      /* reserved */
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct bsx {
13733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t drv;           /* drive number */
13833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t rsvd;          /* reserved */
13933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t sig;           /* extended boot signature */
14033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t volid[4];      /* volume ID number */
14133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t label[11];     /* volume label */
14233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t type[8];       /* file system type */
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct de {
14633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t namext[11];    /* name and extension */
14733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t attr;          /* attributes */
14833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t rsvd[10];      /* reserved */
14933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t time[2];       /* creation time */
15033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t date[2];       /* creation date */
15133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t clus[2];       /* starting cluster */
15233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int8_t size[4];       /* size */
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct bpb {
15633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int bps;          /* bytes per sector */
15733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int spc;          /* sectors per cluster */
15833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int res;          /* reserved sectors */
15933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int nft;          /* number of FATs */
16033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int rde;          /* root directory entries */
16133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int sec;          /* total sectors */
16233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int mid;          /* media descriptor */
16333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int spf;          /* sectors per FAT */
16433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int spt;          /* sectors per track */
16533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int hds;          /* drive heads */
16633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int hid;          /* hidden sectors */
16733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int bsec;         /* big total sectors */
16833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int bspf;         /* big sectors per FAT */
16933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int rdcl;         /* root directory start cluster */
17033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int infs;         /* file system info sector */
17133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    u_int bkbs;         /* backup boot sector */
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat#define BPBGAP 0, 0, 0, 0, 0, 0
17572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
17672eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehatstatic struct {
17772eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    const char *name;
17872eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    struct bpb bpb;
17972eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat} const stdfmt[] = {
18072eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    {"160",  {512, 1, 1, 2,  64,  320, 0xfe, 1,  8, 1, BPBGAP}},
18172eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    {"180",  {512, 1, 1, 2,  64,  360, 0xfc, 2,  9, 1, BPBGAP}},
18272eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    {"320",  {512, 2, 1, 2, 112,  640, 0xff, 1,  8, 2, BPBGAP}},
18372eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    {"360",  {512, 2, 1, 2, 112,  720, 0xfd, 2,  9, 2, BPBGAP}},
18433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    {"640",  {512, 2, 1, 2, 112, 1280, 0xfb, 2,  8, 2, BPBGAP}},
18572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    {"720",  {512, 2, 1, 2, 112, 1440, 0xf9, 3,  9, 2, BPBGAP}},
18672eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    {"1200", {512, 1, 1, 2, 224, 2400, 0xf9, 7, 15, 2, BPBGAP}},
18733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    {"1232", {1024,1, 1, 2, 192, 1232, 0xfe, 2,  8, 2, BPBGAP}},
18872eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    {"1440", {512, 1, 1, 2, 224, 2880, 0xf0, 9, 18, 2, BPBGAP}},
18972eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    {"2880", {512, 2, 1, 2, 240, 5760, 0xf0, 9, 36, 2, BPBGAP}}
19072eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat};
19172eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
19272eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehatstatic const u_int8_t bootcode[] = {
19333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0xfa,               /* cli             */
19433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0x31, 0xc0,         /* xor    ax,ax    */
19533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0x8e, 0xd0,         /* mov    ss,ax    */
19633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0xbc, 0x00, 0x7c,   /* mov    sp,7c00h */
19733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0xfb,               /* sti             */
19833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0x8e, 0xd8,         /* mov    ds,ax    */
19933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0xe8, 0x00, 0x00,   /* call   $ + 3    */
20033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0x5e,               /* pop    si       */
20133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0x83, 0xc6, 0x19,   /* add    si,+19h  */
20233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0xbb, 0x07, 0x00,   /* mov    bx,0007h */
20333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0xfc,               /* cld             */
20433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0xac,               /* lodsb           */
20533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0x84, 0xc0,         /* test   al,al    */
20633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0x74, 0x06,         /* jz     $ + 8    */
20733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0xb4, 0x0e,         /* mov    ah,0eh   */
20833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0xcd, 0x10,         /* int    10h      */
20933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0xeb, 0xf5,         /* jmp    $ - 9    */
21033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0x30, 0xe4,         /* xor    ah,ah    */
21133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0xcd, 0x16,         /* int    16h      */
21233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    0xcd, 0x19,         /* int    19h      */
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0x0d, 0x0a,
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    'N', 'o', 'n', '-', 's', 'y', 's', 't',
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    'e', 'm', ' ', 'd', 'i', 's', 'k',
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0x0d, 0x0a,
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    'P', 'r', 'e', 's', 's', ' ', 'a', 'n',
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    'y', ' ', 'k', 'e', 'y', ' ', 't', 'o',
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ' ', 'r', 'e', 'b', 'o', 'o', 't',
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0x0d, 0x0a,
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    0
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
22472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehatstatic void check_mounted(const char *, mode_t);
22572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehatstatic void getstdfmt(const char *, struct bpb *);
22633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenbergstatic void getdiskinfo(int, const char *, const char *, int, struct bpb *);
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void print_bpb(struct bpb *);
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic u_int ckgeom(const char *, u_int, const char *);
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic u_int argtou(const char *, u_int, u_int, const char *);
23072eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehatstatic off_t argtooff(const char *, const char *);
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int oklabel(const char *);
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void mklabel(u_int8_t *, const char *);
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void setstr(u_int8_t *, const char *, size_t);
23472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehatstatic void usage(void);
23572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Construct a FAT12, FAT16, or FAT32 file system.
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
23933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenbergint newfs_msdos_main(int argc, char *argv[])
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
241052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg    static const char opts[] = "@:NAB:C:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:u:";
24272eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    const char *opt_B = NULL, *opt_L = NULL, *opt_O = NULL, *opt_f = NULL;
24372eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    u_int opt_F = 0, opt_I = 0, opt_S = 0, opt_a = 0, opt_b = 0, opt_c = 0;
24472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    u_int opt_e = 0, opt_h = 0, opt_i = 0, opt_k = 0, opt_m = 0, opt_n = 0;
24572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    u_int opt_o = 0, opt_r = 0, opt_s = 0, opt_u = 0;
246052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg    u_int opt_A = 0;
24772eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    int opt_N = 0;
24872eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    int Iflag = 0, mflag = 0, oflag = 0;
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char buf[MAXPATHLEN];
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct stat sb;
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct timeval tv;
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct bpb bpb;
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct tm *tm;
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct bs *bs;
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct bsbpb *bsbpb;
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct bsxbpb *bsxbpb;
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct bsx *bsx;
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct de *de;
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    u_int8_t *img;
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const char *fname, *dtype, *bname;
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ssize_t n;
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    time_t now;
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    u_int fat, bss, rds, cls, dir, lsn, x, x1, x2;
264052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg    u_int extra_res, alignment=0, set_res, set_spf, set_spc, tempx, attempts=0;
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int ch, fd, fd1;
26672eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    off_t opt_create = 0, opt_ofs = 0;
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while ((ch = getopt(argc, argv, opts)) != -1)
26933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        switch (ch) {
27033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case '@':
27133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_ofs = argtooff(optarg, "offset");
27233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
27333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'N':
27433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_N = 1;
27533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
276052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        case 'A':
277052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg            opt_A = 1;
278052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg            break;
27933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'B':
28033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_B = optarg;
28133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
28233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'C':
28333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_create = argtooff(optarg, "create size");
28433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
28533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'F':
28633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            if (strcmp(optarg, "12") &&  strcmp(optarg, "16") && strcmp(optarg, "32"))
28733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                errx(1, "%s: bad FAT type", optarg);
28833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_F = atoi(optarg);
28933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
29033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'I':
29133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_I = argto4(optarg, 0, "volume ID");
29233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            Iflag = 1;
29333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
29433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'L':
29533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            if (!oklabel(optarg))
29633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                errx(1, "%s: bad volume label", optarg);
29733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_L = optarg;
29833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
29933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'O':
30033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            if (strlen(optarg) > 8)
30133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                errx(1, "%s: bad OEM string", optarg);
30233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_O = optarg;
30333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
30433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'S':
30533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_S = argto2(optarg, 1, "bytes/sector");
30633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
30733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'a':
30833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_a = argto4(optarg, 1, "sectors/FAT");
30933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
31033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'b':
31133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_b = argtox(optarg, 1, "block size");
31233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_c = 0;
31333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
31433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'c':
31533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_c = argto1(optarg, 1, "sectors/cluster");
31633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_b = 0;
31733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
31833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'e':
31933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_e = argto2(optarg, 1, "directory entries");
32033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
32133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'f':
32233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_f = optarg;
32333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
32433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'h':
32533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_h = argto2(optarg, 1, "drive heads");
32633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
32733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'i':
32833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_i = argto2(optarg, 1, "info sector");
32933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
33033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'k':
33133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_k = argto2(optarg, 1, "backup sector");
33233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
33333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'm':
33433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_m = argto1(optarg, 0, "media descriptor");
33533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            mflag = 1;
33633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
33733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'n':
33833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_n = argto1(optarg, 1, "number of FATs");
33933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
34033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'o':
34133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_o = argto4(optarg, 0, "hidden sectors");
34233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            oflag = 1;
34333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
34433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'r':
34533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_r = argto2(optarg, 1, "reserved sectors");
34633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
34733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 's':
34833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_s = argto4(optarg, 1, "file system size");
34933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
35033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        case 'u':
35133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            opt_u = argto2(optarg, 1, "sectors/track");
35233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
35333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        default:
35433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            usage();
35533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        }
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    argc -= optind;
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    argv += optind;
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (argc < 1 || argc > 2)
35933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        usage();
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fname = *argv++;
36172eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (!opt_create && !strchr(fname, '/')) {
36233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname);
36333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (!(fname = strdup(buf)))
36433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            err(1, "%s", buf);
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dtype = *argv;
367052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg    if (opt_A) {
368052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        if (opt_r)
369052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg            errx(1, "align (-A) is incompatible with -r");
370052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        if (opt_N)
371052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg            errx(1, "align (-A) is incompatible with -N");
372052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg    }
37372eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (opt_create) {
37433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (opt_N)
37533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            errx(1, "create (-C) is incompatible with -N");
37633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644);
37733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (fd == -1)
37833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            errx(1, "failed to create %s", fname);
37933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (ftruncate(fd, opt_create))
38033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            errx(1, "failed to initialize %jd bytes", (intmax_t)opt_create);
38172eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    } else if ((fd = open(fname, opt_N ? O_RDONLY : O_RDWR)) == -1)
38233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        err(1, "%s", fname);
38372eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (fstat(fd, &sb))
38433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        err(1, "%s", fname);
38572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (opt_create) {
38633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (!S_ISREG(sb.st_mode))
38733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            warnx("warning, %s is not a regular file", fname);
38872eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    } else {
38933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (!S_ISCHR(sb.st_mode))
39033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            warnx("warning, %s is not a character device", fname);
39172eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    }
39272eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (!opt_N)
39333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        check_mounted(fname, sb.st_mode);
39472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (opt_ofs && opt_ofs != lseek(fd, opt_ofs, SEEK_SET))
39533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        errx(1, "cannot seek to %jd", (intmax_t)opt_ofs);
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&bpb, 0, sizeof(bpb));
39772eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (opt_f) {
39833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        getstdfmt(opt_f, &bpb);
39933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.bsec = bpb.sec;
40033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.sec = 0;
40133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.bspf = bpb.spf;
40233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.spf = 0;
40372eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    }
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (opt_h)
40533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.hds = opt_h;
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (opt_u)
40733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.spt = opt_u;
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (opt_S)
40933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.bps = opt_S;
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (opt_s)
41133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.bsec = opt_s;
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (oflag)
41333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.hid = opt_o;
41472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (!(opt_f || (opt_h && opt_u && opt_S && opt_s && oflag))) {
41533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        off_t delta;
41633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        getdiskinfo(fd, fname, dtype, oflag, &bpb);
417661aff600c5cb8e72aa2892a2a75ea6015bf1457San Mehat        if (opt_s) {
418661aff600c5cb8e72aa2892a2a75ea6015bf1457San Mehat            bpb.bsec = opt_s;
419661aff600c5cb8e72aa2892a2a75ea6015bf1457San Mehat        }
42033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.bsec -= (opt_ofs / bpb.bps);
42133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        delta = bpb.bsec % bpb.spt;
42233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (delta != 0) {
42333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            warnx("trim %d sectors from %d to adjust to a multiple of %d",
42433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                  (int)delta, bpb.bsec, bpb.spt);
42533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            bpb.bsec -= delta;
42633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        }
42733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (bpb.spc == 0) {    /* set defaults */
42833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            if (bpb.bsec <= 6000)    /* about 3MB -> 512 bytes */
42933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                bpb.spc = 1;
43033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            else if (bpb.bsec <= (1<<17)) /* 64M -> 4k */
43133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                bpb.spc = 8;
43233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            else if (bpb.bsec <= (1<<19)) /* 256M -> 8k */
43333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                bpb.spc = 16;
43433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            else if (bpb.bsec <= (1<<22)) /* 2G -> 16k, some versions of windows
43533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                                         require a minimum of 65527 clusters */
43633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                bpb.spc = 32;
43733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            else
43833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                bpb.spc = 64;        /* otherwise 32k */
43933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        }
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!powerof2(bpb.bps))
44233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        errx(1, "bytes/sector (%u) is not a power of 2", bpb.bps);
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (bpb.bps < MINBPS)
44433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        errx(1, "bytes/sector (%u) is too small; minimum is %u",
44533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg             bpb.bps, MINBPS);
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!(fat = opt_F)) {
44733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (opt_f)
44833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            fat = 12;
44933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        else if (!opt_e && (opt_i || opt_k))
45033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            fat = 32;
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if ((fat == 32 && opt_e) || (fat != 32 && (opt_i || opt_k)))
45333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        errx(1, "-%c is not a legal FAT%s option",
45433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg             fat == 32 ? 'e' : opt_i ? 'i' : 'k',
45533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                     fat == 32 ? "32" : "12/16");
45672eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (opt_f && fat == 32)
45733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.rde = 0;
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (opt_b) {
45933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (!powerof2(opt_b))
46033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            errx(1, "block size (%u) is not a power of 2", opt_b);
46133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (opt_b < bpb.bps)
46233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            errx(1, "block size (%u) is too small; minimum is %u",
46333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                 opt_b, bpb.bps);
46433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (opt_b > bpb.bps * MAXSPC)
46533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            errx(1, "block size (%u) is too large; maximum is %u", opt_b, bpb.bps * MAXSPC);
46633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.spc = opt_b / bpb.bps;
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (opt_c) {
46933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (!powerof2(opt_c))
47033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            errx(1, "sectors/cluster (%u) is not a power of 2", opt_c);
47133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.spc = opt_c;
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (opt_r)
47433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.res = opt_r;
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (opt_n) {
47633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (opt_n > MAXNFT)
47733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            errx(1, "number of FATs (%u) is too large; maximum is %u", opt_n, MAXNFT);
47833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.nft = opt_n;
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (opt_e)
48133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.rde = opt_e;
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (mflag) {
48333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (opt_m < 0xf0)
48433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            errx(1, "illegal media descriptor (%#x)", opt_m);
48533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.mid = opt_m;
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (opt_a)
48833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.bspf = opt_a;
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (opt_i)
49033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.infs = opt_i;
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (opt_k)
49233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.bkbs = opt_k;
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    bss = 1;
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    bname = NULL;
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd1 = -1;
496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (opt_B) {
49733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bname = opt_B;
49833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (!strchr(bname, '/')) {
49933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            snprintf(buf, sizeof(buf), "/boot/%s", bname);
50033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            if (!(bname = strdup(buf)))
50133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                err(1, "%s", buf);
50233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        }
50333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if ((fd1 = open(bname, O_RDONLY)) == -1 || fstat(fd1, &sb))
50433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            err(1, "%s", bname);
50533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (!S_ISREG(sb.st_mode) || sb.st_size % bpb.bps ||
50633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                sb.st_size < bpb.bps || sb.st_size > bpb.bps * MAXU16)
50733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            errx(1, "%s: inappropriate file type or format", bname);
50833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bss = sb.st_size / bpb.bps;
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!bpb.nft)
51133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.nft = 2;
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!fat) {
51333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (bpb.bsec < (bpb.res ? bpb.res : bss) +
51433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                howmany((RESFTE + (bpb.spc ? MINCLS16 : MAXCLS12 + 1)) *
51533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                        ((bpb.spc ? 16 : 12) / BPN), bpb.bps * NPB) *
51633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                        bpb.nft +
51733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                        howmany(bpb.rde ? bpb.rde : DEFRDE,
51833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                                bpb.bps / sizeof(struct de)) +
51933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                                (bpb.spc ? MINCLS16 : MAXCLS12 + 1) *
52033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                                (bpb.spc ? bpb.spc : howmany(DEFBLK, bpb.bps)))
52133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            fat = 12;
52233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        else if (bpb.rde || bpb.bsec <
52333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                (bpb.res ? bpb.res : bss) +
52433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                howmany((RESFTE + MAXCLS16) * 2, bpb.bps) * bpb.nft +
52533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                howmany(DEFRDE, bpb.bps / sizeof(struct de)) +
52633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                (MAXCLS16 + 1) *
52733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                (bpb.spc ? bpb.spc : howmany(8192, bpb.bps)))
52833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            fat = 16;
52933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        else
53033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            fat = 32;
531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    x = bss;
533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fat == 32) {
53433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (!bpb.infs) {
53533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            if (x == MAXU16 || x == bpb.bkbs)
53633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                errx(1, "no room for info sector");
53733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            bpb.infs = x;
53833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        }
53933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (bpb.infs != MAXU16 && x <= bpb.infs)
54033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            x = bpb.infs + 1;
54133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (!bpb.bkbs) {
54233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            if (x == MAXU16)
54333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                errx(1, "no room for backup sector");
54433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            bpb.bkbs = x;
54533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        } else if (bpb.bkbs != MAXU16 && bpb.bkbs == bpb.infs)
54633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            errx(1, "backup sector would overwrite info sector");
54733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (bpb.bkbs != MAXU16 && x <= bpb.bkbs)
54833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            x = bpb.bkbs + 1;
549dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
550052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg
551052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg    extra_res = 0;
552052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg    set_res = !bpb.res;
553052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg    set_spf = !bpb.bspf;
554052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg    set_spc = !bpb.spc;
555052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg    tempx = x;
556052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg    /*
557052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg     * Attempt to align if opt_A is set. This is done by increasing the number
558052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg     * of reserved blocks. This can cause other factors to change, which can in
559052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg     * turn change the alignment. This should take at most 2 iterations, as
560052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg     * increasing the reserved amount may cause the FAT size to decrease by 1,
561052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg     * requiring another nft reserved blocks. If spc changes, it will
562052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg     * be half of its previous size, and thus will not throw off alignment.
563052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg     */
564052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg    do {
565052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        x = tempx;
566052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        if (set_res)
567052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg            bpb.res = (fat == 32 ? MAX(x, MAX(16384 / bpb.bps, 4)) : x) + extra_res;
568052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        else if (bpb.res < x)
569052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg            errx(1, "too few reserved sectors");
570052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        if (fat != 32 && !bpb.rde)
571052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg            bpb.rde = DEFRDE;
572052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        rds = howmany(bpb.rde, bpb.bps / sizeof(struct de));
573052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        if (set_spc)
574052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg            for (bpb.spc = howmany(fat == 16 ? DEFBLK16 : DEFBLK, bpb.bps);
575052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg                    bpb.spc < MAXSPC &&
576052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg                    bpb.res +
577052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg                    howmany((RESFTE + maxcls(fat)) * (fat / BPN),
578052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg                            bpb.bps * NPB) * bpb.nft +
579052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg                            rds +
580052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg                            (u_int64_t)(maxcls(fat) + 1) * bpb.spc <= bpb.bsec;
581052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg                    bpb.spc <<= 1);
582052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        if (fat != 32 && bpb.bspf > MAXU16)
583052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg            errx(1, "too many sectors/FAT for FAT12/16");
584052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        x1 = bpb.res + rds;
585052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        x = bpb.bspf ? bpb.bspf : 1;
586052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        if (x1 + (u_int64_t)x * bpb.nft > bpb.bsec)
587052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg            errx(1, "meta data exceeds file system size");
588052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        x1 += x * bpb.nft;
589052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        x = (u_int64_t)(bpb.bsec - x1) * bpb.bps * NPB /
590052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg                (bpb.spc * bpb.bps * NPB + fat / BPN * bpb.nft);
591052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        x2 = howmany((RESFTE + MIN(x, maxcls(fat))) * (fat / BPN), bpb.bps * NPB);
592052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        if (set_spf) {
5938218b6aae9cd4a19fa074a8a8203fe9275b35447Daniel Rosenberg            if (!bpb.bspf) {
5948218b6aae9cd4a19fa074a8a8203fe9275b35447Daniel Rosenberg                bpb.bspf = x2;
5958218b6aae9cd4a19fa074a8a8203fe9275b35447Daniel Rosenberg            }
596052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg            x1 += (bpb.bspf - 1) * bpb.nft;
597052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        }
598052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        if(set_res) {
599052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg            /* attempt to align root directory */
600052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg            alignment = (bpb.res + bpb.bspf * bpb.nft) % bpb.spc;
601052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg            extra_res += bpb.spc - alignment;
602052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        }
603052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        attempts++;
604052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg    } while(opt_A && alignment != 0 && attempts < 2);
605052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg    if (alignment != 0)
606052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg        warnx("warning: Alignment failed.");
607052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg
608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    cls = (bpb.bsec - x1) / bpb.spc;
609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    x = (u_int64_t)bpb.bspf * bpb.bps * NPB / (fat / BPN) - RESFTE;
610dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (cls > x)
61133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        cls = x;
612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (bpb.bspf < x2)
61333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        warnx("warning: sectors/FAT limits file system to %u clusters", cls);
614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (cls < mincls(fat))
61533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        errx(1, "%u clusters too few clusters for FAT%u, need %u", cls, fat, mincls(fat));
616dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (cls > maxcls(fat)) {
61733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        cls = maxcls(fat);
61833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.bsec = x1 + (cls + 1) * bpb.spc - 1;
61933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        warnx("warning: FAT type limits file system to %u sectors", bpb.bsec);
620dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
62133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    printf("%s: %u sector%s in %u FAT%u cluster%s (%u bytes/cluster)\n",
62233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg           fname, cls * bpb.spc, cls * bpb.spc == 1 ? "" : "s", cls, fat,
62333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg           cls == 1 ? "" : "s", bpb.bps * bpb.spc);
624dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!bpb.mid)
62533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.mid = !bpb.hid ? 0xf0 : 0xf8;
626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fat == 32)
62733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.rdcl = RESFTE;
628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (bpb.hid + bpb.bsec <= MAXU16) {
62933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.sec = bpb.bsec;
63033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.bsec = 0;
631dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fat != 32) {
63333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.spf = bpb.bspf;
63433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb.bspf = 0;
635dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    print_bpb(&bpb);
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!opt_N) {
63833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        gettimeofday(&tv, NULL);
63933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        now = tv.tv_sec;
64033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        tm = localtime(&now);
64133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (!(img = malloc(bpb.bps)))
64233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            err(1, "%u", bpb.bps);
64333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        dir = bpb.res + (bpb.spf ? bpb.spf : bpb.bspf) * bpb.nft;
64433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        for (lsn = 0; lsn < dir + (fat == 32 ? bpb.spc : rds); lsn++) {
64533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            x = lsn;
64633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            if (opt_B && fat == 32 && bpb.bkbs != MAXU16 && bss <= bpb.bkbs && x >= bpb.bkbs) {
64733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                x -= bpb.bkbs;
64833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                if (!x && lseek(fd1, opt_ofs, SEEK_SET))
64933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    err(1, "%s", bname);
65033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            }
65133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            if (opt_B && x < bss) {
65233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                if ((n = read(fd1, img, bpb.bps)) == -1)
65333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    err(1, "%s", bname);
65433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                if ((unsigned)n != bpb.bps)
65533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    errx(1, "%s: can't read sector %u", bname, x);
65633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            } else
65733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                memset(img, 0, bpb.bps);
65833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            if (!lsn || (fat == 32 && bpb.bkbs != MAXU16 && lsn == bpb.bkbs)) {
65933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                x1 = sizeof(struct bs);
66033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                bsbpb = (struct bsbpb *)(img + x1);
66133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk2(bsbpb->bps, bpb.bps);
66233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk1(bsbpb->spc, bpb.spc);
66333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk2(bsbpb->res, bpb.res);
66433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk1(bsbpb->nft, bpb.nft);
66533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk2(bsbpb->rde, bpb.rde);
66633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk2(bsbpb->sec, bpb.sec);
66733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk1(bsbpb->mid, bpb.mid);
66833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk2(bsbpb->spf, bpb.spf);
66933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk2(bsbpb->spt, bpb.spt);
67033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk2(bsbpb->hds, bpb.hds);
67133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk4(bsbpb->hid, bpb.hid);
67233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk4(bsbpb->bsec, bpb.bsec);
67333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                x1 += sizeof(struct bsbpb);
67433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                if (fat == 32) {
67533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    bsxbpb = (struct bsxbpb *)(img + x1);
67633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    mk4(bsxbpb->bspf, bpb.bspf);
67733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    mk2(bsxbpb->xflg, 0);
67833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    mk2(bsxbpb->vers, 0);
67933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    mk4(bsxbpb->rdcl, bpb.rdcl);
68033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    mk2(bsxbpb->infs, bpb.infs);
68133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    mk2(bsxbpb->bkbs, bpb.bkbs);
68233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    x1 += sizeof(struct bsxbpb);
68333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                }
68433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                bsx = (struct bsx *)(img + x1);
68533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk1(bsx->sig, 0x29);
68633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                if (Iflag)
68733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    x = opt_I;
68833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                else
68933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    x = (((u_int)(1 + tm->tm_mon) << 8 |
69033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                            (u_int)tm->tm_mday) +
69133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                            ((u_int)tm->tm_sec << 8 |
69233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                                    (u_int)(tv.tv_usec / 10))) << 16 |
69333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                                    ((u_int)(1900 + tm->tm_year) +
69433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                                            ((u_int)tm->tm_hour << 8 |
69533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                                                    (u_int)tm->tm_min));
69633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk4(bsx->volid, x);
69733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mklabel(bsx->label, opt_L ? opt_L : "NO NAME");
69833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                sprintf(buf, "FAT%u", fat);
69933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                setstr(bsx->type, buf, sizeof(bsx->type));
70033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                if (!opt_B) {
70133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    x1 += sizeof(struct bsx);
70233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    bs = (struct bs *)img;
70333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    mk1(bs->jmp[0], 0xeb);
70433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    mk1(bs->jmp[1], x1 - 2);
70533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    mk1(bs->jmp[2], 0x90);
70633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    setstr(bs->oem, opt_O ? opt_O : "BSD  4.4",
70733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                            sizeof(bs->oem));
70833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    memcpy(img + x1, bootcode, sizeof(bootcode));
70933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    mk2(img + MINBPS - 2, DOSMAGIC);
71033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                }
71133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            } else if (fat == 32 && bpb.infs != MAXU16 &&
71233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    (lsn == bpb.infs || (bpb.bkbs != MAXU16 &&
71333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                                    lsn == bpb.bkbs + bpb.infs))) {
71433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk4(img, 0x41615252);
71533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk4(img + MINBPS - 28, 0x61417272);
71633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk4(img + MINBPS - 24, 0xffffffff);
71733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk4(img + MINBPS - 20, bpb.rdcl);
71833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk2(img + MINBPS - 2, DOSMAGIC);
71933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            } else if (lsn >= bpb.res && lsn < dir &&
72033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    !((lsn - bpb.res) % (bpb.spf ? bpb.spf : bpb.bspf))) {
72133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk1(img[0], bpb.mid);
72233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                for (x = 1; x < fat * (fat == 32 ? 3 : 2) / 8; x++)
72333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    mk1(img[x], fat == 32 && x % 4 == 3 ? 0x0f : 0xff);
72433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            } else if (lsn == dir && opt_L) {
72533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                de = (struct de *)img;
72633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mklabel(de->namext, opt_L);
72733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk1(de->attr, 050);
72833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                x = (u_int)tm->tm_hour << 11 |
72933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                        (u_int)tm->tm_min << 5 |
73033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                        (u_int)tm->tm_sec >> 1;
73133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk2(de->time, x);
73233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                x = (u_int)(tm->tm_year - 80) << 9 |
73333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                        (u_int)(tm->tm_mon + 1) << 5 |
73433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                        (u_int)tm->tm_mday;
73533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                mk2(de->date, x);
73633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            }
73733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            if ((n = write(fd, img, bpb.bps)) == -1)
73833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                err(1, "%s", fname);
73933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            if ((unsigned)n != bpb.bps) {
74033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                errx(1, "%s: can't write sector %u", fname, lsn);
741eab453c612d6d422f863c31da67f00bc4beec914San Mehat                exit(1);
742eab453c612d6d422f863c31da67f00bc4beec914San Mehat            }
74333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        }
744dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
745dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
746dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
747dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
748dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
74972eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat * Exit with error if file system is mounted.
75072eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat */
75133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenbergstatic void check_mounted(const char *fname, mode_t mode)
75272eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat{
753aa907768af7ba9e29901d356cdcac6a436970323Mark Salyzyn#ifdef ANDROID
754aa907768af7ba9e29901d356cdcac6a436970323Mark Salyzyn    warnx("Skipping mount checks");
755aa907768af7ba9e29901d356cdcac6a436970323Mark Salyzyn#else
75672eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    struct statfs *mp;
75772eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    const char *s1, *s2;
75872eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    size_t len;
75972eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    int n, r;
76072eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
76172eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (!(n = getmntinfo(&mp, MNT_NOWAIT)))
76233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        err(1, "getmntinfo");
76372eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    len = strlen(_PATH_DEV);
76472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    s1 = fname;
76572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (!strncmp(s1, _PATH_DEV, len))
76633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        s1 += len;
76772eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    r = S_ISCHR(mode) && s1 != fname && *s1 == 'r';
76872eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    for (; n--; mp++) {
76933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        s2 = mp->f_mntfromname;
77033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (!strncmp(s2, _PATH_DEV, len))
77133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            s2 += len;
77233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if ((r && s2 != mp->f_mntfromname && !strcmp(s1 + 1, s2)) || !strcmp(s1, s2))
77333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            errx(1, "%s is mounted on %s", fname, mp->f_mntonname);
77472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    }
77572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat#endif
77672eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat}
77772eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
77872eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat/*
77972eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat * Get a standard format.
78072eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat */
78133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenbergstatic void getstdfmt(const char *fmt, struct bpb *bpb)
78272eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat{
78372eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    u_int x, i;
78472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
78572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    x = sizeof(stdfmt) / sizeof(stdfmt[0]);
78672eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    for (i = 0; i < x && strcmp(fmt, stdfmt[i].name); i++);
78772eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (i == x)
78833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        errx(1, "%s: unknown standard format", fmt);
78972eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    *bpb = stdfmt[i].bpb;
79072eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat}
79172eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
79272eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat/*
79372eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat * Get disk slice, partition, and geometry information.
79472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat */
79572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
79672eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat#ifdef ANDROID
79733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenbergstatic void getdiskinfo(int fd, const char *fname, const char *dtype,
79833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                        __unused int oflag,struct bpb *bpb)
79972eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat{
80072eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    struct hd_geometry geom;
801c06541912d344d30df51b00d646f40c7c2cdad1dJohan Redestig    u_long block_size;
80272eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
80372eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (ioctl(fd, BLKSSZGET, &bpb->bps)) {
804ff3bcd03079d9e0e94f70955370f3eb940d6244aSan Mehat        fprintf(stderr, "Error getting bytes / sector (%s)\n", strerror(errno));
80572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat        exit(1);
80672eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    }
80772eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
80872eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    ckgeom(fname, bpb->bps, "bytes/sector");
80972eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
810c06541912d344d30df51b00d646f40c7c2cdad1dJohan Redestig    if (ioctl(fd, BLKGETSIZE, &block_size)) {
811ff3bcd03079d9e0e94f70955370f3eb940d6244aSan Mehat        fprintf(stderr, "Error getting blocksize (%s)\n", strerror(errno));
81272eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat        exit(1);
81372eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    }
81472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
815c06541912d344d30df51b00d646f40c7c2cdad1dJohan Redestig    if (block_size > UINT32_MAX) {
816c06541912d344d30df51b00d646f40c7c2cdad1dJohan Redestig        fprintf(stderr, "Error blocksize too large: %lu\n", block_size);
817c06541912d344d30df51b00d646f40c7c2cdad1dJohan Redestig        exit(1);
818c06541912d344d30df51b00d646f40c7c2cdad1dJohan Redestig    }
819c06541912d344d30df51b00d646f40c7c2cdad1dJohan Redestig
820c06541912d344d30df51b00d646f40c7c2cdad1dJohan Redestig    bpb->bsec = (u_int)block_size;
821c06541912d344d30df51b00d646f40c7c2cdad1dJohan Redestig
82272eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (ioctl(fd, HDIO_GETGEO, &geom)) {
823ff3bcd03079d9e0e94f70955370f3eb940d6244aSan Mehat        fprintf(stderr, "Error getting gemoetry (%s) - trying sane values\n", strerror(errno));
824ff3bcd03079d9e0e94f70955370f3eb940d6244aSan Mehat        geom.heads = 64;
825ff3bcd03079d9e0e94f70955370f3eb940d6244aSan Mehat        geom.sectors = 63;
82672eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    }
82772eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
828eab453c612d6d422f863c31da67f00bc4beec914San Mehat    if (!geom.heads) {
829eab453c612d6d422f863c31da67f00bc4beec914San Mehat        printf("Bogus heads from kernel - setting sane value\n");
830eab453c612d6d422f863c31da67f00bc4beec914San Mehat        geom.heads = 64;
831eab453c612d6d422f863c31da67f00bc4beec914San Mehat    }
832eab453c612d6d422f863c31da67f00bc4beec914San Mehat
833eab453c612d6d422f863c31da67f00bc4beec914San Mehat    if (!geom.sectors) {
834eab453c612d6d422f863c31da67f00bc4beec914San Mehat        printf("Bogus sectors from kernel - setting sane value\n");
835eab453c612d6d422f863c31da67f00bc4beec914San Mehat        geom.sectors = 63;
836eab453c612d6d422f863c31da67f00bc4beec914San Mehat    }
837eab453c612d6d422f863c31da67f00bc4beec914San Mehat
83872eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    bpb->spt = geom.sectors;
83972eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    ckgeom(fname, bpb->spt, "sectors/track");
84072eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
84172eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    bpb->hds = geom.heads;
84272eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    ckgeom(fname, bpb->hds, "drive heads");
84372eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat}
84472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
84572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat#else
84672eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
84733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenbergstatic void getdiskinfo(int fd, const char *fname, const char *dtype,
84833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                        __unused int oflag, struct bpb *bpb)
84972eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat{
85072eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    struct disklabel *lp, dlp;
85172eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    struct fd_type type;
85272eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    off_t ms, hs = 0;
85372eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
85472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    lp = NULL;
85572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
85672eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    /* If the user specified a disk type, try to use that */
85772eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (dtype != NULL) {
85833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        lp = getdiskbyname(dtype);
85972eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    }
86072eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
86172eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    /* Maybe it's a floppy drive */
86272eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (lp == NULL) {
86333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (ioctl(fd, DIOCGMEDIASIZE, &ms) == -1) {
86433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            struct stat st;
86533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg
86633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            if (fstat(fd, &st))
86733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                err(1, "Cannot get disk size");
86833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            /* create a fake geometry for a file image */
86933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            ms = st.st_size;
87033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            dlp.d_secsize = 512;
87133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            dlp.d_nsectors = 63;
87233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            dlp.d_ntracks = 255;
87333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            dlp.d_secperunit = ms / dlp.d_secsize;
87433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            lp = &dlp;
87533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        } else if (ioctl(fd, FD_GTYPE, &type) != -1) {
87633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            dlp.d_secsize = 128 << type.secsize;
87733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            dlp.d_nsectors = type.sectrac;
87833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            dlp.d_ntracks = type.heads;
87933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            dlp.d_secperunit = ms / dlp.d_secsize;
88033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            lp = &dlp;
88133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        }
88272eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    }
88372eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
88472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    /* Maybe it's a fixed drive */
88572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (lp == NULL) {
88633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (ioctl(fd, DIOCGDINFO, &dlp) == -1) {
88733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            if (bpb->bps == 0 && ioctl(fd, DIOCGSECTORSIZE, &dlp.d_secsize) == -1)
88833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                errx(1, "Cannot get sector size, %s", strerror(errno));
88933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg
89033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            /* XXX Should we use bpb->bps if it's set? */
89133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            dlp.d_secperunit = ms / dlp.d_secsize;
89233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg
89333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            if (bpb->spt == 0 && ioctl(fd, DIOCGFWSECTORS, &dlp.d_nsectors) == -1) {
89433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                warnx("Cannot get number of sectors per track, %s", strerror(errno));
89533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                dlp.d_nsectors = 63;
89633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            }
89733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            if (bpb->hds == 0 && ioctl(fd, DIOCGFWHEADS, &dlp.d_ntracks) == -1) {
89833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                warnx("Cannot get number of heads, %s", strerror(errno));
89933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                if (dlp.d_secperunit <= 63*1*1024)
90033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    dlp.d_ntracks = 1;
90133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                else if (dlp.d_secperunit <= 63*16*1024)
90233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    dlp.d_ntracks = 16;
90333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                else
90433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                    dlp.d_ntracks = 255;
90533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            }
90633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        }
90733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg
90833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        hs = (ms / dlp.d_secsize) - dlp.d_secperunit;
90933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        lp = &dlp;
91072eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    }
91172eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
91272eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (bpb->bps == 0)
91333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb->bps = ckgeom(fname, lp->d_secsize, "bytes/sector");
91472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (bpb->spt == 0)
91533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb->spt = ckgeom(fname, lp->d_nsectors, "sectors/track");
91672eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (bpb->hds == 0)
91733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb->hds = ckgeom(fname, lp->d_ntracks, "drive heads");
91872eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (bpb->bsec == 0)
91933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb->bsec = lp->d_secperunit;
92072eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (bpb->hid == 0)
92133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        bpb->hid = hs;
92272eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat}
92372eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat#endif
92472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
92572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat/*
926dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Print out BPB values.
927dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
92833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenbergstatic void print_bpb(struct bpb *bpb)
929dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
930dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    printf("bps=%u spc=%u res=%u nft=%u", bpb->bps, bpb->spc, bpb->res,
93133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg           bpb->nft);
932dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (bpb->rde)
93333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        printf(" rde=%u", bpb->rde);
934dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (bpb->sec)
93533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        printf(" sec=%u", bpb->sec);
936dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    printf(" mid=%#x", bpb->mid);
937dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (bpb->spf)
93833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        printf(" spf=%u", bpb->spf);
939dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    printf(" spt=%u hds=%u hid=%u", bpb->spt, bpb->hds, bpb->hid);
940dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (bpb->bsec)
94133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        printf(" bsec=%u", bpb->bsec);
942dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!bpb->spf) {
94333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        printf(" bspf=%u rdcl=%u", bpb->bspf, bpb->rdcl);
94433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        printf(" infs=");
94533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        printf(bpb->infs == MAXU16 ? "%#x" : "%u", bpb->infs);
94633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        printf(" bkbs=");
94733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        printf(bpb->bkbs == MAXU16 ? "%#x" : "%u", bpb->bkbs);
948dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
949dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    printf("\n");
950dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
951dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
952dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
953dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Check a disk geometry value.
954dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
95533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenbergstatic u_int ckgeom(const char *fname, u_int val, const char *msg)
956dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
957dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!val)
95833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        errx(1, "%s: no default %s", fname, msg);
959dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (val > MAXU16)
96033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        errx(1, "%s: illegal %s %d", fname, msg, val);
961dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return val;
962dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
963dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
964dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
965dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Convert and check a numeric option argument.
966dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
96733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenbergstatic u_int argtou(const char *arg, u_int lo, u_int hi, const char *msg)
968dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
969dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *s;
970dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    u_long x;
971dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
972dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    errno = 0;
973dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    x = strtoul(arg, &s, 0);
974dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (errno || !*arg || *s || x < lo || x > hi)
97533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        errx(1, "%s: bad %s", arg, msg);
97672eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    return x;
97772eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat}
97872eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
97972eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat/*
98072eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat * Same for off_t, with optional skmgpP suffix
98172eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat */
98233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenbergstatic off_t argtooff(const char *arg, const char *msg)
98372eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat{
98472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    char *s;
98572eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    off_t x;
98672eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat
98772eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    x = strtoll(arg, &s, 0);
98872eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    /* allow at most one extra char */
98972eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    if (errno || x < 0 || (s[0] && s[1]) )
99033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        errx(1, "%s: bad %s", arg, msg);
99133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    if (*s) {    /* the extra char is the multiplier */
99233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        switch (*s) {
99333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            default:
99433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                errx(1, "%s: bad %s", arg, msg);
99533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                /* notreached */
99633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg
99733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            case 's':       /* sector */
99833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            case 'S':
99933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                x <<= 9;    /* times 512 */
100033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                break;
100133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg
100233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            case 'k':       /* kilobyte */
100333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            case 'K':
100433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                x <<= 10;   /* times 1024 */
100533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                break;
100633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg
100733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            case 'm':       /* megabyte */
100833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            case 'M':
100933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                x <<= 20;   /* times 1024*1024 */
101033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                break;
101133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg
101233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            case 'g':       /* gigabyte */
101333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            case 'G':
101433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                x <<= 30;   /* times 1024*1024*1024 */
101533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                break;
101633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg
101733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            case 'p':       /* partition start */
101833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            case 'P':       /* partition start */
101933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            case 'l':       /* partition length */
102033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            case 'L':       /* partition length */
102133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                errx(1, "%s: not supported yet %s", arg, msg);
102233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg                /* notreached */
102333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        }
102472eead43c7711ca97b2d7f578e6b8854a2856ce0San Mehat    }
1025dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return x;
1026dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1027dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1028dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
1029dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Check a volume label.
1030dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
103133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenbergstatic int oklabel(const char *src)
1032dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1033dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int c, i;
1034dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1035dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i <= 11; i++) {
103633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        c = (u_char)*src++;
103733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        if (c < ' ' + !i || strchr("\"*+,./:;<=>?[\\]|", c))
103833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            break;
1039dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1040dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return i && !c;
1041dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1042dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1043dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
1044dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Make a volume label.
1045dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
104633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenbergstatic void mklabel(u_int8_t *dest, const char *src)
1047dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1048dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int c, i;
1049dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1050dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < 11; i++) {
105133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        c = *src ? toupper(*src++) : ' ';
105233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        *dest++ = !i && c == '\xe5' ? 5 : c;
1053dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1054dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1055dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1056dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
1057dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copy string, padding with spaces.
1058dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
105933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenbergstatic void setstr(u_int8_t *dest, const char *src, size_t len)
1060dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1061dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (len--)
106233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg        *dest++ = *src ? *src++ : ' ';
1063dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1064dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1065dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
1066dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Print usage message.
1067dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
106833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenbergstatic void usage(void)
1069dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
107033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    fprintf(stderr,
107133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "usage: newfs_msdos [ -options ] special [disktype]\n"
107233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "where the options are:\n"
107333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-@ create file system at specified offset\n"
1074052f27562154d175267999106bd6bf18fc8c363eDaniel Rosenberg            "\t-A Attempt to cluster align root directory\n"
107533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-B get bootstrap from file\n"
107633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-C create image file with specified size\n"
107733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-F FAT type (12, 16, or 32)\n"
107833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-I volume ID\n"
107933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-L volume label\n"
108033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-N don't create file system: just print out parameters\n"
108133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-O OEM string\n"
108233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-S bytes/sector\n"
108333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-a sectors/FAT\n"
108433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-b block size\n"
108533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-c sectors/cluster\n"
108633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-e root directory entries\n"
108733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-f standard format\n"
108833e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-h drive heads\n"
108933e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-i file system info sector\n"
109033e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-k backup boot sector\n"
109133e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-m media descriptor\n"
109233e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-n number of FATs\n"
109333e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-o hidden sectors\n"
109433e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-r reserved sectors\n"
109533e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-s file system size (sectors)\n"
109633e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg            "\t-u sectors/track\n");
109733e7b13167bcfd65b6c595e316e515ff8eab4b33Daniel Rosenberg    exit(1);
1098dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1099