diff --git a/lib/libprocstat/msdosfs.c b/lib/libprocstat/msdosfs.c
index 87906423f9b6..3541f252c713 100644
--- a/lib/libprocstat/msdosfs.c
+++ b/lib/libprocstat/msdosfs.c
@@ -1,155 +1,156 @@
 /*-
  * SPDX-License-Identifier: BSD-4-Clause
  *
  * Copyright (c) 2000 Peter Edwards
  * Copyright (c) 1988, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by Peter Edwards
  *
  * 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 the University of
  *	California, Berkeley and its contributors.
  * 4. Neither the name of the University 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 REGENTS AND CONTRIBUTORS ``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 THE REGENTS OR CONTRIBUTORS 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.
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/buf.h>
 #include <sys/time.h>
 #include <sys/stat.h>
 #include <sys/vnode.h>
 
 #include <netinet/in.h>
 
 #define	_KERNEL
 #include <sys/mount.h>
 #include <fs/msdosfs/bpb.h>
 #include <fs/msdosfs/msdosfsmount.h>
 #undef _KERNEL
 
 #include <fs/msdosfs/denode.h>
 #include <fs/msdosfs/direntry.h>
 #include <fs/msdosfs/fat.h>
 
 #include <err.h>
 #include <kvm.h>
 #include <stdio.h>
 #include <stdlib.h>
 
 /*
  * XXX -
  * VTODE is defined in denode.h only if _KERNEL is defined, but that leads to
  * header explosion
  */
 #define VTODE(vp) ((struct denode *)getvnodedata(vp))
 
 #include "libprocstat.h"
 #include "common_kvm.h"
 
 struct dosmount {
 	struct dosmount *next;
 	struct msdosfsmount *kptr;	/* Pointer in kernel space */
 	struct msdosfsmount data;	/* User space copy of structure */
 };
 
 int
 msdosfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
 {
 	struct denode denode;
 	static struct dosmount *mounts;
 	struct dosmount *mnt;
 	u_long dirsperblk;
 	int fileid;
 
 	if (!kvm_read_all(kd, (unsigned long)VTODE(vp), &denode,
 	    sizeof(denode))) {
 		warnx("can't read denode at %p", (void *)VTODE(vp));
 		return (1);
 	}
 
 	/*
 	 * Find msdosfsmount structure for the vnode's filesystem. Needed
 	 * for some filesystem parameters
 	 */
 	for (mnt = mounts; mnt; mnt = mnt->next)
 		if (mnt->kptr == denode.de_pmp)
 			break;
 
 	if (!mnt) {
 		if ((mnt = malloc(sizeof(struct dosmount))) == NULL) {
 			warn("malloc()");
 			return (1);
 		}
 		if (!kvm_read_all(kd, (unsigned long)denode.de_pmp,
 		    &mnt->data, sizeof(mnt->data))) {
 			free(mnt);
 			    warnx("can't read mount info at %p",
 			    (void *)denode.de_pmp);
 			return (1);
 		}
 		mnt->next = mounts;
 		mounts = mnt;
 		mnt->kptr = denode.de_pmp;
 	}
 
 	vn->vn_fsid = dev2udev(kd, mnt->data.pm_dev);
 	vn->vn_mode = 0555;
 	vn->vn_mode |= denode.de_Attributes & ATTR_READONLY ? 0 : 0222;
 	vn->vn_mode &= mnt->data.pm_mask;
 
 	/* Distinguish directories and files. No "special" files in FAT. */
 	vn->vn_mode |= denode.de_Attributes & ATTR_DIRECTORY ? S_IFDIR : S_IFREG;
 	vn->vn_size = denode.de_FileSize;
 
 	/*
 	 * XXX -
 	 * Culled from msdosfs_vnops.c. There appears to be a problem
 	 * here, in that a directory has the same inode number as the first
 	 * file in the directory. stat(2) suffers from this problem also, so
 	 * I won't try to fix it here.
 	 * 
 	 * The following computation of the fileid must be the same as that
 	 * used in msdosfs_readdir() to compute d_fileno. If not, pwd
 	 * doesn't work.
 	 */
 	dirsperblk = mnt->data.pm_BytesPerSec / sizeof(struct direntry);
 	if (denode.de_Attributes & ATTR_DIRECTORY) {
 		fileid = cntobn(&mnt->data, denode.de_StartCluster)
 		    * dirsperblk;
 		if (denode.de_StartCluster == MSDOSFSROOT)
 			fileid = 1;
 	} else {
 		fileid = cntobn(&mnt->data, denode.de_dirclust) * dirsperblk;
 		if (denode.de_dirclust == MSDOSFSROOT)
 			fileid = roottobn(&mnt->data, 0) * dirsperblk;
 		fileid += denode.de_diroffset / sizeof(struct direntry);
 	}
 
 	vn->vn_fileid = fileid;
 	return (0);
 }
diff --git a/sys/fs/msdosfs/denode.h b/sys/fs/msdosfs/denode.h
index f06c11772621..7c838b5cc81c 100644
--- a/sys/fs/msdosfs/denode.h
+++ b/sys/fs/msdosfs/denode.h
@@ -1,293 +1,291 @@
 /* $FreeBSD$ */
 /*	$NetBSD: denode.h,v 1.25 1997/11/17 15:36:28 ws Exp $	*/
 
 /*-
  * SPDX-License-Identifier: BSD-4-Clause
  *
  * 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
  */
 #ifndef _FS_MSDOSFS_DENODE_H_
 #define	_FS_MSDOSFS_DENODE_H_
 
-#include <sys/buf.h>
-
 /*
  * This is the pc filesystem specific portion of the vnode structure.
  *
  * To describe a file uniquely the de_dirclust, de_diroffset, and
  * de_StartCluster fields are used.
  *
  * de_dirclust contains the cluster number of the directory cluster
  *	containing the entry for a file or directory.
  * de_diroffset is the index into the cluster for the entry describing
  *	a file or directory.
  * de_StartCluster is the number of the first cluster of the file or directory.
  *
  * Now to describe the quirks of the pc filesystem.
  * - Clusters 0 and 1 are reserved.
  * - The first allocatable cluster is 2.
  * - The root directory is of fixed size and all blocks that make it up
  *   are contiguous.
  * - Cluster 0 refers to the root directory when it is found in the
  *   startcluster field of a directory entry that points to another directory.
  * - Cluster 0 implies a 0 length file when found in the start cluster field
  *   of a directory entry that points to a file.
  * - You can't use the cluster number 0 to derive the address of the root
  *   directory.
  * - Multiple directory entries can point to a directory. The entry in the
  *   parent directory points to a child directory.  Any directories in the
  *   child directory contain a ".." entry that points back to the parent.
  *   The child directory itself contains a "." entry that points to itself.
  * - The root directory does not contain a "." or ".." entry.
  * - Directory entries for directories are never changed once they are created
  *   (except when removed).  The size stays 0, and the last modification time
  *   is never changed.  This is because so many directory entries can point to
  *   the physical clusters that make up a directory.  It would lead to an
  *   update nightmare.
  * - The length field in a directory entry pointing to a directory contains 0
  *   (always).  The only way to find the end of a directory is to follow the
  *   cluster chain until the "last cluster" marker is found.
  *
  * My extensions to make this house of cards work.  These apply only to the in
  * memory copy of the directory entry.
  * - A reference count for each denode will be kept since dos doesn't keep such
  *   things.
  */
 
 /*
  * Internal pseudo-offset for (nonexistent) directory entry for the root
  * dir in the root dir
  */
 #define	MSDOSFSROOT_OFS	0x1fffffff
 
 /*
  * The FAT cache structure. fc_fsrcn is the filesystem relative cluster
  * number that corresponds to the file relative cluster number in this
  * structure (fc_frcn).
  */
 struct fatcache {
 	u_long fc_frcn;		/* file relative cluster number */
 	u_long fc_fsrcn;	/* filesystem relative cluster number */
 };
 
 /*
  * The FAT entry cache as it stands helps make extending files a "quick"
  * operation by avoiding having to scan the FAT to discover the last
  * cluster of the file. The cache also helps sequential reads by
  * remembering the last cluster read from the file.  This also prevents us
  * from having to rescan the FAT to find the next cluster to read.  This
  * cache is probably pretty worthless if a file is opened by multiple
  * processes.
  */
 #define	FC_SIZE		3	/* number of entries in the cache */
 #define	FC_LASTMAP	0	/* entry the last call to pcbmap() resolved
 				 * to */
 #define	FC_LASTFC	1	/* entry for the last cluster in the file */
 #define	FC_NEXTTOLASTFC	2	/* entry for a close to the last cluster in
 				 * the file */
 
 #define	FCE_EMPTY	0xffffffff	/* doesn't represent an actual cluster # */
 
 /*
  * Set a slot in the FAT cache.
  */
 #define	fc_setcache(dep, slot, frcn, fsrcn) \
 	(dep)->de_fc[(slot)].fc_frcn = (frcn); \
 	(dep)->de_fc[(slot)].fc_fsrcn = (fsrcn);
 
 /*
  * This is the in memory variant of a dos directory entry.  It is usually
  * contained within a vnode.
  */
 struct denode {
 	struct vnode *de_vnode;	/* addr of vnode we are part of */
 	struct vn_clusterw de_clusterw;	/* buffer clustering information */
 	u_long de_flag;		/* flag bits */
 	u_long de_dirclust;	/* cluster of the directory file containing this entry */
 	u_long de_diroffset;	/* offset of this entry in the directory cluster */
 	u_long de_fndoffset;	/* offset of found dir entry */
 	int de_fndcnt;		/* number of slots before de_fndoffset */
 	long de_refcnt;		/* reference count */
 	struct msdosfsmount *de_pmp;	/* addr of our mount struct */
 	u_char de_Name[12];	/* name, from DOS directory entry */
 	u_char de_Attributes;	/* attributes, from directory entry */
 	u_char de_LowerCase;	/* NT VFAT lower case flags */
 	u_char de_CHun;		/* Hundredth of second of CTime*/
 	u_short de_CTime;	/* creation time */
 	u_short de_CDate;	/* creation date */
 	u_short de_ADate;	/* access date */
 	u_short de_MTime;	/* modification time */
 	u_short de_MDate;	/* modification date */
 	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) */
 };
 
 /*
  * Values for the de_flag field of the denode.
  */
 #define	DE_UPDATE	0x0004	/* Modification time update request */
 #define	DE_CREATE	0x0008	/* Creation time update */
 #define	DE_ACCESS	0x0010	/* Access time update */
 #define	DE_MODIFIED	0x0020	/* Denode has been modified */
 #define	DE_RENAME	0x0040	/* Denode is in the process of being renamed */
 
 /* Maximum size of a file on a FAT filesystem */
 #define MSDOSFS_FILESIZE_MAX	0xFFFFFFFFLL
 
 /*
  * Transfer directory entries between internal and external form.
  * dep is a struct denode * (internal form),
  * dp is a struct direntry * (external form).
  */
 #define DE_INTERNALIZE32(dep, dp)			\
 	 ((dep)->de_StartCluster |= getushort((dp)->deHighClust) << 16)
 #define DE_INTERNALIZE(dep, dp)				\
 	(memcpy((dep)->de_Name, (dp)->deName, 11),	\
 	 (dep)->de_Attributes = (dp)->deAttributes,	\
 	 (dep)->de_LowerCase = (dp)->deLowerCase,	\
 	 (dep)->de_CHun = (dp)->deCHundredth,		\
 	 (dep)->de_CTime = getushort((dp)->deCTime),	\
 	 (dep)->de_CDate = getushort((dp)->deCDate),	\
 	 (dep)->de_ADate = getushort((dp)->deADate),	\
 	 (dep)->de_MTime = getushort((dp)->deMTime),	\
 	 (dep)->de_MDate = getushort((dp)->deMDate),	\
 	 (dep)->de_StartCluster = getushort((dp)->deStartCluster), \
 	 (dep)->de_FileSize = getulong((dp)->deFileSize), \
 	 (FAT32((dep)->de_pmp) ? DE_INTERNALIZE32((dep), (dp)) : 0))
 
 #define DE_EXTERNALIZE(dp, dep)				\
 	(memcpy((dp)->deName, (dep)->de_Name, 11),	\
 	 (dp)->deAttributes = (dep)->de_Attributes,	\
 	 (dp)->deLowerCase = (dep)->de_LowerCase,	\
 	 (dp)->deCHundredth = (dep)->de_CHun,		\
 	 putushort((dp)->deCTime, (dep)->de_CTime),	\
 	 putushort((dp)->deCDate, (dep)->de_CDate),	\
 	 putushort((dp)->deADate, (dep)->de_ADate),	\
 	 putushort((dp)->deMTime, (dep)->de_MTime),	\
 	 putushort((dp)->deMDate, (dep)->de_MDate),	\
 	 putushort((dp)->deStartCluster, (dep)->de_StartCluster), \
 	 putulong((dp)->deFileSize,			\
 	     ((dep)->de_Attributes & ATTR_DIRECTORY) ? 0 : (dep)->de_FileSize), \
 	 putushort((dp)->deHighClust, (dep)->de_StartCluster >> 16))
 
 #if defined(_KERNEL) || defined(MAKEFS)
 
 #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)
 
 /*
  * 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;
 
 #ifdef _KERNEL
 int msdosfs_lookup(struct vop_cachedlookup_args *);
 int msdosfs_inactive(struct vop_inactive_args *);
 int msdosfs_reclaim(struct vop_reclaim_args *);
 #endif
 
 /*
  * Internal service routine prototypes.
  */
 struct componentname;
 int deget(struct msdosfsmount *, u_long, u_long, struct denode **);
 int uniqdosname(struct denode *, struct componentname *, u_char *);
 
 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 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 || MAKEFS */
 #endif	/* !_FS_MSDOSFS_DENODE_H_ */
diff --git a/usr.sbin/makefs/msdos.c b/usr.sbin/makefs/msdos.c
index 567122c1db7e..74d55a7f490f 100644
--- a/usr.sbin/makefs/msdos.c
+++ b/usr.sbin/makefs/msdos.c
@@ -1,273 +1,273 @@
 /*	$NetBSD: msdos.c,v 1.20 2017/04/14 15:40:35 christos Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
  * by Christos Zoulas.
  *
  * 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.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``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 THE FOUNDATION OR CONTRIBUTORS
  * 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.
  */
 #if HAVE_NBTOOL_CONFIG_H
 #include "nbtool_config.h"
 #endif
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(__lint)
 __FBSDID("$FreeBSD$");
 #endif	/* !__lint */
 
 #include <sys/param.h>
 
 #if !HAVE_NBTOOL_CONFIG_H
 #include <sys/mount.h>
 #endif
 
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdint.h>
 #include <unistd.h>
 #include <dirent.h>
 #include <util.h>
 
 #include <mkfs_msdos.h>
 #include <fs/msdosfs/bpb.h>
 #include "msdos/direntry.h"
