Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 20 Aug 2019 18:20:45 +0000 (UTC)
From:      Ed Maste <emaste@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r351273 - in head/usr.sbin/makefs: . msdos
Message-ID:  <201908201820.x7KIKjLu080715@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: emaste
Date: Tue Aug 20 18:20:45 2019
New Revision: 351273
URL: https://svnweb.freebsd.org/changeset/base/351273

Log:
  makefs: add msdosfs (FAT) support
  
  Add FAT support to makefs by copying some files from sys/fs/msdosfs/ and
  updating others with changes from NetBSD.
  
  The six files copied from sys/fs/msdosfs at r348251 and modified are:
  denode.h direntry.h fat.h msdosfs_fat.c msdosfs_lookup.c msdosfsmount.h
  
  I would prefer to avoid the duplication, but reluctance to doing so was
  expressed in a previous review (D11197); for now copy the files and
  revisit in the future.
  
  Submitted by:	Siva Mahadevan
  Discussed with:	cem, imp
  MFC after:	1 month
  Relnotes:	Yes
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D16438

Added:
  head/usr.sbin/makefs/msdos/Makefile.inc   (contents, props changed)
  head/usr.sbin/makefs/msdos/denode.h
     - copied, changed from r351251, head/sys/fs/msdosfs/denode.h
  head/usr.sbin/makefs/msdos/direntry.h
     - copied, changed from r351251, head/sys/fs/msdosfs/direntry.h
  head/usr.sbin/makefs/msdos/fat.h
     - copied, changed from r351251, head/sys/fs/msdosfs/fat.h
  head/usr.sbin/makefs/msdos/msdosfs_conv.c   (contents, props changed)
  head/usr.sbin/makefs/msdos/msdosfs_fat.c
     - copied, changed from r351251, head/sys/fs/msdosfs/msdosfs_fat.c
  head/usr.sbin/makefs/msdos/msdosfs_lookup.c
     - copied, changed from r351251, head/sys/fs/msdosfs/msdosfs_lookup.c
  head/usr.sbin/makefs/msdos/msdosfsmount.h
     - copied, changed from r351251, head/sys/fs/msdosfs/msdosfsmount.h
Modified:
  head/usr.sbin/makefs/Makefile
  head/usr.sbin/makefs/makefs.8
  head/usr.sbin/makefs/makefs.c
  head/usr.sbin/makefs/makefs.h
  head/usr.sbin/makefs/msdos.c
  head/usr.sbin/makefs/msdos.h
  head/usr.sbin/makefs/msdos/msdosfs_denode.c
  head/usr.sbin/makefs/msdos/msdosfs_vfsops.c
  head/usr.sbin/makefs/msdos/msdosfs_vnops.c

Modified: head/usr.sbin/makefs/Makefile
==============================================================================
--- head/usr.sbin/makefs/Makefile	Tue Aug 20 18:02:37 2019	(r351272)
+++ head/usr.sbin/makefs/Makefile	Tue Aug 20 18:20:45 2019	(r351273)
@@ -8,8 +8,10 @@ PROG=	makefs
 
 CFLAGS+=-I${SRCDIR}
 
-SRCS=	cd9660.c ffs.c \
+SRCS=	cd9660.c \
+	ffs.c \
 	makefs.c \
+	msdos.c \
 	mtree.c \
 	walk.c
 MAN=	makefs.8
@@ -18,6 +20,7 @@ WARNS?=	2
 
 .include "${SRCDIR}/cd9660/Makefile.inc"
 .include "${SRCDIR}/ffs/Makefile.inc"
+.include "${SRCDIR}/msdos/Makefile.inc"
 
 CFLAGS+=-DHAVE_STRUCT_STAT_ST_FLAGS=1
 

Modified: head/usr.sbin/makefs/makefs.8
==============================================================================
--- head/usr.sbin/makefs/makefs.8	Tue Aug 20 18:02:37 2019	(r351272)
+++ head/usr.sbin/makefs/makefs.8	Tue Aug 20 18:20:45 2019	(r351273)
@@ -35,7 +35,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd August 19, 2019
+.Dd August 20, 2019
 .Dt MAKEFS 8
 .Os
 .Sh NAME
@@ -198,7 +198,9 @@ and
 Instead of creating the filesystem at the beginning of the file, start
 at offset.
 Valid only for
-.Sy ffs .
+.Sy ffs
+and
+.Sy msdos .
 .It Fl o Ar fs-options
 Set file system specific options.
 .Ar fs-options
@@ -232,10 +234,14 @@ and the maximum
 sizes to the same value.
 For
 .Sy ffs
+and
+.Sy msdos
 the
 .Ar image-size
 does not include the
 .Ar offset .
+.Ar offset
+is not included in that size.
 .It Fl T Ar timestamp
 Specify a timestamp to be set for all filesystem files and directories
 created so that repeatable builds are possible.
@@ -258,6 +264,8 @@ The following file system types are supported:
 BSD fast file system (default).
 .It Sy cd9660
 ISO 9660 file system.
+.It Sy msdos
+FAT12, FAT16, or FAT32 file system.
 .El
 .It Fl x
 Exclude file system nodes not explicitly listed in the specfile.
