Allow 0 timestamp.
Grammar fixes.
Use the create_size if given to compute the real size instead of stat'ing
the file again, which might have been larger to start with.
Document history.
closes #274
Change-Id: Ibf881f22f351c7a17488b24a05c2110be1d65ae0
-/* $NetBSD: mkfs_msdos.c,v 1.9 2014/01/05 12:52:39 martin Exp $ */
+/* $NetBSD: mkfs_msdos.c,v 1.13 2017/04/14 15:39:29 christos Exp $ */
/*
* Copyright (c) 1998 Robert Nordier
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: mkfs_msdos.c,v 1.9 2014/01/05 12:52:39 martin Exp $");
+__RCSID("$NetBSD: mkfs_msdos.c,v 1.13 2017/04/14 15:39:29 christos Exp $");
#endif
#endif /* not lint */
static int check_mounted(const char *, mode_t);
#endif
static int getstdfmt(const char *, struct bpb *);
-static int getbpbinfo(int, const char *, const char *, int, struct bpb *, int);
+static int getbpbinfo(int, const char *, const char *, int, struct bpb *, off_t);
static void print_bpb(struct bpb *);
static int ckgeom(const char *, u_int, const char *);
static int oklabel(const char *);
if (!(o.floppy || (o.drive_heads && o.sectors_per_track &&
o.bytes_per_sector && o.size && o.hidden_sectors_set))) {
if (getbpbinfo(fd, fname, dtype, o.hidden_sectors_set, &bpb,
- o.create_size != 0) == -1)
+ o.create_size) == -1)
return -1;
bpb.bsec -= (o.offset / bpb.bps);
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 */
+ /* minimum cluster size */
+ switch (o.fat_type) {
+ case 12:
+ bpb.spc = 1; /* use 512 bytes */
+ x = 2; /* up to 2MB */
+ break;
+ case 16:
+ bpb.spc = 1; /* use 512 bytes */
+ x = 32; /* up to 32MB */
+ break;
+ default:
+ bpb.spc = 8; /* use 4k */
+ x = 8192; /* up to 8GB */
+ break;
+ }
+ x1 = howmany(bpb.bsec, (1048576 / 512)); /* -> MB */
+ while (bpb.spc < 128 && x < x1) {
+ x *= 2;
+ bpb.spc *= 2;
+ }
}
}
printf("MBR type: %d\n", ch);
print_bpb(&bpb);
if (!o.no_create) {
- gettimeofday(&tv, NULL);
- now = tv.tv_sec;
- tm = localtime(&now);
+ if (o.timestamp_set) {
+ tv.tv_sec = now = o.timestamp;
+ tv.tv_usec = 0;
+ tm = gmtime(&now);
+ } else {
+ gettimeofday(&tv, NULL);
+ now = tv.tv_sec;
+ tm = localtime(&now);
+ }
if (!(img = malloc(bpb.bps)))
err(1, NULL);
dir = bpb.res + (bpb.spf ? bpb.spf : bpb.bspf) * bpb.nft;
*/
static int
getbpbinfo(int fd, const char *fname, const char *dtype, int iflag,
- struct bpb *bpb, int create)
+ struct bpb *bpb, off_t create_size)
{
const char *s1, *s2;
int part;
#ifndef MAKEFS
int maxpartitions = getmaxpartitions();
+ struct disk_geom geo;
+ struct dkwedge_info dkw;
// XXX: Does not work with wedges
if (s2 && *s2 >= 'a' && *s2 <= 'a' + maxpartitions - 1) {
part = *s2++ - 'a';
}
#endif
- if (((part != -1) && ((!iflag && part != -1) || !bpb->bsec)) ||
- !bpb->bps || !bpb->spt || !bpb->hds) {
- u_int sector_size;
- u_int nsectors;
- u_int ntracks;
- u_int size;
-#ifndef MAKEFS
- struct disk_geom geo;
- struct dkwedge_info dkw;
- if (!create && getdiskinfo(fname, fd, NULL, &geo, &dkw) != -1) {
- sector_size = geo.dg_secsize = 512;
- nsectors = geo.dg_nsectors = 63;
- ntracks = geo.dg_ntracks = 255;
+ if (!(((part != -1) && ((!iflag && part != -1) || !bpb->bsec)) ||
+ !bpb->bps || !bpb->spt || !bpb->hds)) {
+ return 0;
+ }
+
+ u_int sector_size = 512;
+ u_int nsectors = 63;
+ u_int ntracks = 255;
+ u_int size;
+
+ if (create_size == 0) {
+#ifndef MAKEFS
+ if (getdiskinfo(fname, fd, NULL, &geo, &dkw) != -1) {
+ sector_size = geo.dg_secsize;
+ nsectors = geo.dg_nsectors;
+ ntracks = geo.dg_ntracks;
size = dkw.dkw_size;
} else
#endif
warnx("Can't get disk size for `%s'", fname);
return -1;
}
- /* create a fake geometry for a file image */
- sector_size = 512;
- nsectors = 63;
- ntracks = 255;
size = st.st_size / sector_size;
}
- if (!bpb->bps) {
- if (ckgeom(fname, sector_size, "bytes/sector") == -1)
- return -1;
- bpb->bps = sector_size;
- }
+ } else {
+ size = create_size / sector_size;
+ }
- if (nsectors > 63) {
- /*
- * The kernel doesn't accept BPB with spt > 63.
- * (see sys/fs/msdosfs/msdosfs_vfsops.c:msdosfs_mountfs())
- * If values taken from disklabel don't match these
- * restrictions, use popular BIOS default values instead.
- */
- nsectors = 63;
- }
- if (!bpb->spt) {
- if (ckgeom(fname, nsectors, "sectors/track") == -1)
- return -1;
- bpb->spt = nsectors;
- }
- if (!bpb->hds)
- if (ckgeom(fname, ntracks, "drive heads") == -1)
- return -1;
- bpb->hds = ntracks;
- if (!bpb->bsec)
- bpb->bsec = size;
+ if (!bpb->bps) {
+ if (ckgeom(fname, sector_size, "bytes/sector") == -1)
+ return -1;
+ bpb->bps = sector_size;
+ }
+
+ if (nsectors > 63) {
+ /*
+ * The kernel doesn't accept BPB with spt > 63.
+ * (see sys/fs/msdosfs/msdosfs_vfsops.c:msdosfs_mountfs())
+ * If values taken from disklabel don't match these
+ * restrictions, use popular BIOS default values instead.
+ */
+ nsectors = 63;
+ }
+ if (!bpb->spt) {
+ if (ckgeom(fname, nsectors, "sectors/track") == -1)
+ return -1;
+ bpb->spt = nsectors;
}
+ if (!bpb->hds)
+ if (ckgeom(fname, ntracks, "drive heads") == -1)
+ return -1;
+ bpb->hds = ntracks;
+ if (!bpb->bsec)
+ bpb->bsec = size;
+
return 0;
}
-/* $NetBSD: mkfs_msdos.h,v 1.2 2013/01/23 15:29:15 christos Exp $ */
+/* $NetBSD: mkfs_msdos.h,v 1.6 2017/02/17 09:29:35 wiz Exp $ */
/*-
* Copyright (c) 2013 The NetBSD Foundation, Inc.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
AOPT('F', uint8_t, fat_type, 12, "FAT type (12, 16, or 32)") \
AOPT('I', uint32_t, volume_id, 0, "Volume ID") \
AOPT('L', char *, volume_label, -1, "Volume Label") \
-AOPT('N', bool, no_create, -2, "Don't create filesystem, print params only") \
+AOPT('N', bool, no_create, -2, "Don't create file system, print params only") \
AOPT('O', char *, OEM_string, -1, "OEM string") \
AOPT('S', uint16_t, bytes_per_sector, 1, "Bytes per sector") \
AOPT('a', uint32_t, sectors_per_fat, 1, "Sectors per FAT") \
#define AOPT(_opt, _type, _name, _min, _desc) _type _name;
ALLOPTS
#undef AOPT
+ time_t timestamp;
+ uint32_t timestamp_set:1;
uint32_t volume_id_set:1;
uint32_t media_descriptor_set:1;
uint32_t hidden_sectors_set:1;
-.\" $NetBSD: newfs_msdos.8,v 1.20 2014/04/24 23:49:40 christos Exp $
+.\" $NetBSD: newfs_msdos.8,v 1.23 2017/02/17 09:29:35 wiz Exp $
.\"
.\" Copyright (c) 1998 Robert Nordier
.\" All rights reserved.
.\"
.\" From: $FreeBSD: src/sbin/newfs_msdos/newfs_msdos.8,v 1.13 2001/08/14 10:01:48 ru Exp $
.\"
-.Dd April 24, 2014
+.Dd February 16, 2017
.Dt NEWFS_MSDOS 8
.Os
.Sh NAME
.Op Fl o Ar hidden
.Op Fl r Ar reserved
.Op Fl s Ar total
+.Op Fl T Ar timestamp
.Op Fl u Ar track-size
.Ar special
.Op Ar disktype
The options are as follow:
.Bl -tag -width indent
.It Fl N
-Don't create a file system: just print out parameters.
+Do not 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.
+Build the file system 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.
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.
+the file system size.
.It Fl e Ar dirents
Number of root directory entries (FAT12 and FAT16 only).
.It Fl f Ar format
Number of reserved sectors.
.It Fl s Ar total
File system size.
+.It Fl T At timestamp
+Specify a timestamp to be used for file system creation so that
+it can be consistent for reproducible builds.
+The timestamp can be a pathname, where the timestamps are derived from
+that file, a parseable date for parsedate(3) (this option is not
+yet available in the tools build), or an integer value interpreted
+as the number of seconds from the Epoch.
.It Fl u Ar track-size
Number of sectors per track.
.El
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.
+a multiple of the track size and avoid complaints by some file system 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
.Xr fdisk 8 ,
.Xr newfs 8
.Sh HISTORY
+A
+.Nm
+utility appeared in
+.Fx 3.0 .
The
.Nm
command first appeared in
-/* $NetBSD: newfs_msdos.c,v 1.43 2015/04/23 13:27:14 abs Exp $ */
+/* $NetBSD: newfs_msdos.c,v 1.45 2017/02/16 22:42:25 christos Exp $ */
/*
* Copyright (c) 1998 Robert Nordier
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.43 2015/04/23 13:27:14 abs Exp $");
+__RCSID("$NetBSD: newfs_msdos.c,v 1.45 2017/02/16 22:42:25 christos Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
+#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <err.h>
#include <unistd.h>
#include <paths.h>
#include <errno.h>
+#include <util.h>
#include "mkfs_msdos.h"
static u_int argtou(const char *, u_int, u_int, const char *);
static off_t argtooff(const char *, const char *);
+static time_t
+get_tstamp(const char *b)
+{
+ struct stat st;
+ char *eb;
+ long long l;
+#ifndef HAVE_NBTOOL_CONFIG_H
+ time_t when;
+#endif
+
+ if (stat(b, &st) != -1)
+ return (time_t)st.st_mtime;
+
+#ifndef HAVE_NBTOOL_CONFIG_H
+ errno = 0;
+ if ((when = parsedate(b, NULL, NULL)) != -1 || errno == 0)
+ return when;
+#endif
+ errno = 0;
+ l = strtoll(b, &eb, 0);
+ if (b == eb || *eb || errno)
+ errx(EXIT_FAILURE, "Can't parse timestamp `%s'", b);
+ return (time_t)l;
+}
+
/*
* Construct a FAT12, FAT16, or FAT32 file system.
*/
int
main(int argc, char *argv[])
{
- static const char opts[] = "@:NB:C:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:u:";
+ static const char opts[] = "@:NB:C:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:T:u:";
struct msdos_options o;
char *fname, *dtype;
char buf[MAXPATHLEN];
case 's':
o.size = argto4(optarg, 1, "file system size");
break;
+ case 'T':
+ o.timestamp_set = 1;
+ o.timestamp = get_tstamp(optarg);
+ break;
case 'u':
o.sectors_per_track = argto2(optarg, 1, "sectors/track");
break;