sbin/newfs_msdos: add support for exFAT file systems

Add support for the creation of exFAT file systems, if invoked as
newfs_exfat.

Reviewed by:	olce
Approved by:	olce, mckusick
MFC after:	4 weeks
Relnotes:	yes
Differential Revision:	https://reviews.freebsd.org/D48727
This commit is contained in:
Stefan Eßer
2025-08-05 22:12:18 +02:00
parent 62e5a36294
commit 024f676b39
5 changed files with 1305 additions and 64 deletions
+7
View File
@@ -5,6 +5,13 @@ PROG= newfs_msdos
MAN= newfs_msdos.8
SRCS= newfs_msdos.c mkfs_msdos.c
LINKS= ${BINDIR}/newfs_msdos ${BINDIR}/newfs_exfat
MLINKS= newfs_msdos.8 newfs_exfat.8
.if ${MK_ICONV} == "yes"
CFLAGS+=-DWITH_ICONV
.endif
# XXX - this is verboten
.if ${MACHINE_CPUARCH} == "arm"
WARNS?= 3
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -55,7 +55,7 @@ AOPT('m', uint8_t, media_descriptor, 0, "Media descriptor") \
AOPT('n', uint8_t, num_FAT, 1, "Number of FATs") \
AOPT('o', uint32_t, hidden_sectors, 0, "Hidden sectors") \
AOPT('r', uint16_t, reserved_sectors, 1, "Reserved sectors") \
AOPT('s', uint32_t, size, 1, "File System size") \
AOPT('s', uint64_t, size, 1, "File System size") \
AOPT('u', uint16_t, sectors_per_track, 1, "Sectors per track")
struct msdos_options {
@@ -66,6 +66,7 @@ ALLOPTS
uint32_t volume_id_set:1;
uint32_t media_descriptor_set:1;
uint32_t hidden_sectors_set:1;
uint32_t exfat:1;
};
int mkfs_msdos(const char *, const char *, const struct msdos_options *);
+38 -6
View File
@@ -23,12 +23,13 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd June 6, 2024
.Dd August 5, 2025
.Dt NEWFS_MSDOS 8
.Os
.Sh NAME
.Nm newfs_msdos
.Nd construct a new MS-DOS (FAT) file system
.Nm newfs_msdos ,
.Nm newfs_exfat
.Nd construct a new FAT or exFAT file system
.Sh SYNOPSIS
.Nm
.Op Fl N
@@ -58,10 +59,28 @@
.Op Fl u Ar track-size
.Ar special
.Op Ar disktype
.Nm newfs_exfat
.Op Fl N
.Op Fl @ Ar offset
.Op Fl A
.Op Fl B Ar boot
.Op Fl C Ar create-size
.Op Fl I Ar VolumeID
.Op Fl L Ar label
.Op Fl S Ar sector-size
.Op Fl T Ar timestamp
.Op Fl a Ar FAT-size
.Op Fl b Ar block-size
.Op Fl c Ar cluster-size
.Op Fl n Ar FATs
.Op Fl s Ar total
.Ar special
.Op Ar disktype
.Sh DESCRIPTION
The
.Nm
utility creates a FAT12, FAT16, or FAT32 file system on device or file named
utility creates a FAT12, FAT16, FAT32, or exFAT file system on device or file
named
.Ar special ,
using
.Xr disktab 5
@@ -222,11 +241,13 @@ struct bsxbpb {
};
.Ed
.Sh LIMITATION
The maximum file size is 4GB, even if the file system itself is bigger.
The maximum size of a file on a FAT file system is 4GB, even if the file system
itself is bigger.
This limitation does not apply to exFAT file systems.
.Sh EXIT STATUS
Exit status is 0 on success and 1 on error.
.Sh EXAMPLES
Create a file system, using default parameters, on
Create a FAT file system, using default parameters, on
.Pa /dev/ada0s1 :
.Bd -literal -offset indent
newfs_msdos /dev/ada0s1
@@ -251,6 +272,13 @@ Create a 30MB image file, with the FAT partition starting
.Bd -literal -offset indent
newfs_msdos -C 30M -@63s ./somefile
.Ed
.Pp
Create a 300MB exFAT image file with a block size of 65536
bytes:
.Bd -literal -offset indent
newfs_exfat -C 300M -b 65536 /tmp/1.raw
.Ed
.Pp
.Sh SEE ALSO
.Xr msdosfs 4 ,
.Xr gpart 8 ,
@@ -260,5 +288,9 @@ The
.Nm
utility first appeared in
.Fx 3.0 .
Support for the creation of exFAT file systems has been
introduced in
.Fx 15.0 .
.Sh AUTHORS
.An Robert Nordier Aq Mt rnordier@FreeBSD.org
.An Stefan Eßer Aq Mt se@FreeBSD.org
+27 -9
View File
@@ -31,6 +31,7 @@
#include <sys/stat.h>
#include <err.h>
#include <errno.h>
#include <libgen.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
@@ -42,12 +43,15 @@
#define argto1(arg, lo, msg) argtou(arg, lo, 0xff, msg)
#define argto2(arg, lo, msg) argtou(arg, lo, 0xffff, msg)
#define argto4(arg, lo, msg) argtou(arg, lo, 0xffffffff, msg)
#define argto8(arg, lo, msg) argtou(arg, lo, 0xffffffffffffffff, msg)
#define argtox(arg, lo, msg) argtou(arg, lo, UINT_MAX, msg)
static u_int argtou(const char *, u_int, u_int, const char *);
static u_quad_t argtou(const char *, u_int, u_quad_t, const char *);
static off_t argtooff(const char *, const char *);
static void usage(void) __dead2;
static const char *fsopts;
static time_t
get_tstamp(const char *b)
{
@@ -65,13 +69,23 @@ get_tstamp(const char *b)
return (time_t)l;
}
/*
* Check whether invoked as newfs_exfat.
*/
static int
check_exfat(char *argv0)
{
return (strstr(basename(argv0), "exfat") != NULL);
}
/*
* Construct a FAT12, FAT16, or FAT32 file system.
*/
int
main(int argc, char *argv[])
{
static const char opts[] = "@:NAB:C:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:T:u:";
static const char fatopts[] = "@:NAB:C:F:I:L:O:S:T:a:b:c:e:f:h:i:k:m:n:o:r:s:u:";
static const char exfatopts[] = "@:NAB:C:I:L:S:T:a:b:c:n:s:";
struct msdos_options o;
const char *fname, *dtype;
char buf[MAXPATHLEN];
@@ -79,7 +93,10 @@ main(int argc, char *argv[])
memset(&o, 0, sizeof(o));
while ((ch = getopt(argc, argv, opts)) != -1)
o.exfat = check_exfat(argv[0]);
fsopts = o.exfat ? exfatopts : fatopts;
while ((ch = getopt(argc, argv, fsopts)) != -1)
switch (ch) {
case '@':
o.offset = argtooff(optarg, "offset");
@@ -157,7 +174,7 @@ main(int argc, char *argv[])
o.reserved_sectors = argto2(optarg, 1, "reserved sectors");
break;
case 's':
o.size = argto4(optarg, 1, "file system size");
o.size = argto8(optarg, 1, "file system size");
break;
case 'T':
o.timestamp_set = 1;
@@ -189,14 +206,14 @@ main(int argc, char *argv[])
/*
* Convert and check a numeric option argument.
*/
static u_int
argtou(const char *arg, u_int lo, u_int hi, const char *msg)
static u_quad_t
argtou(const char *arg, u_int lo, u_quad_t hi, const char *msg)
{
char *s;
u_long x;
u_quad_t x;
errno = 0;
x = strtoul(arg, &s, 0);
x = strtoull(arg, &s, 0);
if (errno || !*arg || *s || x < lo || x > hi)
errx(1, "%s: bad %s", arg, msg);
return x;
@@ -271,6 +288,7 @@ ALLOPTS
#undef AOPT
};
for (size_t i = 0; i < nitems(opts); i++)
fprintf(stderr, "\t-%c %s\n", opts[i].o, opts[i].h);
if (strchr(fsopts, opts[i].o) != NULL)
fprintf(stderr, "\t-%c %s\n", opts[i].o, opts[i].h);
exit(1);
}