Module Name:    src
Committed By:   perseant
Date:           Tue Aug 13 05:37:24 UTC 2024

Modified Files:
        src/sbin/newfs_exfatfs [perseant-exfatfs]: extern.h make_exfatfs.c
            newfs.c

Log Message:
Add -x flag to install extended boot code.

Convert default alignments to sectors so we don't end up with absurdly large
alignments.

Check alignment sanity more carefully.

Double-check all the same restrictions we check on mount before creating the
file system.

Replace the previous interpretation of relative pathnames as residing in /dev
with the fsspecname-based computation from newfs(8).


To generate a diff of this commit:
cvs rdiff -u -r1.1.2.3 -r1.1.2.4 src/sbin/newfs_exfatfs/extern.h
cvs rdiff -u -r1.1.2.6 -r1.1.2.7 src/sbin/newfs_exfatfs/make_exfatfs.c
cvs rdiff -u -r1.1.2.4 -r1.1.2.5 src/sbin/newfs_exfatfs/newfs.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sbin/newfs_exfatfs/extern.h
diff -u src/sbin/newfs_exfatfs/extern.h:1.1.2.3 src/sbin/newfs_exfatfs/extern.h:1.1.2.4
--- src/sbin/newfs_exfatfs/extern.h:1.1.2.3	Fri Aug  2 00:23:21 2024
+++ src/sbin/newfs_exfatfs/extern.h	Tue Aug 13 05:37:23 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: extern.h,v 1.1.2.3 2024/08/02 00:23:21 perseant Exp $	*/
+/*	$NetBSD: extern.h,v 1.1.2.4 2024/08/13 05:37:23 perseant Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,8 +37,9 @@ void	fatal(const char *fmt, ...)
      __attribute__((__format__(__printf__,1,2)));
 int	make_exfatfs(struct uvnode *, struct exfatfs *,
 		     uint16_t *, int, uint16_t *, size_t,
+		     char *,
 		     uint32_t, uint32_t);
 
 extern char	*progname;
-extern char	*special;
+extern const char *special;
 

Index: src/sbin/newfs_exfatfs/make_exfatfs.c
diff -u src/sbin/newfs_exfatfs/make_exfatfs.c:1.1.2.6 src/sbin/newfs_exfatfs/make_exfatfs.c:1.1.2.7
--- src/sbin/newfs_exfatfs/make_exfatfs.c:1.1.2.6	Fri Aug  2 00:23:21 2024
+++ src/sbin/newfs_exfatfs/make_exfatfs.c	Tue Aug 13 05:37:24 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: make_exfatfs.c,v 1.1.2.6 2024/08/02 00:23:21 perseant Exp $	*/
+/*	$NetBSD: make_exfatfs.c,v 1.1.2.7 2024/08/13 05:37:24 perseant Exp $	*/
 
 /*-
  * Copyright (c) 2022 The NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
 #if 0
 static char sccsid[] = "@(#)lfs.c	8.5 (Berkeley) 5/24/95";
 #else
-__RCSID("$NetBSD: make_exfatfs.c,v 1.1.2.6 2024/08/02 00:23:21 perseant Exp $");
+__RCSID("$NetBSD: make_exfatfs.c,v 1.1.2.7 2024/08/13 05:37:24 perseant Exp $");
 #endif
 #endif /* not lint */
 
@@ -107,14 +107,16 @@ extern int Qflag; /* Quiet */
 extern int Vflag; /* Verbose */
 
 void pwarn(const char *, ...);