-#include <fs/msdosfs/denode.h>
+#include "msdos/denode.h"
 #include <fs/msdosfs/msdosfsmount.h>
 
 #undef clrbuf
 #include "ffs/buf.h"
 #include "makefs.h"
 #include "msdos.h"
 
 static int msdos_populate_dir(const char *, struct denode *, fsnode *,
     fsnode *, fsinfo_t *);
 
 struct msdos_options_ex {
 	struct msdos_options options;
 };
 
 void
 msdos_prep_opts(fsinfo_t *fsopts)
 {
 	struct msdos_options_ex *msdos_opt = ecalloc(1, sizeof(*msdos_opt));
 	const option_t msdos_options[] = {
 #define AOPT(_opt, _type, _name, _min, _desc) {				\
 	.letter = _opt,							\
 	.name = # _name,						\
 	.type = _min == -1 ? OPT_STRPTR :				\
 	    (_min == -2 ? OPT_BOOL :					\
 	    (sizeof(_type) == 1 ? OPT_INT8 :				\
 	    (sizeof(_type) == 2 ? OPT_INT16 :				\
 	    (sizeof(_type) == 4 ? OPT_INT32 : OPT_INT64)))),		\
 	.value = &msdos_opt->options._name,				\
 	.minimum = _min,						\
 	.maximum = sizeof(_type) == 1 ? UINT8_MAX :			\
 	    (sizeof(_type) == 2 ? UINT16_MAX :				\
 	    (sizeof(_type) == 4 ? UINT32_MAX : INT64_MAX)),		\
 	.desc = _desc,							\
 },
 ALLOPTS
 #undef AOPT
 		{ .name = NULL }
 	};
 
 	fsopts->fs_specific = msdos_opt;
 	fsopts->fs_options = copy_opts(msdos_options);
 }
 
 void
 msdos_cleanup_opts(fsinfo_t *fsopts)
 {
 	free(fsopts->fs_specific);
 	free(fsopts->fs_options);
 }
 
 int
 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);
 	assert(fsopts != NULL);
 	assert(msdos_opt != NULL);
 
 	if (debug & DEBUG_FS_PARSE_OPTS)
 		printf("msdos_parse_opts: got `%s'\n", option);
 
 	rv = set_option(msdos_options, option, NULL, 0);
 	if (rv == -1)
 		return rv;
 
 	if (strcmp(msdos_options[rv].name, "volume_id") == 0)
 		msdos_opt->volume_id_set = 1;
 	else if (strcmp(msdos_options[rv].name, "media_descriptor") == 0)
 		msdos_opt->media_descriptor_set = 1;
 	else if (strcmp(msdos_options[rv].name, "hidden_sectors") == 0)
 		msdos_opt->hidden_sectors_set = 1;
 
 	if (stampst.st_ino) {
 		msdos_opt->timestamp_set = 1;
 		msdos_opt->timestamp = stampst.st_mtime;
 	}
 
 	return 1;
 }
 
 
 void
 msdos_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts)
 {
 	struct msdos_options_ex *msdos_opt = fsopts->fs_specific;
 	struct m_vnode vp, rootvp;
 	struct timeval start;
 	struct msdosfsmount *pmp;
 	uint32_t flags;
 
 	assert(image != NULL);
 	assert(dir != NULL);
 	assert(root != NULL);
 	assert(fsopts != NULL);
 
 	fsopts->size = fsopts->maxsize;
 	msdos_opt->options.create_size = MAX(msdos_opt->options.create_size,
 	    fsopts->offset + fsopts->size);
 	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;
 		msdos_opt->options.bytes_per_sector = fsopts->sectorsize;
 	} else if (fsopts->sectorsize == -1) {
 		fsopts->sectorsize = msdos_opt->options.bytes_per_sector;
 	} else if (fsopts->sectorsize != msdos_opt->options.bytes_per_sector) {
 		err(1, "inconsistent sectorsize -S %u"
 		    "!= -o bytes_per_sector %u",
 		    fsopts->sectorsize, msdos_opt->options.bytes_per_sector);
 	}
 
 	/* create image */
 	printf("Creating `%s'\n", image);
 	TIMER_START(start);
 	if (mkfs_msdos(image, NULL, &msdos_opt->options) == -1)
 		return;
 	TIMER_RESULTS(start, "mkfs_msdos");
 
 	fsopts->fd = open(image, O_RDWR);
 	vp.fs = fsopts;
 
 	flags = 0;
 	if ((pmp = m_msdosfs_mount(&vp)) == NULL)
 		err(1, "msdosfs_mount");
 
 	if (msdosfs_root(pmp, &rootvp) != 0)
 		err(1, "msdosfs_root");
 
 	if (debug & DEBUG_FS_MAKEFS)
 		printf("msdos_makefs: image %s directory %s root %p\n",
 		    image, dir, root);
 
 	/* populate image */
 	printf("Populating `%s'\n", image);
 	TIMER_START(start);
 	if (msdos_populate_dir(dir, VTODE(&rootvp), root, root, fsopts) == -1)
 		errx(1, "Image file `%s' not created.", image);
 	TIMER_RESULTS(start, "msdos_populate_dir");
 
 	if (msdosfs_fsiflush(pmp) != 0)
 		errx(1, "Unable to update FSInfo block.");
 	if (debug & DEBUG_FS_MAKEFS)
 		putchar('\n');
 
 	/* ensure no outstanding buffers remain */
 	if (debug & DEBUG_FS_MAKEFS)
 		bcleanup();
 
 	printf("Image `%s' complete\n", image);
 }
 
 static int
 msdos_populate_dir(const char *path, struct denode *dir, fsnode *root,
     fsnode *parent, fsinfo_t *fsopts)
 {
 	fsnode *cur;
 	char pbuf[MAXPATHLEN];
 
 	assert(dir != NULL);
 	assert(root != NULL);
 	assert(fsopts != NULL);
 
 	for (cur = root->next; cur != NULL; cur = cur->next) {
 		if ((size_t)snprintf(pbuf, sizeof(pbuf), "%s/%s", path,
 		    cur->name) >= sizeof(pbuf)) {
 			warnx("path %s too long", pbuf);
 			return -1;
 		}
 
 		if ((cur->inode->flags & FI_ALLOCATED) == 0) {
 			cur->inode->flags |= FI_ALLOCATED;
 			if (cur != root) {
 				fsopts->curinode++;
 				cur->inode->ino = fsopts->curinode;
 				cur->parent = parent;
 			}
 		}
 
 		if (cur->inode->flags & FI_WRITTEN) {
 			continue;	// hard link
 		}
 		cur->inode->flags |= FI_WRITTEN;
 
 		if (cur->child) {
 			struct denode *de;
 			if ((de = msdosfs_mkdire(pbuf, dir, cur)) == NULL) {
 				warn("msdosfs_mkdire %s", pbuf);
 				return -1;
 			}
 			if (msdos_populate_dir(pbuf, de, cur->child, cur,
 			    fsopts) == -1) {
 				warn("msdos_populate_dir %s", pbuf);
 				return -1;
 			}
 			continue;
 		} else if (!S_ISREG(cur->type)) {
 			warnx("skipping non-regular file %s/%s", cur->path,
 			    cur->name);
 			continue;
 		}
 		if (msdosfs_mkfile(cur->contents ? cur->contents : pbuf, dir,
 		    cur) == NULL) {
 			warn("msdosfs_mkfile %s", pbuf);
 			return -1;
 		}
 	}
 	return 0;
 }
diff --git a/usr.sbin/makefs/msdos.h b/usr.sbin/makefs/msdos.h
index a51420de76e5..ea78e49648a3 100644
--- a/usr.sbin/makefs/msdos.h
+++ b/usr.sbin/makefs/msdos.h
@@ -1,71 +1,70 @@
 /*	$FreeBSD$ */
 /*	$NetBSD: msdos.h,v 1.3 2015/10/16 16:40:02 christos Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
  * by Christos Zoulas.
  *
  * 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.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``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 THE FOUNDATION OR CONTRIBUTORS
  * 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.
  */
 
 #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 componentname {
 	char *cn_nameptr;
 	size_t cn_namelen;
 };
 
 struct m_vnode;
 struct m_buf;
 
 int msdosfs_fsiflush(struct msdosfsmount *);
 struct msdosfsmount *msdosfs_mount(struct m_vnode *);
 int msdosfs_root(struct msdosfsmount *, struct m_vnode *);
 
 struct denode *msdosfs_mkfile(const char *, struct denode *, fsnode *);
 struct denode *msdosfs_mkdire(const char *, struct denode *, fsnode *);
 
 int m_readde(struct denode *dep, struct m_buf **bpp, struct direntry **epp);
 int m_readep(struct msdosfsmount *pmp, u_long dirclust, u_long diroffset,
     struct m_buf **bpp, struct direntry **epp);
 int m_extendfile(struct denode *dep, u_long count, struct m_buf **bpp,
     u_long *ncp, int flags);
 
 struct msdosfsmount *m_msdosfs_mount(struct m_vnode *devvp);
 #endif
