Apply revisions 1.23 and 1.24 from FreeBSD to autocalculate the
necessary geometry when creating a file system directly to a file. In addition, when creating, do not complain about the file not being char special and do not try to execute device ioctl's on it.
This commit is contained in:
parent
02040931ba
commit
32852ecef0
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: newfs_msdos.8,v 1.15 2006/11/25 12:29:33 scw Exp $
|
||||
.\" $NetBSD: newfs_msdos.8,v 1.16 2009/03/26 08:39:24 pooka Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1998 Robert Nordier
|
||||
.\" All rights reserved.
|
||||
@ -27,7 +27,7 @@
|
||||
.\"
|
||||
.\" From: $FreeBSD: src/sbin/newfs_msdos/newfs_msdos.8,v 1.13 2001/08/14 10:01:48 ru Exp $
|
||||
.\"
|
||||
.Dd November 25, 2006
|
||||
.Dd March 26, 2009
|
||||
.Dt NEWFS_MSDOS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -36,7 +36,9 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl N
|
||||
.Op Fl @ Ar offset
|
||||
.Op Fl B Ar boot
|
||||
.Op Fl C Ar create-size
|
||||
.Op Fl F Ar FAT-type
|
||||
.Op Fl I Ar volid
|
||||
.Op Fl L Ar label
|
||||
@ -61,7 +63,7 @@
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility creates a FAT12, FAT16, or FAT32 file system on device
|
||||
utility creates a FAT12, FAT16, or FAT32 file system on device or file named
|
||||
.Ar special ,
|
||||
using
|
||||
.Xr disktab 5
|
||||
@ -73,8 +75,23 @@ The options are as follow:
|
||||
.Bl -tag -width indent
|
||||
.It Fl N
|
||||
Don't create a file system: just print out parameters.
|
||||
.It Fl @ Ar offset
|
||||
Build the filesystem at the specified offset in bytes in the device or file.
|
||||
A suffix s, k, m, g (lower or upper case)
|
||||
appended to the offset specifies that the
|
||||
number is in sectors, kilobytes, megabytes or gigabytes, respectively.
|
||||
.It Fl B Ar boot
|
||||
Get bootstrap from file.
|
||||
.It Fl C Ar create-size
|
||||
Create the image file with the specified size.
|
||||
A suffix character appended to the size is interpreted as for the
|
||||
.Fl @
|
||||
option.
|
||||
The file is created by truncating any existing file with the
|
||||
same name, seeking just before the required size and writing
|
||||
a single 0 byte.
|
||||
As a consequence, the space occupied on disk
|
||||
may be smaller than the size specified as a parameter.
|
||||
.It Fl F Ar FAT-type
|
||||
FAT type (one of 12, 16, or 32).
|
||||
.It Fl I Ar volid
|
||||
@ -101,6 +118,9 @@ per cluster (see below).
|
||||
.It Fl c Ar cluster-size
|
||||
Sectors per cluster.
|
||||
Acceptable values are powers of 2 in the range 1 through 128.
|
||||
If the block or cluster size are not specified, the code
|
||||
uses a cluster between 512 bytes and 32K depending on
|
||||
the filesystem size.
|
||||
.It Fl e Ar dirents
|
||||
Number of root directory entries (FAT12 and FAT16 only).
|
||||
.It Fl f Ar format
|
||||
@ -144,6 +164,15 @@ a line will be written to the standard error output indicating
|
||||
the name of the device currently being formatted, the sector
|
||||
number being written, and the total number of sectors to be written.
|
||||
.Sh NOTES
|
||||
If some parameters (e.g. size, number of sectors, etc.) are not specified
|
||||
through options or disktype, the program tries to generate them
|
||||
automatically. In particular, the size is determined as the
|
||||
device or file size minus the offset specified with the
|
||||
.Fl @
|
||||
option. When the geometry is not available, it is assumed to be
|
||||
63 sectors, 255 heads. The size is then rounded to become
|
||||
a multiple of the track size and avoid complaints by some filesystem code.
|
||||
.Pp
|
||||
FAT file system parameters occupy a "Boot Sector BPB (BIOS Parameter
|
||||
Block)" in the first of the "reserved" sectors which precede the actual
|
||||
file system.
|
||||
@ -188,6 +217,11 @@ Create a standard 1.44M file system, with volume label
|
||||
.Ar foo ,
|
||||
on
|
||||
.Pa /dev/rfd0a .
|
||||
Create a 30MB image file, with the FAT partition starting
|
||||
63 sectors within the image file:
|
||||
.Bd -literal -offset indent
|
||||
newfs_msdos -C 30M -@63s ./somefile
|
||||
.Ed
|
||||
.Sh DIAGNOSTICS
|
||||
Exit status is 0 on success and 1 on error.
|
||||
.Sh SEE ALSO
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: newfs_msdos.c,v 1.30 2009/02/17 00:16:35 christos Exp $ */
|
||||
/* $NetBSD: newfs_msdos.c,v 1.31 2009/03/26 08:39:24 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Robert Nordier
|
||||
@ -33,7 +33,7 @@
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD: src/sbin/newfs_msdos/newfs_msdos.c,v 1.15 2000/10/10 01:49:37 wollman Exp $";
|
||||
#else
|
||||
__RCSID("$NetBSD: newfs_msdos.c,v 1.30 2009/02/17 00:16:35 christos Exp $");
|
||||
__RCSID("$NetBSD: newfs_msdos.c,v 1.31 2009/03/26 08:39:24 pooka Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -229,10 +229,11 @@ static int got_siginfo = 0; /* received a SIGINFO */
|
||||
|
||||
static void check_mounted(const char *, mode_t);
|
||||
static void getstdfmt(const char *, struct bpb *);
|
||||
static void getbpbinfo(int, const char *, const char *, int, struct bpb *);
|
||||
static void getbpbinfo(int, const char *, const char *, int, struct bpb *, int);
|
||||
static void print_bpb(struct bpb *);
|
||||
static u_int ckgeom(const char *, u_int, const char *);
|
||||
static u_int argtou(const char *, u_int, u_int, const char *);
|
||||
static off_t argtooff(const char *, const char *);
|
||||
static int oklabel(const char *);
|
||||
static void mklabel(u_int8_t *, const char *);
|
||||
static void setstr(u_int8_t *, const char *, size_t);
|
||||
@ -245,7 +246,7 @@ static void infohandler(int sig);
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
static char opts[] = "NB:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:u:";
|
||||
static char opts[] = "@:NB:C:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:u:";
|
||||
static const char *opt_B, *opt_L, *opt_O, *opt_f;
|
||||
static u_int opt_F, opt_I, opt_S, opt_a, opt_b, opt_c, opt_e;
|
||||
static u_int opt_h, opt_i, opt_k, opt_m, opt_n, opt_o, opt_r;
|
||||
@ -268,15 +269,22 @@ main(int argc, char *argv[])
|
||||
time_t now;
|
||||
u_int fat, bss, rds, cls, dir, lsn, x, x1, x2;
|
||||
int ch, fd, fd1;
|
||||
static off_t opt_create=0, opt_ofs=0;
|
||||
|
||||
while ((ch = getopt(argc, argv, opts)) != -1)
|
||||
switch (ch) {
|
||||
case '@':
|
||||
opt_ofs = argtooff(optarg, "offset");
|
||||
break;
|
||||
case 'N':
|
||||
opt_N = 1;
|
||||
break;
|
||||
case 'B':
|
||||
opt_B = optarg;
|
||||
break;
|
||||
case 'C':
|
||||
opt_create = argtooff(optarg, "create size");
|
||||
break;
|
||||
case 'F':
|
||||
if (strcmp(optarg, "12") &&
|
||||
strcmp(optarg, "16") &&
|
||||
@ -355,19 +363,33 @@ main(int argc, char *argv[])
|
||||
if (argc < 1 || argc > 2)
|
||||
usage();
|
||||
fname = *argv++;
|
||||
if (!strchr(fname, '/')) {
|
||||
if (!strchr(fname, '/') && !opt_create) {
|
||||
snprintf(buf, sizeof(buf), "%sr%s", _PATH_DEV, fname);
|
||||
if (!(fname = strdup(buf)))
|
||||
err(1, NULL);
|
||||
}
|
||||
dtype = *argv;
|
||||
if ((fd = open(fname, opt_N ? O_RDONLY : O_RDWR)) == -1 ||
|
||||
if (opt_create) {
|
||||
off_t pos;
|
||||
|
||||
if (opt_N)
|
||||
errx(1, "create (-C) is incompatible with -N");
|
||||
fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd == -1)
|
||||
errx(1, "failed to create %s", fname);
|
||||
pos = lseek(fd, opt_create - 1, SEEK_SET);
|
||||
if (write(fd, "\0", 1) != 1)
|
||||
errx(1, "failed to initialize %lld bytes", opt_create);
|
||||
pos = lseek(fd, 0, SEEK_SET);
|
||||
} else if ((fd = open(fname, opt_N ? O_RDONLY : O_RDWR)) == -1 ||
|
||||
fstat(fd, &sb))
|
||||
err(1, "%s", fname);
|
||||
if (!opt_N)
|
||||
check_mounted(fname, sb.st_mode);
|
||||
if (!S_ISCHR(sb.st_mode))
|
||||
warnx("warning: %s is not a character device", fname);
|
||||
if (!S_ISCHR(sb.st_mode) && !opt_create)
|
||||
warnx("warning, %s is not a character device", fname);
|
||||
if (opt_ofs && opt_ofs != lseek(fd, opt_ofs, SEEK_SET))
|
||||
errx(1, "cannot seek to %lld", opt_ofs);
|
||||
memset(&bpb, 0, sizeof(bpb));
|
||||
if (opt_f) {
|
||||
getstdfmt(opt_f, &bpb);
|
||||
@ -386,8 +408,29 @@ main(int argc, char *argv[])
|
||||
bpb.bsec = opt_s;
|
||||
if (oflag)
|
||||
bpb.hid = opt_o;
|
||||
if (!(opt_f || (opt_h && opt_u && opt_S && opt_s && oflag)))
|
||||
getbpbinfo(fd, fname, dtype, oflag, &bpb);
|
||||
if (!(opt_f || (opt_h && opt_u && opt_S && opt_s && oflag))) {
|
||||
off_t delta;
|
||||
getbpbinfo(fd, fname, dtype, oflag, &bpb, opt_create != 0);
|
||||
bpb.bsec -= (opt_ofs / bpb.bps);
|
||||
delta = bpb.bsec % bpb.spt;
|
||||
if (delta != 0) {
|
||||
warnx("trim %d sectors to adjust to a multiple of %d",
|
||||
(int)delta, bpb.spt);
|
||||
bpb.bsec -= delta;
|
||||
}
|
||||
if (bpb.spc == 0) { /* set defaults */
|
||||
if (bpb.bsec <= 6000) /* about 3MB -> 512 bytes */
|
||||
bpb.spc = 1;
|
||||
else if (bpb.bsec <= (1<<17)) /* 64M -> 4k */
|
||||
bpb.spc = 8;
|
||||
else if (bpb.bsec <= (1<<19)) /* 256M -> 8k */
|
||||
bpb.spc = 16;
|
||||
else if (bpb.bsec <= (1<<21)) /* 1G -> 16k */
|
||||
bpb.spc = 32;
|
||||
else
|
||||
bpb.spc = 64; /* otherwise 32k */
|
||||
}
|
||||
}
|
||||
if (!powerof2(bpb.bps))
|
||||
errx(1, "bytes/sector (%u) is not a power of 2", bpb.bps);
|
||||
if (bpb.bps < MINBPS)
|
||||
@ -606,7 +649,7 @@ main(int argc, char *argv[])
|
||||
fat == 32 && bpb.bkbs != MAXU16 &&
|
||||
bss <= bpb.bkbs && x >= bpb.bkbs) {
|
||||
x -= bpb.bkbs;
|
||||
if (!x && lseek(fd1, 0, SEEK_SET))
|
||||
if (!x && lseek(fd1, opt_ofs, SEEK_SET))
|
||||
err(1, "%s", bname);
|
||||
}
|
||||
if (opt_B && x < bss) {
|
||||
@ -755,7 +798,7 @@ getstdfmt(const char *fmt, struct bpb *bpb)
|
||||
*/
|
||||
static void
|
||||
getbpbinfo(int fd, const char *fname, const char *dtype, int oflag,
|
||||
struct bpb *bpb)
|
||||
struct bpb *bpb, int create)
|
||||
{
|
||||
struct disk_geom geo;
|
||||
struct dkwedge_info dkw;
|
||||
@ -781,8 +824,17 @@ getbpbinfo(int fd, const char *fname, const char *dtype, int oflag,
|
||||
}
|
||||
if (((part != -1) && ((!oflag && part != -1) || !bpb->bsec)) ||
|
||||
!bpb->bps || !bpb->spt || !bpb->hds) {
|
||||
if (getdiskinfo(fname, fd, NULL, &geo, &dkw) == -1)
|
||||
errx(1, "Can't read disk label for `%s'", fname);
|
||||
if (create || getdiskinfo(fname, fd, NULL, &geo, &dkw) == -1) {
|
||||
struct stat st;
|
||||
|
||||
if (fstat(fd, &st) == -1)
|
||||
errx(1, "Can't get disk size for `%s'", fname);
|
||||
/* create a fake geometry for a file image */
|
||||
geo.dg_secsize = 512;
|
||||
geo.dg_nsectors = 63;
|
||||
geo.dg_ntracks = 255;
|
||||
dkw.dkw_size = st.st_size / geo.dg_secsize;
|
||||
}
|
||||
if (!bpb->bps)
|
||||
bpb->bps = ckgeom(fname, geo.dg_secsize, "bytes/sector");
|
||||
|
||||
@ -861,6 +913,56 @@ argtou(const char *arg, u_int lo, u_int hi, const char *msg)
|
||||
return x;
|
||||
}
|
||||
|
||||
/*
|
||||
* Same for off_t, with optional skmgpP suffix
|
||||
*/
|
||||
static off_t
|
||||
argtooff(const char *arg, const char *msg)
|
||||
{
|
||||
char *s;
|
||||
off_t x;
|
||||
|
||||
x = strtoll(arg, &s, 0);
|
||||
/* allow at most one extra char */
|
||||
if (errno || x < 0 || (s[0] && s[1]) )
|
||||
errx(1, "%s: bad %s", arg, msg);
|
||||
if (*s) { /* the extra char is the multiplier */
|
||||
switch (*s) {
|
||||
default:
|
||||
errx(1, "%s: bad %s", arg, msg);
|
||||
/* notreached */
|
||||
|
||||
case 's': /* sector */
|
||||
case 'S':
|
||||
x <<= 9; /* times 512 */
|
||||
break;
|
||||
|
||||
case 'k': /* kilobyte */
|
||||
case 'K':
|
||||
x <<= 10; /* times 1024 */
|
||||
break;
|
||||
|
||||
case 'm': /* megabyte */
|
||||
case 'M':
|
||||
x <<= 20; /* times 1024*1024 */
|
||||
break;
|
||||
|
||||
case 'g': /* gigabyte */
|
||||
case 'G':
|
||||
x <<= 30; /* times 1024*1024*1024 */
|
||||
break;
|
||||
|
||||
case 'p': /* partition start */
|
||||
case 'P': /* partition start */
|
||||
case 'l': /* partition length */
|
||||
case 'L': /* partition length */
|
||||
errx(1, "%s: not supported yet %s", arg, msg);
|
||||
/* notreached */
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check a volume label.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user