@@ -420,6 +428,67 @@ Use RockRidge extensions (for longer filenames, etc.).
 Turns on verbose output.
 .It Sy volumeid
 Volume set identifier of the image.
+.El
+.Ss msdos-specific options
+.Sy msdos
+images have MS-DOS-specific optional parameters that may be
+provided.
+The arguments consist of a keyword, an equal sign
+.Pq Ql = ,
+and a value.
+The following keywords are supported (see
+.Xr newfs_msdos 8
+for more details):
+.Pp
+.Bl -tag -width omit-trailing-period -offset indent -compact
+.It Cm backup_sector
+Location of the backup boot sector.
+.It Cm block_size
+Block size.
+.It Cm bootstrap
+Bootstrap file.
+.It Cm bytes_per_sector
+Bytes per sector.
+.It Cm create_size
+Create file size.
+.It Cm directory_entries
+Directory entries.
+.It Cm drive_heads
+Drive heads.
+.It Cm fat_type
+FAT type (12, 16, or 32).
+.It Cm floppy
+Preset drive parameters for standard format floppy disks
+(160, 180, 320, 360, 640, 720, 1200, 1232, 1440, or 2880).
+.It Cm hidden_sectors
+Hidden sectors.
+.It Cm info_sector
+Location of the info sector.
+.It Cm media_descriptor
+Media descriptor.
+.It Cm num_FAT
+Number of FATs.
+.It Cm OEM_string
+OEM string.
+.It Cm offset
+Offset in device.
+This option will be ignored if
+.Fl O
+is set to a positive number.
+.It Cm reserved_sectors
+Reserved sectors.
+.It Cm sectors_per_cluster
+Sectors per cluster.
+.It Cm sectors_per_fat
+Sectors per FAT.
+.It Cm sectors_per_track
+Sectors per track.
+.It Cm size
+File System size.
+.It Cm volume_id
+Volume ID.
+.It Cm volume_label
+Volume Label.
 .El
 .Sh SEE ALSO
 .Xr mtree 5 ,

Modified: head/usr.sbin/makefs/makefs.c
==============================================================================
--- head/usr.sbin/makefs/makefs.c	Tue Aug 20 18:02:37 2019	(r351272)
+++ head/usr.sbin/makefs/makefs.c	Tue Aug 20 18:20:45 2019	(r351273)
@@ -74,8 +74,9 @@ static fstype_t fstypes[] = {
 	# name, name ## _prep_opts, name ## _parse_opts, \
 	name ## _cleanup_opts, name ## _makefs  \
 }
-	ENTRY(ffs),
 	ENTRY(cd9660),
+	ENTRY(ffs),
+	ENTRY(msdos),
 	{ .type = NULL	},
 };
 

Modified: head/usr.sbin/makefs/makefs.h
==============================================================================
--- head/usr.sbin/makefs/makefs.h	Tue Aug 20 18:02:37 2019	(r351272)
+++ head/usr.sbin/makefs/makefs.h	Tue Aug 20 18:20:45 2019	(r351273)
@@ -183,8 +183,9 @@ int		fs ## _parse_opts(const char *, fsinfo_t *);		\
 void		fs ## _cleanup_opts(fsinfo_t *);			\
 void		fs ## _makefs(const char *, const char *, fsnode *, fsinfo_t *)
 
-DECLARE_FUN(ffs);
 DECLARE_FUN(cd9660);
+DECLARE_FUN(ffs);
+DECLARE_FUN(msdos);
 
 extern	u_int		debug;
 extern	int		dupsok;
@@ -225,6 +226,7 @@ extern	struct stat stampst;
 #define	DEBUG_APPLY_SPECFILE		0x04000000
 #define	DEBUG_APPLY_SPECENTRY		0x08000000
 #define	DEBUG_APPLY_SPECONLY		0x10000000
+#define	DEBUG_MSDOSFS			0x20000000
 
 
 #define	TIMER_START(x)				\

Modified: head/usr.sbin/makefs/msdos.c
==============================================================================
--- head/usr.sbin/makefs/msdos.c	Tue Aug 20 18:02:37 2019	(r351272)
+++ head/usr.sbin/makefs/msdos.c	Tue Aug 20 18:20:45 2019	(r351273)
@@ -50,24 +50,28 @@ __FBSDID("$FreeBSD$");
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdint.h>
 #include <unistd.h>
 #include <dirent.h>
 #include <util.h>
 
-#include <ffs/buf.h>
-#include <fs/msdosfs/bpb.h>
-#include <fs/msdosfs/denode.h>
-#include <fs/msdosfs/msdosfsmount.h>
 #include "makefs.h"
 #include "msdos.h"
-#include "mkfs_msdos.h"
 
+#include <mkfs_msdos.h>
+#include <fs/msdosfs/bpb.h>
+
+#include "ffs/buf.h"
+
+#include "msdos/msdosfsmount.h"
+#include "msdos/direntry.h"
+#include "msdos/denode.h"
+
 static int msdos_populate_dir(const char *, struct denode *, fsnode *,
     fsnode *, fsinfo_t *);
 
 struct msdos_options_ex {
 	struct msdos_options options;
-	bool utf8;
 };
 
 void