diff --git a/usr.sbin/makefs/msdos/denode.h b/usr.sbin/makefs/msdos/denode.h
new file mode 100644
index 000000000000..4590a76c3501
--- /dev/null
+++ b/usr.sbin/makefs/msdos/denode.h
@@ -0,0 +1,39 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2018-2020 Alex Richardson <arichardson@FreeBSD.org>
+ *
+ * This work was supported by Innovate UK project 105694, "Digital Security by
+ * Design (DSbD) Technology Platform Prototype".
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
+ */
+#pragma once
+/* Ensure that struct denode uses the local m_buf structure and not sys/buf.h */
+#define buf m_buf
+struct vn_clusterw {
+	/* Not interesting for msdosfs makefs. */
+};
+#include "../ffs/buf.h"
+/* struct direntry needs to be defined to included denode.h */
+#include "msdos/direntry.h"
+#include <fs/msdosfs/denode.h>
diff --git a/usr.sbin/makefs/msdos/msdosfs_denode.c b/usr.sbin/makefs/msdos/msdosfs_denode.c
index f2faed234228..48c305824793 100644
--- a/usr.sbin/makefs/msdos/msdosfs_denode.c
+++ b/usr.sbin/makefs/msdos/msdosfs_denode.c
@@ -1,378 +1,375 @@
 /*	$NetBSD: msdosfs_denode.c,v 1.7 2015/03/29 05:52:59 agc Exp $	*/
 
 /*-
  * SPDX-License-Identifier: BSD-4-Clause
  *
  * 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/errno.h>
 
 #include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <util.h>
 
 #include <fs/msdosfs/bpb.h>
-#include <fs/msdosfs/direntry.h>
-#include <fs/msdosfs/denode.h>
+#include "msdos/denode.h"
 #include <fs/msdosfs/fat.h>
 #include <fs/msdosfs/msdosfsmount.h>
 
-#undef clrbuf
-#include "ffs/buf.h"
 #include "makefs.h"
 #include "msdos.h"
 
 
 /*
  * If deget() succeeds it returns with the gotten denode locked().
  *
  * pmp	     - address of msdosfsmount structure of the filesystem containing
  *	       the denode of interest.  The pm_dev field and the address of
  *	       the msdosfsmount structure are used.
  * dirclust  - which cluster bp contains, if dirclust is 0 (root directory)
  *	       diroffset is relative to the beginning of the root directory,
  *	       otherwise it is cluster relative.
  * diroffset - offset past begin of cluster of denode we want
  * depp	     - returns the address of the gotten denode.
  */
 int
 deget(struct msdosfsmount *pmp, u_long dirclust, u_long diroffset,
     struct denode **depp)
 {
 	int error;
 	uint64_t inode;
 	struct direntry *direntptr;
 	struct denode *ldep;
 	struct m_buf *bp;
 
 	MSDOSFS_DPRINTF(("deget(pmp %p, dirclust %lu, diroffset %lx, depp %p)\n",
 	    pmp, dirclust, diroffset, depp));
 
 	/*
 	 * On FAT32 filesystems, root is a (more or less) normal
 	 * directory
 	 */
 	if (FAT32(pmp) && dirclust == MSDOSFSROOT)
 		dirclust = pmp->pm_rootdirblk;
 
 	inode = (uint64_t)pmp->pm_bpcluster * dirclust + diroffset;
 
 	ldep = ecalloc(1, sizeof(*ldep));
 	ldep->de_vnode = NULL;
 	ldep->de_flag = 0;
 	ldep->de_dirclust = dirclust;
 	ldep->de_diroffset = diroffset;
 	ldep->de_inode = inode;
 	ldep->de_pmp = pmp;
 	ldep->de_refcnt = 1;
 	fc_purge(ldep, 0);	/* init the FAT cache for this denode */
 	/*
 	 * Copy the directory entry into the denode area of the vnode.
 	 */
 	if ((dirclust == MSDOSFSROOT
 	     || (FAT32(pmp) && dirclust == pmp->pm_rootdirblk))
 	    && diroffset == MSDOSFSROOT_OFS) {
 		/*
 		 * Directory entry for the root directory. There isn't one,
 		 * so we manufacture one. We should probably rummage
 		 * through the root directory and find a label entry (if it
 		 * exists), and then use the time and date from that entry
 		 * as the time and date for the root denode.
 		 */
 		ldep->de_vnode = (struct vnode *)-1;
 
 		ldep->de_Attributes = ATTR_DIRECTORY;
 		ldep->de_LowerCase = 0;
 		if (FAT32(pmp))
 			ldep->de_StartCluster = pmp->pm_rootdirblk;
 			/* de_FileSize will be filled in further down */
 		else {
 			ldep->de_StartCluster = MSDOSFSROOT;
 			ldep->de_FileSize = pmp->pm_rootdirsize * DEV_BSIZE;
 		}
 		/*
 		 * fill in time and date so that dos2unixtime() doesn't
 		 * spit up when called from msdosfs_getattr() with root
 		 * denode
 		 */
 		ldep->de_CHun = 0;
 		ldep->de_CTime = 0x0000;	/* 00:00:00	 */
 		ldep->de_CDate = (0 << DD_YEAR_SHIFT) | (1 << DD_MONTH_SHIFT)
 		    | (1 << DD_DAY_SHIFT);
 		/* Jan 1, 1980	 */
 		ldep->de_ADate = ldep->de_CDate;
 		ldep->de_MTime = ldep->de_CTime;
 		ldep->de_MDate = ldep->de_CDate;
 		/* leave the other fields as garbage */
 	} else {
 		error = m_readep(pmp, dirclust, diroffset, &bp, &direntptr);
 		if (error) {
 			ldep->de_Name[0] = SLOT_DELETED;
 
 			*depp = NULL;
 			return (error);
 		}
 		(void)DE_INTERNALIZE(ldep, direntptr);
 		brelse(bp);
 	}
 
 	/*
 	 * Fill in a few fields of the vnode and finish filling in the
 	 * denode.  Then return the address of the found denode.
 	 */
 	if (ldep->de_Attributes & ATTR_DIRECTORY) {
 		/*
 		 * Since DOS directory entries that describe directories
 		 * have 0 in the filesize field, we take this opportunity
 		 * to find out the length of the directory and plug it into
 		 * the denode structure.
 		 */
 		u_long size;
 
 		/*
 		 * XXX it sometimes happens that the "." entry has cluster
 		 * number 0 when it shouldn't.  Use the actual cluster number
 		 * instead of what is written in directory entry.
 		 */
 		if (diroffset == 0 && ldep->de_StartCluster != dirclust) {
 			MSDOSFS_DPRINTF(("deget(): \".\" entry at clust %lu != %lu\n",
 			    dirclust, ldep->de_StartCluster));
 
 			ldep->de_StartCluster = dirclust;
 		}
 
 		if (ldep->de_StartCluster != MSDOSFSROOT) {
 			error = pcbmap(ldep, 0xffff, 0, &size, 0);
 			if (error == E2BIG) {
 				ldep->de_FileSize = de_cn2off(pmp, size);
 				error = 0;
 			} else {
 				MSDOSFS_DPRINTF(("deget(): pcbmap returned %d\n",
 				    error));
 			}
 		}
 	}
 	*depp = ldep;
 	return (0);
 }
 
 /*
  * Truncate the file described by dep to the length specified by length.
  */
 int
 detrunc(struct denode *dep, u_long length, int flags, struct ucred *cred)
 {
 	int error;
 	int allerror;
 	u_long eofentry;
 	u_long chaintofree;
 	daddr_t bn;
 	int boff;
 	int isadir = dep->de_Attributes & ATTR_DIRECTORY;
 	struct m_buf *bp;
 	struct msdosfsmount *pmp = dep->de_pmp;
 
 	MSDOSFS_DPRINTF(("detrunc(): file %s, length %lu, flags %x\n",
 	    dep->de_Name, length, flags));
 
 	/*
 	 * Disallow attempts to truncate the root directory since it is of
 	 * fixed size.  That's just the way dos filesystems are.  We use
 	 * the VROOT bit in the vnode because checking for the directory
 	 * bit and a startcluster of 0 in the denode is not adequate to
 	 * recognize the root directory at this point in a file or
 	 * directory's life.
 	 */
 	if (dep->de_vnode != NULL && !FAT32(pmp)) {
 		MSDOSFS_DPRINTF(("detrunc(): can't truncate root directory, "
 		    "clust %ld, offset %ld\n",
 		    dep->de_dirclust, dep->de_diroffset));
 
 		return (EINVAL);
 	}
 
 	if (dep->de_FileSize < length)
 		return deextend(dep, length, cred);
 
 	/*
 	 * If the desired length is 0 then remember the starting cluster of
 	 * the file and set the StartCluster field in the directory entry
 	 * to 0.  If the desired length is not zero, then get the number of
 	 * the last cluster in the shortened file.  Then get the number of
 	 * the first cluster in the part of the file that is to be freed.
 	 * Then set the next cluster pointer in the last cluster of the
 	 * file to CLUST_EOFE.
 	 */
 	if (length == 0) {
 		chaintofree = dep->de_StartCluster;
 		dep->de_StartCluster = 0;
 		eofentry = ~0;
 	} else {
 		error = pcbmap(dep, de_clcount(pmp, length) - 1, 0,
 		    &eofentry, 0);
 		if (error) {
 			MSDOSFS_DPRINTF(("detrunc(): pcbmap fails %d\n",
 			    error));
 			return (error);
 		}
 	}
 
 	fc_purge(dep, de_clcount(pmp, length));
 
 	/*
 	 * If the new length is not a multiple of the cluster size then we
 	 * must zero the tail end of the new last cluster in case it
 	 * becomes part of the file again because of a seek.
 	 */
 	if ((boff = length & pmp->pm_crbomask) != 0) {
 		if (isadir) {
 			bn = cntobn(pmp, eofentry);
 			error = bread((void *)pmp->pm_devvp, bn,
 			    pmp->pm_bpcluster, 0, &bp);
 			if (error) {
 				brelse(bp);
 				MSDOSFS_DPRINTF(("detrunc(): bread fails %d\n",
 				    error));
 
 				return (error);
 			}
 			memset(bp->b_data + boff, 0, pmp->pm_bpcluster - boff);
 			bwrite(bp);
 		}
 	}
 
 	/*
 	 * Write out the updated directory entry.  Even if the update fails
 	 * we free the trailing clusters.
 	 */
 	dep->de_FileSize = length;
 	if (!isadir)
 		dep->de_flag |= DE_UPDATE|DE_MODIFIED;
 	MSDOSFS_DPRINTF(("detrunc(): allerror %d, eofentry %lu\n",
 	    allerror, eofentry));
 
 	/*
 	 * If we need to break the cluster chain for the file then do it
 	 * now.
 	 */
 	if (eofentry != ~0) {
 		error = fatentry(FAT_GET_AND_SET, pmp, eofentry,
 				 &chaintofree, CLUST_EOFE);
 		if (error) {
 			MSDOSFS_DPRINTF(("detrunc(): fatentry errors %d\n",
 			    error));
 			return (error);
 		}
 		fc_setcache(dep, FC_LASTFC, de_cluster(pmp, length - 1),
 		    eofentry);
 	}
 
 	/*
 	 * Now free the clusters removed from the file because of the
 	 * truncation.
 	 */
 	if (chaintofree != 0 && !MSDOSFSEOF(pmp, chaintofree))
 		freeclusterchain(pmp, chaintofree);
 
 	return (allerror);
 }
 
 /*
  * Extend the file described by dep to length specified by length.
  */
 int
 deextend(struct denode *dep, u_long length, struct ucred *cred)
 {
 	struct msdosfsmount *pmp = dep->de_pmp;
 	u_long count;
 	int error;
 
 	/*
 	 * The root of a DOS filesystem cannot be extended.
 	 */
 	if (dep->de_vnode != NULL && !FAT32(pmp))
 		return (EINVAL);
 
 	/*
 	 * Directories cannot be extended.
 	 */
 	if (dep->de_Attributes & ATTR_DIRECTORY)
 		return (EISDIR);
 
 	if (length <= dep->de_FileSize)
 		return (E2BIG);
 
 	/*
 	 * Compute the number of clusters to allocate.
 	 */
 	count = de_clcount(pmp, length) - de_clcount(pmp, dep->de_FileSize);
 	if (count > 0) {
 		if (count > pmp->pm_freeclustercount)
 			return (ENOSPC);
 		error = m_extendfile(dep, count, NULL, NULL, DE_CLEAR);
 		if (error) {
 			/* truncate the added clusters away again */
 			(void) detrunc(dep, dep->de_FileSize, 0, cred);
 			return (error);
 		}
 	}
 
 	/*
 	 * Zero extend file range; ubc_zerorange() uses ubc_alloc() and a
 	 * memset(); we set the write size so ubc won't read in file data that
 	 * is zero'd later.
 	 */
 	dep->de_FileSize = length;
 	dep->de_flag |= DE_UPDATE | DE_MODIFIED;
 	return 0;
 }
