svn commit: r351273 - in head/usr.sbin/makefs: . msdos
Ed Maste
emaste at FreeBSD.org
Tue Aug 20 18:20:48 UTC 2019
Author: emaste
Date: Tue Aug 20 18:20:45 2019
New Revision: 351273
URL: https://svnweb.freebsd.org/changeset/base/351273
Log:
makefs: add msdosfs (FAT) support
Add FAT support to makefs by copying some files from sys/fs/msdosfs/ and
updating others with changes from NetBSD.
The six files copied from sys/fs/msdosfs at r348251 and modified are:
denode.h direntry.h fat.h msdosfs_fat.c msdosfs_lookup.c msdosfsmount.h
I would prefer to avoid the duplication, but reluctance to doing so was
expressed in a previous review (D11197); for now copy the files and
revisit in the future.
Submitted by: Siva Mahadevan
Discussed with: cem, imp
MFC after: 1 month
Relnotes: Yes
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D16438
Added:
head/usr.sbin/makefs/msdos/Makefile.inc (contents, props changed)
head/usr.sbin/makefs/msdos/denode.h
- copied, changed from r351251, head/sys/fs/msdosfs/denode.h
head/usr.sbin/makefs/msdos/direntry.h
- copied, changed from r351251, head/sys/fs/msdosfs/direntry.h
head/usr.sbin/makefs/msdos/fat.h
- copied, changed from r351251, head/sys/fs/msdosfs/fat.h
head/usr.sbin/makefs/msdos/msdosfs_conv.c (contents, props changed)
head/usr.sbin/makefs/msdos/msdosfs_fat.c
- copied, changed from r351251, head/sys/fs/msdosfs/msdosfs_fat.c
head/usr.sbin/makefs/msdos/msdosfs_lookup.c
- copied, changed from r351251, head/sys/fs/msdosfs/msdosfs_lookup.c
head/usr.sbin/makefs/msdos/msdosfsmount.h
- copied, changed from r351251, head/sys/fs/msdosfs/msdosfsmount.h
Modified:
head/usr.sbin/makefs/Makefile
head/usr.sbin/makefs/makefs.8
head/usr.sbin/makefs/makefs.c
head/usr.sbin/makefs/makefs.h
head/usr.sbin/makefs/msdos.c
head/usr.sbin/makefs/msdos.h
head/usr.sbin/makefs/msdos/msdosfs_denode.c
head/usr.sbin/makefs/msdos/msdosfs_vfsops.c
head/usr.sbin/makefs/msdos/msdosfs_vnops.c
Modified: head/usr.sbin/makefs/Makefile
==============================================================================
--- head/usr.sbin/makefs/Makefile Tue Aug 20 18:02:37 2019 (r351272)
+++ head/usr.sbin/makefs/Makefile Tue Aug 20 18:20:45 2019 (r351273)
@@ -8,8 +8,10 @@ PROG= makefs
CFLAGS+=-I${SRCDIR}
-SRCS= cd9660.c ffs.c \
+SRCS= cd9660.c \
+ ffs.c \
makefs.c \
+ msdos.c \
mtree.c \
walk.c
MAN= makefs.8
@@ -18,6 +20,7 @@ WARNS?= 2
.include "${SRCDIR}/cd9660/Makefile.inc"
.include "${SRCDIR}/ffs/Makefile.inc"
+.include "${SRCDIR}/msdos/Makefile.inc"
CFLAGS+=-DHAVE_STRUCT_STAT_ST_FLAGS=1
Modified: head/usr.sbin/makefs/makefs.8
==============================================================================
--- head/usr.sbin/makefs/makefs.8 Tue Aug 20 18:02:37 2019 (r351272)
+++ head/usr.sbin/makefs/makefs.8 Tue Aug 20 18:20:45 2019 (r351273)
@@ -35,7 +35,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 19, 2019
+.Dd August 20, 2019
.Dt MAKEFS 8
.Os
.Sh NAME
@@ -198,7 +198,9 @@ and
Instead of creating the filesystem at the beginning of the file, start
at offset.
Valid only for
-.Sy ffs .
+.Sy ffs
+and
+.Sy msdos .
.It Fl o Ar fs-options
Set file system specific options.
.Ar fs-options
@@ -232,10 +234,14 @@ and the maximum
sizes to the same value.
For
.Sy ffs
+and
+.Sy msdos
the
.Ar image-size
does not include the
.Ar offset .
+.Ar offset
+is not included in that size.
.It Fl T Ar timestamp
Specify a timestamp to be set for all filesystem files and directories
created so that repeatable builds are possible.
@@ -258,6 +264,8 @@ The following file system types are supported:
BSD fast file system (default).
.It Sy cd9660
ISO 9660 file system.
+.It Sy msdos
+FAT12, FAT16, or FAT32 file system.
.El
.It Fl x
Exclude file system nodes not explicitly listed in the specfile.
@@ -420,6 +428,67 @@ Use RockRidge extensions (for longer filenames, etc.).
Turns on verbose output.
.It Sy volumeid
Volume set identifier of the image.
+.El
+.Ss msdos-specific options
+.Sy msdos
+images have MS-DOS-specific optional parameters that may be
+provided.
+The arguments consist of a keyword, an equal sign
+.Pq Ql = ,
+and a value.
+The following keywords are supported (see
+.Xr newfs_msdos 8
+for more details):
+.Pp
+.Bl -tag -width omit-trailing-period -offset indent -compact
+.It Cm backup_sector
+Location of the backup boot sector.
+.It Cm block_size
+Block size.
+.It Cm bootstrap
+Bootstrap file.
+.It Cm bytes_per_sector
+Bytes per sector.
+.It Cm create_size
+Create file size.
+.It Cm directory_entries
+Directory entries.
+.It Cm drive_heads
+Drive heads.
+.It Cm fat_type
+FAT type (12, 16, or 32).
+.It Cm floppy
+Preset drive parameters for standard format floppy disks
+(160, 180, 320, 360, 640, 720, 1200, 1232, 1440, or 2880).
+.It Cm hidden_sectors
+Hidden sectors.
+.It Cm info_sector
+Location of the info sector.
+.It Cm media_descriptor
+Media descriptor.
+.It Cm num_FAT
+Number of FATs.
+.It Cm OEM_string
+OEM string.
+.It Cm offset
+Offset in device.
+This option will be ignored if
+.Fl O
+is set to a positive number.
+.It Cm reserved_sectors
+Reserved sectors.
+.It Cm sectors_per_cluster
+Sectors per cluster.
+.It Cm sectors_per_fat
+Sectors per FAT.
+.It Cm sectors_per_track
+Sectors per track.
+.It Cm size
+File System size.
+.It Cm volume_id
+Volume ID.
+.It Cm volume_label
+Volume Label.
.El
.Sh SEE ALSO
.Xr mtree 5 ,
Modified: head/usr.sbin/makefs/makefs.c
==============================================================================
--- head/usr.sbin/makefs/makefs.c Tue Aug 20 18:02:37 2019 (r351272)
+++ head/usr.sbin/makefs/makefs.c Tue Aug 20 18:20:45 2019 (r351273)
@@ -74,8 +74,9 @@ static fstype_t fstypes[] = {
# name, name ## _prep_opts, name ## _parse_opts, \
name ## _cleanup_opts, name ## _makefs \
}
- ENTRY(ffs),
ENTRY(cd9660),
+ ENTRY(ffs),
+ ENTRY(msdos),
{ .type = NULL },
};
Modified: head/usr.sbin/makefs/makefs.h
==============================================================================
--- head/usr.sbin/makefs/makefs.h Tue Aug 20 18:02:37 2019 (r351272)
+++ head/usr.sbin/makefs/makefs.h Tue Aug 20 18:20:45 2019 (r351273)
@@ -183,8 +183,9 @@ int fs ## _parse_opts(const char *, fsinfo_t *); \
void fs ## _cleanup_opts(fsinfo_t *); \
void fs ## _makefs(const char *, const char *, fsnode *, fsinfo_t *)
-DECLARE_FUN(ffs);
DECLARE_FUN(cd9660);
+DECLARE_FUN(ffs);
+DECLARE_FUN(msdos);
extern u_int debug;
extern int dupsok;
@@ -225,6 +226,7 @@ extern struct stat stampst;
#define DEBUG_APPLY_SPECFILE 0x04000000
#define DEBUG_APPLY_SPECENTRY 0x08000000
#define DEBUG_APPLY_SPECONLY 0x10000000
+#define DEBUG_MSDOSFS 0x20000000
#define TIMER_START(x) \
Modified: head/usr.sbin/makefs/msdos.c
==============================================================================
--- head/usr.sbin/makefs/msdos.c Tue Aug 20 18:02:37 2019 (r351272)
+++ head/usr.sbin/makefs/msdos.c Tue Aug 20 18:20:45 2019 (r351273)
@@ -50,24 +50,28 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdint.h>
#include <unistd.h>
#include <dirent.h>
#include <util.h>
-#include <ffs/buf.h>
-#include <fs/msdosfs/bpb.h>
-#include <fs/msdosfs/denode.h>
-#include <fs/msdosfs/msdosfsmount.h>
#include "makefs.h"
#include "msdos.h"
-#include "mkfs_msdos.h"
+#include <mkfs_msdos.h>
+#include <fs/msdosfs/bpb.h>
+
+#include "ffs/buf.h"
+
+#include "msdos/msdosfsmount.h"
+#include "msdos/direntry.h"
+#include "msdos/denode.h"
+
static int msdos_populate_dir(const char *, struct denode *, fsnode *,
fsnode *, fsinfo_t *);
struct msdos_options_ex {
struct msdos_options options;
- bool utf8;
};
void
@@ -85,15 +89,13 @@ msdos_prep_opts(fsinfo_t *fsopts)
(sizeof(_type) == 4 ? OPT_INT32 : OPT_INT64)))), \
.value = &msdos_opt->options._name, \
.minimum = _min, \
- .maximum = sizeof(_type) == 1 ? 0xff : \
- (sizeof(_type) == 2 ? 0xffff : \
- (sizeof(_type) == 4 ? 0xffffffff : 0xffffffffffffffffLL)), \
- .desc = _desc, \
+ .maximum = sizeof(_type) == 1 ? UINT8_MAX : \
+ (sizeof(_type) == 2 ? UINT16_MAX : \
+ (sizeof(_type) == 4 ? UINT32_MAX : INT64_MAX)), \
+ .desc = _desc, \
},
ALLOPTS
#undef AOPT
- { 'U', "utf8", &msdos_opt->utf8, OPT_BOOL,
- 0, 1, "Use UTF8 names" },
{ .name = NULL }
};
@@ -113,7 +115,6 @@ msdos_parse_opts(const char *option, fsinfo_t *fsopts)
{
struct msdos_options *msdos_opt = fsopts->fs_specific;
option_t *msdos_options = fsopts->fs_options;
-
int rv;
assert(option != NULL);
@@ -148,7 +149,7 @@ msdos_makefs(const char *image, const char *dir, fsnod
{
struct msdos_options_ex *msdos_opt = fsopts->fs_specific;
struct vnode vp, rootvp;
- struct timeval start;
+ struct timeval start;
struct msdosfsmount *pmp;
uint32_t flags;
@@ -160,7 +161,8 @@ msdos_makefs(const char *image, const char *dir, fsnod
fsopts->size = fsopts->maxsize;
msdos_opt->options.create_size = MAX(msdos_opt->options.create_size,
fsopts->offset + fsopts->size);
- msdos_opt->options.offset = fsopts->offset;
+ if (fsopts->offset > 0)
+ msdos_opt->options.offset = fsopts->offset;
if (msdos_opt->options.bytes_per_sector == 0) {
if (fsopts->sectorsize == -1)
fsopts->sectorsize = 512;
@@ -173,7 +175,7 @@ msdos_makefs(const char *image, const char *dir, fsnod
fsopts->sectorsize, msdos_opt->options.bytes_per_sector);
}
- /* create image */
+ /* create image */
printf("Creating `%s'\n", image);
TIMER_START(start);
if (mkfs_msdos(image, NULL, &msdos_opt->options) == -1)
@@ -184,10 +186,7 @@ msdos_makefs(const char *image, const char *dir, fsnod
vp.fs = fsopts;
flags = 0;
- if (msdos_opt->utf8)
- flags |= MSDOSFSMNT_UTF8;
-
- if ((pmp = msdosfs_mount(&vp, flags)) == NULL)
+ if ((pmp = msdosfs_mount(&vp)) == NULL)
err(1, "msdosfs_mount");
if (msdosfs_root(pmp, &rootvp) != 0)
@@ -197,7 +196,7 @@ msdos_makefs(const char *image, const char *dir, fsnod
printf("msdos_makefs: image %s directory %s root %p\n",
image, dir, root);
- /* populate image */
+ /* populate image */
printf("Populating `%s'\n", image);
TIMER_START(start);
if (msdos_populate_dir(dir, VTODE(&rootvp), root, root, fsopts) == -1)
@@ -207,7 +206,7 @@ msdos_makefs(const char *image, const char *dir, fsnod
if (debug & DEBUG_FS_MAKEFS)
putchar('\n');
- /* ensure no outstanding buffers remain */
+ /* ensure no outstanding buffers remain */
if (debug & DEBUG_FS_MAKEFS)
bcleanup();
Modified: head/usr.sbin/makefs/msdos.h
==============================================================================
--- head/usr.sbin/makefs/msdos.h Tue Aug 20 18:02:37 2019 (r351272)
+++ head/usr.sbin/makefs/msdos.h Tue Aug 20 18:20:45 2019 (r351273)
@@ -30,11 +30,31 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef _MAKEFS_MSDOS_H
+#define _MAKEFS_MSDOS_H
+
+#define NOCRED NULL
+
+#define MSDOSFS_DPRINTF(args) do { \
+ if (debug & DEBUG_MSDOSFS) \
+ printf args; \
+} while (0);
+
+
struct vnode;
struct denode;
+struct fsnode;
+struct msdosfsmount;
-struct msdosfsmount *msdosfs_mount(struct vnode *, int);
+struct componentname {
+ char *cn_nameptr;
+ size_t cn_namelen;
+};
+
+struct msdosfsmount *msdosfs_mount(struct vnode *);
int msdosfs_root(struct msdosfsmount *, struct vnode *);
struct denode *msdosfs_mkfile(const char *, struct denode *, fsnode *);
struct denode *msdosfs_mkdire(const char *, struct denode *, fsnode *);
+
+#endif
Added: head/usr.sbin/makefs/msdos/Makefile.inc
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/usr.sbin/makefs/msdos/Makefile.inc Tue Aug 20 18:20:45 2019 (r351273)
@@ -0,0 +1,13 @@
+# $FreeBSD$
+#
+
+MSDOS= ${SRCTOP}/sys/fs/msdosfs
+MSDOS_NEWFS= ${SRCTOP}/sbin/newfs_msdos
+
+.PATH: ${SRCDIR}/msdos ${MSDOS} ${MSDOS_NEWFS}
+
+CFLAGS+= -I${MSDOS} -I${MSDOS_NEWFS}
+
+SRCS+= mkfs_msdos.c
+SRCS+= msdosfs_conv.c msdosfs_denode.c msdosfs_fat.c msdosfs_lookup.c
+SRCS+= msdosfs_vnops.c msdosfs_vfsops.c
Copied and modified: head/usr.sbin/makefs/msdos/denode.h (from r351251, head/sys/fs/msdosfs/denode.h)
==============================================================================
--- head/sys/fs/msdosfs/denode.h Tue Aug 20 16:07:17 2019 (r351251, copy source)
+++ head/usr.sbin/makefs/msdos/denode.h Tue Aug 20 18:20:45 2019 (r351273)
@@ -161,7 +161,6 @@ struct denode {
u_long de_StartCluster; /* starting cluster of file */
u_long de_FileSize; /* size of file in bytes */
struct fatcache de_fc[FC_SIZE]; /* FAT cache */
- u_quad_t de_modrev; /* Revision level for lease. */
uint64_t de_inode; /* Inode number (really byte offset of direntry) */
};
@@ -213,60 +212,16 @@ struct denode {
((dep)->de_Attributes & ATTR_DIRECTORY) ? 0 : (dep)->de_FileSize), \
putushort((dp)->deHighClust, (dep)->de_StartCluster >> 16))
-#ifdef _KERNEL
-
#define VTODE(vp) ((struct denode *)(vp)->v_data)
#define DETOV(de) ((de)->de_vnode)
-#define DETIMES(dep, acc, mod, cre) do { \
- if ((dep)->de_flag & DE_UPDATE) { \
- (dep)->de_flag |= DE_MODIFIED; \
- timespec2fattime((mod), 0, &(dep)->de_MDate, \
- &(dep)->de_MTime, NULL); \
- (dep)->de_Attributes |= ATTR_ARCHIVE; \
- } \
- if ((dep)->de_pmp->pm_flags & MSDOSFSMNT_NOWIN95) { \
- (dep)->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS); \
- break; \
- } \
- if ((dep)->de_flag & DE_ACCESS) { \
- uint16_t adate; \
- \
- timespec2fattime((acc), 0, &adate, NULL, NULL); \
- if (adate != (dep)->de_ADate) { \
- (dep)->de_flag |= DE_MODIFIED; \
- (dep)->de_ADate = adate; \
- } \
- } \
- if ((dep)->de_flag & DE_CREATE) { \
- timespec2fattime((cre), 0, &(dep)->de_CDate, \
- &(dep)->de_CTime, &(dep)->de_CHun); \
- (dep)->de_flag |= DE_MODIFIED; \
- } \
- (dep)->de_flag &= ~(DE_UPDATE | DE_CREATE | DE_ACCESS); \
-} while (0)
+struct buf;
+struct msdosfsmount;
+struct direntry;
+struct componentname;
+struct denode;
/*
- * This overlays the fid structure (see mount.h)
- */
-struct defid {
- u_short defid_len; /* length of structure */
- u_short defid_pad; /* force long alignment */
-
- uint32_t defid_dirclust; /* cluster this dir entry came from */
- uint32_t defid_dirofs; /* offset of entry within the cluster */
-#if 0
- uint32_t defid_gen; /* generation number */
-#endif
-};
-
-extern struct vop_vector msdosfs_vnodeops;
-
-int msdosfs_lookup(struct vop_cachedlookup_args *);
-int msdosfs_inactive(struct vop_inactive_args *);
-int msdosfs_reclaim(struct vop_reclaim_args *);
-
-/*
* Internal service routine prototypes.
*/
int deget(struct msdosfsmount *, u_long, u_long, struct denode **);
@@ -274,14 +229,9 @@ int uniqdosname(struct denode *, struct componentname
int readep(struct msdosfsmount *pmp, u_long dirclu, u_long dirofs, struct buf **bpp, struct direntry **epp);
int readde(struct denode *dep, struct buf **bpp, struct direntry **epp);
-int deextend(struct denode *dep, u_long length, struct ucred *cred);
+int deextend(struct denode *dep, u_long length);
int fillinusemap(struct msdosfsmount *pmp);
-void reinsert(struct denode *dep);
-int dosdirempty(struct denode *dep);
int createde(struct denode *dep, struct denode *ddep, struct denode **depp, struct componentname *cnp);
-int deupdat(struct denode *dep, int waitfor);
int removede(struct denode *pdep, struct denode *dep);
-int detrunc(struct denode *dep, u_long length, int flags, struct ucred *cred);
-int doscheckpath( struct denode *source, struct denode *target);
-#endif /* _KERNEL */
+int detrunc(struct denode *dep, u_long length, int flags);
#endif /* !_FS_MSDOSFS_DENODE_H_ */
Copied and modified: head/usr.sbin/makefs/msdos/direntry.h (from r351251, head/sys/fs/msdosfs/direntry.h)
==============================================================================
--- head/sys/fs/msdosfs/direntry.h Tue Aug 20 16:07:17 2019 (r351251, copy source)
+++ head/usr.sbin/makefs/msdos/direntry.h Tue Aug 20 18:20:45 2019 (r351273)
@@ -135,31 +135,12 @@ struct winentry {
#define DD_YEAR_MASK 0xFE00 /* year - 1980 */
#define DD_YEAR_SHIFT 9
-#ifdef _KERNEL
-struct mbnambuf {
- size_t nb_len;
- int nb_last_id;
- char nb_buf[WIN_MAXLEN + 1];
-};
-
-struct dirent;
-struct msdosfsmount;
-
-char *mbnambuf_flush(struct mbnambuf *nbp, struct dirent *dp);
-void mbnambuf_init(struct mbnambuf *nbp);
-int mbnambuf_write(struct mbnambuf *nbp, char *name, int id);
-int dos2unixfn(u_char dn[11], u_char *un, int lower,
- struct msdosfsmount *pmp);
-int unix2dosfn(const u_char *un, u_char dn[12], size_t unlen, u_int gen,
- struct msdosfsmount *pmp);
-int unix2winfn(const u_char *un, size_t unlen, struct winentry *wep, int cnt,
- int chksum, struct msdosfsmount *pmp);
-int winChkName(struct mbnambuf *nbp, const u_char *un, size_t unlen,
- int chksum, struct msdosfsmount *pmp);
-int win2unixfn(struct mbnambuf *nbp, struct winentry *wep, int chksum,
- struct msdosfsmount *pmp);
uint8_t winChksum(uint8_t *name);
-int winSlotCnt(const u_char *un, size_t unlen, struct msdosfsmount *pmp);
-size_t winLenFixup(const u_char *un, size_t unlen);
-#endif /* _KERNEL */
+int winSlotCnt(const u_char *un, size_t unlen);
+int unix2dosfn(const u_char *un, u_char dn[12], size_t unlen, u_int gen);
+int winChkName(const u_char *un, size_t unlen, struct winentry *wep,
+ int chksum);
+int unix2winfn(const u_char *un, size_t unlen, struct winentry *wep, int cnt,
+ int chksum);
+
#endif /* !_FS_MSDOSFS_DIRENTRY_H_ */
Copied and modified: head/usr.sbin/makefs/msdos/fat.h (from r351251, head/sys/fs/msdosfs/fat.h)
==============================================================================
--- head/sys/fs/msdosfs/fat.h Tue Aug 20 16:07:17 2019 (r351251, copy source)
+++ head/usr.sbin/makefs/msdos/fat.h Tue Aug 20 18:20:45 2019 (r351273)
@@ -82,7 +82,6 @@
#define MSDOSFSEOF(pmp, cn) ((((cn) | ~(pmp)->pm_fatmask) & CLUST_EOFS) == CLUST_EOFS)
-#ifdef _KERNEL
/*
* These are the values for the function argument to the function
* fatentry().
@@ -96,6 +95,10 @@
*/
#define DE_CLEAR 1 /* Zero out the blocks allocated */
+struct buf;
+struct denode;
+struct msdosfsmount;
+
int pcbmap(struct denode *dep, u_long findcn, daddr_t *bnp, u_long *cnp, int* sp);
int clusterfree(struct msdosfsmount *pmp, u_long cn, u_long *oldcnp);
int clusteralloc(struct msdosfsmount *pmp, u_long start, u_long count, u_long fillwith, u_long *retcluster, u_long *got);
@@ -103,7 +106,5 @@ int fatentry(int function, struct msdosfsmount *pmp, u
int freeclusterchain(struct msdosfsmount *pmp, u_long startchain);
int extendfile(struct denode *dep, u_long count, struct buf **bpp, u_long *ncp, int flags);
void fc_purge(struct denode *dep, u_int frcn);
-int markvoldirty(struct msdosfsmount *pmp, int dirty);
-#endif /* _KERNEL */
#endif /* !_FS_MSDOSFS_FAT_H_ */
Added: head/usr.sbin/makefs/msdos/msdosfs_conv.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/usr.sbin/makefs/msdos/msdosfs_conv.c Tue Aug 20 18:20:45 2019 (r351273)
@@ -0,0 +1,508 @@
+/*-
+ * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
+ * Copyright (C) 1994, 1995, 1997 TooLs GmbH.
+ * All rights reserved.
+ * Original code by Paul Popelka (paulp at 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 at 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 ***
More information about the svn-src-all
mailing list