+static void check_asserts(struct exfatfs *);
 
 int
 make_exfatfs(struct uvnode *devvp, struct exfatfs *fs,
 	     uint16_t *uclabel, int uclabellen,
 	     uint16_t *uctable, size_t uctablesize,
+	     char *xbootcode,
 	     uint32_t fatalign, uint32_t heapalign)
 {
-	uint32_t clust, nclust;
+	uint32_t clust, nclust, nnclust;
 	struct exfatfs_dirent_allocation_bitmap dirent_bitmap[2];
 	struct exfatfs_dirent_upcase_table dirent_upcase;
 	struct exfatfs_dirent_volume_label dirent_label;
@@ -128,7 +130,8 @@ make_exfatfs(struct uvnode *devvp, struc
 	uint32_t secsize = (1 << fs->xf_BytesPerSectorShift);
 
 	if (Vflag) {
-		printf("VolumeLength: %lu\n",
+		printf("VolumeLength: %lu (0x%lx)\n",
+			(unsigned long)fs->xf_VolumeLength,
 			(unsigned long)fs->xf_VolumeLength);
 		printf("Serial Number: 0x%lx (%lu)\n",
 			(unsigned long)fs->xf_VolumeSerialNumber,
@@ -167,28 +170,44 @@ make_exfatfs(struct uvnode *devvp, struc
 	else if (nclust > fs->xf_FatLength * secsize / sizeof(uint32_t) - 2)
 		nclust = fs->xf_FatLength * secsize / sizeof(uint32_t) - 2;
 	fs->xf_ClusterHeapOffset = fs->xf_FatOffset + fs->xf_NumberOfFats * fs->xf_FatLength;
-	if (heapalign) {
-		uint32_t halignoff = fs->xf_PartitionOffset % heapalign;
-		fs->xf_ClusterHeapOffset = roundup(fs->xf_ClusterHeapOffset
-						   + halignoff, heapalign);
-	}
 	if (Vflag) {
 		printf("FatLength: %lx\n",
 			(unsigned long)fs->xf_FatLength);
-		printf("ClusterHeapOffset: 0x%lx (byte 0x%llx)\n",
-		       (unsigned long)fs->xf_ClusterHeapOffset,
-		       (unsigned long long)fs->xf_ClusterHeapOffset << fs->xf_BytesPerSectorShift);
 	}
 
 	/* Recalculate to take FATs into account */
 	nclust = (fs->xf_VolumeLength - fs->xf_ClusterHeapOffset) >> fs->xf_SectorsPerClusterShift;
 	/* Make sure it fits in our given FAT */
-	if (nclust > fs->xf_FatLength * secsize / sizeof(uint32_t) - 2)
-		nclust = fs->xf_FatLength * secsize / sizeof(uint32_t) - 2;
+	nnclust = fs->xf_FatLength * secsize / sizeof(uint32_t) - 2;
+	if (nclust > nnclust) {
+		fs->xf_ClusterHeapOffset += (nclust - nnclust)
+			<< fs->xf_SectorsPerClusterShift;
+		nclust = nnclust;
+	}
+	if (heapalign) {
+		uint32_t halignoff = fs->xf_PartitionOffset % heapalign;
+		uint32_t nho = roundup(fs->xf_ClusterHeapOffset
+					 + halignoff, heapalign);
+		if ((fs->xf_VolumeLength - nho) >> fs->xf_SectorsPerClusterShift <= 0) {
+			if (Vflag)
+				printf("Volume is too small to align cluster heap to %lu sectors\n",
+					(unsigned long)heapalign);
+		} else {
+			fs->xf_ClusterHeapOffset = nho;
+			nclust = (fs->xf_VolumeLength - fs->xf_ClusterHeapOffset) >> fs->xf_SectorsPerClusterShift;
+		}
+	}
 	fs->xf_ClusterCount = nclust;
-	if (Vflag)
+	if (Vflag) {
 		printf("File system contains %d clusters\n",
 		       (int)fs->xf_ClusterCount);
+		printf("ClusterHeapOffset: 0x%lx (byte 0x%llx)\n",
+		       (unsigned long)fs->xf_ClusterHeapOffset,
+		       (unsigned long long)fs->xf_ClusterHeapOffset << fs->xf_BytesPerSectorShift);
+	}
+
+	assert(fs->xf_ClusterHeapOffset >= fs->xf_FatOffset
+            + fs->xf_FatLength * fs->xf_NumberOfFats);
 	
 	/*
 	 * Prepare root directory entries.
@@ -447,10 +466,27 @@ make_exfatfs(struct uvnode *devvp, struc
 
 	fs->xf_PercentInUse = 100 * (fs->xf_FirstClusterOfRootDirectory - 1)
 		/ (fs->xf_ClusterCount);
+
+	/*
+	 * If given extended boot code,
+	 * write the boot code sectors.
+	 */
+	if (xbootcode != NULL) {
+		for (i = 0; i < 8; i++) {
+			bp = getblk(devvp, i + 1, BSSIZE(fs));
+			memcpy(bp->b_data, xbootcode + i * BSSIZE(fs),
+			       BSSIZE(fs));
+			bwrite(bp);
+		}
+	}
+
+	check_asserts(fs);
 	
 	/*
 	 * Finally, write the boot sector.
 	 */
+	if (Vflag)
+		printf("Write boot sector\n");
 	if (!Nflag)
 		exfatfs_write_sb(fs, 1);
 
@@ -514,3 +550,26 @@ exfatfs_bitmap_init(struct exfatfs *unus
 {
 	return 0;
 }
+
+static void
+check_asserts(struct exfatfs *fs) {
+	assert(fs->xf_FatOffset >= 24);
+	assert(fs->xf_FatOffset <= fs->xf_ClusterHeapOffset
+	    - (fs->xf_FatLength * fs->xf_NumberOfFats));
+	assert(fs->xf_FatLength >= ((fs->xf_ClusterCount + 2) * 4)
+	    >> fs->xf_BytesPerSectorShift);
+	assert(fs->xf_FatLength <= (fs->xf_ClusterHeapOffset - fs->xf_FatOffset)
+	    / fs->xf_NumberOfFats);
+	assert(fs->xf_ClusterHeapOffset >= fs->xf_FatOffset
+	    + fs->xf_FatLength * fs->xf_NumberOfFats);
+	assert(fs->xf_ClusterHeapOffset <= ~(u_int32_t)0);
+	assert(fs->xf_ClusterHeapOffset <= fs->xf_VolumeLength
+					- (fs->xf_ClusterCount
+	    << fs->xf_SectorsPerClusterShift));
+	assert(fs->xf_ClusterCount >= (fs->xf_VolumeLength
+					- fs->xf_ClusterHeapOffset)
+	    >> fs->xf_SectorsPerClusterShift);
+	assert(fs->xf_ClusterCount <= ~(u_int32_t)0 - 10);
+	assert(fs->xf_FirstClusterOfRootDirectory >= 2);
+	assert(fs->xf_FirstClusterOfRootDirectory <= fs->xf_ClusterCount + 1);
+}

Index: src/sbin/newfs_exfatfs/newfs.c
diff -u src/sbin/newfs_exfatfs/newfs.c:1.1.2.4 src/sbin/newfs_exfatfs/newfs.c:1.1.2.5
--- src/sbin/newfs_exfatfs/newfs.c:1.1.2.4	Fri Aug  2 00:23:21 2024
+++ src/sbin/newfs_exfatfs/newfs.c	Tue Aug 13 05:37:24 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: newfs.c,v 1.1.2.4 2024/08/02 00:23:21 perseant Exp $	*/
+/*	$NetBSD: newfs.c,v 1.1.2.5 2024/08/13 05:37:24 perseant Exp $	*/
 
 /*-
  * Copyright (c) 1989, 1992, 1993
@@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 19
 #if 0
 static char sccsid[] = "@(#)newfs.c	8.5 (Berkeley) 5/24/95";
 #else
-__RCSID("$NetBSD: newfs.c,v 1.1.2.4 2024/08/02 00:23:21 perseant Exp $");
+__RCSID("$NetBSD: newfs.c,v 1.1.2.5 2024/08/13 05:37:24 perseant Exp $");
 #endif
 #endif /* not lint */
 
@@ -95,7 +95,8 @@ uint32_t serial = 0;
 uint32_t partition_offset = 0;
 
 char	device[MAXPATHLEN];
-char	*progname, *special, *disktype = NULL;
+char	*progname, *disktype = NULL;
+const char *special;
 
 extern long	dev_bsize;		/* device block size */
 
@@ -119,13 +120,14 @@ main(int argc, char **argv)
 	struct stat st;
 	struct uvnode *devvp;
 	struct exfatfs *fs;
-	int debug, force, fsi, fso, maxpartitions, nfats = 0;
+	int debug, Fflag, fsi = -1, fso = -1, maxpartitions, nfats = 0;
 	uint secsize = 0, secshift = 0;
 	int byte_sized = 0;
 	const char *label = "NONE GIVEN";
 	uint16_t uclabel[11];
 	uint16_t uclabellen;
 	char *bootcodefile = NULL;
+	char *xbootcodefile = NULL, *xbootcode = NULL;
 	char *uctablefile = NULL;
 	uint16_t *uctable = NULL;
 	size_t uctablesize = 0;
@@ -140,15 +142,17 @@ main(int argc, char **argv)
 	if (maxpartitions > 26)
 		fatal("insane maxpartitions value %d", maxpartitions);
 
-	debug = force = 0;
+	debug = Fflag = 0;
 	memset(&dkw, 0, sizeof(dkw));
-	while ((ch = getopt(argc, argv, "a:b:c:Dh:FL:l:Nn:o:qS:s:T:u:vw#:")) != -1)
+	while ((ch = getopt(argc, argv, "a:b:c:Dh:FL:l:Nn:o:qS:s:T:u:vwx:#:")) != -1)
 		switch(ch) {
 		case 'D': /* debug */
 			debug = 1;
+			/* Set Fflag too since we will create a regular file */
+			Fflag = 1;
 			break;
-		case 'F': /* force create filesystem even on non disk */
-			force = 1;
+		case 'F': /* Fflag create filesystem even on non disk */
+			Fflag = 1;
 			break;
 		case 'L': /* specify label */
 			label = optarg;
@@ -167,8 +171,8 @@ main(int argc, char **argv)
 			disktype = optarg;
 			break;
 		case 'a': /* FAT alignment */
-		  	fatalign = strsuftoi64("alignment", optarg,
-						MINBLOCKSIZE, INT64_MAX, NULL);
+		  	fatalign = strsuftoi64("FAT alignment", optarg,
+						0, INT64_MAX, NULL);
 			break;
 		case 'b': /* take bootcode from file */
 			bootcodefile = optarg;
@@ -179,7 +183,7 @@ main(int argc, char **argv)
 			break;
 		case 'h': /* cluster heap alignment */
 		  	heapalign = strsuftoi64("heap alignment", optarg,
-						MINBLOCKSIZE, INT64_MAX, NULL);
+						0, INT64_MAX, NULL);
 			break;
 		case 'n': /* number of FATs */
 			nfats = strtol(optarg, NULL, 10);
@@ -203,6 +207,9 @@ main(int argc, char **argv)
 		case 'v': /* verbose */
 			Vflag++;
 			break;
+		case 'x': /* take xbootcode from file */
+			xbootcodefile = optarg;
+			break;
 		case '#': /* specify serial number */
 			serial = strtoul(optarg, NULL, 0);
 			break;
@@ -216,23 +223,33 @@ main(int argc, char **argv)
 	if (argc != 2 && argc != 1)
 		usage();
 
+	special = argv[0];
+
 	/*
-	 * If the -N flag isn't specified, open the output file.  If no path
-	 * prefix, try /dev/r%s and then /dev/%s.
+	 * Open the input file.
 	 */
-	special = argv[0];
-	if (strchr(special, '/') == NULL) {
-		(void)snprintf(device, sizeof(device), "%sr%s", _PATH_DEV,
-		    special);
-		if (stat(device, &st) == -1)
-			(void)snprintf(device, sizeof(device), "%s%s",
-			    _PATH_DEV, special);
+	if (!Fflag) {
+		char specname[MAXPATHLEN];
+		char rawname[MAXPATHLEN];
+		const char *raw;
+
+		/* Translate wedge name to device name, if necessary */
+		raw = getfsspecname(specname, sizeof(specname), special);
+		if (raw == NULL)
+			err(1, "%s: %s", special, specname);
+		special = getdiskrawname(rawname, sizeof(rawname), raw);
+		if (special == NULL)
+			special = raw;
+		
+		fsi = opendisk(special, O_RDONLY, device, sizeof(device), 0);
 		special = device;
-	}
-	if (!Nflag) {
-		fso = open(special, O_RDWR, DEFFILEMODE);
-		if (debug && fso < 0) {
-			/* Create a file of the requested size. */
+		if (fsi < 0)
+			err(1, "%s: open for read", special);
+	} else { /* Fflag: just open the named file */
+		fsi = open(special, O_RDONLY);
+
+		/* If debugging, create the file */
+		if (debug && !Nflag && fsi < 0) {
 			fso = open(special, O_CREAT | O_RDWR, DEFFILEMODE);
 			if (fso >= 0) {
 				char buf[512];
@@ -241,19 +258,27 @@ main(int argc, char **argv)
 					write(fso, buf, sizeof(buf));
 				lseek(fso, 0, SEEK_SET);
 			}
+			/* Now try again */
+			fsi = open(special, O_RDONLY);
 		}
-		if (fso < 0)
-			fatal("%s: %s", special, strerror(errno));
-	} else
-		fso = -1;
-
-	/* Open the input file. */
-	fsi = open(special, O_RDONLY);
-	if (fsi < 0)
-		fatal("%s: %s", special, strerror(errno));
+		if (fsi < 0)
+			err(1, "%s", special);
+	}
 	if (fstat(fsi, &st) < 0)
-		fatal("%s: %s", special, strerror(errno));
+		err(1, "%s", special);
+
+	/*
+	 * If the -N flag isn't specified, open the output file.
+	 */
+	if (!Nflag) {
+		if (fso < 0)
+			fso = open(special, O_RDWR, DEFFILEMODE);
+		if (fso < 0)
+			err(1, "%s", special);
+	}
 
+	if (Vflag)
+		printf("making exFAT file system on %s\n", special);
 
 	if (!S_ISCHR(st.st_mode)) {
 		if (!S_ISREG(st.st_mode)) {
@@ -262,7 +287,7 @@ main(int argc, char **argv)
 		}
 		(void)strcpy(dkw.dkw_ptype, DKW_PTYPE_EXFAT); 
 		if (secsize == 0)
-			secsize = 512;
+			secsize = DEV_BSIZE;
 		dkw.dkw_size = st.st_size / secsize;
 	} else {
 		if (getdiskinfo(special, fsi, disktype, &geo, &dkw) == -1)
@@ -270,7 +295,7 @@ main(int argc, char **argv)
 
 		if (dkw.dkw_size == 0)
 			fatal("%s: is zero sized", argv[0]);
-		if (!force && strcmp(dkw.dkw_ptype, DKW_PTYPE_EXFAT) != 0)
+		if (!Fflag && strcmp(dkw.dkw_ptype, DKW_PTYPE_EXFAT) != 0)
 			fatal("%s: is not `%s', but `%s'", argv[0],
 			    DKW_PTYPE_EXFAT, dkw.dkw_ptype);
 	}
@@ -284,16 +309,15 @@ main(int argc, char **argv)
 	dev_bsize = secsize;
 
 	/* From here on out fssize is in sectors */
-	if (byte_sized) {
+	if (byte_sized)
 		fssize /= secsize;
-	}
 
 	/* If not specified, use partition offset from wedge */
 	if (partition_offset <= 0)
 		partition_offset = dkw.dkw_offset;
 
-	/* If force, make the partition look like EXFAT */
-	if (force) {
+	/* If Fflag, make the partition look like EXFAT */
+	if (Fflag) {
 		(void)strcpy(dkw.dkw_ptype, DKW_PTYPE_EXFAT); 
 		if (fssize)
 			dkw.dkw_size = fssize;
@@ -333,8 +357,8 @@ main(int argc, char **argv)
 	/* If there is none, or we were asked to ignore it, start with default values */
 	if (fs == NULL) {
 		fs = default_exfat_sb(&dkw);
-		fatalign = default_fatalign(fs->xf_VolumeLength);
-		heapalign = default_heapalign(fs->xf_VolumeLength);
+		fatalign = default_fatalign(fs->xf_VolumeLength) >> (secshift ? secshift : DEV_BSHIFT);
+		heapalign = default_heapalign(fs->xf_VolumeLength) >> (secshift ? secshift : DEV_BSHIFT);
 	}
 	fs->xf_devvp = devvp;
 
@@ -387,6 +411,17 @@ main(int argc, char **argv)
 		fclose(fp);
 	}
 
+	/* Load extended bootcode from file if requested */
+	if (xbootcodefile != NULL) {
+		FILE *fp = fopen(xbootcodefile, "rb");
+		xbootcode = malloc(8 * BSSIZE(fs));
+		if (fp == NULL || fread(xbootcode, BSSIZE(fs), 8, fp) != 8) {
+			perror(xbootcodefile);
+			exit(1);
+		}
+		fclose(fp);
+	}
+
 	/* Load upcase table from file if requested */
 	if (uctablefile != NULL) {
 		FILE *fp;
@@ -413,7 +448,7 @@ main(int argc, char **argv)
 	
 	/* Make the filesystem */
 	r = make_exfatfs(devvp, fs, uclabel, uclabellen,
-			 uctable, uctablesize,
+			 uctable, uctablesize, xbootcode,
 			 fatalign, heapalign);
 
 	if (debug)
@@ -515,7 +550,7 @@ usage(void)
 	fprintf(stderr, "where fsoptions are:\n");
 	fprintf(stderr, "\t-# serial number\n");
 	fprintf(stderr, "\t-D (debug)\n");
-	fprintf(stderr, "\t-F (force)\n");
+	fprintf(stderr, "\t-F (create on regular file)\n");
 	fprintf(stderr, "\t-L label\n");
 	fprintf(stderr, "\t-N (do not create file system)\n");
 	fprintf(stderr, "\t-S sector size\n");

Reply via email to