diff --git a/usr.sbin/makefs/msdos/msdosfs_fat.c b/usr.sbin/makefs/msdos/msdosfs_fat.c
index a70b5741aa78..b5700d8c7d1d 100644
--- a/usr.sbin/makefs/msdos/msdosfs_fat.c
+++ b/usr.sbin/makefs/msdos/msdosfs_fat.c
@@ -1,1060 +1,1057 @@
 /* $FreeBSD$ */
 /*	$NetBSD: msdosfs_fat.c,v 1.28 1997/11/17 15:36:49 ws Exp $	*/
 
 /*-
  * SPDX-License-Identifier: BSD-4-Clause
  *
  * 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/param.h>
 #include <sys/errno.h>
 
 #include <assert.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
 #include <strings.h>
 
 #include <fs/msdosfs/bpb.h>
-#include "msdos/direntry.h"
-#include <fs/msdosfs/denode.h>
+#include "msdos/denode.h"
 #include <fs/msdosfs/fat.h>
 #include <fs/msdosfs/msdosfsmount.h>
 
-#undef clrbuf
-#include "ffs/buf.h"
 #include "makefs.h"
 #include "msdos.h"
 
 #define	FULL_RUN	((u_int)0xffffffff)
 #define	SYNCHRONOUS_WRITES(pmp)	1
 
 static int	chainalloc(struct msdosfsmount *pmp, u_long start,
 		    u_long count, u_long fillwith, u_long *retcluster,
 		    u_long *got);
 static int	chainlength(struct msdosfsmount *pmp, u_long start,
 		    u_long count);
 static void	fatblock(struct msdosfsmount *pmp, u_long ofs, u_long *bnp,
 		    u_long *sizep, u_long *bop);
 static int	fatchain(struct msdosfsmount *pmp, u_long start, u_long count,
 		    u_long fillwith);
 static void	fc_lookup(struct denode *dep, u_long findcn, u_long *frcnp,
 		    u_long *fsrcnp);
 static void	updatefats(struct msdosfsmount *pmp, struct m_buf *bp,
 		    u_long fatbn);
 static __inline void
 		usemap_alloc(struct msdosfsmount *pmp, u_long cn);
 static __inline void
 		usemap_free(struct msdosfsmount *pmp, u_long cn);
 static int	clusteralloc1(struct msdosfsmount *pmp, u_long start,
 		    u_long count, u_long fillwith, u_long *retcluster,
 		    u_long *got);
 
 static void
 fatblock(struct msdosfsmount *pmp, u_long ofs, u_long *bnp, u_long *sizep,
     u_long *bop)
 {
 	u_long bn, size;
 
 	bn = ofs / pmp->pm_fatblocksize * pmp->pm_fatblocksec;
 	size = MIN(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn)
 	    * DEV_BSIZE;
 	bn += pmp->pm_fatblk + pmp->pm_curfat * pmp->pm_FATsecs;
 
 	if (bnp)
 		*bnp = bn;
 	if (sizep)
 		*sizep = size;
 	if (bop)
 		*bop = ofs % pmp->pm_fatblocksize;
 }
 
 /*
  * Map the logical cluster number of a file into a physical disk sector
  * that is filesystem relative.
  *
  * dep	  - address of denode representing the file of interest
  * findcn - file relative cluster whose filesystem relative cluster number
  *	    and/or block number are/is to be found
  * bnp	  - address of where to place the filesystem relative block number.
  *	    If this pointer is null then don't return this quantity.
  * cnp	  - address of where to place the filesystem relative cluster number.
  *	    If this pointer is null then don't return this quantity.
  * sp     - pointer to returned block size
  *
  * NOTE: Either bnp or cnp must be non-null.
  * This function has one side effect.  If the requested file relative cluster
  * is beyond the end of file, then the actual number of clusters in the file
  * is returned in *cnp.  This is useful for determining how long a directory is.
  *  If cnp is null, nothing is returned.
  */
 int
 pcbmap(struct denode *dep, u_long findcn, daddr_t *bnp, u_long *cnp, int *sp)
 {
 	int error;
 	u_long i;
 	u_long cn;
 	u_long prevcn = 0; /* XXX: prevcn could be used unititialized */
 	u_long byteoffset;
 	u_long bn;
 	u_long bo;
 	struct m_buf *bp = NULL;
 	u_long bp_bn = -1;
 	struct msdosfsmount *pmp = dep->de_pmp;
 	u_long bsize;
 
 	assert(bnp != NULL || cnp != NULL || sp != NULL);
 
 	cn = dep->de_StartCluster;
 	/*
 	 * The "file" that makes up the root directory is contiguous,
 	 * permanently allocated, of fixed size, and is not made up of
 	 * clusters.  If the cluster number is beyond the end of the root
 	 * directory, then return the number of clusters in the file.
 	 */
 	if (cn == MSDOSFSROOT) {
 		if (dep->de_Attributes & ATTR_DIRECTORY) {
 			if (de_cn2off(pmp, findcn) >= dep->de_FileSize) {
 				if (cnp)
 					*cnp = de_bn2cn(pmp, pmp->pm_rootdirsize);
 				return (E2BIG);
 			}
 			if (bnp)
 				*bnp = pmp->pm_rootdirblk + de_cn2bn(pmp, findcn);
 			if (cnp)
 				*cnp = MSDOSFSROOT;
 			if (sp)
 				*sp = MIN(pmp->pm_bpcluster,
 				    dep->de_FileSize - de_cn2off(pmp, findcn));
 			return (0);
 		} else {		/* just an empty file */
 			if (cnp)
 				*cnp = 0;
 			return (E2BIG);
 		}
 	}
 
 	/*
 	 * All other files do I/O in cluster sized blocks
 	 */
 	if (sp)
 		*sp = pmp->pm_bpcluster;
 
 	/*
 	 * Rummage around in the FAT cache, maybe we can avoid tromping
 	 * through every FAT entry for the file. And, keep track of how far
 	 * off the cache was from where we wanted to be.
 	 */
 	i = 0;
 	fc_lookup(dep, findcn, &i, &cn);
 
 	/*
 	 * Handle all other files or directories the normal way.
 	 */
 	for (; i < findcn; i++) {
 		/*
 		 * Stop with all reserved clusters, not just with EOF.
 		 */
 		if ((cn | ~pmp->pm_fatmask) >= CLUST_RSRVD)
 			goto hiteof;
 		byteoffset = FATOFS(pmp, cn);
 		fatblock(pmp, byteoffset, &bn, &bsize, &bo);
 		if (bn != bp_bn) {
 			if (bp)
 				brelse(bp);
 			error = bread((void *)pmp->pm_devvp, bn, bsize,
 			    NOCRED, &bp);
 			if (error) {
 				brelse(bp);
 				return (error);
 			}
 			bp_bn = bn;
 		}
 		prevcn = cn;
 		if (bo >= bsize) {
 			if (bp)
 				brelse(bp);
 			return (EIO);
 		}
 		if (FAT32(pmp))
 			cn = getulong(bp->b_data + bo);
 		else
 			cn = getushort(bp->b_data + bo);
 		if (FAT12(pmp) && (prevcn & 1))
 			cn >>= 4;
 		cn &= pmp->pm_fatmask;
 
 		/*
 		 * Force the special cluster numbers
 		 * to be the same for all cluster sizes
 		 * to let the rest of msdosfs handle
 		 * all cases the same.
 		 */
 		if ((cn | ~pmp->pm_fatmask) >= CLUST_RSRVD)
 			cn |= ~pmp->pm_fatmask;
 	}
 
 	if (!MSDOSFSEOF(pmp, cn)) {
 		if (bp)
 			brelse(bp);
 		if (bnp)
 			*bnp = cntobn(pmp, cn);
 		if (cnp)
 			*cnp = cn;
 		fc_setcache(dep, FC_LASTMAP, i, cn);
 		return (0);
 	}
 
 hiteof:;
 	if (cnp)
 		*cnp = i;
 	if (bp)
 		brelse(bp);
 	/* update last file cluster entry in the FAT cache */
 	fc_setcache(dep, FC_LASTFC, i - 1, prevcn);
 	return (E2BIG);
 }
 
 /*
  * Find the closest entry in the FAT cache to the cluster we are looking
  * for.
  */
 static void
 fc_lookup(struct denode *dep, u_long findcn, u_long *frcnp, u_long *fsrcnp)
 {
 	int i;
 	u_long cn;
 	struct fatcache *closest = NULL;
 
 	for (i = 0; i < FC_SIZE; i++) {
 		cn = dep->de_fc[i].fc_frcn;
 		if (cn != FCE_EMPTY && cn <= findcn) {
 			if (closest == NULL || cn > closest->fc_frcn)
 				closest = &dep->de_fc[i];
 		}
 	}
 	if (closest) {
 		*frcnp = closest->fc_frcn;
 		*fsrcnp = closest->fc_fsrcn;
 	}
 }
 
 /*
  * Purge the FAT cache in denode dep of all entries relating to file
  * relative cluster frcn and beyond.
  */
 void
 fc_purge(struct denode *dep, u_int frcn)
 {
 	int i;
 	struct fatcache *fcp;
 
 	fcp = dep->de_fc;
 	for (i = 0; i < FC_SIZE; i++, fcp++) {
 		if (fcp->fc_frcn >= frcn)
 			fcp->fc_frcn = FCE_EMPTY;
 	}
 }
 
 /*
  * Update the FAT.
  * If mirroring the FAT, update all copies, with the first copy as last.
  * Else update only the current FAT (ignoring the others).
  *
  * pmp	 - msdosfsmount structure for filesystem to update
  * bp	 - addr of modified FAT block
  * fatbn - block number relative to begin of filesystem of the modified FAT block.
  */
 static void
 updatefats(struct msdosfsmount *pmp, struct m_buf *bp, u_long fatbn)
 {
 	struct m_buf *bpn;
 	int cleanfat, i;
 
 #ifdef MSDOSFS_DEBUG
 	printf("updatefats(pmp %p, bp %p, fatbn %lu)\n", pmp, bp, fatbn);
 #endif
 
 	if (pmp->pm_flags & MSDOSFS_FATMIRROR) {
 		/*
 		 * Now copy the block(s) of the modified FAT to the other copies of
 		 * the FAT and write them out.  This is faster than reading in the
 		 * other FATs and then writing them back out.  This could tie up
 		 * the FAT for quite a while. Preventing others from accessing it.
 		 * To prevent us from going after the FAT quite so much we use
 		 * delayed writes, unless they specified "synchronous" when the
 		 * filesystem was mounted.  If synch is asked for then use
 		 * bwrite()'s and really slow things down.
 		 */
 		if (fatbn != pmp->pm_fatblk || FAT12(pmp))
 			cleanfat = 0;
 		else if (FAT16(pmp))
 			cleanfat = 16;
 		else
 			cleanfat = 32;
 		for (i = 1; i < pmp->pm_FATs; i++) {
 			fatbn += pmp->pm_FATsecs;
 			/* getblk() never fails */
 			bpn = getblk((void *)pmp->pm_devvp, fatbn,
 			    bp->b_bcount, 0, 0, 0);
 			memcpy(bpn->b_data, bp->b_data, bp->b_bcount);
 			/* Force the clean bit on in the other copies. */
 			if (cleanfat == 16)
 				((uint8_t *)bpn->b_data)[3] |= 0x80;
 			else if (cleanfat == 32)
 				((uint8_t *)bpn->b_data)[7] |= 0x08;
 			if (SYNCHRONOUS_WRITES(pmp))
 				bwrite(bpn);
 			else
 				bdwrite(bpn);
 		}
 	}
 
 	/*
 	 * Write out the first (or current) FAT last.
 	 */
 	if (SYNCHRONOUS_WRITES(pmp))
 		bwrite(bp);
 	else
 		bdwrite(bp);
 }
 
 /*
  * Updating entries in 12 bit FATs is a pain in the butt.
  *
  * The following picture shows where nibbles go when moving from a 12 bit
  * cluster number into the appropriate bytes in the FAT.
  *
  *	byte m        byte m+1      byte m+2
  *	+----+----+   +----+----+   +----+----+
  *	|  0    1 |   |  2    3 |   |  4    5 |   FAT bytes
  *	+----+----+   +----+----+   +----+----+
  *
  *	+----+----+----+   +----+----+----+
  *	|  3    0    1 |   |  4    5    2 |
  *	+----+----+----+   +----+----+----+
  *	cluster n	   cluster n+1
  *
  * Where n is even. m = n + (n >> 2)
  *
  */
 static __inline void
 usemap_alloc(struct msdosfsmount *pmp, u_long cn)
 {
 
 	assert(cn <= pmp->pm_maxcluster);
 	assert((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0);
 	assert((pmp->pm_inusemap[cn / N_INUSEBITS] & (1 << (cn % N_INUSEBITS)))
 	    == 0);
 	assert(pmp->pm_freeclustercount > 0);
 
 	pmp->pm_inusemap[cn / N_INUSEBITS] |= 1U << (cn % N_INUSEBITS);
 	pmp->pm_freeclustercount--;
 	pmp->pm_flags |= MSDOSFS_FSIMOD;
 }
 
 static __inline void
 usemap_free(struct msdosfsmount *pmp, u_long cn)
 {
 
 	assert(cn <= pmp->pm_maxcluster);
 	assert((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0);
 	assert((pmp->pm_inusemap[cn / N_INUSEBITS] & (1 << (cn % N_INUSEBITS)))
 	    != 0);
 
 	pmp->pm_freeclustercount++;
 	pmp->pm_flags |= MSDOSFS_FSIMOD;
 	pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1U << (cn % N_INUSEBITS));
 }
 
 int
 clusterfree(struct msdosfsmount *pmp, u_long cluster, u_long *oldcnp)
 {
 	int error;
 	u_long oldcn;
 
 	error = fatentry(FAT_GET_AND_SET, pmp, cluster, &oldcn, MSDOSFSFREE);
 	if (error)
 		return (error);
 	/*
 	 * If the cluster was successfully marked free, then update
 	 * the count of free clusters, and turn off the "allocated"
 	 * bit in the "in use" cluster bit map.
 	 */
 	usemap_free(pmp, cluster);
 	if (oldcnp)
 		*oldcnp = oldcn;
 	return (0);
 }
 
 /*
  * Get or Set or 'Get and Set' the cluster'th entry in the FAT.
  *
  * function	- whether to get or set a FAT entry
  * pmp		- address of the msdosfsmount structure for the filesystem
  *		  whose FAT is to be manipulated.
  * cn		- which cluster is of interest
  * oldcontents	- address of a word that is to receive the contents of the
  *		  cluster'th entry if this is a get function
  * newcontents	- the new value to be written into the cluster'th element of
  *		  the FAT if this is a set function.
  *
  * This function can also be used to free a cluster by setting the FAT entry
  * for a cluster to 0.
  *
  * All copies of the FAT are updated if this is a set function. NOTE: If
  * fatentry() marks a cluster as free it does not update the inusemap in
  * the msdosfsmount structure. This is left to the caller.
  */
 int
 fatentry(int function, struct msdosfsmount *pmp, u_long cn, u_long *oldcontents,
     u_long newcontents)
 {
 	int error;
 	u_long readcn;
 	u_long bn, bo, bsize, byteoffset;
 	struct m_buf *bp;
 
 #ifdef	MSDOSFS_DEBUG
 	printf("fatentry(func %d, pmp %p, clust %lu, oldcon %p, newcon %lx)\n",
 	    function, pmp, cn, oldcontents, newcontents);
 #endif
 
 #ifdef DIAGNOSTIC
 	/*
 	 * Be sure they asked us to do something.
 	 */
 	if ((function & (FAT_SET | FAT_GET)) == 0) {
 #ifdef MSDOSFS_DEBUG
 		printf("fatentry(): function code doesn't specify get or set\n");
 #endif
 		return (EINVAL);
 	}
 
 	/*
 	 * If they asked us to return a cluster number but didn't tell us
 	 * where to put it, give them an error.
 	 */
 	if ((function & FAT_GET) && oldcontents == NULL) {
 #ifdef MSDOSFS_DEBUG
 		printf("fatentry(): get function with no place to put result\n");
 #endif
 		return (EINVAL);
 	}
 #endif
 
 	/*
 	 * Be sure the requested cluster is in the filesystem.
 	 */
 	if (cn < CLUST_FIRST || cn > pmp->pm_maxcluster)
 		return (EINVAL);
 
 	byteoffset = FATOFS(pmp, cn);
 	fatblock(pmp, byteoffset, &bn, &bsize, &bo);
 	error = bread((void *)pmp->pm_devvp, bn, bsize, NOCRED, &bp);
 	if (error) {
 		brelse(bp);
 		return (error);
 	}
 
 	if (function & FAT_GET) {
 		if (FAT32(pmp))
 			readcn = getulong(bp->b_data + bo);
 		else
 			readcn = getushort(bp->b_data + bo);
 		if (FAT12(pmp) & (cn & 1))
 			readcn >>= 4;
 		readcn &= pmp->pm_fatmask;
 		/* map reserved FAT entries to same values for all FATs */
 		if ((readcn | ~pmp->pm_fatmask) >= CLUST_RSRVD)
 			readcn |= ~pmp->pm_fatmask;
 		*oldcontents = readcn;
 	}
 	if (function & FAT_SET) {
 		switch (pmp->pm_fatmask) {
 		case FAT12_MASK:
 			readcn = getushort(bp->b_data + bo);
 			if (cn & 1) {
 				readcn &= 0x000f;
 				readcn |= newcontents << 4;
 			} else {
 				readcn &= 0xf000;
 				readcn |= newcontents & 0xfff;
 			}
 			putushort(bp->b_data + bo, readcn);
 			break;
 		case FAT16_MASK:
 			putushort(bp->b_data + bo, newcontents);
 			break;
 		case FAT32_MASK:
 			/*
 			 * According to spec we have to retain the
 			 * high order bits of the FAT entry.
 			 */
 			readcn = getulong(bp->b_data + bo);
 			readcn &= ~FAT32_MASK;
 			readcn |= newcontents & FAT32_MASK;
 			putulong(bp->b_data + bo, readcn);
 			break;
 		}
 		updatefats(pmp, bp, bn);
 		bp = NULL;
 		pmp->pm_fmod = 1;
 	}
 	if (bp)
 		brelse(bp);
 	return (0);
 }
 
 /*
  * Update a contiguous cluster chain
  *
  * pmp	    - mount point
  * start    - first cluster of chain
  * count    - number of clusters in chain
  * fillwith - what to write into FAT entry of last cluster
  */
 static int
 fatchain(struct msdosfsmount *pmp, u_long start, u_long count, u_long fillwith)
 {
 	int error;
 	u_long bn, bo, bsize, byteoffset, readcn, newc;
 	struct m_buf *bp;
 
 #ifdef MSDOSFS_DEBUG
 	printf("fatchain(pmp %p, start %lu, count %lu, fillwith %lx)\n",
 	    pmp, start, count, fillwith);
 #endif
 	/*
 	 * Be sure the clusters are in the filesystem.
 	 */
 	if (start < CLUST_FIRST || start + count - 1 > pmp->pm_maxcluster)
 		return (EINVAL);
 
 	while (count > 0) {
 		byteoffset = FATOFS(pmp, start);
 		fatblock(pmp, byteoffset, &bn, &bsize, &bo);
 		error = bread((void *)pmp->pm_devvp, bn, bsize, NOCRED, &bp);
 		if (error) {
 			brelse(bp);
 			return (error);
 		}
 		while (count > 0) {
 			start++;
 			newc = --count > 0 ? start : fillwith;
 			switch (pmp->pm_fatmask) {
 			case FAT12_MASK:
 				readcn = getushort(bp->b_data + bo);
 				if (start & 1) {
 					readcn &= 0xf000;
 					readcn |= newc & 0xfff;
 				} else {
 					readcn &= 0x000f;
 					readcn |= newc << 4;
 				}
 				putushort(bp->b_data + bo, readcn);
 				bo++;
 				if (!(start & 1))
 					bo++;
 				break;
 			case FAT16_MASK:
 				putushort(bp->b_data + bo, newc);
 				bo += 2;
 				break;
 			case FAT32_MASK:
 				readcn = getulong(bp->b_data + bo);
 				readcn &= ~pmp->pm_fatmask;
 				readcn |= newc & pmp->pm_fatmask;
 				putulong(bp->b_data + bo, readcn);
 				bo += 4;
 				break;
 			}
 			if (bo >= bsize)
 				break;
 		}
 		updatefats(pmp, bp, bn);
 	}
 	pmp->pm_fmod = 1;
 	return (0);
 }
 
 /*
  * Check the length of a free cluster chain starting at start.
  *
  * pmp	 - mount point
  * start - start of chain
  * count - maximum interesting length
  */
 static int
 chainlength(struct msdosfsmount *pmp, u_long start, u_long count)
 {
 	u_long idx, max_idx;
 	u_int map;
 	u_long len;
 
 	if (start > pmp->pm_maxcluster)
 		return (0);
 	max_idx = pmp->pm_maxcluster / N_INUSEBITS;
 	idx = start / N_INUSEBITS;
 	start %= N_INUSEBITS;
 	map = pmp->pm_inusemap[idx];
 	map &= ~((1 << start) - 1);
 	if (map) {
 		len = ffs(map) - 1 - start;
 		len = MIN(len, count);
 		if (start + len > pmp->pm_maxcluster)
 			len = pmp->pm_maxcluster - start + 1;
 		return (len);
 	}
 	len = N_INUSEBITS - start;
 	if (len >= count) {
 		len = count;
 		if (start + len > pmp->pm_maxcluster)
 			len = pmp->pm_maxcluster - start + 1;
 		return (len);
 	}
 	while (++idx <= max_idx) {
 		if (len >= count)
 			break;
 		map = pmp->pm_inusemap[idx];
 		if (map) {
 			len += ffs(map) - 1;
 			break;
 		}
 		len += N_INUSEBITS;
 	}
 	len = MIN(len, count);
 	if (start + len > pmp->pm_maxcluster)
 		len = pmp->pm_maxcluster - start + 1;
 	return (len);
 }
 
 /*
  * Allocate contigous free clusters.
  *
  * pmp	      - mount point.
  * start      - start of cluster chain.
  * count      - number of clusters to allocate.
  * fillwith   - put this value into the FAT entry for the
  *		last allocated cluster.
  * retcluster - put the first allocated cluster's number here.
  * got	      - how many clusters were actually allocated.
  */
 static int
 chainalloc(struct msdosfsmount *pmp, u_long start, u_long count,
     u_long fillwith, u_long *retcluster, u_long *got)
 {
 	int error;
 	u_long cl, n;
 
 	assert((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0);
 
 	for (cl = start, n = count; n-- > 0;)
 		usemap_alloc(pmp, cl++);
 	pmp->pm_nxtfree = start + count;
 	if (pmp->pm_nxtfree > pmp->pm_maxcluster)
 		pmp->pm_nxtfree = CLUST_FIRST;
 	pmp->pm_flags |= MSDOSFS_FSIMOD;
 	error = fatchain(pmp, start, count, fillwith);
 	if (error != 0) {
 		for (cl = start, n = count; n-- > 0;)
 			usemap_free(pmp, cl++);
 		return (error);
 	}
 #ifdef MSDOSFS_DEBUG
 	printf("clusteralloc(): allocated cluster chain at %lu (%lu clusters)\n",
 	    start, count);
 #endif
 	if (retcluster)
 		*retcluster = start;
 	if (got)
 		*got = count;
 	return (0);
 }
 
 /*
  * Allocate contiguous free clusters.
  *
  * pmp	      - mount point.
  * start      - preferred start of cluster chain.
  * count      - number of clusters requested.
  * fillwith   - put this value into the FAT entry for the
  *		last allocated cluster.
  * retcluster - put the first allocated cluster's number here.
  * got	      - how many clusters were actually allocated.
  */
 int
 clusteralloc(struct msdosfsmount *pmp, u_long start, u_long count,
     u_long fillwith, u_long *retcluster, u_long *got)
 {
 	int error;
 
 	error = clusteralloc1(pmp, start, count, fillwith, retcluster, got);
 	return (error);
 }
 
 static int
 clusteralloc1(struct msdosfsmount *pmp, u_long start, u_long count,
     u_long fillwith, u_long *retcluster, u_long *got)
 {
 	u_long idx;
 	u_long len, newst, foundl, cn, l;
 	u_long foundcn = 0; /* XXX: foundcn could be used unititialized */
 	u_int map;
 
 	MSDOSFS_DPRINTF(("clusteralloc(): find %lu clusters\n", count));
 
 	if (start) {
 		if ((len = chainlength(pmp, start, count)) >= count)
 			return (chainalloc(pmp, start, count, fillwith, retcluster, got));
 	} else
 		len = 0;
 
 	newst = pmp->pm_nxtfree;
 	foundl = 0;
 
 	for (cn = newst; cn <= pmp->pm_maxcluster;) {
 		idx = cn / N_INUSEBITS;
 		map = pmp->pm_inusemap[idx];
 		map |= (1U << (cn % N_INUSEBITS)) - 1;
 		if (map != FULL_RUN) {
 			cn = idx * N_INUSEBITS + ffs(map ^ FULL_RUN) - 1;
 			if ((l = chainlength(pmp, cn, count)) >= count)
 				return (chainalloc(pmp, cn, count, fillwith, retcluster, got));
 			if (l > foundl) {
 				foundcn = cn;
 				foundl = l;
 			}
 			cn += l + 1;
 			continue;
 		}
 		cn += N_INUSEBITS - cn % N_INUSEBITS;
 	}
 	for (cn = 0; cn < newst;) {
 		idx = cn / N_INUSEBITS;
 		map = pmp->pm_inusemap[idx];
 		map |= (1U << (cn % N_INUSEBITS)) - 1;
 		if (map != FULL_RUN) {
 			cn = idx * N_INUSEBITS + ffs(map ^ FULL_RUN) - 1;
 			if ((l = chainlength(pmp, cn, count)) >= count)
 				return (chainalloc(pmp, cn, count, fillwith, retcluster, got));
 			if (l > foundl) {
 				foundcn = cn;
 				foundl = l;
 			}
 			cn += l + 1;
 			continue;
 		}
 		cn += N_INUSEBITS - cn % N_INUSEBITS;
 	}
 
 	if (!foundl)
 		return (ENOSPC);
 
 	if (len)
 		return (chainalloc(pmp, start, len, fillwith, retcluster, got));
 	else
 		return (chainalloc(pmp, foundcn, foundl, fillwith, retcluster, got));
 }
 
 
 /*
  * Free a chain of clusters.
  *
  * pmp		- address of the msdosfs mount structure for the filesystem
  *		  containing the cluster chain to be freed.
  * startcluster - number of the 1st cluster in the chain of clusters to be
  *		  freed.
  */
 int
 freeclusterchain(struct msdosfsmount *pmp, u_long cluster)
 {
 	int error;
 	struct m_buf *bp = NULL;
 	u_long bn, bo, bsize, byteoffset;
 	u_long readcn, lbn = -1;
 
 	while (cluster >= CLUST_FIRST && cluster <= pmp->pm_maxcluster) {
 		byteoffset = FATOFS(pmp, cluster);
 		fatblock(pmp, byteoffset, &bn, &bsize, &bo);
 		if (lbn != bn) {
 			if (bp)
 				updatefats(pmp, bp, lbn);
 			error = bread((void *)pmp->pm_devvp, bn, bsize,
 			    NOCRED, &bp);
 			if (error) {
 				brelse(bp);
 				return (error);
 			}
 			lbn = bn;
 		}
 		usemap_free(pmp, cluster);
 		switch (pmp->pm_fatmask) {
 		case FAT12_MASK:
 			readcn = getushort(bp->b_data + bo);
 			if (cluster & 1) {
 				cluster = readcn >> 4;
 				readcn &= 0x000f;
 				readcn |= MSDOSFSFREE << 4;
 			} else {
 				cluster = readcn;
 				readcn &= 0xf000;
 				readcn |= MSDOSFSFREE & 0xfff;
 			}
 			putushort(bp->b_data + bo, readcn);
 			break;
 		case FAT16_MASK:
 			cluster = getushort(bp->b_data + bo);
 			putushort(bp->b_data + bo, MSDOSFSFREE);
 			break;
 		case FAT32_MASK:
 			cluster = getulong(bp->b_data + bo);
 			putulong(bp->b_data + bo,
 				 (MSDOSFSFREE & FAT32_MASK) | (cluster & ~FAT32_MASK));
 			break;
 		}
 		cluster &= pmp->pm_fatmask;
 		if ((cluster | ~pmp->pm_fatmask) >= CLUST_RSRVD)
 			cluster |= pmp->pm_fatmask;
 	}
 	if (bp)
 		updatefats(pmp, bp, bn);
 	return (0);
 }
 
 /*
  * Read in FAT blocks looking for free clusters. For every free cluster
  * found turn off its corresponding bit in the pm_inusemap.
  */
 int
 fillinusemap(struct msdosfsmount *pmp)
 {
 	struct m_buf *bp;
 	u_long bn, bo, bsize, byteoffset, cn, readcn;
 	int error;
 
 	bp = NULL;
 
 	/*
 	 * Mark all clusters in use, we mark the free ones in the FAT scan
 	 * loop further down.
 	 */
 	for (cn = 0; cn < (pmp->pm_maxcluster + N_INUSEBITS) / N_INUSEBITS; cn++)
 		pmp->pm_inusemap[cn] = FULL_RUN;
 
 	/*
 	 * Figure how many free clusters are in the filesystem by ripping
 	 * through the FAT counting the number of entries whose content is
 	 * zero.  These represent free clusters.
 	 */
 	pmp->pm_freeclustercount = 0;
 	for (cn = 0; cn <= pmp->pm_maxcluster; cn++) {
 		byteoffset = FATOFS(pmp, cn);
 		bo = byteoffset % pmp->pm_fatblocksize;
 		if (bo == 0) {
 			/* Read new FAT block */
 			if (bp != NULL)
 				brelse(bp);
 			fatblock(pmp, byteoffset, &bn, &bsize, NULL);
 			error = bread((void *)pmp->pm_devvp, bn, bsize,
 			    NOCRED, &bp);
 			if (error != 0)
 				return (error);
 		}
 		if (FAT32(pmp))
 			readcn = getulong(bp->b_data + bo);
 		else
 			readcn = getushort(bp->b_data + bo);
 		if (FAT12(pmp) && (cn & 1))
 			readcn >>= 4;
 		readcn &= pmp->pm_fatmask;
 
 		/*
 		 * Check if the FAT ID matches the BPB's media descriptor and
 		 * all other bits are set to 1.
 		 */
 		if (cn == 0 && readcn != ((pmp->pm_fatmask & 0xffffff00) |
 		    pmp->pm_bpb.bpbMedia)) {
 #ifdef MSDOSFS_DEBUG
 			printf("mountmsdosfs(): Media descriptor in BPB"
 			    "does not match FAT ID\n");
 #endif
 			brelse(bp);
 			return (EINVAL);
 		} else if (readcn == CLUST_FREE)
 			usemap_free(pmp, cn);
 	}
 	if (bp != NULL)
 		brelse(bp);
 
 	for (cn = pmp->pm_maxcluster + 1; cn < (pmp->pm_maxcluster +
 	    N_INUSEBITS) / N_INUSEBITS; cn++)
 		pmp->pm_inusemap[cn / N_INUSEBITS] |= 1U << (cn % N_INUSEBITS);
 
 	return (0);
 }
 
 /*
  * Allocate a new cluster and chain it onto the end of the file.
  *
  * dep	 - the file to extend
  * count - number of clusters to allocate
  * bpp	 - where to return the address of the buf header for the first new
  *	   file block
  * ncp	 - where to put cluster number of the first newly allocated cluster
  *	   If this pointer is 0, do not return the cluster number.
  * flags - see fat.h
  *
  * NOTE: This function is not responsible for turning on the DE_UPDATE bit of
  * the de_flag field of the denode and it does not change the de_FileSize
  * field.  This is left for the caller to do.
  */
 int
 m_extendfile(struct denode *dep, u_long count, struct m_buf **bpp, u_long *ncp,
     int flags)
 {
 	int error;
 	u_long frcn;
 	u_long cn, got;
 	struct msdosfsmount *pmp = dep->de_pmp;
 	struct m_buf *bp;
 
 	/*
 	 * Don't try to extend the root directory
 	 */
 	if (dep->de_StartCluster == MSDOSFSROOT
 	    && (dep->de_Attributes & ATTR_DIRECTORY)) {
 #ifdef MSDOSFS_DEBUG
 		printf("extendfile(): attempt to extend root directory\n");
 #endif
 		return (ENOSPC);
 	}
 
 	/*
 	 * If the "file's last cluster" cache entry is empty, and the file
 	 * is not empty, then fill the cache entry by calling pcbmap().
 	 */
 	if (dep->de_fc[FC_LASTFC].fc_frcn == FCE_EMPTY &&
 	    dep->de_StartCluster != 0) {
 		error = pcbmap(dep, 0xffff, 0, &cn, 0);
 		/* we expect it to return E2BIG */
 		if (error != E2BIG)
 			return (error);
 	}
 
 	dep->de_fc[FC_NEXTTOLASTFC].fc_frcn =
 	    dep->de_fc[FC_LASTFC].fc_frcn;
 	dep->de_fc[FC_NEXTTOLASTFC].fc_fsrcn =
 	    dep->de_fc[FC_LASTFC].fc_fsrcn;
 	while (count > 0) {
 		/*
 		 * Allocate a new cluster chain and cat onto the end of the
 		 * file.  If the file is empty we make de_StartCluster point
 		 * to the new block.  Note that de_StartCluster being 0 is
 		 * sufficient to be sure the file is empty since we exclude
 		 * attempts to extend the root directory above, and the root
 		 * dir is the only file with a startcluster of 0 that has
 		 * blocks allocated (sort of).
 		 */
 		if (dep->de_StartCluster == 0)
 			cn = 0;
 		else
 			cn = dep->de_fc[FC_LASTFC].fc_fsrcn + 1;
 		error = clusteralloc(pmp, cn, count, CLUST_EOFE, &cn, &got);
 		if (error)
 			return (error);
 
 		count -= got;
 
 		/*
 		 * Give them the filesystem relative cluster number if they want
 		 * it.
 		 */
 		if (ncp) {
 			*ncp = cn;
 			ncp = NULL;
 		}
 
 		if (dep->de_StartCluster == 0) {
 			dep->de_StartCluster = cn;
 			frcn = 0;
 		} else {
 			error = fatentry(FAT_SET, pmp,
 					 dep->de_fc[FC_LASTFC].fc_fsrcn,
 					 0, cn);
 			if (error) {
 				clusterfree(pmp, cn, NULL);
 				return (error);
 			}
 			frcn = dep->de_fc[FC_LASTFC].fc_frcn + 1;
 		}
 
 		/*
 		 * Update the "last cluster of the file" entry in the
 		 * denode's FAT cache.
 		 */
 		fc_setcache(dep, FC_LASTFC, frcn + got - 1, cn + got - 1);
 
 		if ((flags & DE_CLEAR) &&
 		    (dep->de_Attributes & ATTR_DIRECTORY)) {
 			while (got-- > 0) {
 				bp = getblk((void *)pmp->pm_devvp,
 				    cntobn(pmp, cn++),
 				    pmp->pm_bpcluster, 0, 0, 0);
 				clrbuf(bp);
 				if (bpp) {
 					*bpp = bp;
 					bpp = NULL;
 				} else {
 					bdwrite(bp);
 				}
 			}
 		}
 	}
 
 	return (0);
 }
diff --git a/usr.sbin/makefs/msdos/msdosfs_lookup.c b/usr.sbin/makefs/msdos/msdosfs_lookup.c
index 3fca0532468b..a4db6ae1a4a2 100644
--- a/usr.sbin/makefs/msdos/msdosfs_lookup.c
+++ b/usr.sbin/makefs/msdos/msdosfs_lookup.c
@@ -1,306 +1,303 @@
 /* $FreeBSD$ */
 /*	$NetBSD: msdosfs_lookup.c,v 1.37 1997/11/17 15:36:54 ws Exp $	*/
 
 /*-
  * SPDX-License-Identifier: BSD-4-Clause
  *
  * 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/param.h>
 #include <sys/errno.h>
 
 #include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
 
 #include <fs/msdosfs/bpb.h>
-#include "msdos/direntry.h"
-#include <fs/msdosfs/denode.h>
+#include "msdos/denode.h"
 #include <fs/msdosfs/fat.h>
 #include <fs/msdosfs/msdosfsmount.h>
 
-#undef clrbuf
-#include "ffs/buf.h"
 #include "makefs.h"
 #include "msdos.h"
 
 /*
  * dep  - directory entry to copy into the directory
  * ddep - directory to add to
  * depp - return the address of the denode for the created directory entry
  *	  if depp != 0
  * cnp  - componentname needed for Win95 long filenames
  */
 int
 createde(struct denode *dep, struct denode *ddep, struct denode **depp,
     struct componentname *cnp)
 {
 	int error;
 	u_long dirclust, diroffset;
 	struct direntry *ndep;
 	struct msdosfsmount *pmp = ddep->de_pmp;
 	struct m_buf *bp;
 	daddr_t bn;
 	int blsize;
 
 	MSDOSFS_DPRINTF(("createde(dep %p, ddep %p, depp %p, cnp %p)\n",
 	    dep, ddep, depp, cnp));
 
 	/*
 	 * If no space left in the directory then allocate another cluster
 	 * and chain it onto the end of the file.  There is one exception
 	 * to this.  That is, if the root directory has no more space it
 	 * can NOT be expanded.  extendfile() checks for and fails attempts
 	 * to extend the root directory.  We just return an error in that
 	 * case.
 	 */
 	if (ddep->de_fndoffset >= ddep->de_FileSize) {
 		diroffset = ddep->de_fndoffset + sizeof(struct direntry)
 		    - ddep->de_FileSize;
 		dirclust = de_clcount(pmp, diroffset);
 		error = m_extendfile(ddep, dirclust, 0, 0, DE_CLEAR);
 		if (error) {
 			(void)detrunc(ddep, ddep->de_FileSize, 0, NULL);
 			return error;
 		}
 
 		/*
 		 * Update the size of the directory
 		 */
 		ddep->de_FileSize += de_cn2off(pmp, dirclust);
 	}
 
 	/*
 	 * We just read in the cluster with space.  Copy the new directory
 	 * entry in.  Then write it to disk. NOTE:  DOS directories
 	 * do not get smaller as clusters are emptied.
 	 */
 	error = pcbmap(ddep, de_cluster(pmp, ddep->de_fndoffset),
 		       &bn, &dirclust, &blsize);
 	if (error)
 		return error;
 	diroffset = ddep->de_fndoffset;
 	if (dirclust != MSDOSFSROOT)
 		diroffset &= pmp->pm_crbomask;
 	if ((error = bread((void *)pmp->pm_devvp, bn, blsize, NOCRED,
 	    &bp)) != 0) {
 		brelse(bp);
 		return error;
 	}
 	ndep = bptoep(pmp, bp, ddep->de_fndoffset);
 
 	DE_EXTERNALIZE(ndep, dep);
 
 	/*
 	 * Now write the Win95 long name
 	 */
 	if (ddep->de_fndcnt > 0) {
 		uint8_t chksum = winChksum(ndep->deName);
 		const u_char *un = (const u_char *)cnp->cn_nameptr;
 		int unlen = cnp->cn_namelen;
 		int cnt = 1;
 
 		while (--ddep->de_fndcnt >= 0) {
 			if (!(ddep->de_fndoffset & pmp->pm_crbomask)) {
 				if ((error = bwrite(bp)) != 0)
 					return error;
 
 				ddep->de_fndoffset -= sizeof(struct direntry);
 				error = pcbmap(ddep,
 					       de_cluster(pmp,
 							  ddep->de_fndoffset),
 					       &bn, 0, &blsize);
 				if (error)
 					return error;
 
 				error = bread((void *)pmp->pm_devvp, bn, blsize,
 					      NOCRED, &bp);
 				if (error) {
 					brelse(bp);
 					return error;
 				}
 				ndep = bptoep(pmp, bp, ddep->de_fndoffset);
 			} else {
 				ndep--;
 				ddep->de_fndoffset -= sizeof(struct direntry);
 			}
 			if (!unix2winfn(un, unlen, (struct winentry *)ndep,
 					cnt++, chksum))
 				break;
 		}
 	}
 
 	if ((error = bwrite(bp)) != 0)
 		return error;
 
 	/*
 	 * If they want us to return with the denode gotten.
 	 */
 	if (depp) {
 		if (dep->de_Attributes & ATTR_DIRECTORY) {
 			dirclust = dep->de_StartCluster;
 			if (FAT32(pmp) && dirclust == pmp->pm_rootdirblk)
 				dirclust = MSDOSFSROOT;
 			if (dirclust == MSDOSFSROOT)
 				diroffset = MSDOSFSROOT_OFS;
 			else
 				diroffset = 0;
 		}
 		return deget(pmp, dirclust, diroffset, depp);
 	}
 
 	return 0;
 }
 
 /*
  * Read in the disk block containing the directory entry (dirclu, dirofs)
  * and return the address of the buf header, and the address of the
  * directory entry within the block.
  */
 int
 m_readep(struct msdosfsmount *pmp, u_long dirclust, u_long diroffset,
     struct m_buf **bpp, struct direntry **epp)
 {
 	int error;
 	daddr_t bn;
 	int blsize;
 
 	blsize = pmp->pm_bpcluster;
 	if (dirclust == MSDOSFSROOT
 	    && de_blk(pmp, diroffset + blsize) > pmp->pm_rootdirsize)
 		blsize = de_bn2off(pmp, pmp->pm_rootdirsize) & pmp->pm_crbomask;
 	bn = detobn(pmp, dirclust, diroffset);
 	if ((error = bread((void *)pmp->pm_devvp, bn, blsize, NOCRED,
 	    bpp)) != 0) {
 		brelse(*bpp);
 		*bpp = NULL;
 		return (error);
 	}
 	if (epp)
 		*epp = bptoep(pmp, *bpp, diroffset);
 	return (0);
 }
 
 /*
  * Read in the disk block containing the directory entry dep came from and
  * return the address of the buf header, and the address of the directory
  * entry within the block.
  */
 int
 m_readde(struct denode *dep, struct m_buf **bpp, struct direntry **epp)
 {
 
 	return (m_readep(dep->de_pmp, dep->de_dirclust, dep->de_diroffset,
 	    bpp, epp));
 }
 
 /*
  * Create a unique DOS name in dvp
  */
 int
 uniqdosname(struct denode *dep, struct componentname *cnp, u_char *cp)
 {
 	struct msdosfsmount *pmp = dep->de_pmp;
 	struct direntry *dentp;
 	int gen;
 	int blsize;
 	u_long cn;
 	daddr_t bn;
 	struct m_buf *bp;
 	int error;
 
 	if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME)
 		return (unix2dosfn((const u_char *)cnp->cn_nameptr, cp,
 		    cnp->cn_namelen, 0) ? 0 : EINVAL);
 
 	for (gen = 1;; gen++) {
 		/*
 		 * Generate DOS name with generation number
 		 */
 		if (!unix2dosfn((const u_char *)cnp->cn_nameptr, cp,
 		    cnp->cn_namelen, gen))
 			return gen == 1 ? EINVAL : EEXIST;
 
 		/*
 		 * Now look for a dir entry with this exact name
 		 */
 		for (cn = error = 0; !error; cn++) {
 			if ((error = pcbmap(dep, cn, &bn, 0, &blsize)) != 0) {
 				if (error == E2BIG)	/* EOF reached and not found */
 					return 0;
 				return error;
 			}
 			error = bread((void *)pmp->pm_devvp, bn, blsize,
 			    NOCRED, &bp);
 			if (error) {
 				brelse(bp);
 				return error;
 			}
 			for (dentp = (struct direntry *)bp->b_data;
 			     (char *)dentp < bp->b_data + blsize;
 			     dentp++) {
 				if (dentp->deName[0] == SLOT_EMPTY) {
 					/*
 					 * Last used entry and not found
 					 */
 					brelse(bp);
 					return 0;
 				}
 				/*
 				 * Ignore volume labels and Win95 entries
 				 */
 				if (dentp->deAttributes & ATTR_VOLUME)
 					continue;
 				if (!bcmp(dentp->deName, cp, 11)) {
 					error = EEXIST;
 					break;
 				}
 			}
 			brelse(bp);
 		}
 	}
 }
diff --git a/usr.sbin/makefs/msdos/msdosfs_vfsops.c b/usr.sbin/makefs/msdos/msdosfs_vfsops.c
index b6788f6876f9..dd933bb2be61 100644
--- a/usr.sbin/makefs/msdos/msdosfs_vfsops.c
+++ b/usr.sbin/makefs/msdos/msdosfs_vfsops.c
@@ -1,391 +1,388 @@
 /*-
  * SPDX-License-Identifier: BSD-4-Clause
  *
  * 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>
 /* $NetBSD: msdosfs_vfsops.c,v 1.10 2016/01/30 09:59:27 mlelstv Exp $ */
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/mount.h>
 
 #include <errno.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <util.h>
 
 #include <fs/msdosfs/bootsect.h>
 #include <fs/msdosfs/bpb.h>
-#include "msdos/direntry.h"
-#include <fs/msdosfs/denode.h>
+#include "msdos/denode.h"
 #include <fs/msdosfs/fat.h>
 #include <fs/msdosfs/msdosfsmount.h>
 
 #include <mkfs_msdos.h>
 
-#undef clrbuf
-#include "ffs/buf.h"
 #include "makefs.h"
 #include "msdos.h"
 
 struct msdosfsmount *
 m_msdosfs_mount(struct m_vnode *devvp)
 {
 	struct msdosfsmount *pmp = NULL;
 	struct m_buf *bp;
 	union bootsector *bsp;
 	struct byte_bpb33 *b33;
 	struct byte_bpb50 *b50;
 	struct byte_bpb710 *b710;
 	uint8_t SecPerClust;
 	int	ronly = 0, error;
 	int	bsize;
 	unsigned secsize = 512;
 
 	MSDOSFS_DPRINTF(("%s(bread 0)\n", __func__));
 	if ((error = bread((void *)devvp, 0, secsize, 0, &bp)) != 0)
 		goto error_exit;
 
 	bsp = (union bootsector *)bp->b_data;
 	b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB;
 	b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB;
 	b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB;
 
 	if (bsp->bs50.bsBootSectSig0 != BOOTSIG0 ||
 	    bsp->bs50.bsBootSectSig1 != BOOTSIG1) {
 		MSDOSFS_DPRINTF(("bootsig0 %d bootsig1 %d\n",
 		    bsp->bs50.bsBootSectSig0,
 		    bsp->bs50.bsBootSectSig1));
 		error = EINVAL;
 		goto error_exit;
 	}
 	bsize = 0;
 
 	pmp = ecalloc(1, sizeof(*pmp));
 	/*
 	 * Compute several useful quantities from the bpb in the
 	 * bootsector.  Copy in the dos 5 variant of the bpb then fix up
 	 * the fields that are different between dos 5 and dos 3.3.
 	 */
 	SecPerClust = b50->bpbSecPerClust;
 	pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec);
 	pmp->pm_ResSectors = getushort(b50->bpbResSectors);
 	pmp->pm_FATs = b50->bpbFATs;
 	pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts);
 	pmp->pm_Sectors = getushort(b50->bpbSectors);
 	pmp->pm_FATsecs = getushort(b50->bpbFATsecs);
 	pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack);
 	pmp->pm_Heads = getushort(b50->bpbHeads);
 	pmp->pm_Media = b50->bpbMedia;
 
 	MSDOSFS_DPRINTF(("%s(BytesPerSec=%u, ResSectors=%u, FATs=%d, "
 	    "RootDirEnts=%u, Sectors=%u, FATsecs=%lu, SecPerTrack=%u, "
 	    "Heads=%u, Media=%u)\n",
 	    __func__, pmp->pm_BytesPerSec, pmp->pm_ResSectors,
 	    pmp->pm_FATs, pmp->pm_RootDirEnts, pmp->pm_Sectors,
 	    pmp->pm_FATsecs, pmp->pm_SecPerTrack, pmp->pm_Heads,
 	    pmp->pm_Media));
 
 	/* XXX - We should probably check more values here */
 	if (!pmp->pm_BytesPerSec || !SecPerClust
 		|| pmp->pm_SecPerTrack > 63) {
 		MSDOSFS_DPRINTF(("bytespersec %d secperclust %d "
 		    "secpertrack %d\n", pmp->pm_BytesPerSec,
 		    SecPerClust, pmp->pm_SecPerTrack));
 		error = EINVAL;
 		goto error_exit;
 	}
 
 	if (pmp->pm_Sectors == 0) {
 		pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);
 		pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors);
 	} else {
 		pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs);
 		pmp->pm_HugeSectors = pmp->pm_Sectors;
 	}
 
 	pmp->pm_flags = 0;
 	if (pmp->pm_RootDirEnts == 0) {
 		unsigned short vers = getushort(b710->bpbFSVers);
 		/*
 		 * Some say that bsBootSectSig[23] must be zero, but
 		 * Windows does not require this and some digital cameras
 		 * do not set these to zero.  Therefore, do not insist.
 		 */
 		if (pmp->pm_Sectors || pmp->pm_FATsecs || vers) {
 			MSDOSFS_DPRINTF(("sectors %d fatsecs %lu vers %d\n",
 			    pmp->pm_Sectors, pmp->pm_FATsecs, vers));
 			error = EINVAL;
 			goto error_exit;
 		}
 		pmp->pm_fatmask = FAT32_MASK;
 		pmp->pm_fatmult = 4;
 		pmp->pm_fatdiv = 1;
 		pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs);
 
 		/* mirrorring is enabled if the FATMIRROR bit is not set */
 		if ((getushort(b710->bpbExtFlags) & FATMIRROR) == 0)
 			pmp->pm_flags |= MSDOSFS_FATMIRROR;
 		else
 			pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM;
 	} else
 		pmp->pm_flags |= MSDOSFS_FATMIRROR;
 
 	/* Check that fs has nonzero FAT size */
 	if (pmp->pm_FATsecs == 0) {
 		MSDOSFS_DPRINTF(("FATsecs is 0\n"));
 		error = EINVAL;
 		goto error_exit;
 	}
 
 	pmp->pm_fatblk = pmp->pm_ResSectors;
 	if (FAT32(pmp)) {
 		pmp->pm_rootdirblk = getulong(b710->bpbRootClust);
 		pmp->pm_firstcluster = pmp->pm_fatblk
 			+ (pmp->pm_FATs * pmp->pm_FATsecs);
 		pmp->pm_fsinfo = getushort(b710->bpbFSInfo);
 	} else {
 		pmp->pm_rootdirblk = pmp->pm_fatblk +
 			(pmp->pm_FATs * pmp->pm_FATsecs);
 		pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry)
 				       + pmp->pm_BytesPerSec - 1)
 			/ pmp->pm_BytesPerSec;/* in sectors */
 		pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize;
 	}
 
 	pmp->pm_maxcluster = ((pmp->pm_HugeSectors - pmp->pm_firstcluster) /
 	    SecPerClust) + 1;
 	pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec;
 
 	if (pmp->pm_fatmask == 0) {
 		if (pmp->pm_maxcluster
 		    <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) {
 			/*
 			 * This will usually be a floppy disk. This size makes
 			 * sure that one FAT entry will not be split across
 			 * multiple blocks.
 			 */
 			pmp->pm_fatmask = FAT12_MASK;
 			pmp->pm_fatmult = 3;
 			pmp->pm_fatdiv = 2;
 		} else {
 			pmp->pm_fatmask = FAT16_MASK;
 			pmp->pm_fatmult = 2;
 			pmp->pm_fatdiv = 1;
 		}
 	}
 	if (FAT12(pmp))
 		pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec;
 	else
 		pmp->pm_fatblocksize = MAXBSIZE;
 
 	pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec;
 	pmp->pm_bnshift = ffs(pmp->pm_BytesPerSec) - 1;
 
 	/*
 	 * Compute mask and shift value for isolating cluster relative byte
 	 * offsets and cluster numbers from a file offset.
 	 */
 	pmp->pm_bpcluster = SecPerClust * pmp->pm_BytesPerSec;
 	pmp->pm_crbomask = pmp->pm_bpcluster - 1;
 	pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1;
 
 	MSDOSFS_DPRINTF(("%s(fatmask=%lu, fatmult=%u, fatdiv=%u, "
 	    "fatblocksize=%lu, fatblocksec=%lu, bnshift=%lu, pbcluster=%lu, "
 	    "crbomask=%lu, cnshift=%lu)\n",
 	    __func__, (unsigned long)pmp->pm_fatmask, pmp->pm_fatmult,
 	    pmp->pm_fatdiv, pmp->pm_fatblocksize, pmp->pm_fatblocksec,
 	    pmp->pm_bnshift, pmp->pm_bpcluster, pmp->pm_crbomask,
 	    pmp->pm_cnshift));
 	/*
 	 * Check for valid cluster size
 	 * must be a power of 2
 	 */
 	if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) {
 		MSDOSFS_DPRINTF(("bpcluster %lu cnshift %lu\n",
 		    pmp->pm_bpcluster, pmp->pm_cnshift));
 		error = EINVAL;
 		goto error_exit;
 	}
 
 	/*
 	 * Release the bootsector buffer.
 	 */
 	brelse(bp);
 	bp = NULL;
 
 	/*
 	 * Check FSInfo.
 	 */
 	if (pmp->pm_fsinfo) {
 		struct fsinfo *fp;
 
 		/*
 		 * XXX	If the fsinfo block is stored on media with
 		 *	2KB or larger sectors, is the fsinfo structure
 		 *	padded at the end or in the middle?
 		 */
 		if ((error = bread((void *)devvp, pmp->pm_fsinfo,
 		    pmp->pm_BytesPerSec, 0, &bp)) != 0)
 			goto error_exit;
 		fp = (struct fsinfo *)bp->b_data;
 		if (!memcmp(fp->fsisig1, "RRaA", 4)
 		    && !memcmp(fp->fsisig2, "rrAa", 4)
 		    && !memcmp(fp->fsisig3, "\0\0\125\252", 4))
 			pmp->pm_nxtfree = getulong(fp->fsinxtfree);
 		else
 			pmp->pm_fsinfo = 0;
 		brelse(bp);
 		bp = NULL;
 	}
 
 	/*
 	 * Check and validate (or perhaps invalidate?) the fsinfo structure?
 	 * XXX
 	 */
 	if (pmp->pm_fsinfo) {
 		if ((pmp->pm_nxtfree == 0xffffffffUL) ||
 		    (pmp->pm_nxtfree > pmp->pm_maxcluster))
 			pmp->pm_fsinfo = 0;
 	}
 
 	/*
 	 * Allocate memory for the bitmap of allocated clusters, and then
 	 * fill it in.
 	 */
 	pmp->pm_inusemap = ecalloc(sizeof(*pmp->pm_inusemap),
 	    ((pmp->pm_maxcluster + N_INUSEBITS) / N_INUSEBITS));
 	/*
 	 * fillinusemap() needs pm_devvp.
 	 */
 	pmp->pm_dev = 0;
 	pmp->pm_devvp = (void *)devvp;
 
 	/*
 	 * Have the inuse map filled in.
 	 */
 	if ((error = fillinusemap(pmp)) != 0) {
 		MSDOSFS_DPRINTF(("fillinusemap %d\n", error));
 		goto error_exit;
 	}
 
 	/*
 	 * Finish up.
 	 */
 	if (ronly)
 		pmp->pm_flags |= MSDOSFSMNT_RONLY;
 	else
 		pmp->pm_fmod = 1;
 
 	/*
 	 * If we ever do quotas for DOS filesystems this would be a place
 	 * to fill in the info in the msdosfsmount structure. You dolt,
 	 * quotas on dos filesystems make no sense because files have no
 	 * owners on dos filesystems. of course there is some empty space
 	 * in the directory entry where we could put uid's and gid's.
 	 */
 
 	return pmp;
 
 error_exit:
 	if (bp)
 		brelse(bp);
 	if (pmp) {
 		if (pmp->pm_inusemap)
 			free(pmp->pm_inusemap);
 		free(pmp);
 	}
 	errno = error;
 	return NULL;
 }
 
 int
 msdosfs_root(struct msdosfsmount *pmp, struct m_vnode *vp) {
 	struct denode *ndep;
 	int error;
 
 	*vp = *(struct m_vnode *)pmp->pm_devvp;
 	if ((error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, &ndep)) != 0) {
 		errno = error;
 		return -1;
 	}
 	vp->v_data = ndep;
 	return 0;
 }
 
 /*
  * If we have an FSInfo block, update it.
  */
 int
 msdosfs_fsiflush(struct msdosfsmount *pmp)
 {
 	struct fsinfo *fp;
 	struct m_buf *bp;
 	int error;
 
 	if (pmp->pm_fsinfo == 0 || (pmp->pm_flags & MSDOSFS_FSIMOD) == 0) {
 		error = 0;
 		goto out;
 	}
 	error = bread((void *)pmp->pm_devvp, pmp->pm_fsinfo,
 	    pmp->pm_BytesPerSec, NOCRED, &bp);
 	if (error != 0) {
 		brelse(bp);
 		goto out;
 	}
 	fp = (struct fsinfo *)bp->b_data;
 	putulong(fp->fsinfree, pmp->pm_freeclustercount);
 	putulong(fp->fsinxtfree, pmp->pm_nxtfree);
 	pmp->pm_flags &= ~MSDOSFS_FSIMOD;
 	error = bwrite(bp);
 
 out:
 	return (error);
 }
