summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2021-01-26 20:43:43 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-01-26 20:43:43 +0000
commite69f3197ea2976e8e48d8d095f30b18dc6a9ff3d (patch)
tree2cae0765b948d20714862f3c9f0b8b8b0e8660bd
parentcda7b1f453995254c44d40f91f0adc87e50998c0 (diff)
parentec4355c4b28e67104c61102814faca7249bdc17f (diff)
downloadnewfs_msdos-e69f3197ea2976e8e48d8d095f30b18dc6a9ff3d.tar.gz
Update to upstream 6424881cc82a65a833fc6fb79730474caedf6222. am: 8c4b3f0afd am: 4bd115afd2 am: ec4355c4b2
Original change: https://android-review.googlesource.com/c/platform/external/newfs_msdos/+/1555547 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: If798f740391d9edcdb1b44082bb0919498d6d4bd
-rwxr-xr-xAndroid.bp5
-rw-r--r--METADATA6
-rw-r--r--freebsd-compat.h42
-rw-r--r--mkfs_msdos.c181
-rw-r--r--mkfs_msdos.h7
-rw-r--r--newfs_msdos.c15
6 files changed, 192 insertions, 64 deletions
diff --git a/Android.bp b/Android.bp
index fcaffbc..a447263 100755
--- a/Android.bp
+++ b/Android.bp
@@ -1,5 +1,6 @@
cc_binary {
name: "newfs_msdos",
+ c_std: "gnu11",
cflags: [
"-Wall",
"-Werror",
@@ -7,9 +8,7 @@ cc_binary {
"-Wno-unused-parameter",
"-Wno-unused-variable",
"-D_FILE_OFFSET_BITS=64",
- "-D_GNU_SOURCE",
- "-DSIGINFO=SIGUSR2",
- "-Dnitems(x)=(sizeof((x))/sizeof((x)[0]))",
+ "-include freebsd-compat.h"
],
srcs: [
"mkfs_msdos.c",
diff --git a/METADATA b/METADATA
index a0b9090..af1cf5d 100644
--- a/METADATA
+++ b/METADATA
@@ -9,9 +9,9 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://github.git.corp.google.com/freebsd/freebsd/+archive/b25a2bc/sbin/newfs_msdos.tar.gz"
+ value: "https://github.git.corp.google.com/freebsd/freebsd/+archive/6424881cc82a65a833fc6fb79730474caedf6222/sbin/newfs_msdos.tar.gz"
}
- version: "b25a2bc"
- last_upgrade_date { year: 2018 month: 4 day: 26 }
+ version: "6424881cc82a65a833fc6fb79730474caedf6222"
+ last_upgrade_date { year: 2021 month: 1 day: 20 }
license_type: NOTICE
}
diff --git a/freebsd-compat.h b/freebsd-compat.h
new file mode 100644
index 0000000..5e39c5a
--- /dev/null
+++ b/freebsd-compat.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#define _GNU_SOURCE
+
+#include <stdint.h>
+
+#include <sys/param.h>
+// Ensure we use a BSD powerof2 that works in static_assert (unlike glibc's).
+#undef powerof2
+#define powerof2(x) ((((x)-1)&(x))==0)
+// This is in BSD's <sys/param.h>.
+#define nitems(x) (sizeof((x))/sizeof((x)[0]))
+
+// This is used as the size of the write buffer of sectors.
+#define MAXPHYS (1024 * 1024)
+
+//#define static_assert _Static_assert
+
+// TODO: do we actually want this, or should we live without?
+#define SIGINFO SIGUSR2
+
+
+// On glibc, these headers use `__unused` as an identifier, so drag them in
+// first.
+#include <sys/stat.h>
+#if __has_include(<sys/sysctl.h>)
+#include <sys/sysctl.h>
+#endif
+// Bionic, like the BSDs, has __unused. glibc doesn't.
+#if defined(__GLIBC__)
+#define __unused __attribute__((__unused__))
+#endif
+// Neither macOS nor glibc has __packed.
+#if defined(__APPLE__) || defined(__GLIBC__)
+#define __packed __attribute__((__packed__))
+#endif
+
+// The BSDs (including Android and macOS) have getprogname(), but glibc doesn't.
+#if defined(__GLIBC__)
+#include <errno.h>
+static inline char* getprogname() { return program_invocation_short_name; }
+#endif
diff --git a/mkfs_msdos.c b/mkfs_msdos.c
index 878ff8f..667df47 100644
--- a/mkfs_msdos.c
+++ b/mkfs_msdos.c
@@ -27,11 +27,14 @@
#ifndef lint
static const char rcsid[] =
- "$FreeBSD: head/sbin/newfs_msdos/mkfs_msdos.c 335189 2018-06-15 06:03:40Z delphij $";
+ "$FreeBSD$";
#endif /* not lint */
#include <sys/param.h>
-#if defined(__linux__)
+#ifdef MAKEFS
+/* In the makefs case we only want struct disklabel */
+#include <sys/disk/bsd.h>
+#elif defined(__linux__)
#include <linux/fs.h>
#include <linux/hdreg.h>
#include <sys/ioctl.h>
@@ -44,8 +47,12 @@ static const char rcsid[] =
#include <sys/mount.h>
#endif
#include <sys/stat.h>
+#if __has_include(<sys/sysctl.h>)
+#include <sys/sysctl.h>
+#endif
#include <sys/time.h>
+#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
@@ -61,19 +68,13 @@ static const char rcsid[] =
#include "mkfs_msdos.h"
-#if !defined(__packed)
-#define __packed __attribute__((__packed__))
-#endif
-#if !defined(__unused)
-#define __unused __attribute__((__unused__))
-#endif
-
#define MAXU16 0xffff /* maximum unsigned 16-bit quantity */
#define BPN 4 /* bits per nibble */
#define NPB 2 /* nibbles per byte */
#define DOSMAGIC 0xaa55 /* DOS magic number */
#define MINBPS 512 /* minimum bytes per sector */
+#define MAXBPS 4096 /* maximum bytes per sector */
#define MAXSPC 128 /* maximum sectors per cluster */
#define MAXNFT 16 /* maximum number of FATs */
#define DEFBLK 4096 /* default block size */
@@ -230,6 +231,7 @@ static volatile sig_atomic_t got_siginfo;
static void infohandler(int);
static int check_mounted(const char *, mode_t);
+static ssize_t getchunksize(void);
static int getstdfmt(const char *, struct bpb *);
static int getdiskinfo(int, const char *, const char *, int, struct bpb *);
static void print_bpb(struct bpb *);
@@ -253,6 +255,7 @@ mkfs_msdos(const char *fname, const char *dtype, const struct msdos_options *op)
struct bsx *bsx;
struct de *de;
u_int8_t *img;
+ u_int8_t *physbuf, *physbuf_end;
const char *bname;
ssize_t n;
time_t now;
@@ -261,8 +264,9 @@ mkfs_msdos(const char *fname, const char *dtype, const struct msdos_options *op)
bool set_res, set_spf, set_spc;
int fd, fd1, rv;
struct msdos_options o = *op;
+ ssize_t chunksize;
- img = NULL;
+ physbuf = NULL;
rv = -1;
fd = fd1 = -1;
@@ -300,12 +304,18 @@ mkfs_msdos(const char *fname, const char *dtype, const struct msdos_options *op)
if (!S_ISREG(sb.st_mode))
warnx("warning, %s is not a regular file", fname);
} else {
+#ifdef MAKEFS
+ errx(1, "o.create_size must be set!");
+#else
if (!S_ISCHR(sb.st_mode))
warnx("warning, %s is not a character device", fname);
+#endif
}
+#ifndef MAKEFS
if (!o.no_create)
if (check_mounted(fname, sb.st_mode) == -1)
goto done;
+#endif
if (o.offset && o.offset != lseek(fd, o.offset, SEEK_SET)) {
warnx("cannot seek to %jd", (intmax_t)o.offset);
goto done;
@@ -331,7 +341,8 @@ mkfs_msdos(const char *fname, const char *dtype, const struct msdos_options *op)
bpb.bpbHiddenSecs = o.hidden_sectors;
if (!(o.floppy || (o.drive_heads && o.sectors_per_track &&
o.bytes_per_sector && o.size && o.hidden_sectors_set))) {
- getdiskinfo(fd, fname, dtype, o.hidden_sectors_set, &bpb);
+ if (getdiskinfo(fd, fname, dtype, o.hidden_sectors_set, &bpb) == -1)
+ goto done;
bpb.bpbHugeSectors -= (o.offset / bpb.bpbBytesPerSec);
if (bpb.bpbSecPerClust == 0) { /* set defaults */
if (bpb.bpbHugeSectors <= 6000) /* about 3MB -> 512 bytes */
@@ -346,13 +357,11 @@ mkfs_msdos(const char *fname, const char *dtype, const struct msdos_options *op)
bpb.bpbSecPerClust = 64; /* otherwise 32k */
}
}
- if (!powerof2(bpb.bpbBytesPerSec)) {
- warnx("bytes/sector (%u) is not a power of 2", bpb.bpbBytesPerSec);
- goto done;
- }
- if (bpb.bpbBytesPerSec < MINBPS) {
- warnx("bytes/sector (%u) is too small; minimum is %u",
- bpb.bpbBytesPerSec, MINBPS);
+ if (bpb.bpbBytesPerSec < MINBPS ||
+ bpb.bpbBytesPerSec > MAXBPS ||
+ !powerof2(bpb.bpbBytesPerSec)) {
+ warnx("Invalid bytes/sector (%u): must be 512, 1024, 2048 or 4096",
+ bpb.bpbBytesPerSec);
goto done;
}
@@ -436,10 +445,7 @@ mkfs_msdos(const char *fname, const char *dtype, const struct msdos_options *op)
bname = o.bootstrap;
if (!strchr(bname, '/')) {
snprintf(buf, sizeof(buf), "/boot/%s", bname);
- if (!(bname = strdup(buf))) {
- warn(NULL);
- goto done;
- }
+ bname = buf;
}
if ((fd1 = open(bname, O_RDONLY)) == -1 || fstat(fd1, &sb)) {
warn("%s", bname);
@@ -627,19 +633,25 @@ mkfs_msdos(const char *fname, const char *dtype, const struct msdos_options *op)
tm = localtime(&now);
}
-
- if (!(img = malloc(bpb.bpbBytesPerSec))) {
+ chunksize = getchunksize();
+ physbuf = malloc(chunksize);
+ if (physbuf == NULL) {
warn(NULL);
goto done;
}
+ physbuf_end = physbuf + chunksize;
+ img = physbuf;
+
dir = bpb.bpbResSectors + (bpb.bpbFATsecs ? bpb.bpbFATsecs :
bpb.bpbBigFATsecs) * bpb.bpbFATs;
memset(&si_sa, 0, sizeof(si_sa));
si_sa.sa_handler = infohandler;
+#ifdef SIGINFO
if (sigaction(SIGINFO, &si_sa, NULL) == -1) {
warn("sigaction SIGINFO");
goto done;
}
+#endif
#if defined(__linux__)
if (ioctl(fd, BLKBSZSET, &bpb.bpbBytesPerSec))
@@ -738,7 +750,7 @@ mkfs_msdos(const char *fname, const char *dtype, const struct msdos_options *op)
mk4(img, 0x41615252);
mk4(img + MINBPS - 28, 0x61417272);
mk4(img + MINBPS - 24, 0xffffffff);
- mk4(img + MINBPS - 20, bpb.bpbRootClust);
+ mk4(img + MINBPS - 20, 0xffffffff);
mk2(img + MINBPS - 2, DOSMAGIC);
} else if (lsn >= bpb.bpbResSectors && lsn < dir &&
!((lsn - bpb.bpbResSectors) %
@@ -760,19 +772,37 @@ mkfs_msdos(const char *fname, const char *dtype, const struct msdos_options *op)
(u_int)tm->tm_mday;
mk2(de->deMDate, x);
}
- if ((n = write(fd, img, bpb.bpbBytesPerSec)) == -1) {
- warn("%s", fname);
- goto done;
- }
- if ((unsigned)n != bpb.bpbBytesPerSec) {
- warnx("%s: can't write sector %u", fname, lsn);
- goto done;
+ /*
+ * Issue a write of chunksize once we have collected
+ * enough sectors.
+ */
+ img += bpb.bpbBytesPerSec;
+ if (img >= physbuf_end) {
+ n = write(fd, physbuf, chunksize);
+ if (n != chunksize) {
+ warnx("%s: can't write sector %u", fname, lsn);
+ goto done;
+ }
+ img = physbuf;
}
}
+ /*
+ * Write remaining sectors, if the last write didn't end
+ * up filling a whole chunk.
+ */
+ if (img != physbuf) {
+ ssize_t tailsize = img - physbuf;
+
+ n = write(fd, physbuf, tailsize);
+ if (n != tailsize) {
+ warnx("%s: can't write sector %u", fname, lsn);
+ goto done;
+ }
+ }
}
rv = 0;
done:
- free(img);
+ free(physbuf);
if (fd != -1)
close(fd);
if (fd1 != -1)
@@ -787,7 +817,11 @@ done:
static int
check_mounted(const char *fname, mode_t mode)
{
-#if 0
+/*
+ * If getmntinfo() is not available (e.g. Linux) don't check. This should
+ * not be a problem since we will only be using makefs to create images.
+ */
+#if 0 && !defined(MAKEFS)
struct statfs *mp;
const char *s1, *s2;
size_t len;
@@ -817,6 +851,47 @@ check_mounted(const char *fname, mode_t mode)
}
/*
+ * Get optimal I/O size
+ */
+static ssize_t
+getchunksize(void)
+{
+ static int chunksize;
+
+ if (chunksize != 0)
+ return ((ssize_t)chunksize);
+
+#ifdef KERN_MAXPHYS
+ int mib[2];
+ size_t len;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_MAXPHYS;
+ len = sizeof(chunksize);
+
+ if (sysctl(mib, 2, &chunksize, &len, NULL, 0) == -1) {
+ warn("sysctl: KERN_MAXPHYS, using %zu", (size_t)MAXPHYS);
+ chunksize = 0;
+ }
+#endif
+ if (chunksize == 0)
+ chunksize = MAXPHYS;
+
+ /*
+ * For better performance, we want to write larger chunks instead of
+ * individual sectors (the size can only be 512, 1024, 2048 or 4096
+ * bytes). Assert that chunksize can always hold an integer number of
+ * sectors by asserting that both are power of two numbers and the
+ * chunksize is greater than MAXBPS.
+ */
+ static_assert(powerof2(MAXBPS), "MAXBPS is not power of 2");
+ assert(powerof2(chunksize));
+ assert(chunksize > MAXBPS);
+
+ return ((ssize_t)chunksize);
+}
+
+/*
* Get a standard format.
*/
static int
@@ -834,6 +909,25 @@ getstdfmt(const char *fmt, struct bpb *bpb)
return 0;
}
+#if 0
+static void
+compute_geometry_from_file(int fd, const char *fname, struct disklabel *lp)
+{
+ struct stat st;
+ off_t ms;
+
+ if (fstat(fd, &st))
+ err(1, "cannot get disk size");
+ if (!S_ISREG(st.st_mode))
+ errx(1, "%s is not a regular file", fname);
+ ms = st.st_size;
+ lp->d_secsize = 512;
+ lp->d_nsectors = 63;
+ lp->d_ntracks = 255;
+ lp->d_secperunit = ms / lp->d_secsize;
+}
+#endif
+
/*
* Get disk slice, partition, and geometry information.
*/
@@ -879,8 +973,10 @@ getdiskinfo(int fd, const char *fname, const char *dtype, __unused int oflag,
struct bpb *bpb)
{
struct disklabel *lp, dlp;
+ off_t hs = 0;
+#ifndef MAKEFS
+ off_t ms;
struct fd_type type;
- off_t ms, hs = 0;
lp = NULL;
@@ -892,16 +988,8 @@ getdiskinfo(int fd, const char *fname, const char *dtype, __unused int oflag,
/* Maybe it's a floppy drive */
if (lp == NULL) {
if (ioctl(fd, DIOCGMEDIASIZE, &ms) == -1) {
- struct stat st;
-
- if (fstat(fd, &st))
- err(1, "cannot get disk size");
/* create a fake geometry for a file image */
- ms = st.st_size;
- dlp.d_secsize = 512;
- dlp.d_nsectors = 63;
- dlp.d_ntracks = 255;
- dlp.d_secperunit = ms / dlp.d_secsize;
+ compute_geometry_from_file(fd, fname, &dlp);
lp = &dlp;
} else if (ioctl(fd, FD_GTYPE, &type) != -1) {
dlp.d_secsize = 128 << type.secsize;
@@ -941,6 +1029,11 @@ getdiskinfo(int fd, const char *fname, const char *dtype, __unused int oflag,
hs = (ms / dlp.d_secsize) - dlp.d_secperunit;
lp = &dlp;
}
+#else
+ /* In the makefs case we only support image files: */
+ compute_geometry_from_file(fd, fname, &dlp);
+ lp = &dlp;
+#endif
if (bpb->bpbBytesPerSec == 0) {
if (ckgeom(fname, lp->d_secsize, "bytes/sector") == -1)
diff --git a/mkfs_msdos.h b/mkfs_msdos.h
index b49a577..7e0c662 100644
--- a/mkfs_msdos.h
+++ b/mkfs_msdos.h
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sbin/newfs_msdos/mkfs_msdos.h 335189 2018-06-15 06:03:40Z delphij $ */
+/* $FreeBSD$ */
/* $NetBSD: mkfs_msdos.h,v 1.3 2015/10/16 17:38:17 christos Exp $ */
/*-
@@ -32,7 +32,6 @@
#include <sys/types.h>
#include <stdbool.h>
-#include <stdint.h>
#define ALLOPTS \
AOPT('@', off_t, offset, 0, "Offset in device") \
AOPT('A', bool, align, -2, "Attempt to cluster align root directory") \
@@ -71,7 +70,3 @@ ALLOPTS
};
int mkfs_msdos(const char *, const char *, const struct msdos_options *);
-
-#if defined(__GLIBC__)
-static inline char* getprogname() { return program_invocation_short_name; }
-#endif
diff --git a/newfs_msdos.c b/newfs_msdos.c
index cd03164..bac250e 100644
--- a/newfs_msdos.c
+++ b/newfs_msdos.c
@@ -29,7 +29,7 @@
#ifndef lint
static const char rcsid[] =
- "$FreeBSD: head/sbin/newfs_msdos/newfs_msdos.c 335189 2018-06-15 06:03:40Z delphij $";
+ "$FreeBSD$";
#endif /* not lint */
#include <sys/param.h>
@@ -178,18 +178,17 @@ main(int argc, char *argv[])
argv += optind;
if (argc < 1 || argc > 2)
usage();
- if (o.align) {
- if (o.hidden_sectors_set)
- errx(1, "align (-A) is incompatible with -r");
- }
+ if (o.align) {
+ if (o.reserved_sectors)
+ errx(1, "align (-A) is incompatible with -r");
+ }
fname = *argv++;
if (!o.create_size && !strchr(fname, '/')) {
snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname);
- if (!(fname = strdup(buf)))
- err(1, NULL);
+ fname = buf;
}
dtype = *argv;
- return !!mkfs_msdos(fname, dtype, &o);
+ exit(!!mkfs_msdos(fname, dtype, &o));
}
/*