Author: emaste
Date: Tue Aug 20 18:20:45 2019
New Revision: 351273
URL: https://svnweb.freebsd.org/changeset/base/351273

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

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

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

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

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

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

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

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

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

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

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

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

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

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to