diff --git a/usr.sbin/makefs/msdos/msdosfs_vnops.c b/usr.sbin/makefs/msdos/msdosfs_vnops.c
index 2233c4b35eb2..7e927b4b99c7 100644
--- a/usr.sbin/makefs/msdos/msdosfs_vnops.c
+++ b/usr.sbin/makefs/msdos/msdosfs_vnops.c
@@ -1,646 +1,643 @@
 /*	$NetBSD: msdosfs_vnops.c,v 1.19 2017/04/13 17:10:12 christos Exp $ */
 
 /*-
  * SPDX-License-Identifier: BSD-4-Clause
  *
  * 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/errno.h>
 #include <sys/mman.h>
 #include <sys/time.h>
 
 #include <fcntl.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
 
 #include <fs/msdosfs/bpb.h>
-#include "msdos/direntry.h"
-#include <fs/msdosfs/denode.h>
+#include "msdos/denode.h"
 #include <fs/msdosfs/fat.h>
 #include <fs/msdosfs/msdosfsmount.h>
 
-#undef clrbuf
-#include "ffs/buf.h"
 #include "makefs.h"
 #include "msdos.h"
 
 /*
  * Some general notes:
  *
  * In the ufs filesystem the inodes, superblocks, and indirect blocks are
  * read/written using the vnode for the filesystem. Blocks that represent
  * the contents of a file are read/written using the vnode for the file
  * (including directories when they are read/written as files). This
  * presents problems for the dos filesystem because data that should be in
  * an inode (if dos had them) resides in the directory itself.	Since we
  * must update directory entries without the benefit of having the vnode
  * for the directory we must use the vnode for the filesystem.	This means
  * that when a directory is actually read/written (via read, write, or
  * readdir, or seek) we must use the vnode for the filesystem instead of
  * the vnode for the directory as would happen in ufs. This is to insure we
  * retrieve the correct block from the buffer cache since the hash value is
  * based upon the vnode address and the desired block number.
  */
 
 static int msdosfs_wfile(const char *, struct denode *, fsnode *);
 static void unix2fattime(const struct timespec *tsp, uint16_t *ddp,
     uint16_t *dtp);
 
 static void
 msdosfs_times(struct denode *dep, const struct stat *st)
 {
 	if (stampst.st_ino)
 		st = &stampst;
 
 #ifdef HAVE_STRUCT_STAT_BIRTHTIME
 	unix2fattime(&st->st_birthtim, &dep->de_CDate, &dep->de_CTime);
 #else
 	unix2fattime(&st->st_ctim, &dep->de_CDate, &dep->de_CTime);
 #endif
 	unix2fattime(&st->st_atim, &dep->de_ADate, NULL);
 	unix2fattime(&st->st_mtim, &dep->de_MDate, &dep->de_MTime);
 }
 
 static void
 unix2fattime(const struct timespec *tsp, uint16_t *ddp, uint16_t *dtp)
 {
 	time_t t1;
 	struct tm lt = {0};
 
 	t1 = tsp->tv_sec;
 	localtime_r(&t1, &lt);
 
 	unsigned long fat_time = ((lt.tm_year - 80) << 25) |
             ((lt.tm_mon + 1) << 21) |
             (lt.tm_mday << 16) |
             (lt.tm_hour << 11) |
             (lt.tm_min << 5) |
             (lt.tm_sec >> 1);
 
 	if (ddp != NULL)
 		*ddp = (uint16_t)(fat_time >> 16);
 	if (dtp != NULL)
 		*dtp = (uint16_t)fat_time;
 }
 
 /*
  * When we search a directory the blocks containing directory entries are
  * read and examined.  The directory entries contain information that would
  * normally be in the inode of a unix filesystem.  This means that some of
  * a directory's contents may also be in memory resident denodes (sort of
  * an inode).  This can cause problems if we are searching while some other
  * process is modifying a directory.  To prevent one process from accessing
  * incompletely modified directory information we depend upon being the
  * sole owner of a directory block.  bread/brelse provide this service.
  * This being the case, when a process modifies a directory it must first
  * acquire the disk block that contains the directory entry to be modified.
  * Then update the disk block and the denode, and then write the disk block
  * out to disk.	 This way disk blocks containing directory entries and in
  * memory denode's will be in synch.
  */
 static int
 msdosfs_findslot(struct denode *dp, struct componentname *cnp)
 {
 	daddr_t bn;
 	int error;
 	int slotcount;
 	int slotoffset = 0;
 	int frcn;
 	u_long cluster;
 	int blkoff;
 	u_int diroff;
 	int blsize;
 	struct msdosfsmount *pmp;
 	struct m_buf *bp = 0;
 	struct direntry *dep;
 	u_char dosfilename[12];
 	int wincnt = 1;
 	int chksum = -1, chksum_ok;
 	int olddos = 1;
 
 	pmp = dp->de_pmp;
 
 	switch (unix2dosfn((const u_char *)cnp->cn_nameptr, dosfilename,
 	    cnp->cn_namelen, 0)) {
 	case 0:
 		return (EINVAL);
 	case 1:
 		break;
 	case 2:
 		wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr,
 		    cnp->cn_namelen) + 1;
 		break;
 	case 3:
 		olddos = 0;
 		wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr,
 		    cnp->cn_namelen) + 1;
 		break;
 	}
 
 	if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME)
 		wincnt = 1;
 
 	/*
 	 * Suppress search for slots unless creating
 	 * file and at end of pathname, in which case
 	 * we watch for a place to put the new file in
 	 * case it doesn't already exist.
 	 */
 	slotcount = 0;
 	MSDOSFS_DPRINTF(("%s(): dos filename: %s\n", __func__, dosfilename));
 	/*
 	 * Search the directory pointed at by vdp for the name pointed at
 	 * by cnp->cn_nameptr.
 	 */
 	/*
 	 * The outer loop ranges over the clusters that make up the
 	 * directory.  Note that the root directory is different from all
 	 * other directories.  It has a fixed number of blocks that are not
 	 * part of the pool of allocatable clusters.  So, we treat it a
 	 * little differently. The root directory starts at "cluster" 0.
 	 */
 	diroff = 0;
 	for (frcn = 0; diroff < dp->de_FileSize; frcn++) {
 		if ((error = pcbmap(dp, frcn, &bn, &cluster, &blsize)) != 0) {
 			if (error == E2BIG)
 				break;
 			return (error);
 		}
 		error = bread((void *)pmp->pm_devvp, bn, blsize, 0, &bp);
 		if (error) {
 			return (error);
 		}
 		for (blkoff = 0; blkoff < blsize;
 		     blkoff += sizeof(struct direntry),
 		     diroff += sizeof(struct direntry)) {
 			dep = (struct direntry *)(bp->b_data + blkoff);
 			/*
 			 * If the slot is empty and we are still looking
 			 * for an empty then remember this one.	 If the
 			 * slot is not empty then check to see if it
 			 * matches what we are looking for.  If the slot
 			 * has never been filled with anything, then the
 			 * remainder of the directory has never been used,
 			 * so there is no point in searching it.
 			 */
 			if (dep->deName[0] == SLOT_EMPTY ||
 			    dep->deName[0] == SLOT_DELETED) {
 				/*
 				 * Drop memory of previous long matches
 				 */
 				chksum = -1;
 
 				if (slotcount < wincnt) {
 					slotcount++;
 					slotoffset = diroff;
 				}
 				if (dep->deName[0] == SLOT_EMPTY) {
 					brelse(bp);
 					goto notfound;
 				}
 			} else {
 				/*
 				 * If there wasn't enough space for our
 				 * winentries, forget about the empty space
 				 */
 				if (slotcount < wincnt)
 					slotcount = 0;
 
 				/*
 				 * Check for Win95 long filename entry
 				 */
 				if (dep->deAttributes == ATTR_WIN95) {
 					if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME)
 						continue;
 
 					chksum = winChkName(
 					    (const u_char *)cnp->cn_nameptr,
 					    cnp->cn_namelen,
 					    (struct winentry *)dep, chksum);
 					continue;
 				}
 
 				/*
 				 * Ignore volume labels (anywhere, not just
 				 * the root directory).
 				 */
 				if (dep->deAttributes & ATTR_VOLUME) {
 					chksum = -1;
 					continue;
 				}
 
 				/*
 				 * Check for a checksum or name match
 				 */
 				chksum_ok = (chksum == winChksum(dep->deName));
 				if (!chksum_ok
 				    && (!olddos || memcmp(dosfilename, dep->deName, 11))) {
 					chksum = -1;
 					continue;
 				}
 				MSDOSFS_DPRINTF(("%s(): match blkoff %d, diroff %u\n",
 				    __func__, blkoff, diroff));
 				/*
 				 * Remember where this directory
 				 * entry came from for whoever did
 				 * this lookup.
 				 */
 				dp->de_fndoffset = diroff;
 				dp->de_fndcnt = 0;
 
 				return EEXIST;
 			}
 		}	/* for (blkoff = 0; .... */
 		/*
 		 * Release the buffer holding the directory cluster just
 		 * searched.
 		 */
 		brelse(bp);
 	}	/* for (frcn = 0; ; frcn++) */
 
 notfound:
 	/*
 	 * We hold no disk buffers at this point.
 	 */
 
 	/*
 	 * If we get here we didn't find the entry we were looking for. But
 	 * that's ok if we are creating or renaming and are at the end of
 	 * the pathname and the directory hasn't been removed.
 	 */
 	MSDOSFS_DPRINTF(("%s(): refcnt %ld, slotcount %d, slotoffset %d\n",
 	    __func__, dp->de_refcnt, slotcount, slotoffset));
 	/*
 	 * Fixup the slot description to point to the place where
 	 * we might put the new DOS direntry (putting the Win95
 	 * long name entries before that)
 	 */
 	if (!slotcount) {
 		slotcount = 1;
 		slotoffset = diroff;
 	}
 	if (wincnt > slotcount) {
 		slotoffset += sizeof(struct direntry) * (wincnt - slotcount);
 	}
 
 	/*
 	 * Return an indication of where the new directory
 	 * entry should be put.
 	 */
 	dp->de_fndoffset = slotoffset;
 	dp->de_fndcnt = wincnt - 1;
 
 	/*
 	 * We return with the directory locked, so that
 	 * the parameters we set up above will still be
 	 * valid if we actually decide to do a direnter().
 	 * We return ni_vp == NULL to indicate that the entry
 	 * does not currently exist; we leave a pointer to
 	 * the (locked) directory inode in ndp->ni_dvp.
 	 *
 	 * NB - if the directory is unlocked, then this
 	 * information cannot be used.
 	 */
 	return 0;
 }
 
 /*
  * Create a regular file. On entry the directory to contain the file being
  * created is locked.  We must release before we return.
  */
 struct denode *
 msdosfs_mkfile(const char *path, struct denode *pdep, fsnode *node)
 {
 	struct componentname cn;
 	struct denode ndirent;
 	struct denode *dep;
 	int error;
 	struct stat *st = &node->inode->st;
 
 	cn.cn_nameptr = node->name;
 	cn.cn_namelen = strlen(node->name);
 
 	MSDOSFS_DPRINTF(("%s(name %s, mode 0%o size %zu)\n",
 	    __func__, node->name, st->st_mode, (size_t)st->st_size));
 
 	/*
 	 * If this is the root directory and there is no space left we
 	 * can't do anything.  This is because the root directory can not
 	 * change size.
 	 */
 	if (pdep->de_StartCluster == MSDOSFSROOT
 	    && pdep->de_fndoffset >= pdep->de_FileSize) {
 		error = ENOSPC;
 		goto bad;
 	}
 
 	/*
 	 * Create a directory entry for the file, then call createde() to
 	 * have it installed. NOTE: DOS files are always executable.  We
 	 * use the absence of the owner write bit to make the file
 	 * readonly.
 	 */
 	memset(&ndirent, 0, sizeof(ndirent));
 	if ((error = uniqdosname(pdep, &cn, ndirent.de_Name)) != 0)
 		goto bad;
 
 	ndirent.de_Attributes = (st->st_mode & S_IWUSR) ?
 				ATTR_ARCHIVE : ATTR_ARCHIVE | ATTR_READONLY;
 	ndirent.de_StartCluster = 0;
 	ndirent.de_FileSize = 0;
 	ndirent.de_pmp = pdep->de_pmp;
 	ndirent.de_flag = DE_ACCESS | DE_CREATE | DE_UPDATE;
 	msdosfs_times(&ndirent, &node->inode->st);
 
 	if ((error = msdosfs_findslot(pdep, &cn)) != 0)
 		goto bad;
 	if ((error = createde(&ndirent, pdep, &dep, &cn)) != 0)
 		goto bad;
 	if ((error = msdosfs_wfile(path, dep, node)) != 0)
 		goto bad;
 	return dep;
 
 bad:
 	errno = error;
 	return NULL;
 }
 static int
 msdosfs_updatede(struct denode *dep)
 {
 	struct m_buf *bp;
 	struct direntry *dirp;
 	int error;
 
 	dep->de_flag &= ~DE_MODIFIED;
 	error = m_readde(dep, &bp, &dirp);
 	if (error)
 		return error;
 	DE_EXTERNALIZE(dirp, dep);
 	error = bwrite(bp);
 	return error;
 }
 
 /*
  * Write data to a file or directory.
  */
 static int
 msdosfs_wfile(const char *path, struct denode *dep, fsnode *node)
 {
 	int error, fd;
 	size_t osize = dep->de_FileSize;
 	struct stat *st = &node->inode->st;
 	size_t nsize, offs;
 	struct msdosfsmount *pmp = dep->de_pmp;
 	struct m_buf *bp;
 	char *dat;
 	u_long cn = 0;
 
 	error = 0;	/* XXX: gcc/vax */
 	MSDOSFS_DPRINTF(("%s(diroff %lu, dirclust %lu, startcluster %lu)\n",
 	    __func__, dep->de_diroffset, dep->de_dirclust,
 	    dep->de_StartCluster));
 	if (st->st_size == 0)
 		return 0;
 
 	/* Don't bother to try to write files larger than the fs limit */
 	if (st->st_size > MSDOSFS_FILESIZE_MAX)
 		return EFBIG;
 
 	nsize = st->st_size;
 	MSDOSFS_DPRINTF(("%s(nsize=%zu, osize=%zu)\n", __func__, nsize, osize));
 	if (nsize > osize) {
 		if ((error = deextend(dep, nsize, NULL)) != 0)
 			return error;
 		if ((error = msdosfs_updatede(dep)) != 0)
 			return error;
 	}
 
 	if ((fd = open(path, O_RDONLY)) == -1) {
 		error = errno;
 		fprintf(stderr, "open %s: %s\n", path, strerror(error));
 		return error;
 	}
 
 	if ((dat = mmap(0, nsize, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0))
 	    == MAP_FAILED) {
 		error = errno;
 		fprintf(stderr, "%s: mmap %s: %s\n", __func__, node->name,
 		    strerror(error));
 		close(fd);
 		goto out;
 	}
 	close(fd);
 
 	for (offs = 0; offs < nsize;) {
 		int blsize, cpsize;
 		daddr_t bn;
 		u_long on = offs & pmp->pm_crbomask;
 
 		if ((error = pcbmap(dep, cn++, &bn, NULL, &blsize)) != 0) {
 			MSDOSFS_DPRINTF(("%s: pcbmap %lu",
 			    __func__, (unsigned long)bn));
 			goto out;
 		}
 
 		MSDOSFS_DPRINTF(("%s(cn=%lu, bn=%llu, blsize=%d)\n",
 		    __func__, cn, (unsigned long long)bn, blsize));
 		if ((error = bread((void *)pmp->pm_devvp, bn, blsize, 0,
 		    &bp)) != 0) {
 			MSDOSFS_DPRINTF(("bread %d\n", error));
 			goto out;
 		}
 		cpsize = MIN((nsize - offs), blsize - on);
 		memcpy(bp->b_data + on, dat + offs, cpsize);
 		bwrite(bp);
 		offs += cpsize;
 	}
 
 	munmap(dat, nsize);
 	return 0;
 out:
 	munmap(dat, nsize);
 	return error;
 }
 
 static const struct {
 	struct direntry dot;
 	struct direntry dotdot;
 } dosdirtemplate = {
 	{	".          ",				/* the . entry */
 		ATTR_DIRECTORY,				/* file attribute */
 		0,					/* reserved */
 		0, { 0, 0 }, { 0, 0 },			/* create time & date */
 		{ 0, 0 },				/* access date */
 		{ 0, 0 },				/* high bits of start cluster */
 		{ 210, 4 }, { 210, 4 },			/* modify time & date */
 		{ 0, 0 },				/* startcluster */
 		{ 0, 0, 0, 0 }				/* filesize */
 	},
 	{	"..         ",				/* the .. entry */
 		ATTR_DIRECTORY,				/* file attribute */
 		0,					/* reserved */
 		0, { 0, 0 }, { 0, 0 },			/* create time & date */
 		{ 0, 0 },				/* access date */
 		{ 0, 0 },				/* high bits of start cluster */
 		{ 210, 4 }, { 210, 4 },			/* modify time & date */
 		{ 0, 0 },				/* startcluster */
 		{ 0, 0, 0, 0 }				/* filesize */
 	}
 };
 
 struct denode *
 msdosfs_mkdire(const char *path, struct denode *pdep, fsnode *node) {
 	struct denode ndirent;
 	struct denode *dep;
 	struct componentname cn;
 	struct msdosfsmount *pmp = pdep->de_pmp;
 	int error;
 	u_long newcluster, pcl, bn;
 	struct direntry *denp;
 	struct m_buf *bp;
 
 	cn.cn_nameptr = node->name;
 	cn.cn_namelen = strlen(node->name);
 	/*
 	 * If this is the root directory and there is no space left we
 	 * can't do anything.  This is because the root directory can not
 	 * change size.
 	 */
 	if (pdep->de_StartCluster == MSDOSFSROOT
 	    && pdep->de_fndoffset >= pdep->de_FileSize) {
 		error = ENOSPC;
 		goto bad2;
 	}
 
 	/*
 	 * Allocate a cluster to hold the about to be created directory.
 	 */
 	error = clusteralloc(pmp, 0, 1, CLUST_EOFE, &newcluster, NULL);
 	if (error)
 		goto bad2;
 
 	memset(&ndirent, 0, sizeof(ndirent));
 	ndirent.de_pmp = pmp;
 	ndirent.de_flag = DE_ACCESS | DE_CREATE | DE_UPDATE;
 	msdosfs_times(&ndirent, &node->inode->st);
 
 	/*
 	 * Now fill the cluster with the "." and ".." entries. And write
 	 * the cluster to disk.	 This way it is there for the parent
 	 * directory to be pointing at if there were a crash.
 	 */
 	bn = cntobn(pmp, newcluster);
 	MSDOSFS_DPRINTF(("%s(newcluster %lu, bn=%lu)\n",
 	    __func__, newcluster, bn));
 	/* always succeeds */
 	bp = getblk((void *)pmp->pm_devvp, bn, pmp->pm_bpcluster, 0, 0, 0);
 	memset(bp->b_data, 0, pmp->pm_bpcluster);
 	memcpy(bp->b_data, &dosdirtemplate, sizeof dosdirtemplate);
 	denp = (struct direntry *)bp->b_data;
 	putushort(denp[0].deStartCluster, newcluster);
 	putushort(denp[0].deCDate, ndirent.de_CDate);
 	putushort(denp[0].deCTime, ndirent.de_CTime);
 	denp[0].deCHundredth = ndirent.de_CHun;
 	putushort(denp[0].deADate, ndirent.de_ADate);
 	putushort(denp[0].deMDate, ndirent.de_MDate);
 	putushort(denp[0].deMTime, ndirent.de_MTime);
 	pcl = pdep->de_StartCluster;
 	MSDOSFS_DPRINTF(("%s(pcl %lu, rootdirblk=%lu)\n", __func__, pcl,
 	    pmp->pm_rootdirblk));
 	if (FAT32(pmp) && pcl == pmp->pm_rootdirblk)
 		pcl = 0;
 	putushort(denp[1].deStartCluster, pcl);
 	putushort(denp[1].deCDate, ndirent.de_CDate);
 	putushort(denp[1].deCTime, ndirent.de_CTime);
 	denp[1].deCHundredth = ndirent.de_CHun;
 	putushort(denp[1].deADate, ndirent.de_ADate);
 	putushort(denp[1].deMDate, ndirent.de_MDate);
 	putushort(denp[1].deMTime, ndirent.de_MTime);
 	if (FAT32(pmp)) {
 		putushort(denp[0].deHighClust, newcluster >> 16);
 		putushort(denp[1].deHighClust, pdep->de_StartCluster >> 16);
 	} else {
 		putushort(denp[0].deHighClust, 0);
 		putushort(denp[1].deHighClust, 0);
 	}
 
 	if ((error = bwrite(bp)) != 0)
 		goto bad;
 
 	/*
 	 * Now build up a directory entry pointing to the newly allocated
 	 * cluster.  This will be written to an empty slot in the parent
 	 * directory.
 	 */
 	if ((error = uniqdosname(pdep, &cn, ndirent.de_Name)) != 0)
 		goto bad;
 
 	ndirent.de_Attributes = ATTR_DIRECTORY;
 	ndirent.de_StartCluster = newcluster;
 	ndirent.de_FileSize = 0;
 	ndirent.de_pmp = pdep->de_pmp;
 	if ((error = msdosfs_findslot(pdep, &cn)) != 0)
 		goto bad;
 	if ((error = createde(&ndirent, pdep, &dep, &cn)) != 0)
 		goto bad;
 	if ((error = msdosfs_updatede(dep)) != 0)
 		goto bad;
 	return dep;
 
 bad:
 	clusterfree(pmp, newcluster, NULL);
 bad2:
 	errno = error;
 	return NULL;
 }
diff --git a/usr.sbin/makefs/sys/buf.h b/usr.sbin/makefs/sys/buf.h
new file mode 100644
index 000000000000..4b640a98dd2c
--- /dev/null
+++ b/usr.sbin/makefs/sys/buf.h
@@ -0,0 +1,30 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2018-2020 Alex Richardson <arichardson@FreeBSD.org>
+ *
+ * This work was supported by Innovate UK project 105694, "Digital Security by
+ * Design (DSbD) Technology Platform Prototype".
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
+ */
+#error "<sys/buf.h> should not be included by makefs"