Index: usr.sbin/makefs/Makefile =================================================================== --- usr.sbin/makefs/Makefile +++ usr.sbin/makefs/Makefile @@ -8,7 +8,7 @@ CFLAGS+=-I${SRCDIR} -SRCS= cd9660.c ffs.c \ +SRCS= cd9660.c ffs.c msdos.c \ makefs.c \ mtree.c \ walk.c @@ -18,6 +18,7 @@ .include "${SRCDIR}/cd9660/Makefile.inc" .include "${SRCDIR}/ffs/Makefile.inc" +.include "${SRCDIR}/msdos/Makefile.inc" CFLAGS+=-DHAVE_STRUCT_STAT_ST_FLAGS=1 Index: usr.sbin/makefs/makefs.h =================================================================== --- usr.sbin/makefs/makefs.h +++ usr.sbin/makefs/makefs.h @@ -185,6 +185,7 @@ DECLARE_FUN(ffs); DECLARE_FUN(cd9660); +DECLARE_FUN(msdos); extern u_int debug; extern int dupsok; @@ -225,7 +226,7 @@ #define DEBUG_APPLY_SPECFILE 0x04000000 #define DEBUG_APPLY_SPECENTRY 0x08000000 #define DEBUG_APPLY_SPECONLY 0x10000000 - +#define DEBUG_MSDOSFS 0x20000000 #define TIMER_START(x) \ if (debug & DEBUG_TIME) \ Index: usr.sbin/makefs/makefs.8 =================================================================== --- usr.sbin/makefs/makefs.8 +++ usr.sbin/makefs/makefs.8 @@ -200,7 +200,9 @@ 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 @@ -229,6 +231,19 @@ Set the size of the file system image to .Ar image-size bytes. +This is equivalent of setting both the minimum +.Fl ( m ) +and the maximum +.Fl ( M ) +sizes to +.Ar image-size . +For +.Sy ffs +and +.Sy msdos +the +.Ar offset +is not included on 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. @@ -251,6 +266,8 @@ 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. @@ -411,6 +428,66 @@ .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 , .Xr mtree 8 , Index: usr.sbin/makefs/makefs.c =================================================================== --- usr.sbin/makefs/makefs.c +++ usr.sbin/makefs/makefs.c @@ -74,8 +74,9 @@ # name, name ## _prep_opts, name ## _parse_opts, \ name ## _cleanup_opts, name ## _makefs \ } - ENTRY(ffs), ENTRY(cd9660), + ENTRY(ffs), + ENTRY(msdos), { .type = NULL }, }; Index: usr.sbin/makefs/msdos.h =================================================================== --- usr.sbin/makefs/msdos.h +++ usr.sbin/makefs/msdos.h @@ -30,11 +30,39 @@ * POSSIBILITY OF SUCH DAMAGE. */ -struct vnode; +#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 denode; +struct fsnode; +struct msdosfsmount; +struct vnode; -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 *); + +struct winentry; +uint8_t winChksum(uint8_t *name); +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 Index: usr.sbin/makefs/msdos.c =================================================================== --- usr.sbin/makefs/msdos.c +++ usr.sbin/makefs/msdos.c @@ -28,20 +28,13 @@ * 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 #if defined(__RCSID) && !defined(__lint) __FBSDID("$FreeBSD$"); #endif /* !__lint */ #include - -#if !HAVE_NBTOOL_CONFIG_H #include -#endif #include #include @@ -50,30 +43,30 @@ #include #include #include +#include #include #include #include -#include +#include "makefs.h" +#include "msdos.h" + +#include #include #include +#include #include -#include "makefs.h" -#include "msdos.h" -#include "mkfs_msdos.h" + +#include "ffs/buf.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 msdos_prep_opts(fsinfo_t *fsopts) { - struct msdos_options_ex *msdos_opt = ecalloc(1, sizeof(*msdos_opt)); + struct msdos_options *msdos_opt = ecalloc(1, sizeof(*msdos_opt)); const option_t msdos_options[] = { #define AOPT(_opt, _type, _name, _min, _desc) { \ .letter = _opt, \ @@ -83,17 +76,15 @@ (sizeof(_type) == 1 ? OPT_INT8 : \ (sizeof(_type) == 2 ? OPT_INT16 : \ (sizeof(_type) == 4 ? OPT_INT32 : OPT_INT64)))), \ - .value = &msdos_opt->options._name, \ + .value = &msdos_opt->_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 +104,6 @@ { struct msdos_options *msdos_opt = fsopts->fs_specific; option_t *msdos_options = fsopts->fs_options; - int rv; assert(option != NULL); @@ -121,7 +111,7 @@ assert(msdos_opt != NULL); if (debug & DEBUG_FS_PARSE_OPTS) - printf("msdos_parse_opts: got `%s'\n", option); + printf("msdos_parse_opts: got '%s'\n", option); rv = set_option(msdos_options, option, NULL, 0); if (rv == -1) @@ -146,9 +136,9 @@ void msdos_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts) { - struct msdos_options_ex *msdos_opt = fsopts->fs_specific; + struct msdos_options *msdos_opt = fsopts->fs_specific; struct vnode vp, rootvp; - struct timeval start; + struct timeval start; struct msdosfsmount *pmp; uint32_t flags; @@ -158,25 +148,26 @@ assert(fsopts != NULL); fsopts->size = fsopts->maxsize; - msdos_opt->options.create_size = MAX(msdos_opt->options.create_size, + msdos_opt->create_size = MAX(msdos_opt->create_size, fsopts->offset + fsopts->size); - msdos_opt->options.offset = fsopts->offset; - if (msdos_opt->options.bytes_per_sector == 0) { + if (fsopts->offset > 0) + msdos_opt->offset = fsopts->offset; + if (msdos_opt->bytes_per_sector == 0) { if (fsopts->sectorsize == -1) fsopts->sectorsize = 512; - msdos_opt->options.bytes_per_sector = fsopts->sectorsize; + msdos_opt->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) { + fsopts->sectorsize = msdos_opt->bytes_per_sector; + } else if (fsopts->sectorsize != msdos_opt->bytes_per_sector) { err(1, "inconsistent sectorsize -S %u" "!= -o bytes_per_sector %u", - fsopts->sectorsize, msdos_opt->options.bytes_per_sector); + fsopts->sectorsize, msdos_opt->bytes_per_sector); } - /* create image */ - printf("Creating `%s'\n", image); + /* create image */ + printf("Creating '%s'\n", image); TIMER_START(start); - if (mkfs_msdos(image, NULL, &msdos_opt->options) == -1) + if (mkfs_msdos(image, NULL, msdos_opt) == -1) return; TIMER_RESULTS(start, "mkfs_msdos"); @@ -184,10 +175,7 @@ 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,21 +185,21 @@ printf("msdos_makefs: image %s directory %s root %p\n", image, dir, root); - /* populate image */ - printf("Populating `%s'\n", image); + /* 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); + errx(1, "Image file '%s' not created.", image); TIMER_RESULTS(start, "msdos_populate_dir"); if (debug & DEBUG_FS_MAKEFS) putchar('\n'); - /* ensure no outstanding buffers remain */ + /* ensure no outstanding buffers remain */ if (debug & DEBUG_FS_MAKEFS) bcleanup(); - printf("Image `%s' complete\n", image); + printf("Image '%s' complete\n", image); } static int Index: usr.sbin/makefs/msdos/Makefile.inc =================================================================== --- /dev/null +++ usr.sbin/makefs/msdos/Makefile.inc @@ -0,0 +1,13 @@ +# $NetBSD: Makefile.inc,v 1.7 2016/02/06 10:40:58 mlelstv Exp $ +# + +MSDOS= ${SRCTOP}/sys/fs/msdosfs +MSDOS_NEWFS= ${SRCTOP}/sbin/newfs_msdos + +.PATH: ${SRCDIR}/msdos ${MSDOS_NEWFS} + +CFLAGS+= -I${MSDOS} -I${MSDOS_NEWFS} -DMAKEFS + +SRCS+= msdosfs_denode.c msdosfs_vnops.c msdosfs_vfsops.c msdosfs_conv.c +SRCS+= msdosfs_fat.c msdosfs_lookup.c +SRCS+= mkfs_msdos.c Index: usr.sbin/makefs/msdos/msdosfs_conv.c =================================================================== --- /dev/null +++ usr.sbin/makefs/msdos/msdosfs_conv.c @@ -0,0 +1,507 @@ +/*- + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "makefs.h" +#include "msdos.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; + + while (n > 0) { + u1 = le16toh(*w1); + u2 = le16toh(*w2); + if (u1 == 0 || u2 == 0) + return u1 == u2; + if (u1 > 255 || u2 > 255) + return 0; + u1 = u2l[u1 & 0xff]; + u2 = u2l[u2 & 0xff]; + if (u1 != u2) + return 0; + ++w1; + ++w2; + --n; + } + + return 1; +} Index: usr.sbin/makefs/msdos/msdosfs_denode.c =================================================================== --- usr.sbin/makefs/msdos/msdosfs_denode.c +++ usr.sbin/makefs/msdos/msdosfs_denode.c @@ -47,24 +47,28 @@ * October 1992 */ -#if HAVE_NBTOOL_CONFIG_H -#include "nbtool_config.h" -#endif - #include __FBSDID("$FreeBSD$"); #include +#include +#include -#include +#include +#include +#include +#include #include -#include -#include #include +#include #include +#include -#include +#include "makefs.h" +#include "msdos.h" + +#include "ffs/buf.h" /* * If deget() succeeds it returns with the gotten denode locked(). @@ -81,20 +85,15 @@ int deget(struct msdosfsmount *pmp, u_long dirclust, u_long diroffset, struct denode **depp) - /* pmp: so we know the maj/min number */ - /* dirclust: cluster this dir entry came from */ - /* diroffset: index of entry within the cluster */ - /* depp: returns the addr of the gotten denode */ { int error; + uint64_t inode; struct direntry *direntptr; struct denode *ldep; struct buf *bp; -#ifdef MSDOSFS_DEBUG - printf("deget(pmp %p, dirclust %lu, diroffset %lx, depp %p)\n", - pmp, dirclust, diroffset, depp); -#endif + 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 @@ -103,18 +102,17 @@ 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_devvp = 0; - ldep->de_lockf = 0; - ldep->de_dev = pmp->pm_dev; ldep->de_dirclust = dirclust; ldep->de_diroffset = diroffset; + ldep->de_inode = inode; ldep->de_pmp = pmp; - ldep->de_devvp = pmp->pm_devvp; ldep->de_refcnt = 1; - fc_purge(ldep, 0); + fc_purge(ldep, 0); /* init the FAT cache for this denode */ /* * Copy the directory entry into the denode area of the vnode. */ @@ -131,12 +129,13 @@ 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 * pmp->pm_BytesPerSec; + ldep->de_FileSize = pmp->pm_rootdirsize * DEV_BSIZE; } /* * fill in time and date so that dos2unixtime() doesn't @@ -155,11 +154,12 @@ } else { error = readep(pmp, dirclust, diroffset, &bp, &direntptr); if (error) { - ldep->de_devvp = NULL; ldep->de_Name[0] = SLOT_DELETED; + + *depp = NULL; return (error); } - DE_INTERNALIZE(ldep, direntptr); + (void)DE_INTERNALIZE(ldep, direntptr); brelse(bp); } @@ -176,13 +176,27 @@ */ 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, CLUST_END, 0, &size, 0); + error = pcbmap(ldep, 0xffff, 0, &size, 0); if (error == E2BIG) { ldep->de_FileSize = de_cn2off(pmp, size); error = 0; - } else - printf("deget(): pcbmap returned %d\n", error); + } else { + MSDOSFS_DPRINTF(("deget(): pcbmap returned %d\n", + error)); + } } } *depp = ldep; @@ -193,21 +207,20 @@ * Truncate the file described by dep to the length specified by length. */ int -detrunc(struct denode *dep, u_long length, int flags, struct kauth_cred *cred) +detrunc(struct denode *dep, u_long length, int flags, struct ucred *cred) { int error; - int allerror = 0; + int allerror; u_long eofentry; - u_long chaintofree = 0; - daddr_t bn, lastblock; + u_long chaintofree; + daddr_t bn; int boff; int isadir = dep->de_Attributes & ATTR_DIRECTORY; struct buf *bp; struct msdosfsmount *pmp = dep->de_pmp; -#ifdef MSDOSFS_DEBUG - printf("detrunc(): file %s, length %lu, flags %x\n", dep->de_Name, length, flags); -#endif + 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 @@ -218,14 +231,15 @@ * directory's life. */ if (dep->de_vnode != NULL && !FAT32(pmp)) { - printf("detrunc(): can't truncate root directory, clust %ld, offset %ld\n", - dep->de_dirclust, dep->de_diroffset); + 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)); - lastblock = de_clcount(pmp, length) - 1; + return deextend(dep, length, cred); /* * If the desired length is 0 then remember the starting cluster of @@ -241,15 +255,17 @@ dep->de_StartCluster = 0; eofentry = ~0; } else { - error = pcbmap(dep, lastblock, 0, &eofentry, 0); + error = pcbmap(dep, de_clcount(pmp, length) - 1, 0, + &eofentry, 0); if (error) { -#ifdef MSDOSFS_DEBUG - printf("detrunc(): pcbmap fails %d\n", error); -#endif - return (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 @@ -258,13 +274,14 @@ if ((boff = length & pmp->pm_crbomask) != 0) { if (isadir) { bn = cntobn(pmp, eofentry); - error = bread(pmp->pm_devvp, de_bn2kb(pmp, bn), - pmp->pm_bpcluster, B_MODIFY, &bp); + error = bread(pmp->pm_devvp, bn, pmp->pm_bpcluster, + 0, &bp); if (error) { -#ifdef MSDOSFS_DEBUG - printf("detrunc(): bread fails %d\n", error); -#endif - return (error); + brelse(bp); + MSDOSFS_DPRINTF(("detrunc(): bread fails %d\n", + error)); + + return error; } memset((char *)bp->b_data + boff, 0, pmp->pm_bpcluster - boff); @@ -282,41 +299,40 @@ dep->de_FileSize = length; if (!isadir) dep->de_flag |= DE_UPDATE|DE_MODIFIED; -#ifdef MSDOSFS_DEBUG - printf("detrunc(): allerror %d, eofentry %lu\n", - allerror, eofentry); -#endif + 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 != (u_long)~0) { + if (eofentry != ~0) { error = fatentry(FAT_GET_AND_SET, pmp, eofentry, &chaintofree, CLUST_EOFE); if (error) { -#ifdef MSDOSFS_DEBUG - printf("detrunc(): fatentry errors %d\n", error); -#endif + 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(chaintofree, pmp->pm_fatmask)) + if (chaintofree != 0 && !MSDOSFSEOF(pmp, chaintofree)) freeclusterchain(pmp, chaintofree); - return (allerror); + return allerror; } /* * Extend the file described by dep to length specified by length. */ int -deextend(struct denode *dep, u_long length, struct kauth_cred *cred) +deextend(struct denode *dep, u_long length, struct ucred *cred) { struct msdosfsmount *pmp = dep->de_pmp; u_long count; @@ -358,6 +374,6 @@ * is zero'd later. */ dep->de_FileSize = length; - dep->de_flag |= DE_UPDATE|DE_MODIFIED; + dep->de_flag |= DE_UPDATE | DE_MODIFIED; return 0; } Index: usr.sbin/makefs/msdos/msdosfs_fat.c =================================================================== --- usr.sbin/makefs/msdos/msdosfs_fat.c +++ usr.sbin/makefs/msdos/msdosfs_fat.c @@ -51,18 +51,26 @@ */ #include -#include -#include -#include -#include +#include + +#include +#include +#include +#include #include -#include #include +#include #include #include -#define FULL_RUN ((u_int)0xffffffff) +#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, @@ -92,7 +100,7 @@ u_long bn, size; bn = ofs / pmp->pm_fatblocksize * pmp->pm_fatblocksec; - size = min(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn) + size = MIN(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn) * DEV_BSIZE; bn += pmp->pm_fatblk + pmp->pm_curfat * pmp->pm_FATsecs; @@ -138,9 +146,7 @@ struct msdosfsmount *pmp = dep->de_pmp; u_long bsize; - KASSERT(bnp != NULL || cnp != NULL || sp != NULL, - ("pcbmap: extra call")); - ASSERT_VOP_ELOCKED(DETOV(dep), "pcbmap"); + assert(bnp != NULL || cnp != NULL || sp != NULL); cn = dep->de_StartCluster; /* @@ -161,7 +167,7 @@ if (cnp) *cnp = MSDOSFSROOT; if (sp) - *sp = min(pmp->pm_bpcluster, + *sp = MIN(pmp->pm_bpcluster, dep->de_FileSize - de_cn2off(pmp, findcn)); return (0); } else { /* just an empty file */ @@ -262,8 +268,6 @@ u_long cn; struct fatcache *closest = NULL; - ASSERT_VOP_LOCKED(DETOV(dep), "fc_lookup"); - for (i = 0; i < FC_SIZE; i++) { cn = dep->de_fc[i].fc_frcn; if (cn != FCE_EMPTY && cn <= findcn) { @@ -287,8 +291,6 @@ int i; struct fatcache *fcp; - ASSERT_VOP_ELOCKED(DETOV(dep), "fc_purge"); - fcp = dep->de_fc; for (i = 0; i < FC_SIZE; i++, fcp++) { if (fcp->fc_frcn >= frcn) @@ -343,7 +345,7 @@ ((uint8_t *)bpn->b_data)[3] |= 0x80; else if (cleanfat == 32) ((uint8_t *)bpn->b_data)[7] |= 0x08; - if (pmp->pm_mountp->mnt_flag & MNT_SYNCHRONOUS) + if (SYNCHRONOUS_WRITES(pmp)) bwrite(bpn); else bdwrite(bpn); @@ -353,7 +355,7 @@ /* * Write out the first (or current) FAT last. */ - if (pmp->pm_mountp->mnt_flag & MNT_SYNCHRONOUS) + if (SYNCHRONOUS_WRITES(pmp)) bwrite(bp); else bdwrite(bp); @@ -382,17 +384,13 @@ usemap_alloc(struct msdosfsmount *pmp, u_long cn) { - MSDOSFS_ASSERT_MP_LOCKED(pmp); + 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); - KASSERT(cn <= pmp->pm_maxcluster, ("cn too large %lu %lu", cn, - pmp->pm_maxcluster)); - KASSERT((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0, - ("usemap_alloc on ro msdosfs mount")); - KASSERT((pmp->pm_inusemap[cn / N_INUSEBITS] & (1 << (cn % N_INUSEBITS))) - == 0, ("Allocating used sector %ld %ld %x", cn, cn % N_INUSEBITS, - (unsigned)pmp->pm_inusemap[cn / N_INUSEBITS])); pmp->pm_inusemap[cn / N_INUSEBITS] |= 1 << (cn % N_INUSEBITS); - KASSERT(pmp->pm_freeclustercount > 0, ("usemap_alloc: too little")); pmp->pm_freeclustercount--; pmp->pm_flags |= MSDOSFS_FSIMOD; } @@ -401,17 +399,13 @@ usemap_free(struct msdosfsmount *pmp, u_long cn) { - MSDOSFS_ASSERT_MP_LOCKED(pmp); + assert(cn <= pmp->pm_maxcluster); + assert((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0); + assert((pmp->pm_inusemap[cn / N_INUSEBITS] & + (1 << (cn % N_INUSEBITS))) != 0); - KASSERT(cn <= pmp->pm_maxcluster, ("cn too large %lu %lu", cn, - pmp->pm_maxcluster)); - KASSERT((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0, - ("usemap_free on ro msdosfs mount")); pmp->pm_freeclustercount++; pmp->pm_flags |= MSDOSFS_FSIMOD; - KASSERT((pmp->pm_inusemap[cn / N_INUSEBITS] & (1 << (cn % N_INUSEBITS))) - != 0, ("Freeing unused sector %ld %ld %x", cn, cn % N_INUSEBITS, - (unsigned)pmp->pm_inusemap[cn / N_INUSEBITS])); pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1 << (cn % N_INUSEBITS)); } @@ -429,9 +423,7 @@ * the count of free clusters, and turn off the "allocated" * bit in the "in use" cluster bit map. */ - MSDOSFS_LOCK_MP(pmp); usemap_free(pmp, cluster); - MSDOSFS_UNLOCK_MP(pmp); if (oldcnp) *oldcnp = oldcn; return (0); @@ -642,8 +634,6 @@ u_int map; u_long len; - MSDOSFS_ASSERT_MP_LOCKED(pmp); - if (start > pmp->pm_maxcluster) return (0); max_idx = pmp->pm_maxcluster / N_INUSEBITS; @@ -699,9 +689,7 @@ int error; u_long cl, n; - MSDOSFS_ASSERT_MP_LOCKED(pmp); - KASSERT((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0, - ("chainalloc on ro msdosfs mount")); + assert((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0); for (cl = start, n = count; n-- > 0;) usemap_alloc(pmp, cl++); @@ -743,9 +731,7 @@ { int error; - MSDOSFS_LOCK_MP(pmp); error = clusteralloc1(pmp, start, count, fillwith, retcluster, got); - MSDOSFS_UNLOCK_MP(pmp); return (error); } @@ -758,11 +744,8 @@ u_long foundcn = 0; /* XXX: foundcn could be used unititialized */ u_int map; - MSDOSFS_ASSERT_MP_LOCKED(pmp); + MSDOSFS_DPRINTF(("clusteralloc(): find %lu clusters\n", count)); -#ifdef MSDOSFS_DEBUG - printf("clusteralloc(): find %lu clusters\n", count); -#endif if (start) { if ((len = chainlength(pmp, start, count)) >= count) return (chainalloc(pmp, start, count, fillwith, retcluster, got)); @@ -833,7 +816,6 @@ u_long bn, bo, bsize, byteoffset; u_long readcn, lbn = -1; - MSDOSFS_LOCK_MP(pmp); while (cluster >= CLUST_FIRST && cluster <= pmp->pm_maxcluster) { byteoffset = FATOFS(pmp, cluster); fatblock(pmp, byteoffset, &bn, &bsize, &bo); @@ -843,7 +825,6 @@ error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp); if (error) { brelse(bp); - MSDOSFS_UNLOCK_MP(pmp); return (error); } lbn = bn; @@ -879,7 +860,6 @@ } if (bp) updatefats(pmp, bp, bn); - MSDOSFS_UNLOCK_MP(pmp); return (0); } @@ -894,9 +874,7 @@ u_long bn, bo, bsize, byteoffset, cn, readcn; int error; - MSDOSFS_ASSERT_MP_LOCKED(pmp); bp = NULL; - /* * Mark all clusters in use, we mark the free ones in the FAT scan * loop further down. @@ -979,7 +957,6 @@ u_long cn, got; struct msdosfsmount *pmp = dep->de_pmp; struct buf *bp; - daddr_t blkno; /* * Don't try to extend the root directory @@ -1057,117 +1034,22 @@ */ fc_setcache(dep, FC_LASTFC, frcn + got - 1, cn + got - 1); - if (flags & DE_CLEAR) { + if ((flags & DE_CLEAR) && + (dep->de_Attributes & ATTR_DIRECTORY)) { while (got-- > 0) { - /* - * Get the buf header for the new block of the file. - */ - if (dep->de_Attributes & ATTR_DIRECTORY) - bp = getblk(pmp->pm_devvp, - cntobn(pmp, cn++), - pmp->pm_bpcluster, 0, 0, 0); - else { - bp = getblk(DETOV(dep), - frcn++, - pmp->pm_bpcluster, 0, 0, 0); - /* - * Do the bmap now, as in msdosfs_write - */ - if (pcbmap(dep, - bp->b_lblkno, - &blkno, 0, 0)) - bp->b_blkno = -1; - if (bp->b_blkno == -1) - panic("extendfile: pcbmap"); - else - bp->b_blkno = blkno; - } + bp = getblk(pmp->pm_devvp, + cntobn(pmp, cn++), + pmp->pm_bpcluster, 0, 0, 0); clrbuf(bp); if (bpp) { *bpp = bp; bpp = NULL; - } else + } else { bdwrite(bp); + } } } } return (0); } - -/*- - * Routine to mark a FAT16 or FAT32 volume as "clean" or "dirty" by - * manipulating the upper bit of the FAT entry for cluster 1. Note that - * this bit is not defined for FAT12 volumes, which are always assumed to - * be clean. - * - * The fatentry() routine only works on cluster numbers that a file could - * occupy, so it won't manipulate the entry for cluster 1. So we have to do - * it here. The code was stolen from fatentry() and tailored for cluster 1. - * - * Inputs: - * pmp The MS-DOS volume to mark - * dirty Non-zero if the volume should be marked dirty; zero if it - * should be marked clean - * - * Result: - * 0 Success - * EROFS Volume is read-only - * ? (other errors from called routines) - */ -int -markvoldirty(struct msdosfsmount *pmp, int dirty) -{ - struct buf *bp; - u_long bn, bo, bsize, byteoffset, fatval; - int error; - - /* - * FAT12 does not support a "clean" bit, so don't do anything for - * FAT12. - */ - if (FAT12(pmp)) - return (0); - - /* Can't change the bit on a read-only filesystem. */ - if (pmp->pm_flags & MSDOSFSMNT_RONLY) - return (EROFS); - - /* - * Fetch the block containing the FAT entry. It is given by the - * pseudo-cluster 1. - */ - byteoffset = FATOFS(pmp, 1); - fatblock(pmp, byteoffset, &bn, &bsize, &bo); - error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (error); - } - - /* - * Get the current value of the FAT entry and set/clear the relevant - * bit. Dirty means clear the "clean" bit; clean means set the - * "clean" bit. - */ - if (FAT32(pmp)) { - /* FAT32 uses bit 27. */ - fatval = getulong(&bp->b_data[bo]); - if (dirty) - fatval &= 0xF7FFFFFF; - else - fatval |= 0x08000000; - putulong(&bp->b_data[bo], fatval); - } else { - /* Must be FAT16; use bit 15. */ - fatval = getushort(&bp->b_data[bo]); - if (dirty) - fatval &= 0x7FFF; - else - fatval |= 0x8000; - putushort(&bp->b_data[bo], fatval); - } - - /* Write out the modified FAT block synchronously. */ - return (bwrite(bp)); -} Index: usr.sbin/makefs/msdos/msdosfs_lookup.c =================================================================== --- usr.sbin/makefs/msdos/msdosfs_lookup.c +++ usr.sbin/makefs/msdos/msdosfs_lookup.c @@ -51,540 +51,21 @@ */ #include -#include -#include -#include -#include -#include +#include + +#include +#include #include -#include #include +#include #include #include -static int msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp, - struct componentname *cnp, uint64_t *inum); - -int -msdosfs_lookup(struct vop_cachedlookup_args *ap) -{ - - return (msdosfs_lookup_(ap->a_dvp, ap->a_vpp, ap->a_cnp, NULL)); -} +#include "ffs/buf.h" -struct deget_dotdot { - u_long cluster; - int blkoff; -}; - -static int -msdosfs_deget_dotdot(struct mount *mp, void *arg, int lkflags, - struct vnode **rvp) -{ - struct deget_dotdot *dd_arg; - struct denode *rdp; - struct msdosfsmount *pmp; - int error; - - pmp = VFSTOMSDOSFS(mp); - dd_arg = arg; - error = deget(pmp, dd_arg->cluster, dd_arg->blkoff, &rdp); - if (error == 0) - *rvp = DETOV(rdp); - return (error); -} - -/* - * 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_lookup_(struct vnode *vdp, struct vnode **vpp, - struct componentname *cnp, uint64_t *dd_inum) -{ - struct mbnambuf nb; - daddr_t bn; - int error; - int slotcount; - int slotoffset = 0; - int frcn; - u_long cluster; - int blkoff; - int diroff; - int blsize; - int isadir; /* ~0 if found direntry is a directory */ - u_long scn; /* starting cluster number */ - struct vnode *pdp; - struct denode *dp; - struct denode *tdp; - struct msdosfsmount *pmp; - struct buf *bp = NULL; - struct direntry *dep = NULL; - struct deget_dotdot dd_arg; - u_char dosfilename[12]; - int flags = cnp->cn_flags; - int nameiop = cnp->cn_nameiop; - int unlen; - uint64_t inode1; - - int wincnt = 1; - int chksum = -1, chksum_ok; - int olddos = 1; - -#ifdef MSDOSFS_DEBUG - printf("msdosfs_lookup(): looking for %s\n", cnp->cn_nameptr); -#endif - dp = VTODE(vdp); - pmp = dp->de_pmp; -#ifdef MSDOSFS_DEBUG - printf("msdosfs_lookup(): vdp %p, dp %p, Attr %02x\n", - vdp, dp, dp->de_Attributes); -#endif - - restart: - if (vpp != NULL) - *vpp = NULL; - /* - * If they are going after the . or .. entry in the root directory, - * they won't find it. DOS filesystems don't have them in the root - * directory. So, we fake it. deget() is in on this scam too. - */ - if ((vdp->v_vflag & VV_ROOT) && cnp->cn_nameptr[0] == '.' && - (cnp->cn_namelen == 1 || - (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.'))) { - isadir = ATTR_DIRECTORY; - scn = MSDOSFSROOT; -#ifdef MSDOSFS_DEBUG - printf("msdosfs_lookup(): looking for . or .. in root directory\n"); -#endif - cluster = MSDOSFSROOT; - blkoff = MSDOSFSROOT_OFS; - goto foundroot; - } - - switch (unix2dosfn((const u_char *)cnp->cn_nameptr, dosfilename, - cnp->cn_namelen, 0, pmp)) { - case 0: - return (EINVAL); - case 1: - break; - case 2: - wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, - cnp->cn_namelen, pmp) + 1; - break; - case 3: - olddos = 0; - wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, - cnp->cn_namelen, pmp) + 1; - break; - } - if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) { - wincnt = 1; - olddos = 1; - } - unlen = winLenFixup(cnp->cn_nameptr, cnp->cn_namelen); - - /* - * 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 = wincnt; - if ((nameiop == CREATE || nameiop == RENAME) && - (flags & ISLASTCN)) - slotcount = 0; - -#ifdef MSDOSFS_DEBUG - printf("msdosfs_lookup(): dos version of filename %s, length %ld\n", - dosfilename, cnp->cn_namelen); -#endif - /* - * Search the directory pointed at by vdp for the name pointed at - * by cnp->cn_nameptr. - */ - tdp = NULL; - mbnambuf_init(&nb); - /* - * 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;; frcn++) { - error = pcbmap(dp, frcn, &bn, &cluster, &blsize); - if (error) { - if (error == E2BIG) - break; - return (error); - } - error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp); - if (error) { - brelse(bp); - 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; - mbnambuf_init(&nb); - - 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 = win2unixfn(&nb, - (struct winentry *)dep, chksum, - pmp); - continue; - } - - chksum = winChkName(&nb, - (const u_char *)cnp->cn_nameptr, unlen, - chksum, pmp); - if (chksum == -2) { - chksum = -1; - 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 || bcmp(dosfilename, dep->deName, 11))) { - chksum = -1; - continue; - } -#ifdef MSDOSFS_DEBUG - printf("msdosfs_lookup(): match blkoff %d, diroff %d\n", - blkoff, diroff); -#endif - /* - * Remember where this directory - * entry came from for whoever did - * this lookup. - */ - dp->de_fndoffset = diroff; - if (chksum_ok && nameiop == RENAME) { - /* - * Target had correct long name - * directory entries, reuse them - * as needed. - */ - dp->de_fndcnt = wincnt - 1; - } else { - /* - * Long name directory entries - * not present or corrupt, can only - * reuse dos directory entry. - */ - dp->de_fndcnt = 0; - } - - goto found; - } - } /* 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. - */ - - /* - * 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); - - /* - * 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. - */ -#ifdef MSDOSFS_DEBUG - printf("msdosfs_lookup(): op %d, refcnt %ld\n", - nameiop, dp->de_refcnt); - printf(" slotcount %d, slotoffset %d\n", - slotcount, slotoffset); -#endif - if ((nameiop == CREATE || nameiop == RENAME) && - (flags & ISLASTCN) && dp->de_refcnt != 0) { - /* - * Access for write is interpreted as allowing - * creation of files in the directory. - */ - error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred, cnp->cn_thread); - if (error) - return (error); - /* - * 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. - * The pathname buffer is saved so that the name - * can be obtained later. - * - * NB - if the directory is unlocked, then this - * information cannot be used. - */ - cnp->cn_flags |= SAVENAME; - return (EJUSTRETURN); - } -#if 0 - /* - * Insert name into cache (as non-existent) if appropriate. - * - * XXX Negative caching is broken for msdosfs because the name - * cache doesn't understand peculiarities such as case insensitivity - * and 8.3 filenames. Hence, it may not invalidate all negative - * entries if a file with this name is later created. - */ - if ((cnp->cn_flags & MAKEENTRY) != 0) - cache_enter(vdp, *vpp, cnp); -#endif - return (ENOENT); - -found: - /* - * NOTE: We still have the buffer with matched directory entry at - * this point. - */ - isadir = dep->deAttributes & ATTR_DIRECTORY; - scn = getushort(dep->deStartCluster); - if (FAT32(pmp)) { - scn |= getushort(dep->deHighClust) << 16; - if (scn == pmp->pm_rootdirblk) { - /* - * There should actually be 0 here. - * Just ignore the error. - */ - scn = MSDOSFSROOT; - } - } - - if (isadir) { - cluster = scn; - if (cluster == MSDOSFSROOT) - blkoff = MSDOSFSROOT_OFS; - else - blkoff = 0; - } else if (cluster == MSDOSFSROOT) - blkoff = diroff; - - /* - * Now release buf to allow deget to read the entry again. - * Reserving it here and giving it to deget could result - * in a deadlock. - */ - brelse(bp); - bp = NULL; - -foundroot: - /* - * If we entered at foundroot, then we are looking for the . or .. - * entry of the filesystems root directory. isadir and scn were - * setup before jumping here. And, bp is already null. - */ - if (FAT32(pmp) && scn == MSDOSFSROOT) - scn = pmp->pm_rootdirblk; - - if (dd_inum != NULL) { - *dd_inum = (uint64_t)pmp->pm_bpcluster * scn + blkoff; - return (0); - } - - /* - * If deleting, and at end of pathname, return - * parameters which can be used to remove file. - */ - if (nameiop == DELETE && (flags & ISLASTCN)) { - /* - * Don't allow deleting the root. - */ - if (blkoff == MSDOSFSROOT_OFS) - return (EBUSY); - - /* - * Write access to directory required to delete files. - */ - error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred, cnp->cn_thread); - if (error) - return (error); - - /* - * Return pointer to current entry in dp->i_offset. - * Save directory inode pointer in ndp->ni_dvp for dirremove(). - */ - if (dp->de_StartCluster == scn && isadir) { /* "." */ - VREF(vdp); - *vpp = vdp; - return (0); - } - error = deget(pmp, cluster, blkoff, &tdp); - if (error) - return (error); - *vpp = DETOV(tdp); - return (0); - } - - /* - * If rewriting (RENAME), return the inode and the - * information required to rewrite the present directory - * Must get inode of directory entry to verify it's a - * regular file, or empty directory. - */ - if (nameiop == RENAME && (flags & ISLASTCN)) { - if (blkoff == MSDOSFSROOT_OFS) - return (EBUSY); - - error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred, cnp->cn_thread); - if (error) - return (error); - - /* - * Careful about locking second inode. - * This can only occur if the target is ".". - */ - if (dp->de_StartCluster == scn && isadir) - return (EISDIR); - - if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0) - return (error); - *vpp = DETOV(tdp); - cnp->cn_flags |= SAVENAME; - return (0); - } - - /* - * Step through the translation in the name. We do not `vput' the - * directory because we may need it again if a symbolic link - * is relative to the current directory. Instead we save it - * unlocked as "pdp". We must get the target inode before unlocking - * the directory to insure that the inode will not be removed - * before we get it. We prevent deadlock by always fetching - * inodes from the root, moving down the directory tree. Thus - * when following backward pointers ".." we must unlock the - * parent directory before getting the requested directory. - */ - pdp = vdp; - if (flags & ISDOTDOT) { - dd_arg.cluster = cluster; - dd_arg.blkoff = blkoff; - error = vn_vget_ino_gen(vdp, msdosfs_deget_dotdot, - &dd_arg, cnp->cn_lkflags, vpp); - if (error != 0) { - *vpp = NULL; - return (error); - } - /* - * Recheck that ".." still points to the inode we - * looked up before pdp lock was dropped. - */ - error = msdosfs_lookup_(pdp, NULL, cnp, &inode1); - if (error) { - vput(*vpp); - *vpp = NULL; - return (error); - } - if (VTODE(*vpp)->de_inode != inode1) { - vput(*vpp); - goto restart; - } - } else if (dp->de_StartCluster == scn && isadir) { - VREF(vdp); /* we want ourself, ie "." */ - *vpp = vdp; - } else { - if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0) - return (error); - *vpp = DETOV(tdp); - } - - /* - * Insert name into cache if appropriate. - */ - if (cnp->cn_flags & MAKEENTRY) - cache_enter(vdp, *vpp, cnp); - return (0); -} +#include "makefs.h" +#include "msdos.h" /* * dep - directory entry to copy into the directory @@ -605,10 +86,8 @@ daddr_t bn; int blsize; -#ifdef MSDOSFS_DEBUG - printf("createde(dep %p, ddep %p, depp %p, cnp %p)\n", - dep, ddep, depp, cnp); -#endif + 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 @@ -624,7 +103,7 @@ dirclust = de_clcount(pmp, diroffset); error = extendfile(ddep, dirclust, 0, 0, DE_CLEAR); if (error) { - (void)detrunc(ddep, ddep->de_FileSize, 0, NOCRED); + (void)detrunc(ddep, ddep->de_FileSize, 0, NULL); return error; } @@ -665,9 +144,7 @@ while (--ddep->de_fndcnt >= 0) { if (!(ddep->de_fndoffset & pmp->pm_crbomask)) { - if (DOINGASYNC(DETOV(ddep))) - bdwrite(bp); - else if ((error = bwrite(bp)) != 0) + if ((error = bwrite(bp)) != 0) return error; ddep->de_fndoffset -= sizeof(struct direntry); @@ -690,14 +167,12 @@ ddep->de_fndoffset -= sizeof(struct direntry); } if (!unix2winfn(un, unlen, (struct winentry *)ndep, - cnt++, chksum, pmp)) + cnt++, chksum)) break; } } - if (DOINGASYNC(DETOV(ddep))) - bdwrite(bp); - else if ((error = bwrite(bp)) != 0) + if ((error = bwrite(bp)) != 0) return error; /* @@ -719,170 +194,6 @@ return 0; } -/* - * Be sure a directory is empty except for "." and "..". Return 1 if empty, - * return 0 if not empty or error. - */ -int -dosdirempty(struct denode *dep) -{ - int blsize; - int error; - u_long cn; - daddr_t bn; - struct buf *bp; - struct msdosfsmount *pmp = dep->de_pmp; - struct direntry *dentp; - - /* - * Since the filesize field in directory entries for a directory is - * zero, we just have to feel our way through the directory until - * we hit end of file. - */ - for (cn = 0;; cn++) { - if ((error = pcbmap(dep, cn, &bn, 0, &blsize)) != 0) { - if (error == E2BIG) - return (1); /* it's empty */ - return (0); - } - error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp); - if (error) { - brelse(bp); - return (0); - } - for (dentp = (struct direntry *)bp->b_data; - (char *)dentp < bp->b_data + blsize; - dentp++) { - if (dentp->deName[0] != SLOT_DELETED && - (dentp->deAttributes & ATTR_VOLUME) == 0) { - /* - * In dos directories an entry whose name - * starts with SLOT_EMPTY (0) starts the - * beginning of the unused part of the - * directory, so we can just return that it - * is empty. - */ - if (dentp->deName[0] == SLOT_EMPTY) { - brelse(bp); - return (1); - } - /* - * Any names other than "." and ".." in a - * directory mean it is not empty. - */ - if (bcmp(dentp->deName, ". ", 11) && - bcmp(dentp->deName, ".. ", 11)) { - brelse(bp); -#ifdef MSDOSFS_DEBUG - printf("dosdirempty(): entry found %02x, %02x\n", - dentp->deName[0], dentp->deName[1]); -#endif - return (0); /* not empty */ - } - } - } - brelse(bp); - } - /* NOTREACHED */ -} - -/* - * Check to see if the directory described by target is in some - * subdirectory of source. This prevents something like the following from - * succeeding and leaving a bunch or files and directories orphaned. mv - * /a/b/c /a/b/c/d/e/f Where c and f are directories. - * - * source - the inode for /a/b/c - * target - the inode for /a/b/c/d/e/f - * - * Returns 0 if target is NOT a subdirectory of source. - * Otherwise returns a non-zero error number. - * The target inode is always unlocked on return. - */ -int -doscheckpath(struct denode *source, struct denode *target) -{ - daddr_t scn; - struct msdosfsmount *pmp; - struct direntry *ep; - struct denode *dep; - struct buf *bp = NULL; - int error = 0; - - dep = target; - if ((target->de_Attributes & ATTR_DIRECTORY) == 0 || - (source->de_Attributes & ATTR_DIRECTORY) == 0) { - error = ENOTDIR; - goto out; - } - if (dep->de_StartCluster == source->de_StartCluster) { - error = EEXIST; - goto out; - } - if (dep->de_StartCluster == MSDOSFSROOT) - goto out; - pmp = dep->de_pmp; -#ifdef DIAGNOSTIC - if (pmp != source->de_pmp) - panic("doscheckpath: source and target on different filesystems"); -#endif - if (FAT32(pmp) && dep->de_StartCluster == pmp->pm_rootdirblk) - goto out; - - for (;;) { - if ((dep->de_Attributes & ATTR_DIRECTORY) == 0) { - error = ENOTDIR; - break; - } - scn = dep->de_StartCluster; - error = bread(pmp->pm_devvp, cntobn(pmp, scn), - pmp->pm_bpcluster, NOCRED, &bp); - if (error) - break; - - ep = (struct direntry *) bp->b_data + 1; - if ((ep->deAttributes & ATTR_DIRECTORY) == 0 || - bcmp(ep->deName, ".. ", 11) != 0) { - error = ENOTDIR; - break; - } - scn = getushort(ep->deStartCluster); - if (FAT32(pmp)) - scn |= getushort(ep->deHighClust) << 16; - - if (scn == source->de_StartCluster) { - error = EINVAL; - break; - } - if (scn == MSDOSFSROOT) - break; - if (FAT32(pmp) && scn == pmp->pm_rootdirblk) { - /* - * scn should be 0 in this case, - * but we silently ignore the error. - */ - break; - } - - vput(DETOV(dep)); - brelse(bp); - bp = NULL; - /* NOTE: deget() clears dep on error */ - if ((error = deget(pmp, scn, 0, &dep)) != 0) - break; - } -out:; - if (bp) - brelse(bp); -#ifdef MSDOSFS_DEBUG - if (error == ENOTDIR) - printf("doscheckpath(): .. not a directory?\n"); -#endif - if (dep != NULL) - vput(DETOV(dep)); - return (error); -} - /* * Read in the disk block containing the directory entry (dirclu, dirofs) * and return the address of the buf header, and the address of the @@ -924,81 +235,6 @@ bpp, epp)); } -/* - * Remove a directory entry. At this point the file represented by the - * directory entry to be removed is still full length until no one has it - * open. When the file no longer being used msdosfs_inactive() is called - * and will truncate the file to 0 length. When the vnode containing the - * denode is needed for some other purpose by VFS it will call - * msdosfs_reclaim() which will remove the denode from the denode cache. - * - * pdep directory where the entry is removed - * dep file to be removed - */ -int -removede(struct denode *pdep, struct denode *dep) -{ - int error; - struct direntry *ep; - struct buf *bp; - daddr_t bn; - int blsize; - struct msdosfsmount *pmp = pdep->de_pmp; - u_long offset = pdep->de_fndoffset; - -#ifdef MSDOSFS_DEBUG - printf("removede(): filename %s, dep %p, offset %08lx\n", - dep->de_Name, dep, offset); -#endif - - dep->de_refcnt--; - offset += sizeof(struct direntry); - do { - offset -= sizeof(struct direntry); - error = pcbmap(pdep, de_cluster(pmp, offset), &bn, 0, &blsize); - if (error) - return error; - error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp); - if (error) { - brelse(bp); - return error; - } - ep = bptoep(pmp, bp, offset); - /* - * Check whether, if we came here the second time, i.e. - * when underflowing into the previous block, the last - * entry in this block is a longfilename entry, too. - */ - if (ep->deAttributes != ATTR_WIN95 - && offset != pdep->de_fndoffset) { - brelse(bp); - break; - } - offset += sizeof(struct direntry); - while (1) { - /* - * We are a bit aggressive here in that we delete any Win95 - * entries preceding this entry, not just the ones we "own". - * Since these presumably aren't valid anyway, - * there should be no harm. - */ - offset -= sizeof(struct direntry); - ep--->deName[0] = SLOT_DELETED; - if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) - || !(offset & pmp->pm_crbomask) - || ep->deAttributes != ATTR_WIN95) - break; - } - if (DOINGASYNC(DETOV(pdep))) - bdwrite(bp); - else if ((error = bwrite(bp)) != 0) - return error; - } while (!(pmp->pm_flags & MSDOSFSMNT_NOWIN95) - && !(offset & pmp->pm_crbomask) - && offset); - return 0; -} - /* * Create a unique DOS name in dvp */ @@ -1013,17 +249,17 @@ daddr_t bn; struct buf *bp; int error; - + if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) return (unix2dosfn((const u_char *)cnp->cn_nameptr, cp, - cnp->cn_namelen, 0, pmp) ? 0 : EINVAL); + 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, pmp)) + cnp->cn_namelen, gen)) return gen == 1 ? EINVAL : EEXIST; /* @@ -1041,7 +277,7 @@ return error; } for (dentp = (struct direntry *)bp->b_data; - (char *)dentp < bp->b_data + blsize; + (char *)dentp < (char *)bp->b_data + blsize; dentp++) { if (dentp->deName[0] == SLOT_EMPTY) { /* Index: usr.sbin/makefs/msdos/msdosfs_vfsops.c =================================================================== --- usr.sbin/makefs/msdos/msdosfs_vfsops.c +++ usr.sbin/makefs/msdos/msdosfs_vfsops.c @@ -45,43 +45,34 @@ * October 1992 */ -#if HAVE_NBTOOL_CONFIG_H -#include "nbtool_config.h" -#endif - #include -/* $NetBSD: msdosfs_vfsops.c,v 1.10 2016/01/30 09:59:27 mlelstv Exp $ */ __FBSDID("$FreeBSD$"); #include +#include -#include +#include +#include +#include +#include +#include -#include #include -#include +#include #include -#include +#include #include +#include -#include -#include -#include -#include -#include +#include #include "makefs.h" #include "msdos.h" -#include "mkfs_msdos.h" -#ifdef MSDOSFS_DEBUG -#define DPRINTF(a) printf a -#else -#define DPRINTF(a) -#endif +#include "ffs/buf.h" struct msdosfsmount * -msdosfs_mount(struct vnode *devvp, int flags) +msdosfs_mount(struct vnode *devvp) { struct msdosfsmount *pmp = NULL; struct buf *bp; @@ -90,13 +81,11 @@ struct byte_bpb50 *b50; struct byte_bpb710 *b710; uint8_t SecPerClust; - int ronly = 0, error, tmp; + int ronly = 0, error; int bsize; - struct msdos_options *m = devvp->fs->fs_specific; - uint64_t psize = m->create_size; unsigned secsize = 512; - DPRINTF(("%s(bread 0)\n", __func__)); + MSDOSFS_DPRINTF(("%s(bread 0)\n", __func__)); if ((error = bread(devvp, 0, secsize, 0, &bp)) != 0) goto error_exit; @@ -105,20 +94,17 @@ b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB; b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB; - if (!(flags & MSDOSFSMNT_GEMDOSFS)) { - if (bsp->bs50.bsBootSectSig0 != BOOTSIG0 - || bsp->bs50.bsBootSectSig1 != BOOTSIG1) { - DPRINTF(("bootsig0 %d bootsig1 %d\n", - bsp->bs50.bsBootSectSig0, - bsp->bs50.bsBootSectSig1)); - error = EINVAL; - goto error_exit; - } - bsize = 0; - } else - bsize = 512; + 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); + 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 @@ -135,30 +121,24 @@ pmp->pm_Heads = getushort(b50->bpbHeads); pmp->pm_Media = b50->bpbMedia; - 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)); - if (!(flags & MSDOSFSMNT_GEMDOSFS)) { - /* XXX - We should probably check more values here */ - if (!pmp->pm_BytesPerSec || !SecPerClust - || pmp->pm_SecPerTrack > 63) { - DPRINTF(("bytespersec %d secperclust %d " - "secpertrack %d\n", - pmp->pm_BytesPerSec, SecPerClust, - pmp->pm_SecPerTrack)); - error = EINVAL; - goto error_exit; - } + 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; } - pmp->pm_flags = flags & MSDOSFSMNT_MNTOPT; - if (pmp->pm_flags & MSDOSFSMNT_GEMDOSFS) - pmp->pm_flags |= MSDOSFSMNT_NOWIN95; - if (pmp->pm_flags & MSDOSFSMNT_NOWIN95) - pmp->pm_flags |= MSDOSFSMNT_SHORTNAME; - if (pmp->pm_Sectors == 0) { pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs); pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors); @@ -167,6 +147,7 @@ pmp->pm_HugeSectors = pmp->pm_Sectors; } + pmp->pm_flags = 0; if (pmp->pm_RootDirEnts == 0) { unsigned short vers = getushort(b710->bpbFSVers); /* @@ -175,7 +156,7 @@ * do not set these to zero. Therefore, do not insist. */ if (pmp->pm_Sectors || pmp->pm_FATsecs || vers) { - DPRINTF(("sectors %d fatsecs %lu vers %d\n", + MSDOSFS_DPRINTF(("sectors %d fatsecs %lu vers %d\n", pmp->pm_Sectors, pmp->pm_FATsecs, vers)); error = EINVAL; goto error_exit; @@ -193,52 +174,9 @@ } else pmp->pm_flags |= MSDOSFS_FATMIRROR; - if (flags & MSDOSFSMNT_GEMDOSFS) { - if (FAT32(pmp)) { - DPRINTF(("FAT32 for GEMDOS\n")); - /* - * GEMDOS doesn't know FAT32. - */ - error = EINVAL; - goto error_exit; - } - - /* - * Check a few values (could do some more): - * - logical sector size: power of 2, >= block size - * - sectors per cluster: power of 2, >= 1 - * - number of sectors: >= 1, <= size of partition - */ - if ( (SecPerClust == 0) - || (SecPerClust & (SecPerClust - 1)) - || (pmp->pm_BytesPerSec < bsize) - || (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1)) - || (pmp->pm_HugeSectors == 0) - || (pmp->pm_HugeSectors * (pmp->pm_BytesPerSec / bsize) - > psize)) { - DPRINTF(("consistency checks for GEMDOS\n")); - error = EINVAL; - goto error_exit; - } - /* - * XXX - Many parts of the msdosfs driver seem to assume that - * the number of bytes per logical sector (BytesPerSec) will - * always be the same as the number of bytes per disk block - * Let's pretend it is. - */ - tmp = pmp->pm_BytesPerSec / bsize; - pmp->pm_BytesPerSec = bsize; - pmp->pm_HugeSectors *= tmp; - pmp->pm_HiddenSects *= tmp; - pmp->pm_ResSectors *= tmp; - pmp->pm_Sectors *= tmp; - pmp->pm_FATsecs *= tmp; - SecPerClust *= tmp; - } - /* Check that fs has nonzero FAT size */ if (pmp->pm_FATsecs == 0) { - DPRINTF(("FATsecs is 0\n")); + MSDOSFS_DPRINTF(("FATsecs is 0\n")); error = EINVAL; goto error_exit; } @@ -258,22 +196,11 @@ pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize; } - pmp->pm_nmbrofclusters = (pmp->pm_HugeSectors - pmp->pm_firstcluster) / - SecPerClust; - pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1; + pmp->pm_maxcluster = ((pmp->pm_HugeSectors - pmp->pm_firstcluster) / + SecPerClust) + 1; pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec; - if (flags & MSDOSFSMNT_GEMDOSFS) { - if (pmp->pm_nmbrofclusters <= (0xff0 - 2)) { - 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; - } - } else if (pmp->pm_fatmask == 0) { + if (pmp->pm_fatmask == 0) { if (pmp->pm_maxcluster <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) { /* @@ -306,18 +233,19 @@ pmp->pm_crbomask = pmp->pm_bpcluster - 1; pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1; - DPRINTF(("%s(fatmask=%lu, fatmult=%u, fatdiv=%u, fatblocksize=%lu, " - "fatblocksec=%lu, bnshift=%lu, pbcluster=%lu, crbomask=%lu, " - "cnshift=%lu)\n", - __func__, 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)); + 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)) { - DPRINTF(("bpcluster %lu cnshift %lu\n", + MSDOSFS_DPRINTF(("bpcluster %lu cnshift %lu\n", pmp->pm_bpcluster, pmp->pm_cnshift)); error = EINVAL; goto error_exit; @@ -340,16 +268,13 @@ * 2KB or larger sectors, is the fsinfo structure * padded at the end or in the middle? */ - DPRINTF(("%s(bread %lu)\n", __func__, - (unsigned long)de_bn2kb(pmp, pmp->pm_fsinfo))); - if ((error = bread(devvp, de_bn2kb(pmp, pmp->pm_fsinfo), - pmp->pm_BytesPerSec, 0, &bp)) != 0) + if ((error = bread(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) - && !memcmp(fp->fsisig4, "\0\0\125\252", 4)) + && !memcmp(fp->fsisig3, "\0\0\125\252", 4)) pmp->pm_nxtfree = getulong(fp->fsinxtfree); else pmp->pm_fsinfo = 0; @@ -383,7 +308,7 @@ * Have the inuse map filled in. */ if ((error = fillinusemap(pmp)) != 0) { - DPRINTF(("fillinusemap %d\n", error)); + MSDOSFS_DPRINTF(("fillinusemap %d\n", error)); goto error_exit; } @@ -407,7 +332,7 @@ error_exit: if (bp) - brelse(bp, BC_AGE); + brelse(bp); if (pmp) { if (pmp->pm_inusemap) free(pmp->pm_inusemap); Index: usr.sbin/makefs/msdos/msdosfs_vnops.c =================================================================== --- usr.sbin/makefs/msdos/msdosfs_vnops.c +++ usr.sbin/makefs/msdos/msdosfs_vnops.c @@ -46,34 +46,33 @@ * * October 1992 */ -#if HAVE_NBTOOL_CONFIG_H -#include "nbtool_config.h" -#endif #include __FBSDID("$FreeBSD$"); #include #include +#include +#include +#include + #include +#include +#include +#include #include -#include - #include -#include #include -#include +#include #include +#include #include "makefs.h" #include "msdos.h" -#ifdef MSDOSFS_DEBUG -#define DPRINTF(a) printf a -#else -#define DPRINTF(a) -#endif +#include "ffs/buf.h" + /* * Some general notes: * @@ -93,28 +92,40 @@ */ 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 msdosfsmount *pmp, struct denode *dep, - const struct stat *st) +msdosfs_times(struct denode *dep, const struct stat *st) { - struct timespec at; - struct timespec mt; - if (stampst.st_ino) - st = &stampst; - -#ifndef HAVE_NBTOOL_CONFIG_H - at = st->st_atimespec; - mt = st->st_mtimespec; -#else - at.tv_sec = st->st_atime; - at.tv_nsec = 0; - mt.tv_sec = st->st_mtime; - mt.tv_nsec = 0; -#endif - unix2dostime(&at, pmp->pm_gmtoff, &dep->de_ADate, NULL, NULL); - unix2dostime(&mt, pmp->pm_gmtoff, &dep->de_MDate, &dep->de_MTime, NULL); + st = &stampst; + + unix2fattime(&st->st_birthtim, &dep->de_CDate, &dep->de_CTime); + 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, <); + + 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; } /* @@ -162,12 +173,12 @@ break; case 2: wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, - cnp->cn_namelen, pmp->pm_flags & MSDOSFSMNT_UTF8) + 1; + cnp->cn_namelen) + 1; break; case 3: olddos = 0; wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, - cnp->cn_namelen, pmp->pm_flags & MSDOSFSMNT_UTF8) + 1; + cnp->cn_namelen) + 1; break; } @@ -181,7 +192,7 @@ * case it doesn't already exist. */ slotcount = 0; - DPRINTF(("%s(): dos filename: %s\n", __func__, dosfilename)); + 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. @@ -200,8 +211,7 @@ break; return (error); } - error = bread(pmp->pm_devvp, de_bn2kb(pmp, bn), blsize, - 0, &bp); + error = bread(pmp->pm_devvp, bn, blsize, 0, &bp); if (error) { return (error); } @@ -248,11 +258,10 @@ if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) continue; - chksum = winChkName((const u_char *)cnp->cn_nameptr, - cnp->cn_namelen, - (struct winentry *)dep, - chksum, - pmp->pm_flags & MSDOSFSMNT_UTF8); + chksum = winChkName( + (const u_char *)cnp->cn_nameptr, + cnp->cn_namelen, + (struct winentry *)dep, chksum); continue; } @@ -274,7 +283,7 @@ chksum = -1; continue; } - DPRINTF(("%s(): match blkoff %d, diroff %d\n", + MSDOSFS_DPRINTF(("%s(): match blkoff %d, diroff %u\n", __func__, blkoff, diroff)); /* * Remember where this directory @@ -304,7 +313,7 @@ * that's ok if we are creating or renaming and are at the end of * the pathname and the directory hasn't been removed. */ - DPRINTF(("%s(): refcnt %ld, slotcount %d, slotoffset %d\n", + 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 @@ -352,13 +361,12 @@ struct denode *dep; int error; struct stat *st = &node->inode->st; - struct msdosfsmount *pmp = pdep->de_pmp; cn.cn_nameptr = node->name; cn.cn_namelen = strlen(node->name); - DPRINTF(("%s(name %s, mode 0%o size %zu)\n", __func__, node->name, - st->st_mode, (size_t)st->st_size)); + 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 @@ -385,11 +393,10 @@ ATTR_ARCHIVE : ATTR_ARCHIVE | ATTR_READONLY; ndirent.de_StartCluster = 0; ndirent.de_FileSize = 0; - ndirent.de_dev = pdep->de_dev; - ndirent.de_devvp = pdep->de_devvp; ndirent.de_pmp = pdep->de_pmp; ndirent.de_flag = DE_ACCESS | DE_CREATE | DE_UPDATE; - msdosfs_times(pmp, &ndirent, st); + msdosfs_times(&ndirent, &node->inode->st); + if ((error = msdosfs_findslot(pdep, &cn)) != 0) goto bad; if ((error = createde(&ndirent, pdep, &dep, &cn)) != 0) @@ -434,8 +441,9 @@ u_long cn = 0; error = 0; /* XXX: gcc/vax */ - DPRINTF(("%s(diroff %lu, dirclust %lu, startcluster %lu)\n", __func__, - dep->de_diroffset, dep->de_dirclust, dep->de_StartCluster)); + 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; @@ -444,7 +452,7 @@ return EFBIG; nsize = st->st_size; - DPRINTF(("%s(nsize=%zu, osize=%zu)\n", __func__, nsize, osize)); + MSDOSFS_DPRINTF(("%s(nsize=%zu, osize=%zu)\n", __func__, nsize, osize)); if (nsize > osize) { if ((error = deextend(dep, nsize, NULL)) != 0) return error; @@ -454,14 +462,14 @@ if ((fd = open(path, O_RDONLY)) == -1) { error = errno; - DPRINTF((1, "open %s: %s", path, strerror(error))); + MSDOSFS_DPRINTF(("open %s: %s", path, strerror(error))); return error; } if ((dat = mmap(0, nsize, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0)) == MAP_FAILED) { error = errno; - DPRINTF(("%s: mmap %s: %s", __func__, node->name, + MSDOSFS_DPRINTF(("%s: mmap %s: %s", __func__, node->name, strerror(error))); close(fd); goto out; @@ -472,27 +480,17 @@ int blsize, cpsize; daddr_t bn; u_long on = offs & pmp->pm_crbomask; -#ifdef HACK - cn = dep->de_StartCluster; - if (cn == MSDOSFSROOT) { - DPRINTF(("%s: bad lbn %lu", __func__, cn)); - error = EINVAL; - goto out; - } - bn = cntobn(pmp, cn); - blsize = pmp->pm_bpcluster; -#else + if ((error = pcbmap(dep, cn++, &bn, NULL, &blsize)) != 0) { - DPRINTF(("%s: pcbmap %lu", __func__, bn)); + MSDOSFS_DPRINTF(("%s: pcbmap %lu", + __func__, (unsigned long)bn)); goto out; } -#endif - DPRINTF(("%s(cn=%lu, bn=%llu/%llu, blsize=%d)\n", __func__, - cn, (unsigned long long)bn, - (unsigned long long)de_bn2kb(pmp, bn), blsize)); - if ((error = bread(pmp->pm_devvp, de_bn2kb(pmp, bn), blsize, - 0, &bp)) != 0) { - DPRINTF(("bread %d\n", error)); + + MSDOSFS_DPRINTF(("%s(cn=%lu, bn=%llu, blsize=%d)\n", + __func__, cn, (unsigned long long)bn, blsize)); + if ((error = bread(pmp->pm_devvp, bn, blsize, 0, &bp)) != 0) { + MSDOSFS_DPRINTF(("bread %d\n", error)); goto out; } cpsize = MIN((nsize - offs), blsize - on); @@ -508,12 +506,11 @@ return error; } - static const struct { struct direntry dot; struct direntry dotdot; } dosdirtemplate = { - { ". ", " ", /* the . entry */ + { ". ", /* the . entry */ ATTR_DIRECTORY, /* file attribute */ 0, /* reserved */ 0, { 0, 0 }, { 0, 0 }, /* create time & date */ @@ -523,7 +520,7 @@ { 0, 0 }, /* startcluster */ { 0, 0, 0, 0 } /* filesize */ }, - { ".. ", " ", /* the .. entry */ + { ".. ", /* the .. entry */ ATTR_DIRECTORY, /* file attribute */ 0, /* reserved */ 0, { 0, 0 }, { 0, 0 }, /* create time & date */ @@ -540,11 +537,9 @@ struct denode ndirent; struct denode *dep; struct componentname cn; - struct stat *st = &node->inode->st; struct msdosfsmount *pmp = pdep->de_pmp; int error; u_long newcluster, pcl, bn; - daddr_t lbn; struct direntry *denp; struct buf *bp; @@ -564,14 +559,14 @@ /* * Allocate a cluster to hold the about to be created directory. */ - error = clusteralloc(pmp, 0, 1, &newcluster, NULL); + 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(pmp, &ndirent, st); + msdosfs_times(&ndirent, &node->inode->st); /* * Now fill the cluster with the "." and ".." entries. And write @@ -579,11 +574,10 @@ * directory to be pointing at if there were a crash. */ bn = cntobn(pmp, newcluster); - lbn = de_bn2kb(pmp, bn); - DPRINTF(("%s(newcluster %lu, bn=%lu, lbn=%lu)\n", __func__, newcluster, - bn, lbn)); + MSDOSFS_DPRINTF(("%s(newcluster %lu, bn=%lu)\n", + __func__, newcluster, bn)); /* always succeeds */ - bp = getblk(pmp->pm_devvp, lbn, pmp->pm_bpcluster, 0, 0); + bp = getblk(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; @@ -595,7 +589,7 @@ putushort(denp[0].deMDate, ndirent.de_MDate); putushort(denp[0].deMTime, ndirent.de_MTime); pcl = pdep->de_StartCluster; - DPRINTF(("%s(pcl %lu, rootdirblk=%lu)\n", __func__, pcl, + MSDOSFS_DPRINTF(("%s(pcl %lu, rootdirblk=%lu)\n", __func__, pcl, pmp->pm_rootdirblk)); if (FAT32(pmp) && pcl == pmp->pm_rootdirblk) pcl = 0; @@ -628,8 +622,6 @@ ndirent.de_Attributes = ATTR_DIRECTORY; ndirent.de_StartCluster = newcluster; ndirent.de_FileSize = 0; - ndirent.de_dev = pdep->de_dev; - ndirent.de_devvp = pdep->de_devvp; ndirent.de_pmp = pdep->de_pmp; if ((error = msdosfs_findslot(pdep, &cn)) != 0) goto bad;