@@ -85,15 +89,13 @@ msdos_prep_opts(fsinfo_t *fsopts)
 	    (sizeof(_type) == 4 ? OPT_INT32 : OPT_INT64)))),		\
 	.value = &msdos_opt->options._name,				\
 	.minimum = _min,						\
-	.maximum = sizeof(_type) == 1 ? 0xff :				\
-	    (sizeof(_type) == 2 ? 0xffff :				\
-	    (sizeof(_type) == 4 ? 0xffffffff : 0xffffffffffffffffLL)),	\
-	.desc = _desc,						\
+	.maximum = sizeof(_type) == 1 ? UINT8_MAX :			\
+	    (sizeof(_type) == 2 ? UINT16_MAX :				\
+	    (sizeof(_type) == 4 ? UINT32_MAX : INT64_MAX)),		\
+	.desc = _desc,							\
 },
 ALLOPTS
 #undef AOPT
-		{ 'U', "utf8", &msdos_opt->utf8, OPT_BOOL,
-		  0, 1, "Use UTF8 names" },
 		{ .name = NULL }
 	};
 
@@ -113,7 +115,6 @@ msdos_parse_opts(const char *option, fsinfo_t *fsopts)
 {
 	struct msdos_options *msdos_opt = fsopts->fs_specific;
 	option_t *msdos_options = fsopts->fs_options;
-
 	int rv;
 
 	assert(option != NULL);
@@ -148,7 +149,7 @@ msdos_makefs(const char *image, const char *dir, fsnod
 {
 	struct msdos_options_ex *msdos_opt = fsopts->fs_specific;
 	struct vnode vp, rootvp;
-	struct timeval	start;
+	struct timeval start;
 	struct msdosfsmount *pmp;
 	uint32_t flags;
 
@@ -160,7 +161,8 @@ msdos_makefs(const char *image, const char *dir, fsnod
 	fsopts->size = fsopts->maxsize;
 	msdos_opt->options.create_size = MAX(msdos_opt->options.create_size,
 	    fsopts->offset + fsopts->size);
-	msdos_opt->options.offset = fsopts->offset;
+	if (fsopts->offset > 0)
+		msdos_opt->options.offset = fsopts->offset;
 	if (msdos_opt->options.bytes_per_sector == 0) {
 		if (fsopts->sectorsize == -1)
 			fsopts->sectorsize = 512;
@@ -173,7 +175,7 @@ msdos_makefs(const char *image, const char *dir, fsnod
 		    fsopts->sectorsize, msdos_opt->options.bytes_per_sector);
 	}
 
-		/* create image */
+	/* create image */
 	printf("Creating `%s'\n", image);
 	TIMER_START(start);
 	if (mkfs_msdos(image, NULL, &msdos_opt->options) == -1)
@@ -184,10 +186,7 @@ msdos_makefs(const char *image, const char *dir, fsnod
 	vp.fs = fsopts;
 
 	flags = 0;
-	if (msdos_opt->utf8)
-		flags |= MSDOSFSMNT_UTF8;
-
-	if ((pmp = msdosfs_mount(&vp, flags)) == NULL)
+	if ((pmp = msdosfs_mount(&vp)) == NULL)
 		err(1, "msdosfs_mount");
 
 	if (msdosfs_root(pmp, &rootvp) != 0)
@@ -197,7 +196,7 @@ msdos_makefs(const char *image, const char *dir, fsnod
 		printf("msdos_makefs: image %s directory %s root %p\n",
 		    image, dir, root);
 
-		/* populate image */
+	/* populate image */
 	printf("Populating `%s'\n", image);
 	TIMER_START(start);
 	if (msdos_populate_dir(dir, VTODE(&rootvp), root, root, fsopts) == -1)
@@ -207,7 +206,7 @@ msdos_makefs(const char *image, const char *dir, fsnod
 	if (debug & DEBUG_FS_MAKEFS)
 		putchar('\n');
 
-		/* ensure no outstanding buffers remain */
+	/* ensure no outstanding buffers remain */
 	if (debug & DEBUG_FS_MAKEFS)
 		bcleanup();
 

Modified: head/usr.sbin/makefs/msdos.h
==============================================================================
--- head/usr.sbin/makefs/msdos.h	Tue Aug 20 18:02:37 2019	(r351272)
+++ head/usr.sbin/makefs/msdos.h	Tue Aug 20 18:20:45 2019	(r351273)
@@ -30,11 +30,31 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifndef _MAKEFS_MSDOS_H
+#define _MAKEFS_MSDOS_H
+
+#define NOCRED NULL
+
+#define MSDOSFS_DPRINTF(args) do {	\
+	if (debug & DEBUG_MSDOSFS)	\
+		printf args;		\
+} while (0);
+
+
 struct vnode;
 struct denode;
+struct fsnode;
+struct msdosfsmount;
 
-struct msdosfsmount *msdosfs_mount(struct vnode *, int);
+struct componentname {
+	char *cn_nameptr;
+	size_t cn_namelen;
+};
+
+struct msdosfsmount *msdosfs_mount(struct vnode *);
 int msdosfs_root(struct msdosfsmount *, struct vnode *);
 
 struct denode *msdosfs_mkfile(const char *, struct denode *, fsnode *);
 struct denode *msdosfs_mkdire(const char *, struct denode *, fsnode *);
+
+#endif

Added: head/usr.sbin/makefs/msdos/Makefile.inc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.sbin/makefs/msdos/Makefile.inc	Tue Aug 20 18:20:45 2019	(r351273)
@@ -0,0 +1,13 @@
+#	$FreeBSD$
+#
+
+MSDOS=		${SRCTOP}/sys/fs/msdosfs
+MSDOS_NEWFS=	${SRCTOP}/sbin/newfs_msdos
+
+.PATH:	${SRCDIR}/msdos ${MSDOS} ${MSDOS_NEWFS}
+
+CFLAGS+= -I${MSDOS} -I${MSDOS_NEWFS}
+
+SRCS+= mkfs_msdos.c
+SRCS+= msdosfs_conv.c msdosfs_denode.c msdosfs_fat.c msdosfs_lookup.c
+SRCS+= msdosfs_vnops.c msdosfs_vfsops.c

Copied and modified: head/usr.sbin/makefs/msdos/denode.h (from r351251, head/sys/fs/msdosfs/denode.h)
==============================================================================
--- head/sys/fs/msdosfs/denode.h	Tue Aug 20 16:07:17 2019	(r351251, copy source)
+++ head/usr.sbin/makefs/msdos/denode.h	Tue Aug 20 18:20:45 2019	(r351273)
@@ -161,7 +161,6 @@ struct denode {
 	u_long de_StartCluster; /* starting cluster of file */
 	u_long de_FileSize;	/* size of file in bytes */
 	struct fatcache de_fc[FC_SIZE];	/* FAT cache */
-	u_quad_t de_modrev;	/* Revision level for lease. */
 	uint64_t de_inode;	/* Inode number (really byte offset of direntry) */
 };
 
@@ -213,60 +212,16 @@ struct denode {
 	     ((dep)->de_Attributes & ATTR_DIRECTORY) ? 0 : (dep)->de_FileSize), \
 	 putushort((dp)->deHighClust, (dep)->de_StartCluster >> 16))
 
-#ifdef _KERNEL
-
 #define	VTODE(vp)	((struct denode *)(vp)->v_data)
 #define	DETOV(de)	((de)->de_vnode)
 
-#define	DETIMES(dep, acc, mod, cre) do {				\
-	if ((dep)->de_flag & DE_UPDATE) {				\
-		(dep)->de_flag |= DE_MODIFIED;				\
-		timespec2fattime((mod), 0, &(dep)->de_MDate,		\
-		    &(dep)->de_MTime, NULL);				\
-		(dep)->de_Attributes |= ATTR_ARCHIVE;			\
-	}								\
-	if ((dep)->de_pmp->pm_flags & MSDOSFSMNT_NOWIN95) {		\
-		(dep)->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS);	\
-		break;							\
-	}								\
-	if ((dep)->de_flag & DE_ACCESS) {				\
-		uint16_t adate;						\
-									\
-		timespec2fattime((acc), 0, &adate, NULL, NULL);		\
-		if (adate != (dep)->de_ADate) {				\
-			(dep)->de_flag |= DE_MODIFIED;			\
-			(dep)->de_ADate = adate;			\
-		}							\
-	}								\
-	if ((dep)->de_flag & DE_CREATE) {				\
-		timespec2fattime((cre), 0, &(dep)->de_CDate,		\
-		    &(dep)->de_CTime, &(dep)->de_CHun);			\
-		(dep)->de_flag |= DE_MODIFIED;				\
-	}								\
-	(dep)->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS);		\
-} while (0)
+struct buf;
+struct msdosfsmount;
+struct direntry;
+struct componentname;
+struct denode;
 
 /*
- * This overlays the fid structure (see mount.h)
- */
-struct defid {
-	u_short defid_len;	/* length of structure */
-	u_short defid_pad;	/* force long alignment */
-
-	uint32_t defid_dirclust; /* cluster this dir entry came from */
-	uint32_t defid_dirofs;	/* offset of entry within the cluster */
-#if 0
-	uint32_t defid_gen;	/* generation number */
-#endif
-};
-
-extern struct vop_vector msdosfs_vnodeops;
-
-int msdosfs_lookup(struct vop_cachedlookup_args *);
-int msdosfs_inactive(struct vop_inactive_args *);
-int msdosfs_reclaim(struct vop_reclaim_args *);
-
-/*
  * Internal service routine prototypes.
  */
 int deget(struct msdosfsmount *, u_long, u_long, struct denode **);
@@ -274,14 +229,9 @@ int uniqdosname(struct denode *, struct componentname 
 
 int readep(struct msdosfsmount *pmp, u_long dirclu, u_long dirofs,  struct buf **bpp, struct direntry **epp);
 int readde(struct denode *dep, struct buf **bpp, struct direntry **epp);
-int deextend(struct denode *dep, u_long length, struct ucred *cred);
+int deextend(struct denode *dep, u_long length);
 int fillinusemap(struct msdosfsmount *pmp);
-void reinsert(struct denode *dep);
-int dosdirempty(struct denode *dep);
 int createde(struct denode *dep, struct denode *ddep, struct denode **depp, struct componentname *cnp);
-int deupdat(struct denode *dep, int waitfor);
 int removede(struct denode *pdep, struct denode *dep);
-int detrunc(struct denode *dep, u_long length, int flags, struct ucred *cred);
-int doscheckpath( struct denode *source, struct denode *target);
-#endif	/* _KERNEL */
+int detrunc(struct denode *dep, u_long length, int flags);
 #endif	/* !_FS_MSDOSFS_DENODE_H_ */

Copied and modified: head/usr.sbin/makefs/msdos/direntry.h (from r351251, head/sys/fs/msdosfs/direntry.h)
==============================================================================
--- head/sys/fs/msdosfs/direntry.h	Tue Aug 20 16:07:17 2019	(r351251, copy source)
+++ head/usr.sbin/makefs/msdos/direntry.h	Tue Aug 20 18:20:45 2019	(r351273)
@@ -135,31 +135,12 @@ struct winentry {
 #define DD_YEAR_MASK		0xFE00	/* year - 1980 */
 #define DD_YEAR_SHIFT		9
 
-#ifdef _KERNEL
-struct mbnambuf {
-	size_t	nb_len;
-	int	nb_last_id;
-	char	nb_buf[WIN_MAXLEN + 1];
-};
-
-struct dirent;
-struct msdosfsmount;
-
-char	*mbnambuf_flush(struct mbnambuf *nbp, struct dirent *dp);
-void	mbnambuf_init(struct mbnambuf *nbp);
-int	mbnambuf_write(struct mbnambuf *nbp, char *name, int id);
-int	dos2unixfn(u_char dn[11], u_char *un, int lower,
-	    struct msdosfsmount *pmp);
-int	unix2dosfn(const u_char *un, u_char dn[12], size_t unlen, u_int gen,
-	    struct msdosfsmount *pmp);
-int	unix2winfn(const u_char *un, size_t unlen, struct winentry *wep, int cnt,
-	    int chksum, struct msdosfsmount *pmp);
-int	winChkName(struct mbnambuf *nbp, const u_char *un, size_t unlen,
-	    int chksum, struct msdosfsmount *pmp);
-int	win2unixfn(struct mbnambuf *nbp, struct winentry *wep, int chksum,
-	    struct msdosfsmount *pmp);
 uint8_t winChksum(uint8_t *name);
-int	winSlotCnt(const u_char *un, size_t unlen, struct msdosfsmount *pmp);
-size_t	winLenFixup(const u_char *un, size_t unlen);
-#endif	/* _KERNEL */
+int winSlotCnt(const u_char *un, size_t unlen);
+int unix2dosfn(const u_char *un, u_char dn[12], size_t unlen, u_int gen);
+int winChkName(const u_char *un, size_t unlen, struct winentry *wep,
+    int chksum);
+int unix2winfn(const u_char *un, size_t unlen, struct winentry *wep, int cnt,
+    int chksum);
+
 #endif	/* !_FS_MSDOSFS_DIRENTRY_H_ */

Copied and modified: head/usr.sbin/makefs/msdos/fat.h (from r351251, head/sys/fs/msdosfs/fat.h)
==============================================================================
--- head/sys/fs/msdosfs/fat.h	Tue Aug 20 16:07:17 2019	(r351251, copy source)
+++ head/usr.sbin/makefs/msdos/fat.h	Tue Aug 20 18:20:45 2019	(r351273)
@@ -82,7 +82,6 @@
 
 #define	MSDOSFSEOF(pmp, cn)	((((cn) | ~(pmp)->pm_fatmask) & CLUST_EOFS) == CLUST_EOFS)
 
-#ifdef _KERNEL
 /*
  * These are the values for the function argument to the function
  * fatentry().
@@ -96,6 +95,10 @@
  */
 #define	DE_CLEAR	1	/* Zero out the blocks allocated */
 
+struct buf;
+struct denode;
+struct msdosfsmount;
+
 int pcbmap(struct denode *dep, u_long findcn, daddr_t *bnp, u_long *cnp, int* sp);
 int clusterfree(struct msdosfsmount *pmp, u_long cn, u_long *oldcnp);
 int clusteralloc(struct msdosfsmount *pmp, u_long start, u_long count, u_long fillwith, u_long *retcluster, u_long *got);
@@ -103,7 +106,5 @@ int fatentry(int function, struct msdosfsmount *pmp, u
 int freeclusterchain(struct msdosfsmount *pmp, u_long startchain);
 int extendfile(struct denode *dep, u_long count, struct buf **bpp, u_long *ncp, int flags);
 void fc_purge(struct denode *dep, u_int frcn);
-int markvoldirty(struct msdosfsmount *pmp, int dirty);
 
-#endif	/* _KERNEL */
 #endif	/* !_FS_MSDOSFS_FAT_H_ */

Added: head/usr.sbin/makefs/msdos/msdosfs_conv.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.sbin/makefs/msdos/msdosfs_conv.c	Tue Aug 20 18:20:45 2019	(r351273)
@@ -0,0 +1,508 @@
+/*-
+ * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
+ * Copyright (C) 1994, 1995, 1997 TooLs GmbH.
+ * All rights reserved.
+ * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Written by Paul Popelka (paulp@uts.amdahl.com)
+ *
+ * You can do anything you want with this software, just don't say you wrote
+ * it, and don't remove this notice.
+ *
+ * This software is provided "as is".
+ *
+ * The author supplies this software to be publicly redistributed on the
+ * understanding that the author is not responsible for the correct
+ * functioning of this software in any circumstances and is not liable for
+ * any damages caused by this software.
+ *
+ * October 1992
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/endian.h>
+
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <fs/msdosfs/bpb.h>
+
+#include "makefs.h"
+#include "msdos.h"
+
+#include "msdos/denode.h"
+#include "msdos/direntry.h"
+#include "msdos/fat.h"
+#include "msdos/msdosfsmount.h"
+
+static int char8ucs2str(const uint8_t *in, int n, uint16_t *out, int m);
+static void ucs2pad(uint16_t *buf, int len, int size);
+static int char8match(uint16_t *w1, uint16_t *w2, int n);
+
+static const u_char unix2dos[256] = {
+	0,    0,    0,    0,    0,    0,    0,    0,	/* 00-07 */
+	0,    0,    0,    0,    0,    0,    0,    0,	/* 08-0f */
+	0,    0,    0,    0,    0,    0,    0,    0,	/* 10-17 */
+	0,    0,    0,    0,    0,    0,    0,    0,	/* 18-1f */
+	0,    '!',  0,    '#',  '$',  '%',  '&',  '\'',	/* 20-27 */
+	'(',  ')',  0,    '+',  0,    '-',  0,    0,	/* 28-2f */
+	'0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',	/* 30-37 */
+	'8',  '9',  0,    0,    0,    0,    0,    0,	/* 38-3f */
+	'@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',	/* 40-47 */
+	'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',	/* 48-4f */
+	'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',	/* 50-57 */
+	'X',  'Y',  'Z',  0,    0,    0,    '^',  '_',	/* 58-5f */
+	'`',  'A',  'B',  'C',  'D',  'E',  'F',  'G',	/* 60-67 */
+	'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',	/* 68-6f */
+	'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',	/* 70-77 */
+	'X',  'Y',  'Z',  '{',  0,    '}',  '~',  0,	/* 78-7f */
+	0,    0,    0,    0,    0,    0,    0,    0,	/* 80-87 */
+	0,    0,    0,    0,    0,    0,    0,    0,	/* 88-8f */
+	0,    0,    0,    0,    0,    0,    0,    0,	/* 90-97 */
+	0,    0,    0,    0,    0,    0,    0,    0,	/* 98-9f */
+	0,    0xad, 0xbd, 0x9c, 0xcf, 0xbe, 0xdd, 0xf5,	/* a0-a7 */
+	0xf9, 0xb8, 0xa6, 0xae, 0xaa, 0xf0, 0xa9, 0xee,	/* a8-af */
+	0xf8, 0xf1, 0xfd, 0xfc, 0xef, 0xe6, 0xf4, 0xfa,	/* b0-b7 */
+	0xf7, 0xfb, 0xa7, 0xaf, 0xac, 0xab, 0xf3, 0xa8,	/* b8-bf */
+	0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80,	/* c0-c7 */
+	0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8,	/* c8-cf */
+	0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0x9e,	/* d0-d7 */
+	0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0xe1,	/* d8-df */
+	0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80,	/* e0-e7 */
+	0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8,	/* e8-ef */
+	0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0xf6,	/* f0-f7 */
+	0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0x98,	/* f8-ff */
+};
+
+static const u_char u2l[256] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 00-07 */
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 08-0f */
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 10-17 */
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 18-1f */
+	' ',  '!',  '"',  '#',  '$',  '%',  '&', '\'', /* 20-27 */
+	'(',  ')',  '*',  '+',  ',',  '-',  '.',  '/', /* 28-2f */
+	'0',  '1',  '2',  '3',  '4',  '5',  '6',  '7', /* 30-37 */
+	'8',  '9',  ':',  ';',  '<',  '=',  '>',  '?', /* 38-3f */
+	'@',  'a',  'b',  'c',  'd',  'e',  'f',  'g', /* 40-47 */
+	'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o', /* 48-4f */
+	'p',  'q',  'r',  's',  't',  'u',  'v',  'w', /* 50-57 */
+	'x',  'y',  'z',  '[', '\\',  ']',  '^',  '_', /* 58-5f */
+	'`',  'a',  'b',  'c',  'd',  'e',  'f',  'g', /* 60-67 */
+	'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o', /* 68-6f */
+	'p',  'q',  'r',  's',  't',  'u',  'v',  'w', /* 70-77 */
+	'x',  'y',  'z',  '{',  '|',  '}',  '~', 0x7f, /* 78-7f */
+	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 80-87 */
+	0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 88-8f */
+	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 90-97 */
+	0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 98-9f */
+	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* a0-a7 */
+	0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* a8-af */
+	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* b0-b7 */
+	0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* b8-bf */
+	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* c0-c7 */
+	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* c8-cf */
+	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* d0-d7 */
+	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* d8-df */
+	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* e0-e7 */
+	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* e8-ef */
+	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* f0-f7 */
+	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* f8-ff */
+};
+
+/*
+ * Determine the number of slots necessary for Win95 names
+ */
+int
+winSlotCnt(const u_char *un, size_t unlen)
+{
+	const u_char *cp;
+
+	/*
+	 * Drop trailing blanks and dots
+	 */
+	for (cp = un + unlen; unlen > 0; unlen--)
+		if (*--cp != ' ' && *cp != '.')
+			break;
+
+	return howmany(unlen, WIN_CHARS);
+}
+
+/*
+ * Compare our filename to the one in the Win95 entry
+ * Returns the checksum or -1 if no match
+ */
+int
+winChkName(const u_char *un, size_t unlen, struct winentry *wep, int chksum)
+{
+	uint16_t wn[WIN_MAXLEN], *p;
+	uint16_t buf[WIN_CHARS];
+	int i, len;
+
+	/*
+	 * First compare checksums
+	 */
+	if (wep->weCnt & WIN_LAST)
+		chksum = wep->weChksum;
+	else if (chksum != wep->weChksum)
+		chksum = -1;
+	if (chksum == -1)
+		return -1;
+
+	/*
+	 * Offset of this entry
+	 */
+	i = ((wep->weCnt & WIN_CNT) - 1) * WIN_CHARS;
+
+	/*
+	 * Translate UNIX name to ucs-2
+	 */
+	len = char8ucs2str(un, unlen, wn, WIN_MAXLEN);
+	ucs2pad(wn, len, WIN_MAXLEN);
+
+	if (i >= len + 1)
+		return -1;
+	if ((wep->weCnt & WIN_LAST) && (len - i > WIN_CHARS))
+		return -1;
+
+	/*
+	 * Fetch name segment from directory entry
+	 */
+	p = &buf[0];
+	memcpy(p, wep->wePart1, sizeof(wep->wePart1));
+	p += sizeof(wep->wePart1) / sizeof(*p);
+	memcpy(p, wep->wePart2, sizeof(wep->wePart2));
+	p += sizeof(wep->wePart2) / sizeof(*p);
+	memcpy(p, wep->wePart3, sizeof(wep->wePart3));
+
+	/*
+	 * And compare name segment
+	 */
+	if (!(char8match(&wn[i], buf, WIN_CHARS)))
+		return -1;
+
+	return chksum;
+}
+
+/*
+ * Compute the checksum of a DOS filename for Win95 use
+ */
+uint8_t
+winChksum(uint8_t *name)
+{
+	int i;
+	uint8_t s;
+
+	for (s = 0, i = 11; --i >= 0; s += *name++)
+		s = (s << 7) | (s >> 1);
+	return s;
+}
+
+/*
+ * Create a Win95 long name directory entry
+ * Note: assumes that the filename is valid,
+ *	 i.e. doesn't consist solely of blanks and dots
+ */
+int
+unix2winfn(const u_char *un, size_t unlen, struct winentry *wep, int cnt,
+    int chksum)
+{
+	uint16_t wn[WIN_MAXLEN], *p;
+	int i, len;
+	const u_char *cp;
+
+	/*
+	 * Drop trailing blanks and dots
+	 */
+	for (cp = un + unlen; unlen > 0; unlen--)
+		if (*--cp != ' ' && *cp != '.')
+			break;
+
+	/*
+	 * Offset of this entry
+	 */
+	i = (cnt - 1) * WIN_CHARS;
+
+	/*
+	 * Translate UNIX name to ucs-2
+	 */
+	len = char8ucs2str(un, unlen, wn, WIN_MAXLEN);
+	ucs2pad(wn, len, WIN_MAXLEN);
+
+	/*
+	 * Initialize winentry to some useful default
+	 */
+	memset(wep, 0xff, sizeof(*wep));
+	wep->weCnt = cnt;
+	wep->weAttributes = ATTR_WIN95;
+	wep->weReserved1 = 0;
+	wep->weChksum = chksum;
+	wep->weReserved2 = 0;
+
+	/*
+	 * Store name segment into directory entry
+	 */
+	p = &wn[i];
+	memcpy(wep->wePart1, p, sizeof(wep->wePart1));
+	p += sizeof(wep->wePart1) / sizeof(*p);
+	memcpy(wep->wePart2, p, sizeof(wep->wePart2));
+	p += sizeof(wep->wePart2) / sizeof(*p);
+	memcpy(wep->wePart3, p, sizeof(wep->wePart3));
+
+	if (len > i + WIN_CHARS)
+		return 1;
+
+	wep->weCnt |= WIN_LAST;
+	return 0;
+}
+
+/*
+ * Convert a unix filename to a DOS filename according to Win95 rules.
+ * If applicable and gen is not 0, it is inserted into the converted
+ * filename as a generation number.
+ * Returns
+ *	0 if name couldn't be converted
+ *	1 if the converted name is the same as the original
+ *	  (no long filename entry necessary for Win95)
+ *	2 if conversion was successful
+ *	3 if conversion was successful and generation number was inserted
+ */
+int
+unix2dosfn(const u_char *un, u_char dn[12], size_t unlen, u_int gen)
+{
+	int i, j, l;
+	int conv = 1;
+	const u_char *cp, *dp, *dp1;
+	u_char gentext[6], *wcp;
+	int shortlen;
+
+	/*
+	 * Fill the dos filename string with blanks. These are DOS's pad
+	 * characters.
+	 */
+	for (i = 0; i < 11; i++)
+		dn[i] = ' ';
+	dn[11] = 0;
+
+	/*
+	 * The filenames "." and ".." are handled specially, since they
+	 * don't follow dos filename rules.
+	 */
+	if (un[0] == '.' && unlen == 1) {
+		dn[0] = '.';
+		return gen <= 1;
+	}
+	if (un[0] == '.' && un[1] == '.' && unlen == 2) {
+		dn[0] = '.';
+		dn[1] = '.';
+		return gen <= 1;
+	}
+
+	/*
+	 * Filenames with only blanks and dots are not allowed!
+	 */
+	for (cp = un, i = unlen; --i >= 0; cp++)
+		if (*cp != ' ' && *cp != '.')
+			break;
+	if (i < 0)
+		return 0;
+
+	/*
+	 * Now find the extension
+	 * Note: dot as first char doesn't start extension
+	 *	 and trailing dots and blanks are ignored
+	 */
+	dp = dp1 = 0;
+	for (cp = un + 1, i = unlen - 1; --i >= 0;) {
+		switch (*cp++) {
+		case '.':
+			if (!dp1)
+				dp1 = cp;
+			break;
+		case ' ':
+			break;
+		default:
+			if (dp1)
+				dp = dp1;
+			dp1 = 0;
+			break;
+		}
+	}
+
+	/*
+	 * Now convert it
+	 */
+	if (dp) {
+		if (dp1)
+			l = dp1 - dp;
+		else
+			l = unlen - (dp - un);
+		for (i = 0, j = 8; i < l && j < 11; i++, j++) {
+			if (dp[i] != (dn[j] = unix2dos[dp[i]])
+			    && conv != 3)
+				conv = 2;
+			if (!dn[j]) {
+				conv = 3;
+				dn[j--] = ' ';
+			}
+		}
+		if (i < l)
+			conv = 3;
+		dp--;
+	} else {
+		for (dp = cp; *--dp == ' ' || *dp == '.';);
+		dp++;
+	}
+
+	shortlen = (dp - un) <= 8;
+
+	/*
+	 * Now convert the rest of the name
+	 */
+	for (i = j = 0; un < dp && j < 8; i++, j++, un++) {
+		if ((*un == ' ') && shortlen)
+			dn[j] = ' ';
+		else
+			dn[j] = unix2dos[*un];
+		if ((*un != dn[j])
+		    && conv != 3)
+			conv = 2;
+		if (!dn[j]) {
+			conv = 3;
+			dn[j--] = ' ';
+		}
+	}
+	if (un < dp)
+		conv = 3;
+	/*
+	 * If we didn't have any chars in filename,
+	 * generate a default
+	 */
+	if (!j)
+		dn[0] = '_';
+
+	/*
+	 * The first character cannot be E5,
+	 * because that means a deleted entry
+	 */
+	if (dn[0] == 0xe5)
+		dn[0] = SLOT_E5;
+
+	/*
+	 * If there wasn't any char dropped,
+	 * there is no place for generation numbers
+	 */
+	if (conv != 3) {
+		if (gen > 1)
+			return 0;
+		return conv;
+	}
+
+	/*
+	 * Now insert the generation number into the filename part
+	 */
+	for (wcp = gentext + sizeof(gentext); wcp > gentext && gen; gen /= 10)
+		*--wcp = gen % 10 + '0';
+	if (gen)
+		return 0;
+	for (i = 8; dn[--i] == ' ';);
+	i++;
+	if (gentext + sizeof(gentext) - wcp + 1 > 8 - i)
+		i = 8 - (gentext + sizeof(gentext) - wcp + 1);
+	dn[i++] = '~';
+	while (wcp < gentext + sizeof(gentext))
+		dn[i++] = *wcp++;
+	return 3;
+}
+
+/*
+ * Convert 8bit character string into UCS-2 string
+ * return total number of output chacters
+ */
+static int
+char8ucs2str(const uint8_t *in, int n, uint16_t *out, int m)
+{
+	uint16_t *p;
+
+	p = out;
+	while (n > 0 && in[0] != 0) {
+		if (m < 1)
+			break;
+		if (p)
+			p[0] = htole16(in[0]);
+		p += 1;
+		m -= 1;
+		in += 1;
+		n -= 1;
+	}
+
+	return p - out;
+}
+
+static void
+ucs2pad(uint16_t *buf, int len, int size)
+{
+
+	if (len < size-1)
+		buf[len++] = 0x0000;
+	while (len < size)
+		buf[len++] = 0xffff;
+}
+
+/*
+ * Compare two 8bit char conversions case-insensitive
+ *
+ * uses the DOS case folding table
+ */
+static int
+char8match(uint16_t *w1, uint16_t *w2, int n)
+{
+	uint16_t u1, u2;
+

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201908201820.x7KIKjLu080715>