usr.sbin/makefs: Synchronize on NetBSD-current (30/03/2021 16:09 UTC)

This commit is contained in:
Marcelo Alencar 2021-03-31 11:30:25 -03:00
parent fd1285b2ec
commit ba797217b8
58 changed files with 2734 additions and 1079 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.5 2014/03/18 18:20:39 riastradh Exp $ # $NetBSD: Makefile,v 1.7 2020/09/06 07:20:27 mrg Exp $
.include <bsd.own.mk> .include <bsd.own.mk>
@ -14,4 +14,9 @@ CPPFLAGS+= -I${MOUNT} -I${KUDF} -I${NETBSDSRCDIR}/sys
DPADD+=${LIBUTIL} DPADD+=${LIBUTIL}
LDADD+=-lutil LDADD+=-lutil
.if !defined(__MINIX)
CWARNFLAGS.clang+= -Wno-error=address-of-packed-member
.endif # !defined(__MINIX)
CWARNFLAGS.gcc+= ${GCC_NO_ADDR_OF_PACKED_MEMBER}
.include <bsd.prog.mk> .include <bsd.prog.mk>

View File

@ -1,4 +1,4 @@
/* $NetBSD: newfs_udf.c,v 1.18 2013/08/09 15:11:08 reinoud Exp $ */ /* $NetBSD: newfs_udf.c,v 1.20 2020/04/05 15:25:40 joerg Exp $ */
/* /*
* Copyright (c) 2006, 2008, 2013 Reinoud Zandijk * Copyright (c) 2006, 2008, 2013 Reinoud Zandijk
@ -72,7 +72,6 @@
int newfs_udf(int argc, char **argv); int newfs_udf(int argc, char **argv);
static void usage(void) __attribute__((__noreturn__)); static void usage(void) __attribute__((__noreturn__));
/* queue for temporary storage of sectors to be written out */ /* queue for temporary storage of sectors to be written out */
struct wrsect { struct wrsect {
uint64_t sectornr; uint64_t sectornr;
@ -121,11 +120,13 @@ udf_write_sector(void *sector, uint64_t location)
if ((seekpos == NULL) || (seekpos->sectornr != location)) { if ((seekpos == NULL) || (seekpos->sectornr != location)) {
pos = calloc(1, sizeof(struct wrsect)); pos = calloc(1, sizeof(struct wrsect));
if (pos == NULL) if (pos == NULL)
return ENOMEM; return errno;
/* allocate space for copy of sector data */ /* allocate space for copy of sector data */
pos->sector_data = calloc(1, context.sector_size); pos->sector_data = calloc(1, context.sector_size);
if (pos->sector_data == NULL) if (pos->sector_data == NULL) {
return ENOMEM; free(pos);
return errno;
}
pos->sectornr = location; pos->sectornr = location;
if (seekpos) { if (seekpos) {

View File

@ -1,3 +1,5 @@
/* $NetBSD: newfs_udf.h,v 1.7 2020/04/05 15:25:40 joerg Exp $ */
/* /*
* Copyright (c) 2006, 2008, 2013 Reinoud Zandijk * Copyright (c) 2006, 2008, 2013 Reinoud Zandijk
* All rights reserved. * All rights reserved.
@ -53,8 +55,8 @@ extern float meta_fract;
/* shared structure between udf_create.c users */ /* shared structure between udf_create.c users */
struct udf_create_context context; extern struct udf_create_context context;
struct udf_disclayout layout; extern struct udf_disclayout layout;
/* prototypes */ /* prototypes */
int udf_write_sector(void *sector, uint64_t location); int udf_write_sector(void *sector, uint64_t location);

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_create.c,v 1.25 2015/06/16 23:18:55 christos Exp $ */ /* $NetBSD: udf_create.c,v 1.28 2020/05/14 08:34:18 msaitoh Exp $ */
/* /*
* Copyright (c) 2006, 2008 Reinoud Zandijk * Copyright (c) 2006, 2008 Reinoud Zandijk
@ -30,7 +30,7 @@
#endif #endif
#include <sys/cdefs.h> #include <sys/cdefs.h>
__RCSID("$NetBSD: udf_create.c,v 1.25 2015/06/16 23:18:55 christos Exp $"); __RCSID("$NetBSD: udf_create.c,v 1.28 2020/05/14 08:34:18 msaitoh Exp $");
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -52,6 +52,9 @@ __RCSID("$NetBSD: udf_create.c,v 1.25 2015/06/16 23:18:55 christos Exp $");
# endif # endif
#endif #endif
struct udf_create_context context;
struct udf_disclayout layout;
/* /*
* NOTE that there is some overlap between this code and the udf kernel fs. * NOTE that there is some overlap between this code and the udf kernel fs.
* This is intentially though it might better be factored out one day. * This is intentially though it might better be factored out one day.
@ -339,7 +342,7 @@ udf_calculate_disc_layout(int format_flags, int min_udf,
if (format_flags & FORMAT_META) { if (format_flags & FORMAT_META) {
/* note: all in backing partition space */ /* note: all in backing partition space */
layout.meta_file = pos++; layout.meta_file = pos++;
layout.meta_bitmap = pos++;; layout.meta_bitmap = pos++;
layout.meta_mirror = layout.part_size_lba-1; layout.meta_mirror = layout.part_size_lba-1;
layout.meta_alignment = MAX(blockingnr, sparable_blockingnr); layout.meta_alignment = MAX(blockingnr, sparable_blockingnr);
layout.meta_blockingnr = MAX(layout.meta_alignment, 32); layout.meta_blockingnr = MAX(layout.meta_alignment, 32);
@ -1720,10 +1723,10 @@ udf_extattr_append_internal(union dscrptr *dscr, struct extattr_entry *extattr)
struct extfile_entry *efe; struct extfile_entry *efe;
struct extattrhdr_desc *extattrhdr; struct extattrhdr_desc *extattrhdr;
struct impl_extattr_entry *implext; struct impl_extattr_entry *implext;
uint32_t impl_attr_loc, appl_attr_loc, l_ea, a_l, exthdr_len; uint32_t impl_attr_loc, appl_attr_loc, l_ea, l_ad, a_l;
uint32_t *l_eap, l_ad;
uint16_t *spos; uint16_t *spos;
uint8_t *bpos, *data; uint8_t *bpos, *data;
void *l_eap;
if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) { if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) {
fe = &dscr->fe; fe = &dscr->fe;
@ -1741,27 +1744,22 @@ udf_extattr_append_internal(union dscrptr *dscr, struct extattr_entry *extattr)
/* should have a header! */ /* should have a header! */
extattrhdr = (struct extattrhdr_desc *) data; extattrhdr = (struct extattrhdr_desc *) data;
l_ea = udf_rw32(*l_eap); memcpy(&l_ea, l_eap, sizeof(l_ea));
l_ea = udf_rw32(l_ea);
if (l_ea == 0) { if (l_ea == 0) {
#if !defined(NDEBUG) && defined(__minix) uint32_t exthdr_len;
assert(l_ad == 0); assert(l_ad == 0);
#else
if (l_ad != 0) {
printf("%s:%d: l_ad != 0\n", __func__, __LINE__);
abort();
}
#endif /* !defined(NDEBUG) && defined(__minix) */
/* create empty extended attribute header */ /* create empty extended attribute header */
exthdr_len = sizeof(struct extattrhdr_desc); l_ea = sizeof(struct extattrhdr_desc);
exthdr_len = udf_rw32(l_ea);
udf_inittag(&extattrhdr->tag, TAGID_EXTATTR_HDR, /* loc */ 0); udf_inittag(&extattrhdr->tag, TAGID_EXTATTR_HDR, /* loc */ 0);
extattrhdr->impl_attr_loc = udf_rw32(exthdr_len); extattrhdr->impl_attr_loc = exthdr_len;
extattrhdr->appl_attr_loc = udf_rw32(exthdr_len); extattrhdr->appl_attr_loc = exthdr_len;
extattrhdr->tag.desc_crc_len = udf_rw16(8); extattrhdr->tag.desc_crc_len = udf_rw16(8);
/* record extended attribute header length */ /* record extended attribute header length */
l_ea = exthdr_len; memcpy(l_eap, &exthdr_len, sizeof(exthdr_len));
*l_eap = udf_rw32(l_ea);
} }
/* extract locations */ /* extract locations */
@ -1794,7 +1792,7 @@ udf_extattr_append_internal(union dscrptr *dscr, struct extattr_entry *extattr)
assert(appl_attr_loc == l_ea); assert(appl_attr_loc == l_ea);
/* append the attribute at the end of the current space */ /* append the attribute at the end of the current space */
bpos = data + udf_rw32(*l_eap); bpos = data + l_ea;
a_l = udf_rw32(extattr->a_l); a_l = udf_rw32(extattr->a_l);
/* update impl. attribute locations */ /* update impl. attribute locations */
@ -1809,7 +1807,8 @@ udf_extattr_append_internal(union dscrptr *dscr, struct extattr_entry *extattr)
/* copy and advance */ /* copy and advance */
memcpy(bpos, extattr, a_l); memcpy(bpos, extattr, a_l);
l_ea += a_l; l_ea += a_l;
*l_eap = udf_rw32(l_ea); l_ea = udf_rw32(l_ea);
memcpy(l_eap, &l_ea, sizeof(l_ea));
/* do the `dance` again backwards */ /* do the `dance` again backwards */
if (context.dscrver != 2) { if (context.dscrver != 2) {
@ -2164,10 +2163,6 @@ udf_create_new_rootdir(union dscrptr **dscr)
struct long_ad root_icb; struct long_ad root_icb;
int filetype, error; int filetype, error;
#if defined(__minix)
/* LSC: -Werror=maybe-uninitialized when compiling with -O3 */
fe = NULL;
#endif /*defined(__minix) */
memset(&root_icb, 0, sizeof(root_icb)); memset(&root_icb, 0, sizeof(root_icb));
root_icb.len = udf_rw32(context.sector_size); root_icb.len = udf_rw32(context.sector_size);
root_icb.loc.lb_num = udf_rw32(layout.rootdir); root_icb.loc.lb_num = udf_rw32(layout.rootdir);

View File

@ -1,4 +1,4 @@
/* $NetBSD: bootsect.h,v 1.5 2012/11/04 17:57:59 jakllsch Exp $ */ /* $NetBSD: bootsect.h,v 1.6 2016/01/22 22:48:18 dholland Exp $ */
/* /*
* Written by Paul Popelka (paulp@uts.amdahl.com) * Written by Paul Popelka (paulp@uts.amdahl.com)
@ -24,13 +24,13 @@
* first sector of a partitioned hard disk. * first sector of a partitioned hard disk.
*/ */
struct bootsector33 { struct bootsector33 {
u_int8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */ uint8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */
int8_t bsOemName[8]; /* OEM name and version */ int8_t bsOemName[8]; /* OEM name and version */
int8_t bsBPB[19]; /* BIOS parameter block */ int8_t bsBPB[19]; /* BIOS parameter block */
int8_t bsDriveNumber; /* drive number (0x80) */ int8_t bsDriveNumber; /* drive number (0x80) */
int8_t bsBootCode[479]; /* pad so struct is 512b */ int8_t bsBootCode[479]; /* pad so struct is 512b */
u_int8_t bsBootSectSig0; uint8_t bsBootSectSig0;
u_int8_t bsBootSectSig1; uint8_t bsBootSectSig1;
#define BOOTSIG0 0x55 #define BOOTSIG0 0x55
#define BOOTSIG1 0xaa #define BOOTSIG1 0xaa
}; };
@ -46,25 +46,25 @@ struct extboot {
}; };
struct bootsector50 { struct bootsector50 {
u_int8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */ uint8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */
int8_t bsOemName[8]; /* OEM name and version */ int8_t bsOemName[8]; /* OEM name and version */
int8_t bsBPB[25]; /* BIOS parameter block */ int8_t bsBPB[25]; /* BIOS parameter block */
int8_t bsExt[26]; /* Bootsector Extension */ int8_t bsExt[26]; /* Bootsector Extension */
int8_t bsBootCode[448]; /* pad so structure is 512b */ int8_t bsBootCode[448]; /* pad so structure is 512b */
u_int8_t bsBootSectSig0; uint8_t bsBootSectSig0;
u_int8_t bsBootSectSig1; uint8_t bsBootSectSig1;
#define BOOTSIG0 0x55 #define BOOTSIG0 0x55
#define BOOTSIG1 0xaa #define BOOTSIG1 0xaa
}; };
struct bootsector710 { struct bootsector710 {
u_int8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */ uint8_t bsJump[3]; /* jump inst E9xxxx or EBxx90 */
int8_t bsOEMName[8]; /* OEM name and version */ int8_t bsOEMName[8]; /* OEM name and version */
int8_t bsBPB[53]; /* BIOS parameter block */ int8_t bsBPB[53]; /* BIOS parameter block */
int8_t bsExt[26]; /* Bootsector Extension */ int8_t bsExt[26]; /* Bootsector Extension */
int8_t bsBootCode[420]; /* pad so structure is 512b */ int8_t bsBootCode[420]; /* pad so structure is 512b */
u_int8_t bsBootSectSig0; uint8_t bsBootSectSig0;
u_int8_t bsBootSectSig1; uint8_t bsBootSectSig1;
#define BOOTSIG0 0x55 #define BOOTSIG0 0x55
#define BOOTSIG1 0xaa #define BOOTSIG1 0xaa
}; };
@ -76,7 +76,7 @@ struct bootsector710 {
*/ */
#if 0 #if 0
struct bootsec_atari { struct bootsec_atari {
u_int8_t bsBranch[2]; /* branch inst if auto-boot */ uint8_t bsBranch[2]; /* branch inst if auto-boot */
int8_t bsFiller[6]; /* anything or nothing */ int8_t bsFiller[6]; /* anything or nothing */
int8_t bsSerial[3]; /* serial no. for mediachange */ int8_t bsSerial[3]; /* serial no. for mediachange */
int8_t bsBPB[19]; /* BIOS parameter block */ int8_t bsBPB[19]; /* BIOS parameter block */

View File

@ -1,4 +1,4 @@
/* $NetBSD: bpb.h,v 1.7 2012/11/04 17:57:59 jakllsch Exp $ */ /* $NetBSD: bpb.h,v 1.8 2016/01/22 22:53:36 dholland Exp $ */
/* /*
* Written by Paul Popelka (paulp@uts.amdahl.com) * Written by Paul Popelka (paulp@uts.amdahl.com)
@ -23,17 +23,17 @@
* BIOS Parameter Block (BPB) for DOS 3.3 * BIOS Parameter Block (BPB) for DOS 3.3
*/ */
struct bpb33 { struct bpb33 {
u_int16_t bpbBytesPerSec; /* bytes per sector */ uint16_t bpbBytesPerSec; /* bytes per sector */
u_int8_t bpbSecPerClust; /* sectors per cluster */ uint8_t bpbSecPerClust; /* sectors per cluster */
u_int16_t bpbResSectors; /* number of reserved sectors */ uint16_t bpbResSectors; /* number of reserved sectors */
u_int8_t bpbFATs; /* number of FATs */ uint8_t bpbFATs; /* number of FATs */
u_int16_t bpbRootDirEnts; /* number of root directory entries */ uint16_t bpbRootDirEnts; /* number of root directory entries */
u_int16_t bpbSectors; /* total number of sectors */ uint16_t bpbSectors; /* total number of sectors */
u_int8_t bpbMedia; /* media descriptor */ uint8_t bpbMedia; /* media descriptor */
u_int16_t bpbFATsecs; /* number of sectors per FAT */ uint16_t bpbFATsecs; /* number of sectors per FAT */
u_int16_t bpbSecPerTrack; /* sectors per track */ uint16_t bpbSecPerTrack; /* sectors per track */
u_int16_t bpbHeads; /* number of heads */ uint16_t bpbHeads; /* number of heads */
u_int16_t bpbHiddenSecs; /* number of hidden sectors */ uint16_t bpbHiddenSecs; /* number of hidden sectors */
}; };
/* /*
@ -41,46 +41,46 @@ struct bpb33 {
* and bpbHugeSectors is not in the 3.3 bpb. * and bpbHugeSectors is not in the 3.3 bpb.
*/ */
struct bpb50 { struct bpb50 {
u_int16_t bpbBytesPerSec; /* bytes per sector */ uint16_t bpbBytesPerSec; /* bytes per sector */
u_int8_t bpbSecPerClust; /* sectors per cluster */ uint8_t bpbSecPerClust; /* sectors per cluster */
u_int16_t bpbResSectors; /* number of reserved sectors */ uint16_t bpbResSectors; /* number of reserved sectors */
u_int8_t bpbFATs; /* number of FATs */ uint8_t bpbFATs; /* number of FATs */
u_int16_t bpbRootDirEnts; /* number of root directory entries */ uint16_t bpbRootDirEnts; /* number of root directory entries */
u_int16_t bpbSectors; /* total number of sectors */ uint16_t bpbSectors; /* total number of sectors */
u_int8_t bpbMedia; /* media descriptor */ uint8_t bpbMedia; /* media descriptor */
u_int16_t bpbFATsecs; /* number of sectors per FAT */ uint16_t bpbFATsecs; /* number of sectors per FAT */
u_int16_t bpbSecPerTrack; /* sectors per track */ uint16_t bpbSecPerTrack; /* sectors per track */
u_int16_t bpbHeads; /* number of heads */ uint16_t bpbHeads; /* number of heads */
u_int32_t bpbHiddenSecs; /* # of hidden sectors */ uint32_t bpbHiddenSecs; /* # of hidden sectors */
u_int32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */ uint32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */
}; };
/* /*
* BPB for DOS 7.10 (FAT32). This one has a few extensions to bpb50. * BPB for DOS 7.10 (FAT32). This one has a few extensions to bpb50.
*/ */
struct bpb710 { struct bpb710 {
u_int16_t bpbBytesPerSec; /* bytes per sector */ uint16_t bpbBytesPerSec; /* bytes per sector */
u_int8_t bpbSecPerClust; /* sectors per cluster */ uint8_t bpbSecPerClust; /* sectors per cluster */
u_int16_t bpbResSectors; /* number of reserved sectors */ uint16_t bpbResSectors; /* number of reserved sectors */
u_int8_t bpbFATs; /* number of FATs */ uint8_t bpbFATs; /* number of FATs */
u_int16_t bpbRootDirEnts; /* number of root directory entries */ uint16_t bpbRootDirEnts; /* number of root directory entries */
u_int16_t bpbSectors; /* total number of sectors */ uint16_t bpbSectors; /* total number of sectors */
u_int8_t bpbMedia; /* media descriptor */ uint8_t bpbMedia; /* media descriptor */
u_int16_t bpbFATsecs; /* number of sectors per FAT */ uint16_t bpbFATsecs; /* number of sectors per FAT */
u_int16_t bpbSecPerTrack; /* sectors per track */ uint16_t bpbSecPerTrack; /* sectors per track */
u_int16_t bpbHeads; /* number of heads */ uint16_t bpbHeads; /* number of heads */
u_int32_t bpbHiddenSecs; /* # of hidden sectors */ uint32_t bpbHiddenSecs; /* # of hidden sectors */
u_int32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */ uint32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */
u_int32_t bpbBigFATsecs; /* like bpbFATsecs for FAT32 */ uint32_t bpbBigFATsecs; /* like bpbFATsecs for FAT32 */
u_int16_t bpbExtFlags; /* extended flags: */ uint16_t bpbExtFlags; /* extended flags: */
#define FATNUM 0xf /* mask for numbering active FAT */ #define FATNUM 0xf /* mask for numbering active FAT */
#define FATMIRROR 0x80 /* FAT is mirrored (like it always was) */ #define FATMIRROR 0x80 /* FAT is mirrored (like it always was) */
u_int16_t bpbFSVers; /* filesystem version */ uint16_t bpbFSVers; /* filesystem version */
#define FSVERS 0 /* currently only 0 is understood */ #define FSVERS 0 /* currently only 0 is understood */
u_int32_t bpbRootClust; /* start cluster for root directory */ uint32_t bpbRootClust; /* start cluster for root directory */
u_int16_t bpbFSInfo; /* filesystem info structure sector */ uint16_t bpbFSInfo; /* filesystem info structure sector */
u_int16_t bpbBackup; /* backup boot sector */ uint16_t bpbBackup; /* backup boot sector */
u_int8_t bpbReserved[12]; /* Reserved for future expansion */ uint8_t bpbReserved[12]; /* Reserved for future expansion */
}; };
#ifdef atari #ifdef atari
@ -90,17 +90,17 @@ struct bpb710 {
*/ */
#if 0 #if 0
struct bpb_a { struct bpb_a {
u_int16_t bpbBytesPerSec; /* bytes per sector */ uint16_t bpbBytesPerSec; /* bytes per sector */
u_int8_t bpbSecPerClust; /* sectors per cluster */ uint8_t bpbSecPerClust; /* sectors per cluster */
u_int16_t bpbResSectors; /* number of reserved sectors */ uint16_t bpbResSectors; /* number of reserved sectors */
u_int8_t bpbFATs; /* number of FATs */ uint8_t bpbFATs; /* number of FATs */
u_int16_t bpbRootDirEnts; /* number of root directory entries */ uint16_t bpbRootDirEnts; /* number of root directory entries */
u_int16_t bpbSectors; /* total number of sectors */ uint16_t bpbSectors; /* total number of sectors */
u_int8_t bpbUseless1; /* meaningless on GEMDOS FS */ uint8_t bpbUseless1; /* meaningless on GEMDOS FS */
u_int16_t bpbFATsecs; /* number of sectors per FAT */ uint16_t bpbFATsecs; /* number of sectors per FAT */
u_int16_t bpbUseless2; /* meaningless for harddisk fs */ uint16_t bpbUseless2; /* meaningless for harddisk fs */
u_int16_t bpbUseless3; /* meaningless for harddisk fs */ uint16_t bpbUseless3; /* meaningless for harddisk fs */
u_int16_t bpbHiddenSecs; /* the TOS-BIOS ignores this */ uint16_t bpbHiddenSecs; /* the TOS-BIOS ignores this */
}; };
#endif #endif
#endif /* atari */ #endif /* atari */
@ -159,39 +159,39 @@ struct byte_bpb50 {
* BPB for DOS 7.10 (FAT32). This one has a few extensions to bpb50. * BPB for DOS 7.10 (FAT32). This one has a few extensions to bpb50.
*/ */
struct byte_bpb710 { struct byte_bpb710 {
u_int8_t bpbBytesPerSec[2]; /* bytes per sector */ uint8_t bpbBytesPerSec[2]; /* bytes per sector */
u_int8_t bpbSecPerClust; /* sectors per cluster */ uint8_t bpbSecPerClust; /* sectors per cluster */
u_int8_t bpbResSectors[2]; /* number of reserved sectors */ uint8_t bpbResSectors[2]; /* number of reserved sectors */
u_int8_t bpbFATs; /* number of FATs */ uint8_t bpbFATs; /* number of FATs */
u_int8_t bpbRootDirEnts[2]; /* number of root directory entries */ uint8_t bpbRootDirEnts[2]; /* number of root directory entries */
u_int8_t bpbSectors[2]; /* total number of sectors */ uint8_t bpbSectors[2]; /* total number of sectors */
u_int8_t bpbMedia; /* media descriptor */ uint8_t bpbMedia; /* media descriptor */
u_int8_t bpbFATsecs[2]; /* number of sectors per FAT */ uint8_t bpbFATsecs[2]; /* number of sectors per FAT */
u_int8_t bpbSecPerTrack[2]; /* sectors per track */ uint8_t bpbSecPerTrack[2]; /* sectors per track */
u_int8_t bpbHeads[2]; /* number of heads */ uint8_t bpbHeads[2]; /* number of heads */
u_int8_t bpbHiddenSecs[4]; /* # of hidden sectors */ uint8_t bpbHiddenSecs[4]; /* # of hidden sectors */
u_int8_t bpbHugeSectors[4]; /* # of sectors if bpbSectors == 0 */ uint8_t bpbHugeSectors[4]; /* # of sectors if bpbSectors == 0 */
u_int8_t bpbBigFATsecs[4]; /* like bpbFATsecs for FAT32 */ uint8_t bpbBigFATsecs[4]; /* like bpbFATsecs for FAT32 */
u_int8_t bpbExtFlags[2]; /* extended flags: */ uint8_t bpbExtFlags[2]; /* extended flags: */
u_int8_t bpbFSVers[2]; /* filesystem version */ uint8_t bpbFSVers[2]; /* filesystem version */
u_int8_t bpbRootClust[4]; /* start cluster for root directory */ uint8_t bpbRootClust[4]; /* start cluster for root directory */
u_int8_t bpbFSInfo[2]; /* filesystem info structure sector */ uint8_t bpbFSInfo[2]; /* filesystem info structure sector */
u_int8_t bpbBackup[2]; /* backup boot sector */ uint8_t bpbBackup[2]; /* backup boot sector */
u_int8_t bpbReserved[12]; /* Reserved for future expansion */ uint8_t bpbReserved[12]; /* Reserved for future expansion */
}; };
/* /*
* FAT32 FSInfo block. * FAT32 FSInfo block.
*/ */
struct fsinfo { struct fsinfo {
u_int8_t fsisig1[4]; uint8_t fsisig1[4];
u_int8_t fsifill1[480]; uint8_t fsifill1[480];
u_int8_t fsisig2[4]; uint8_t fsisig2[4];
u_int8_t fsinfree[4]; uint8_t fsinfree[4];
u_int8_t fsinxtfree[4]; uint8_t fsinxtfree[4];
u_int8_t fsifill2[12]; uint8_t fsifill2[12];
u_int8_t fsisig3[4]; uint8_t fsisig3[4];
u_int8_t fsifill3[508]; uint8_t fsifill3[508];
u_int8_t fsisig4[4]; uint8_t fsisig4[4];
}; };
#endif /* _MSDOSFS_BPB_H_ */ #endif /* _MSDOSFS_BPB_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: denode.h,v 1.24 2014/07/08 09:21:52 hannken Exp $ */ /* $NetBSD: denode.h,v 1.25 2017/01/14 17:17:53 maya Exp $ */
/*- /*-
* Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@ -212,7 +212,8 @@ struct denode {
#define DE_INTERNALIZE32(dep, dp) \ #define DE_INTERNALIZE32(dep, dp) \
((dep)->de_StartCluster |= getushort((dp)->deHighClust) << 16) ((dep)->de_StartCluster |= getushort((dp)->deHighClust) << 16)
#define DE_INTERNALIZE(dep, dp) \ #define DE_INTERNALIZE(dep, dp) \
(memcpy((dep)->de_Name, (dp)->deName, 11), \ (memcpy((dep)->de_Name, (dp)->deName, 8), \
memcpy((dep)->de_Name+8, (dp)->deExtension, 3),\
(dep)->de_Attributes = (dp)->deAttributes, \ (dep)->de_Attributes = (dp)->deAttributes, \
(dep)->de_CHun = (dp)->deCHundredth, \ (dep)->de_CHun = (dp)->deCHundredth, \
(dep)->de_CTime = getushort((dp)->deCTime), \ (dep)->de_CTime = getushort((dp)->deCTime), \
@ -229,7 +230,8 @@ struct denode {
#define DE_EXTERNALIZE16(dp, dep) \ #define DE_EXTERNALIZE16(dp, dep) \
putushort((dp)->deHighClust, 0) putushort((dp)->deHighClust, 0)
#define DE_EXTERNALIZE(dp, dep) \ #define DE_EXTERNALIZE(dp, dep) \
(memcpy((dp)->deName, (dep)->de_Name, 11), \ (memcpy((dp)->deName, (dep)->de_Name, 8), \
memcpy((dp)->deExtension, (dep)->de_Name+8, 3),\
(dp)->deAttributes = (dep)->de_Attributes, \ (dp)->deAttributes = (dep)->de_Attributes, \
(dp)->deCHundredth = (dep)->de_CHun, \ (dp)->deCHundredth = (dep)->de_CHun, \
putushort((dp)->deCTime, (dep)->de_CTime), \ putushort((dp)->deCTime, (dep)->de_CTime), \

View File

@ -1,4 +1,4 @@
/* $NetBSD: direntry.h,v 1.7 2013/10/20 00:01:55 christos Exp $ */ /* $NetBSD: direntry.h,v 1.11 2016/02/01 02:59:33 christos Exp $ */
/*- /*-
* Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@ -53,12 +53,12 @@
* Structure of a dos directory entry. * Structure of a dos directory entry.
*/ */
struct direntry { struct direntry {
u_int8_t deName[8]; /* filename, blank filled */ uint8_t deName[8]; /* filename, blank filled */
#define SLOT_EMPTY 0x00 /* slot has never been used */ #define SLOT_EMPTY 0x00 /* slot has never been used */
#define SLOT_E5 0x05 /* the real value is 0xe5 */ #define SLOT_E5 0x05 /* the real value is 0xe5 */
#define SLOT_DELETED 0xe5 /* file in this slot deleted */ #define SLOT_DELETED 0xe5 /* file in this slot deleted */
u_int8_t deExtension[3]; /* extension, blank filled */ uint8_t deExtension[3]; /* extension, blank filled */
u_int8_t deAttributes; /* file attributes */ uint8_t deAttributes; /* file attributes */
#define ATTR_NORMAL 0x00 /* normal file */ #define ATTR_NORMAL 0x00 /* normal file */
#define ATTR_READONLY 0x01 /* file is readonly */ #define ATTR_READONLY 0x01 /* file is readonly */
#define ATTR_HIDDEN 0x02 /* file is hidden */ #define ATTR_HIDDEN 0x02 /* file is hidden */
@ -66,16 +66,16 @@ struct direntry {
#define ATTR_VOLUME 0x08 /* entry is a volume label */ #define ATTR_VOLUME 0x08 /* entry is a volume label */
#define ATTR_DIRECTORY 0x10 /* entry is a directory name */ #define ATTR_DIRECTORY 0x10 /* entry is a directory name */
#define ATTR_ARCHIVE 0x20 /* file is new or modified */ #define ATTR_ARCHIVE 0x20 /* file is new or modified */
u_int8_t deReserved; /* reserved */ uint8_t deReserved; /* reserved */
u_int8_t deCHundredth; /* hundredth of seconds in CTime */ uint8_t deCHundredth; /* hundredth of seconds in CTime */
u_int8_t deCTime[2]; /* create time */ uint8_t deCTime[2]; /* create time */
u_int8_t deCDate[2]; /* create date */ uint8_t deCDate[2]; /* create date */
u_int8_t deADate[2]; /* access date */ uint8_t deADate[2]; /* access date */
u_int8_t deHighClust[2]; /* high bytes of cluster number */ uint8_t deHighClust[2]; /* high bytes of cluster number */
u_int8_t deMTime[2]; /* last update time */ uint8_t deMTime[2]; /* last update time */
u_int8_t deMDate[2]; /* last update date */ uint8_t deMDate[2]; /* last update date */
u_int8_t deStartCluster[2]; /* starting cluster of file */ uint8_t deStartCluster[2]; /* starting cluster of file */
u_int8_t deFileSize[4]; /* size of file in bytes */ uint8_t deFileSize[4]; /* size of file in bytes */
}; };
static __inline uint8_t static __inline uint8_t
@ -88,17 +88,17 @@ msdos_dirchar(const struct direntry *de, size_t i) {
* Structure of a Win95 long name directory entry * Structure of a Win95 long name directory entry
*/ */
struct winentry { struct winentry {
u_int8_t weCnt; uint8_t weCnt;
#define WIN_LAST 0x40 #define WIN_LAST 0x40
#define WIN_CNT 0x3f #define WIN_CNT 0x3f
u_int8_t wePart1[10]; uint8_t wePart1[10];
u_int8_t weAttributes; uint8_t weAttributes;
#define ATTR_WIN95 0x0f #define ATTR_WIN95 0x0f
u_int8_t weReserved1; uint8_t weReserved1;
u_int8_t weChksum; uint8_t weChksum;
u_int8_t wePart2[12]; uint8_t wePart2[12];
u_int16_t weReserved2; uint16_t weReserved2;
u_int8_t wePart3[4]; uint8_t wePart3[4];
}; };
#define WIN_CHARS 13 /* Number of chars per winentry */ #define WIN_CHARS 13 /* Number of chars per winentry */
@ -128,19 +128,20 @@ struct winentry {
#if defined(_KERNEL) || defined(MAKEFS) #if defined(_KERNEL) || defined(MAKEFS)
struct dirent; struct dirent;
void unix2dostime(const struct timespec *tsp, int gmtoff, u_int16_t *ddp, void unix2dostime(const struct timespec *tsp, int gmtoff, uint16_t *ddp,
u_int16_t *dtp, u_int8_t *dhp); uint16_t *dtp, uint8_t *dhp);
void dos2unixtime(u_int dd, u_int dt, u_int dh, int gmtoff, void dos2unixtime(unsigned int dd, unsigned int dt, unsigned int dh,
struct timespec *tsp); int gmtoff, struct timespec *tsp);
int dos2unixfn(u_char dn[11], u_char *un, int lower); int dos2unixfn(unsigned char dn[11], unsigned char *un, int lower);
int unix2dosfn(const u_char *un, u_char dn[12], int unlen, int unix2dosfn(const unsigned char *un, unsigned char dn[12], int unlen,
u_int gen); unsigned int gen);
int unix2winfn(const u_char *un, int unlen, struct winentry *wep, int unix2winfn(const unsigned char *un, int unlen, struct winentry *wep,
int cnt, int chksum); int cnt, int chksum, int utf8);
int winChkName(const u_char *un, int unlen, struct winentry *wep, int winChkName(const unsigned char *un, int unlen, struct winentry *wep,
int chksum); int chksum, int utf8);
int win2unixfn(struct winentry *wep, struct dirent *dp, int chksum); int win2unixfn(struct winentry *wep, struct dirent *dp, int chksum,
u_int8_t winChksum(u_int8_t *name); uint16_t *namlen, int utf8);
int winSlotCnt(const u_char *un, int unlen); uint8_t winChksum(uint8_t *name);
int winSlotCnt(const unsigned char *un, int unlen, int utf8);
#endif /* _KERNEL || MAKEFS */ #endif /* _KERNEL || MAKEFS */
#endif /* _MSDOSFS_DIRENTRY_H_ */ #endif /* _MSDOSFS_DIRENTRY_H_ */

View File

@ -1,4 +1,4 @@
# $NetBSD: files.msdosfs,v 1.2 2014/10/11 06:42:18 uebayasi Exp $ # $NetBSD: files.msdosfs,v 1.3 2016/02/06 10:40:58 mlelstv Exp $
deffs MSDOSFS deffs MSDOSFS
@ -9,3 +9,4 @@ file fs/msdosfs/msdosfs_fat.c msdosfs
file fs/msdosfs/msdosfs_lookup.c msdosfs file fs/msdosfs/msdosfs_lookup.c msdosfs
file fs/msdosfs/msdosfs_vfsops.c msdosfs file fs/msdosfs/msdosfs_vfsops.c msdosfs
file fs/msdosfs/msdosfs_vnops.c msdosfs file fs/msdosfs/msdosfs_vnops.c msdosfs
file fs/msdosfs/msdosfs_unicode.c msdosfs

View File

@ -1,4 +1,4 @@
/* $NetBSD: msdosfs_conv.c,v 1.10 2014/09/01 09:09:47 martin Exp $ */ /* $NetBSD: msdosfs_conv.c,v 1.17 2016/06/30 09:34:01 nonaka Exp $ */
/*- /*-
* Copyright (C) 1995, 1997 Wolfgang Solfrank. * Copyright (C) 1995, 1997 Wolfgang Solfrank.
@ -45,20 +45,27 @@
* any damages caused by this software. * any damages caused by this software.
* *
* October 1992 * October 1992
*
*/ */
#if HAVE_NBTOOL_CONFIG_H #if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h" #include "nbtool_config.h"
#endif #endif
#ifndef _KERNEL
#include <assert.h>
#define KASSERT(x) assert(x)
#endif
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: msdosfs_conv.c,v 1.10 2014/09/01 09:09:47 martin Exp $"); __KERNEL_RCSID(0, "$NetBSD: msdosfs_conv.c,v 1.17 2016/06/30 09:34:01 nonaka Exp $");
/* /*
* System include files. * System include files.
*/ */
#include <sys/param.h> #include <sys/param.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/endian.h>
#ifdef _KERNEL #ifdef _KERNEL
#include <sys/dirent.h> #include <sys/dirent.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -78,6 +85,22 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_conv.c,v 1.10 2014/09/01 09:09:47 martin Exp
#include <fs/msdosfs/direntry.h> #include <fs/msdosfs/direntry.h>
#include <fs/msdosfs/denode.h> #include <fs/msdosfs/denode.h>
static int invalidname(const u_int16_t *, int);
static int ucs2utf8(const u_int16_t *, u_int8_t *, int);
static int utf8ucs2(const u_int8_t *, int, u_int16_t *);
static int ucs2utf8str(const u_int16_t *, int, u_int8_t *, int);
static int utf8ucs2str(const u_int8_t *, int, u_int16_t *, int);
static int ucs2char8str(const u_int16_t *, int, u_int8_t *, int);
static int char8ucs2str(const u_int8_t *, int, u_int16_t *, int);
static void ucs2pad(u_int16_t *, int, int);
static u_int16_t ucs2fold(u_int16_t);
static int ucs2match(u_int16_t *, u_int16_t *, int n);
static int char8match(u_int16_t *, u_int16_t *, int n);
/* /*
* The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that * The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that
* interval there were 8 regular years and 2 leap years. * interval there were 8 regular years and 2 leap years.
@ -513,24 +536,34 @@ unix2dosfn(const u_char *un, u_char dn[12], int unlen, u_int gen)
* i.e. doesn't consist solely of blanks and dots * i.e. doesn't consist solely of blanks and dots
*/ */
int int
unix2winfn(const u_char *un, int unlen, struct winentry *wep, int cnt, int chksum) unix2winfn(const u_char *un, int unlen, struct winentry *wep, int cnt, int chksum, int utf8)
{ {
const u_int8_t *cp; u_int16_t wn[WIN_MAXLEN], *p;
u_int8_t *wcp; int i, len;
int i; const u_char *cp;
/* /*
* Drop trailing blanks and dots * Drop trailing blanks and dots
*/ */
for (cp = un + unlen; *--cp == ' ' || *cp == '.'; unlen--); for (cp = un + unlen; unlen > 0; unlen--)
if (*--cp != ' ' && *cp != '.')
break;
un += (cnt - 1) * WIN_CHARS; /*
unlen -= (cnt - 1) * WIN_CHARS; * Offset of this entry
*/
i = (cnt - 1) * WIN_CHARS;
/*
* Translate UNIX name to ucs-2
*/
len = utf8 ? utf8ucs2str(un, unlen, wn, WIN_MAXLEN) : char8ucs2str(un, unlen, wn, WIN_MAXLEN);
ucs2pad(wn, len, WIN_MAXLEN);
/* /*
* Initialize winentry to some useful default * Initialize winentry to some useful default
*/ */
for (wcp = (u_int8_t *)wep, i = sizeof(*wep); --i >= 0; *wcp++ = 0xff); memset(wep, 0xff, sizeof(*wep));
wep->weCnt = cnt; wep->weCnt = cnt;
wep->weAttributes = ATTR_WIN95; wep->weAttributes = ATTR_WIN95;
wep->weReserved1 = 0; wep->weReserved1 = 0;
@ -538,33 +571,18 @@ unix2winfn(const u_char *un, int unlen, struct winentry *wep, int cnt, int chksu
wep->weReserved2 = 0; wep->weReserved2 = 0;
/* /*
* Now convert the filename parts * Store name segment into directory entry
*/ */
for (wcp = wep->wePart1, i = sizeof(wep->wePart1)/2; --i >= 0;) { p = &wn[i];
if (--unlen < 0) memcpy(wep->wePart1, p, sizeof(wep->wePart1));
goto done; p += sizeof(wep->wePart1) / sizeof(*p);
*wcp++ = *un++; memcpy(wep->wePart2, p, sizeof(wep->wePart2));
*wcp++ = 0; p += sizeof(wep->wePart2) / sizeof(*p);
} memcpy(wep->wePart3, p, sizeof(wep->wePart3));
for (wcp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) {
if (--unlen < 0) if (len > i + WIN_CHARS)
goto done; return 1;
*wcp++ = *un++;
*wcp++ = 0;
}
for (wcp = wep->wePart3, i = sizeof(wep->wePart3)/2; --i >= 0;) {
if (--unlen < 0)
goto done;
*wcp++ = *un++;
*wcp++ = 0;
}
if (!unlen)
wep->weCnt |= WIN_LAST;
return unlen;
done:
*wcp++ = 0;
*wcp++ = 0;
wep->weCnt |= WIN_LAST; wep->weCnt |= WIN_LAST;
return 0; return 0;
} }
@ -574,15 +592,16 @@ done:
* Returns the checksum or -1 if no match * Returns the checksum or -1 if no match
*/ */
int int
winChkName(const u_char *un, int unlen, struct winentry *wep, int chksum) winChkName(const u_char *un, int unlen, struct winentry *wep, int chksum, int utf8)
{ {
u_int8_t *cp; u_int16_t wn[WIN_MAXLEN], *p;
int i; u_int16_t buf[WIN_CHARS];
int i, len;
/* /*
* First compare checksums * First compare checksums
*/ */
if (wep->weCnt&WIN_LAST) if (wep->weCnt & WIN_LAST)
chksum = wep->weChksum; chksum = wep->weChksum;
else if (chksum != wep->weChksum) else if (chksum != wep->weChksum)
chksum = -1; chksum = -1;
@ -592,56 +611,35 @@ winChkName(const u_char *un, int unlen, struct winentry *wep, int chksum)
/* /*
* Offset of this entry * Offset of this entry
*/ */
i = ((wep->weCnt&WIN_CNT) - 1) * WIN_CHARS; i = ((wep->weCnt & WIN_CNT) - 1) * WIN_CHARS;
un += i;
if ((unlen -= i) < 0) /*
* Translate UNIX name to ucs-2
*/
len = utf8 ? utf8ucs2str(un, unlen, wn, WIN_MAXLEN) : 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; return -1;
/* /*
* Ignore redundant winentries (those with only \0\0 on start in them). * Fetch name segment from directory entry
* An appearance of such entry is a bug; unknown if in NetBSD msdosfs
* or MS Windows.
*/ */
if (unlen == 0) { p = &buf[0];
if (wep->wePart1[0] == '\0' && wep->wePart1[1] == '\0') memcpy(p, wep->wePart1, sizeof(wep->wePart1));
return chksum; p += sizeof(wep->wePart1) / sizeof(*p);
else memcpy(p, wep->wePart2, sizeof(wep->wePart2));
return -1; p += sizeof(wep->wePart2) / sizeof(*p);
} memcpy(p, wep->wePart3, sizeof(wep->wePart3));
if ((wep->weCnt&WIN_LAST) && unlen > WIN_CHARS)
return -1;
/* /*
* Compare the name parts * And compare name segment
*/ */
for (cp = wep->wePart1, i = sizeof(wep->wePart1)/2; --i >= 0;) { if (! (utf8 ? ucs2match(&wn[i], buf, WIN_CHARS) : char8match(&wn[i], buf, WIN_CHARS)))
if (--unlen < 0) { return -1;
if (!*cp++ && !*cp)
return chksum;
return -1;
}
if (u2l[*cp++] != u2l[*un++] || *cp++)
return -1;
}
for (cp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) {
if (--unlen < 0) {
if (!*cp++ && !*cp)
return chksum;
return -1;
}
if (u2l[*cp++] != u2l[*un++] || *cp++)
return -1;
}
for (cp = wep->wePart3, i = sizeof(wep->wePart3)/2; --i >= 0;) {
if (--unlen < 0) {
if (!*cp++ && !*cp)
return chksum;
return -1;
}
if (u2l[*cp++] != u2l[*un++] || *cp++)
return -1;
}
return chksum; return chksum;
} }
@ -650,110 +648,73 @@ winChkName(const u_char *un, int unlen, struct winentry *wep, int chksum)
* Returns the checksum or -1 if impossible * Returns the checksum or -1 if impossible
*/ */
int int
win2unixfn(struct winentry *wep, struct dirent *dp, int chksum) win2unixfn(struct winentry *wep, struct dirent *dp, int chksum,
uint16_t *namlen, int utf8)
{ {
u_int8_t *cp; u_int16_t wn[WIN_CHARS], *p;
u_int8_t *np, *ep = (u_int8_t *)dp->d_name + WIN_MAXLEN; u_int8_t buf[WIN_CHARS*3];
int i; int len;
if ((wep->weCnt&WIN_CNT) > howmany(WIN_MAXLEN, WIN_CHARS) if ((wep->weCnt & WIN_CNT) > howmany(WIN_MAXLEN, WIN_CHARS)
|| !(wep->weCnt&WIN_CNT)) || !(wep->weCnt & WIN_CNT))
return -1; return -1;
/* /*
* First compare checksums * First compare checksums
*/ */
if (wep->weCnt&WIN_LAST) { if (wep->weCnt & WIN_LAST) {
chksum = wep->weChksum; chksum = wep->weChksum;
/* *namlen = 0;
* This works even though d_namlen is one byte!
*/
#ifdef __NetBSD__
dp->d_namlen = (wep->weCnt&WIN_CNT) * WIN_CHARS;
#endif
} else if (chksum != wep->weChksum) } else if (chksum != wep->weChksum)
chksum = -1; chksum = -1;
if (chksum == -1) if (chksum == -1)
return -1; return -1;
/* /*
* Offset of this entry * Fetch name segment from directory entry
*/ */
i = ((wep->weCnt&WIN_CNT) - 1) * WIN_CHARS; p = &wn[0];
np = (u_int8_t *)dp->d_name + i; 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));
/* /*
* Convert the name parts * Don't allow slashes in UNIX names. Discard that entry.
*/ */
for (cp = wep->wePart1, i = sizeof(wep->wePart1)/2; --i >= 0;) { if (invalidname(wn, WIN_CHARS))
switch (*np++ = *cp++) { return -1;
case 0:
#ifdef __NetBSD__ /*
dp->d_namlen -= sizeof(wep->wePart2)/2 * Translate ucs-2 to UNIX name
+ sizeof(wep->wePart3)/2 + i + 1; */
#endif len = utf8 ? ucs2utf8str(wn, WIN_CHARS, buf, sizeof(buf))
return chksum; : ucs2char8str(wn, WIN_CHARS, buf, sizeof(buf));
case '/':
np[-1] = 0; KASSERT(len >= 0);
return -1; KASSERT((size_t)len <= MIN(sizeof(buf), sizeof(dp->d_name)-1));
}
/* /*
* The size comparison should result in the compiler * Prepend name segment to directory entry
* optimizing the whole if away *
*/ * This ignores the slot number from the windows entry but
if (WIN_MAXLEN % WIN_CHARS < sizeof(wep->wePart1) / 2 * assumes that segments are read in reverse order.
&& np > ep) { *
np[-1] = 0; * The UCS-2 name (up to 255 chars) can overflow the UNIX
return -1; * directory entry (up to 511 bytes). Trailing characters
} * are silently discarded. This could also end in multiple
if (*cp++) * files using the same (truncated) name.
return -1; */
} *namlen += len;
for (cp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) { if (*namlen > sizeof(dp->d_name) - 1)
switch (*np++ = *cp++) { *namlen = sizeof(dp->d_name) - 1;
case 0:
#ifdef __NetBSD__ KASSERT(*namlen >= len);
dp->d_namlen -= sizeof(wep->wePart3)/2 + i + 1;
#endif memmove(&dp->d_name[len], &dp->d_name[0], *namlen - len);
return chksum; memcpy(dp->d_name, buf, len);
case '/':
np[-1] = 0;
return -1;
}
/*
* The size comparisons should be optimized away
*/
if (WIN_MAXLEN % WIN_CHARS >= sizeof(wep->wePart1) / 2
&& WIN_MAXLEN % WIN_CHARS < (sizeof(wep->wePart1) + sizeof(wep->wePart2)) / 2
&& np > ep) {
np[-1] = 0;
return -1;
}
if (*cp++)
return -1;
}
for (cp = wep->wePart3, i = sizeof(wep->wePart3)/2; --i >= 0;) {
switch (*np++ = *cp++) {
case 0:
#ifdef __NetBSD__
dp->d_namlen -= i + 1;
#endif
return chksum;
case '/':
np[-1] = 0;
return -1;
}
/*
* See above
*/
if (WIN_MAXLEN % WIN_CHARS >= (sizeof(wep->wePart1) + sizeof(wep->wePart2)) / 2
&& np > ep) {
np[-1] = 0;
return -1;
}
if (*cp++)
return -1;
}
return chksum; return chksum;
} }
@ -767,7 +728,7 @@ winChksum(u_int8_t *name)
u_int8_t s; u_int8_t s;
for (s = 0, i = 11; --i >= 0; s += *name++) for (s = 0, i = 11; --i >= 0; s += *name++)
s = (s << 7)|(s >> 1); s = (s << 7) | (s >> 1);
return s; return s;
} }
@ -775,12 +736,304 @@ winChksum(u_int8_t *name)
* Determine the number of slots necessary for Win95 names * Determine the number of slots necessary for Win95 names
*/ */
int int
winSlotCnt(const u_char *un, int unlen) winSlotCnt(const u_char *un, int unlen, int utf8)
{ {
for (un += unlen; unlen > 0; unlen--) const u_char *cp;
if (*--un != ' ' && *un != '.') int len;
/*
* Drop trailing blanks and dots
*/
for (cp = un + unlen; unlen > 0; unlen--)
if (*--cp != ' ' && *cp != '.')
break; break;
if (unlen > WIN_MAXLEN)
return 0; len = utf8 ? utf8ucs2str(un, unlen, NULL, WIN_MAXLEN) : unlen;
return howmany(unlen, WIN_CHARS);
return howmany(len, WIN_CHARS);
} }
/*
* Scan windows name for characters that must not
* appear in a UNIX filename
*/
static int
invalidname(const u_int16_t *in, int n)
{
while (n-- > 0) {
if (*in++ == '/')
return 1;
}
return 0;
}
/*
* Convert UCS-2 character into UTF-8
* return number of output bytes or 0 if output
* buffer is too short
*/
static int
ucs2utf8(const u_int16_t *in, u_int8_t *out, int n)
{
uint16_t inch = le16toh(in[0]);
if (inch <= 0x007f) {
if (n < 1) return 0;
if (out)
*out++ = inch;
return 1;
} else if (inch <= 0x07ff) {
if (n < 2) return 0;
if (out) {
*out++ = 0xc0 | (inch >> 6);
*out++ = 0x80 | (inch & 0x3f);
}
return 2;
} else {
if (n < 3) return 0;
if (out) {
*out++ = 0xe0 | (inch >> 12);
*out++ = 0x80 | ((inch >> 6) & 0x3f);
*out++ = 0x80 | (inch & 0x3f);
}
return 3;
}
}
/*
* Convert UTF-8 bytes into UCS-2 character
* return number of input bytes, 0 if input
* is too short and -1 if input is invalid
*/
static int
utf8ucs2(const u_int8_t *in, int n, u_int16_t *out)
{
uint16_t outch;
if (n < 1) return 0;
if (in[0] <= 0x7f) {
outch = in[0];
if (out)
*out = htole16(outch);
return 1;
} else if (in[0] <= 0xdf) {
if (n < 2) return 0;
outch = (in[0] & 0x1f) << 6 | (in[1] & 0x3f);
if (out)
*out = htole16(outch);
return 2;
} else if (in[0] <= 0xef) {
if (n < 3) return 0;
outch = (in[0] & 0x1f) << 12 | (in[1] & 0x3f) << 6 | (in[2] & 0x3f);
if (out)
*out = htole16(outch);
return 3;
}
return -1;
}
/*
* Convert UCS-2 string into UTF-8 string
* return total number of output bytes
*/
static int
ucs2utf8str(const u_int16_t *in, int n, u_int8_t *out, int m)
{
u_int8_t *p;
int outlen;
p = out;
while (n > 0 && *in != 0) {
outlen = ucs2utf8(in, out ? p : out, m);
if (outlen == 0)
break;
p += outlen;
m -= outlen;
in += 1;
n -= 1;
}
return p - out;
}
/*
* Convert UTF8 string into UCS-2 string
* return total number of output chacters
*/
static int
utf8ucs2str(const u_int8_t *in, int n, u_int16_t *out, int m)
{
u_int16_t *p;
int inlen;
p = out;
while (n > 0 && *in != 0) {
if (m < 1)
break;
inlen = utf8ucs2(in, n, out ? p : out);
if (inlen <= 0)
break;
in += inlen;
n -= inlen;
p += 1;
m -= 1;
}
return p - out;
}
/*
* Convert UCS-2 string into 8bit character string
* return total number of output bytes
*/
static int
ucs2char8str(const u_int16_t *in, int n, u_int8_t *out, int m)
{
u_int8_t *p;
u_int16_t inch;
p = out;
while (n > 0 && in[0] != 0) {
if (m < 1)
break;
inch = le16toh(in[0]);
if (inch > 255)
break;
if (p)
p[0] = inch;
p += 1;
m -= 1;
in += 1;
n -= 1;
}
return p - out;
}
/*
* Convert 8bit character string into UCS-2 string
* return total number of output chacters
*/
static int
char8ucs2str(const u_int8_t *in, int n, u_int16_t *out, int m)
{
u_int16_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(u_int16_t *buf, int len, int size)
{
if (len < size-1)
buf[len++] = 0x0000;
while (len < size)
buf[len++] = 0xffff;
}
/*
* Fold UCS-2 character to uppercase
*/
static u_int16_t
ucs2fold(u_int16_t w)
{
int low,high,mid;
u_int16_t check;
extern const u_int16_t msdosfs_unicode_foldmap[];
extern size_t msdosfs_unicode_foldmap_entries;
w = le16toh(w);
low = 0;
high = msdosfs_unicode_foldmap_entries / 2;
while (low < high) {
mid = (low + high)/2;
check = msdosfs_unicode_foldmap[2*mid+0];
if (w == check) {
w = msdosfs_unicode_foldmap[2*mid+1];
break;
}
if (w < check)
high = mid;
else
low = mid+1;
}
w = le16toh(w);
return w;
}
/*
* Compare two UCS-2 strings case-insensitive
*
* uses the Unicode case folding table
*/
static int
ucs2match(u_int16_t *w1, u_int16_t *w2, int n)
{
u_int16_t u1, u2;
while (n > 0) {
if (*w1 == 0 || *w2 == 0)
return *w1 == *w2;
u1 = ucs2fold(*w1);
u2 = ucs2fold(*w2);
if (u1 != u2)
return 0;
++w1;
++w2;
--n;
}
return 1;
}
/*
* Compare two 8bit char conversions case-insensitive
*
* uses the DOS case folding table
*/
static int
char8match(u_int16_t *w1, u_int16_t *w2, int n)
{
u_int16_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;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: msdosfs_denode.c,v 1.51 2015/03/28 19:24:05 maxv Exp $ */ /* $NetBSD: msdosfs_denode.c,v 1.59 2020/04/23 21:47:07 ad Exp $ */
/*- /*-
* Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@ -48,12 +48,11 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: msdosfs_denode.c,v 1.51 2015/03/28 19:24:05 maxv Exp $"); __KERNEL_RCSID(0, "$NetBSD: msdosfs_denode.c,v 1.59 2020/04/23 21:47:07 ad Exp $");
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/fstrans.h>
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/pool.h> #include <sys/pool.h>
#include <sys/proc.h> #include <sys/proc.h>
@ -74,8 +73,6 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_denode.c,v 1.51 2015/03/28 19:24:05 maxv Exp
struct pool msdosfs_denode_pool; struct pool msdosfs_denode_pool;
extern int prtactive;
struct fh_key { struct fh_key {
struct msdosfsmount *fhk_mount; struct msdosfsmount *fhk_mount;
uint32_t fhk_dircluster; uint32_t fhk_dircluster;
@ -128,6 +125,7 @@ static const struct genfs_ops msdosfs_genfsops = {
.gop_alloc = msdosfs_gop_alloc, .gop_alloc = msdosfs_gop_alloc,
.gop_write = genfs_gop_write, .gop_write = genfs_gop_write,
.gop_markupdate = msdosfs_gop_markupdate, .gop_markupdate = msdosfs_gop_markupdate,
.gop_putrange = genfs_gop_putrange,
}; };
MALLOC_DECLARE(M_MSDOSFSFAT); MALLOC_DECLARE(M_MSDOSFSFAT);
@ -427,7 +425,7 @@ detrunc(struct denode *dep, u_long length, int flags, kauth_cred_t cred)
} else { } else {
ubc_zerorange(&DETOV(dep)->v_uobj, length, ubc_zerorange(&DETOV(dep)->v_uobj, length,
pmp->pm_bpcluster - boff, pmp->pm_bpcluster - boff,
UBC_UNMAP_FLAG(DETOV(dep))); UBC_VNODE_FLAGS(DETOV(dep)));
} }
} }
@ -525,7 +523,7 @@ deextend(struct denode *dep, u_long length, kauth_cred_t cred)
dep->de_flag |= DE_UPDATE|DE_MODIFIED; dep->de_flag |= DE_UPDATE|DE_MODIFIED;
ubc_zerorange(&DETOV(dep)->v_uobj, (off_t)osize, ubc_zerorange(&DETOV(dep)->v_uobj, (off_t)osize,
(size_t)(round_page(dep->de_FileSize) - osize), (size_t)(round_page(dep->de_FileSize) - osize),
UBC_UNMAP_FLAG(DETOV(dep))); UBC_VNODE_FLAGS(DETOV(dep)));
uvm_vnp_setsize(DETOV(dep), (voff_t)dep->de_FileSize); uvm_vnp_setsize(DETOV(dep), (voff_t)dep->de_FileSize);
return (deupdat(dep, 1)); return (deupdat(dep, 1));
} }
@ -533,25 +531,19 @@ deextend(struct denode *dep, u_long length, kauth_cred_t cred)
int int
msdosfs_reclaim(void *v) msdosfs_reclaim(void *v)
{ {
struct vop_reclaim_args /* { struct vop_reclaim_v2_args /* {
struct vnode *a_vp; struct vnode *a_vp;
} */ *ap = v; } */ *ap = v;
struct vnode *vp = ap->a_vp; struct vnode *vp = ap->a_vp;
struct mount *mp = vp->v_mount;
struct denode *dep = VTODE(vp); struct denode *dep = VTODE(vp);
fstrans_start(mp, FSTRANS_LAZY); VOP_UNLOCK(vp);
#ifdef MSDOSFS_DEBUG #ifdef MSDOSFS_DEBUG
printf("msdosfs_reclaim(): dep %p, file %s, refcnt %ld\n", printf("msdosfs_reclaim(): dep %p, file %s, refcnt %ld\n",
dep, dep->de_Name, dep->de_refcnt); dep, dep->de_Name, dep->de_refcnt);
#endif #endif
if (prtactive && vp->v_usecount > 1)
vprint("msdosfs_reclaim(): pushing active", vp);
/*
* Remove the denode from the vnode cache.
*/
vcache_remove(vp->v_mount, &dep->de_key, sizeof(dep->de_key));
/* /*
* Purge old data structures associated with the denode. * Purge old data structures associated with the denode.
*/ */
@ -570,19 +562,17 @@ msdosfs_reclaim(void *v)
vp->v_data = NULL; vp->v_data = NULL;
mutex_exit(vp->v_interlock); mutex_exit(vp->v_interlock);
pool_put(&msdosfs_denode_pool, dep); pool_put(&msdosfs_denode_pool, dep);
fstrans_done(mp);
return (0); return (0);
} }
int int
msdosfs_inactive(void *v) msdosfs_inactive(void *v)
{ {
struct vop_inactive_args /* { struct vop_inactive_v2_args /* {
struct vnode *a_vp; struct vnode *a_vp;
bool *a_recycle; bool *a_recycle;
} */ *ap = v; } */ *ap = v;
struct vnode *vp = ap->a_vp; struct vnode *vp = ap->a_vp;
struct mount *mp = vp->v_mount;
struct denode *dep = VTODE(vp); struct denode *dep = VTODE(vp);
int error = 0; int error = 0;
@ -590,7 +580,6 @@ msdosfs_inactive(void *v)
printf("msdosfs_inactive(): dep %p, de_Name[0] %x\n", dep, dep->de_Name[0]); printf("msdosfs_inactive(): dep %p, de_Name[0] %x\n", dep, dep->de_Name[0]);
#endif #endif
fstrans_start(mp, FSTRANS_LAZY);
/* /*
* Get rid of denodes related to stale file handles. * Get rid of denodes related to stale file handles.
*/ */
@ -622,12 +611,11 @@ out:
* so that it can be reused immediately. * so that it can be reused immediately.
*/ */
#ifdef MSDOSFS_DEBUG #ifdef MSDOSFS_DEBUG
printf("msdosfs_inactive(): v_usecount %d, de_Name[0] %x\n", printf("msdosfs_inactive(): usecount %d, de_Name[0] %x\n",
vp->v_usecount, dep->de_Name[0]); vrefcnt(vp), dep->de_Name[0]);
#endif #endif
*ap->a_recycle = (dep->de_Name[0] == SLOT_DELETED); *ap->a_recycle = (dep->de_Name[0] == SLOT_DELETED);
VOP_UNLOCK(vp);
fstrans_done(mp);
return (error); return (error);
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: msdosfs_fat.c,v 1.29 2015/03/28 19:24:05 maxv Exp $ */ /* $NetBSD: msdosfs_fat.c,v 1.35 2020/09/07 01:35:25 mrg Exp $ */
/*- /*-
* Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@ -52,7 +52,7 @@
#endif #endif
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: msdosfs_fat.c,v 1.29 2015/03/28 19:24:05 maxv Exp $"); __KERNEL_RCSID(0, "$NetBSD: msdosfs_fat.c,v 1.35 2020/09/07 01:35:25 mrg Exp $");
/* /*
* kernel include files. * kernel include files.
@ -69,6 +69,7 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_fat.c,v 1.29 2015/03/28 19:24:05 maxv Exp $"
#include <sys/buf.h> #include <sys/buf.h>
#include <sys/vnode.h> /* to define vattr structure */ #include <sys/vnode.h> /* to define vattr structure */
#else #else
#include <strings.h>
#include <ffs/buf.h> #include <ffs/buf.h>
#endif #endif
@ -143,7 +144,7 @@ fatblock(struct msdosfsmount *pmp, u_long ofs, u_long *bnp, u_long *sizep, u_lon
u_long bn, size; u_long bn, size;
bn = ofs / pmp->pm_fatblocksize * pmp->pm_fatblocksec; bn = ofs / pmp->pm_fatblocksize * pmp->pm_fatblocksec;
size = min(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn) size = uimin(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn)
* pmp->pm_BytesPerSec; * pmp->pm_BytesPerSec;
bn += pmp->pm_fatblk + pmp->pm_curfat * pmp->pm_FATsecs; bn += pmp->pm_fatblk + pmp->pm_curfat * pmp->pm_FATsecs;
@ -227,7 +228,7 @@ pcbmap(struct denode *dep, u_long findcn, daddr_t *bnp, u_long *cnp, int *sp)
if (cnp) if (cnp)
*cnp = MSDOSFSROOT; *cnp = MSDOSFSROOT;
if (sp) if (sp)
*sp = min(pmp->pm_bpcluster, *sp = uimin(pmp->pm_bpcluster,
dep->de_FileSize - de_cn2off(pmp, findcn)); dep->de_FileSize - de_cn2off(pmp, findcn));
DPRINTF(("%s(root, bn=%lu, cn=%u)\n", __func__, DPRINTF(("%s(root, bn=%lu, cn=%u)\n", __func__,
pmp->pm_rootdirblk + de_cn2bn(pmp, findcn), pmp->pm_rootdirblk + de_cn2bn(pmp, findcn),
@ -273,6 +274,18 @@ pcbmap(struct denode *dep, u_long findcn, daddr_t *bnp, u_long *cnp, int *sp)
*/ */
if (cn >= (CLUST_RSRVD & pmp->pm_fatmask)) if (cn >= (CLUST_RSRVD & pmp->pm_fatmask))
goto hiteof; goto hiteof;
/*
* Also stop when cluster is not in the filesystem
*/
if (cn < CLUST_FIRST || cn > pmp->pm_maxcluster) {
DPRINTF(("%s(cn, %lu not in %lu..%lu)\n", __func__,
cn, (u_long)CLUST_FIRST, pmp->pm_maxcluster));
if (bp)
brelse(bp, 0);
return (EINVAL);
}
byteoffset = FATOFS(pmp, cn); byteoffset = FATOFS(pmp, cn);
fatblock(pmp, byteoffset, &bn, &bsize, &bo); fatblock(pmp, byteoffset, &bn, &bsize, &bo);
if (bn != bp_bn) { if (bn != bp_bn) {
@ -383,7 +396,7 @@ fc_purge(struct denode *dep, u_int frcn)
void void
updatefats(struct msdosfsmount *pmp, struct buf *bp, u_long fatbn) updatefats(struct msdosfsmount *pmp, struct buf *bp, u_long fatbn)
{ {
int i; int i, error;
struct buf *bpn; struct buf *bpn;
DPRINTF(("%s(pmp %p, bp %p, fatbn %lu)\n", __func__, pmp, bp, fatbn)); DPRINTF(("%s(pmp %p, bp %p, fatbn %lu)\n", __func__, pmp, bp, fatbn));
@ -396,7 +409,7 @@ updatefats(struct msdosfsmount *pmp, struct buf *bp, u_long fatbn)
if (pmp->pm_freeclustercount if (pmp->pm_freeclustercount
&& (pmp->pm_inusemap[cn / N_INUSEBITS] && (pmp->pm_inusemap[cn / N_INUSEBITS]
& (1 << (cn % N_INUSEBITS)))) { & (1U << (cn % N_INUSEBITS)))) {
/* /*
* The cluster indicated in FSInfo isn't free * The cluster indicated in FSInfo isn't free
* any longer. Got get a new free one. * any longer. Got get a new free one.
@ -448,9 +461,12 @@ updatefats(struct msdosfsmount *pmp, struct buf *bp, u_long fatbn)
bpn = getblk(pmp->pm_devvp, de_bn2kb(pmp, fatbn), bpn = getblk(pmp->pm_devvp, de_bn2kb(pmp, fatbn),
bp->b_bcount, 0, 0); bp->b_bcount, 0, 0);
memcpy(bpn->b_data, bp->b_data, bp->b_bcount); memcpy(bpn->b_data, bp->b_data, bp->b_bcount);
if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) {
bwrite(bpn); error = bwrite(bpn);
else if (error)
printf("%s: copy FAT %d (error=%d)\n",
__func__, i, error);
} else
bdwrite(bpn); bdwrite(bpn);
} }
} }
@ -458,9 +474,12 @@ updatefats(struct msdosfsmount *pmp, struct buf *bp, u_long fatbn)
/* /*
* Write out the first (or current) FAT last. * Write out the first (or current) FAT last.
*/ */
if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) {
bwrite(bp); error = bwrite(bp);
else if (error)
printf("%s: write FAT (error=%d)\n",
__func__, error);
} else
bdwrite(bp); bdwrite(bp);
/* /*
* Maybe update fsinfo sector here? * Maybe update fsinfo sector here?
@ -490,7 +509,7 @@ static inline void
usemap_alloc(struct msdosfsmount *pmp, u_long cn) usemap_alloc(struct msdosfsmount *pmp, u_long cn)
{ {
pmp->pm_inusemap[cn / N_INUSEBITS] |= 1 << (cn % N_INUSEBITS); pmp->pm_inusemap[cn / N_INUSEBITS] |= 1U << (cn % N_INUSEBITS);
pmp->pm_freeclustercount--; pmp->pm_freeclustercount--;
} }
@ -499,7 +518,7 @@ usemap_free(struct msdosfsmount *pmp, u_long cn)
{ {
pmp->pm_freeclustercount++; pmp->pm_freeclustercount++;
pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1 << (cn % N_INUSEBITS)); pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1U << (cn % N_INUSEBITS));
} }
int int
@ -722,7 +741,7 @@ chainlength(struct msdosfsmount *pmp, u_long start, u_long count)
idx = start / N_INUSEBITS; idx = start / N_INUSEBITS;
start %= N_INUSEBITS; start %= N_INUSEBITS;
map = pmp->pm_inusemap[idx]; map = pmp->pm_inusemap[idx];
map &= ~((1 << start) - 1); map &= ~((1U << start) - 1);
if (map) { if (map) {
len = ffs(map) - 1 - start; len = ffs(map) - 1 - start;
return (len > count ? count : len); return (len > count ? count : len);
@ -818,7 +837,7 @@ clusteralloc(struct msdosfsmount *pmp, u_long start, u_long count, u_long *retcl
for (cn = newst; cn <= pmp->pm_maxcluster;) { for (cn = newst; cn <= pmp->pm_maxcluster;) {
idx = cn / N_INUSEBITS; idx = cn / N_INUSEBITS;
map = pmp->pm_inusemap[idx]; map = pmp->pm_inusemap[idx];
map |= (1 << (cn % N_INUSEBITS)) - 1; map |= (1U << (cn % N_INUSEBITS)) - 1;
if (map != (u_int)-1) { if (map != (u_int)-1) {
cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1; cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1;
if ((l = chainlength(pmp, cn, count)) >= count) if ((l = chainlength(pmp, cn, count)) >= count)
@ -835,7 +854,7 @@ clusteralloc(struct msdosfsmount *pmp, u_long start, u_long count, u_long *retcl
for (cn = 0; cn < newst;) { for (cn = 0; cn < newst;) {
idx = cn / N_INUSEBITS; idx = cn / N_INUSEBITS;
map = pmp->pm_inusemap[idx]; map = pmp->pm_inusemap[idx];
map |= (1 << (cn % N_INUSEBITS)) - 1; map |= (1U << (cn % N_INUSEBITS)) - 1;
if (map != (u_int)-1) { if (map != (u_int)-1) {
cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1; cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1;
if ((l = chainlength(pmp, cn, count)) >= count) if ((l = chainlength(pmp, cn, count)) >= count)
@ -876,6 +895,7 @@ freeclusterchain(struct msdosfsmount *pmp, u_long cluster)
u_long bn, bo, bsize, byteoffset; u_long bn, bo, bsize, byteoffset;
u_long readcn, lbn = -1; u_long readcn, lbn = -1;
bn = 0; /* XXXgcc */
while (cluster >= CLUST_FIRST && cluster <= pmp->pm_maxcluster) { while (cluster >= CLUST_FIRST && cluster <= pmp->pm_maxcluster) {
byteoffset = FATOFS(pmp, cluster); byteoffset = FATOFS(pmp, cluster);
fatblock(pmp, byteoffset, &bn, &bsize, &bo); fatblock(pmp, byteoffset, &bn, &bsize, &bo);

View File

@ -1,4 +1,4 @@
/* $NetBSD: msdosfs_lookup.c,v 1.34 2015/03/28 19:24:05 maxv Exp $ */ /* $NetBSD: msdosfs_lookup.c,v 1.36 2020/04/04 20:49:30 ad Exp $ */
/*- /*-
* Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@ -52,7 +52,7 @@
#endif #endif
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: msdosfs_lookup.c,v 1.34 2015/03/28 19:24:05 maxv Exp $"); __KERNEL_RCSID(0, "$NetBSD: msdosfs_lookup.c,v 1.36 2020/04/04 20:49:30 ad Exp $");
#include <sys/param.h> #include <sys/param.h>
@ -161,6 +161,10 @@ msdosfs_lookup(void *v)
return *vpp == NULLVP ? ENOENT: 0; return *vpp == NULLVP ? ENOENT: 0;
} }
/* May need to restart the lookup with an exclusive lock. */
if (VOP_ISLOCKED(vdp) != LK_EXCLUSIVE)
return ENOLCK;
/* /*
* If they are going after the . or .. entry in the root directory, * 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 * they won't find it. DOS filesystems don't have them in the root
@ -187,12 +191,12 @@ msdosfs_lookup(void *v)
break; break;
case 2: case 2:
wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr,
cnp->cn_namelen) + 1; cnp->cn_namelen, pmp->pm_flags & MSDOSFSMNT_UTF8) + 1;
break; break;
case 3: case 3:
olddos = 0; olddos = 0;
wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr,
cnp->cn_namelen) + 1; cnp->cn_namelen, pmp->pm_flags & MSDOSFSMNT_UTF8) + 1;
break; break;
} }
if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME)
@ -282,7 +286,8 @@ msdosfs_lookup(void *v)
chksum = winChkName((const u_char *)cnp->cn_nameptr, chksum = winChkName((const u_char *)cnp->cn_nameptr,
cnp->cn_namelen, cnp->cn_namelen,
(struct winentry *)dep, (struct winentry *)dep,
chksum); chksum,
pmp->pm_flags & MSDOSFSMNT_UTF8);
continue; continue;
} }
@ -652,7 +657,8 @@ createde(struct denode *dep, struct denode *ddep, struct denode **depp, struct c
fndoffset -= sizeof(struct direntry); fndoffset -= sizeof(struct direntry);
} }
if (!unix2winfn(un, unlen, (struct winentry *)ndep, if (!unix2winfn(un, unlen, (struct winentry *)ndep,
wcnt, chksum)) wcnt, chksum,
ddep->de_pmp->pm_flags & MSDOSFSMNT_UTF8))
break; break;
} }
} }

View File

@ -0,0 +1,965 @@
/* $NetBSD: msdosfs_unicode.c,v 1.2 2016/02/06 14:11:58 joerg Exp $ */
/*
* Unicode 5.0 case folding derived from
*
* http://www.unicode.org/Public/5.0.0/ucd/CaseFolding.txt
*/
/*
* Unicode Character Database
* Copyright (c) 1991-2006 Unicode, Inc.
* For terms of use, see http://www.unicode.org/terms_of_use.html
* For documentation, see UCD.html
*
* COPYRIGHT AND PERMISSION NOTICE
*
* Copyright © 1991-2015 Unicode, Inc. All rights reserved.
* Distributed under the Terms of Use in
* http://www.unicode.org/copyright.html.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of the Unicode data files and any associated documentation
* (the "Data Files") or Unicode software and any associated documentation
* (the "Software") to deal in the Data Files or Software
* without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, and/or sell copies of
* the Data Files or Software, and to permit persons to whom the Data Files
* or Software are furnished to do so, provided that
* (a) this copyright and permission notice appear with all copies
* of the Data Files or Software,
* (b) this copyright and permission notice appear in associated
* documentation, and
* (c) there is clear notice in each modified Data File or in the Software
* as well as in the documentation associated with the Data File(s) or
* Software that the data or software has been modified.
*
* THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT OF THIRD PARTY RIGHTS.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
* NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
* DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THE DATA FILES OR SOFTWARE.
*
* Except as contained in this notice, the name of a copyright holder
* shall not be used in advertising or otherwise to promote the sale,
* use or other dealings in these Data Files or Software without prior
* written authorization of the copyright holder.
*
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#include <sys/types.h>
/*
* Unicode case folding for codes 0x0000..0xffff
*
* common case folding + simple case folding only
*/
const u_int16_t
msdosfs_unicode_foldmap[] = {
0x0041, 0x0061, /* LATIN CAPITAL LETTER A */
0x0042, 0x0062, /* LATIN CAPITAL LETTER B */
0x0043, 0x0063, /* LATIN CAPITAL LETTER C */
0x0044, 0x0064, /* LATIN CAPITAL LETTER D */
0x0045, 0x0065, /* LATIN CAPITAL LETTER E */
0x0046, 0x0066, /* LATIN CAPITAL LETTER F */
0x0047, 0x0067, /* LATIN CAPITAL LETTER G */
0x0048, 0x0068, /* LATIN CAPITAL LETTER H */
0x0049, 0x0069, /* LATIN CAPITAL LETTER I */
0x004A, 0x006A, /* LATIN CAPITAL LETTER J */
0x004B, 0x006B, /* LATIN CAPITAL LETTER K */
0x004C, 0x006C, /* LATIN CAPITAL LETTER L */
0x004D, 0x006D, /* LATIN CAPITAL LETTER M */
0x004E, 0x006E, /* LATIN CAPITAL LETTER N */
0x004F, 0x006F, /* LATIN CAPITAL LETTER O */
0x0050, 0x0070, /* LATIN CAPITAL LETTER P */
0x0051, 0x0071, /* LATIN CAPITAL LETTER Q */
0x0052, 0x0072, /* LATIN CAPITAL LETTER R */
0x0053, 0x0073, /* LATIN CAPITAL LETTER S */
0x0054, 0x0074, /* LATIN CAPITAL LETTER T */
0x0055, 0x0075, /* LATIN CAPITAL LETTER U */
0x0056, 0x0076, /* LATIN CAPITAL LETTER V */
0x0057, 0x0077, /* LATIN CAPITAL LETTER W */
0x0058, 0x0078, /* LATIN CAPITAL LETTER X */
0x0059, 0x0079, /* LATIN CAPITAL LETTER Y */
0x005A, 0x007A, /* LATIN CAPITAL LETTER Z */
0x00B5, 0x03BC, /* MICRO SIGN */
0x00C0, 0x00E0, /* LATIN CAPITAL LETTER A WITH GRAVE */
0x00C1, 0x00E1, /* LATIN CAPITAL LETTER A WITH ACUTE */
0x00C2, 0x00E2, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
0x00C3, 0x00E3, /* LATIN CAPITAL LETTER A WITH TILDE */
0x00C4, 0x00E4, /* LATIN CAPITAL LETTER A WITH DIAERESIS */
0x00C5, 0x00E5, /* LATIN CAPITAL LETTER A WITH RING ABOVE */
0x00C6, 0x00E6, /* LATIN CAPITAL LETTER AE */
0x00C7, 0x00E7, /* LATIN CAPITAL LETTER C WITH CEDILLA */
0x00C8, 0x00E8, /* LATIN CAPITAL LETTER E WITH GRAVE */
0x00C9, 0x00E9, /* LATIN CAPITAL LETTER E WITH ACUTE */
0x00CA, 0x00EA, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
0x00CB, 0x00EB, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
0x00CC, 0x00EC, /* LATIN CAPITAL LETTER I WITH GRAVE */
0x00CD, 0x00ED, /* LATIN CAPITAL LETTER I WITH ACUTE */
0x00CE, 0x00EE, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
0x00CF, 0x00EF, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
0x00D0, 0x00F0, /* LATIN CAPITAL LETTER ETH */
0x00D1, 0x00F1, /* LATIN CAPITAL LETTER N WITH TILDE */
0x00D2, 0x00F2, /* LATIN CAPITAL LETTER O WITH GRAVE */
0x00D3, 0x00F3, /* LATIN CAPITAL LETTER O WITH ACUTE */
0x00D4, 0x00F4, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
0x00D5, 0x00F5, /* LATIN CAPITAL LETTER O WITH TILDE */
0x00D6, 0x00F6, /* LATIN CAPITAL LETTER O WITH DIAERESIS */
0x00D8, 0x00F8, /* LATIN CAPITAL LETTER O WITH STROKE */
0x00D9, 0x00F9, /* LATIN CAPITAL LETTER U WITH GRAVE */
0x00DA, 0x00FA, /* LATIN CAPITAL LETTER U WITH ACUTE */
0x00DB, 0x00FB, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
0x00DC, 0x00FC, /* LATIN CAPITAL LETTER U WITH DIAERESIS */
0x00DD, 0x00FD, /* LATIN CAPITAL LETTER Y WITH ACUTE */
0x00DE, 0x00FE, /* LATIN CAPITAL LETTER THORN */
0x0100, 0x0101, /* LATIN CAPITAL LETTER A WITH MACRON */
0x0102, 0x0103, /* LATIN CAPITAL LETTER A WITH BREVE */
0x0104, 0x0105, /* LATIN CAPITAL LETTER A WITH OGONEK */
0x0106, 0x0107, /* LATIN CAPITAL LETTER C WITH ACUTE */
0x0108, 0x0109, /* LATIN CAPITAL LETTER C WITH CIRCUMFLEX */
0x010A, 0x010B, /* LATIN CAPITAL LETTER C WITH DOT ABOVE */
0x010C, 0x010D, /* LATIN CAPITAL LETTER C WITH CARON */
0x010E, 0x010F, /* LATIN CAPITAL LETTER D WITH CARON */
0x0110, 0x0111, /* LATIN CAPITAL LETTER D WITH STROKE */
0x0112, 0x0113, /* LATIN CAPITAL LETTER E WITH MACRON */
0x0114, 0x0115, /* LATIN CAPITAL LETTER E WITH BREVE */
0x0116, 0x0117, /* LATIN CAPITAL LETTER E WITH DOT ABOVE */
0x0118, 0x0119, /* LATIN CAPITAL LETTER E WITH OGONEK */
0x011A, 0x011B, /* LATIN CAPITAL LETTER E WITH CARON */
0x011C, 0x011D, /* LATIN CAPITAL LETTER G WITH CIRCUMFLEX */
0x011E, 0x011F, /* LATIN CAPITAL LETTER G WITH BREVE */
0x0120, 0x0121, /* LATIN CAPITAL LETTER G WITH DOT ABOVE */
0x0122, 0x0123, /* LATIN CAPITAL LETTER G WITH CEDILLA */
0x0124, 0x0125, /* LATIN CAPITAL LETTER H WITH CIRCUMFLEX */
0x0126, 0x0127, /* LATIN CAPITAL LETTER H WITH STROKE */
0x0128, 0x0129, /* LATIN CAPITAL LETTER I WITH TILDE */
0x012A, 0x012B, /* LATIN CAPITAL LETTER I WITH MACRON */
0x012C, 0x012D, /* LATIN CAPITAL LETTER I WITH BREVE */
0x012E, 0x012F, /* LATIN CAPITAL LETTER I WITH OGONEK */
0x0132, 0x0133, /* LATIN CAPITAL LIGATURE IJ */
0x0134, 0x0135, /* LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
0x0136, 0x0137, /* LATIN CAPITAL LETTER K WITH CEDILLA */
0x0139, 0x013A, /* LATIN CAPITAL LETTER L WITH ACUTE */
0x013B, 0x013C, /* LATIN CAPITAL LETTER L WITH CEDILLA */
0x013D, 0x013E, /* LATIN CAPITAL LETTER L WITH CARON */
0x013F, 0x0140, /* LATIN CAPITAL LETTER L WITH MIDDLE DOT */
0x0141, 0x0142, /* LATIN CAPITAL LETTER L WITH STROKE */
0x0143, 0x0144, /* LATIN CAPITAL LETTER N WITH ACUTE */
0x0145, 0x0146, /* LATIN CAPITAL LETTER N WITH CEDILLA */
0x0147, 0x0148, /* LATIN CAPITAL LETTER N WITH CARON */
0x014A, 0x014B, /* LATIN CAPITAL LETTER ENG */
0x014C, 0x014D, /* LATIN CAPITAL LETTER O WITH MACRON */
0x014E, 0x014F, /* LATIN CAPITAL LETTER O WITH BREVE */
0x0150, 0x0151, /* LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
0x0152, 0x0153, /* LATIN CAPITAL LIGATURE OE */
0x0154, 0x0155, /* LATIN CAPITAL LETTER R WITH ACUTE */
0x0156, 0x0157, /* LATIN CAPITAL LETTER R WITH CEDILLA */
0x0158, 0x0159, /* LATIN CAPITAL LETTER R WITH CARON */
0x015A, 0x015B, /* LATIN CAPITAL LETTER S WITH ACUTE */
0x015C, 0x015D, /* LATIN CAPITAL LETTER S WITH CIRCUMFLEX */
0x015E, 0x015F, /* LATIN CAPITAL LETTER S WITH CEDILLA */
0x0160, 0x0161, /* LATIN CAPITAL LETTER S WITH CARON */
0x0162, 0x0163, /* LATIN CAPITAL LETTER T WITH CEDILLA */
0x0164, 0x0165, /* LATIN CAPITAL LETTER T WITH CARON */
0x0166, 0x0167, /* LATIN CAPITAL LETTER T WITH STROKE */
0x0168, 0x0169, /* LATIN CAPITAL LETTER U WITH TILDE */
0x016A, 0x016B, /* LATIN CAPITAL LETTER U WITH MACRON */
0x016C, 0x016D, /* LATIN CAPITAL LETTER U WITH BREVE */
0x016E, 0x016F, /* LATIN CAPITAL LETTER U WITH RING ABOVE */
0x0170, 0x0171, /* LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
0x0172, 0x0173, /* LATIN CAPITAL LETTER U WITH OGONEK */
0x0174, 0x0175, /* LATIN CAPITAL LETTER W WITH CIRCUMFLEX */
0x0176, 0x0177, /* LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */
0x0178, 0x00FF, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
0x0179, 0x017A, /* LATIN CAPITAL LETTER Z WITH ACUTE */
0x017B, 0x017C, /* LATIN CAPITAL LETTER Z WITH DOT ABOVE */
0x017D, 0x017E, /* LATIN CAPITAL LETTER Z WITH CARON */
0x017F, 0x0073, /* LATIN SMALL LETTER LONG S */
0x0181, 0x0253, /* LATIN CAPITAL LETTER B WITH HOOK */
0x0182, 0x0183, /* LATIN CAPITAL LETTER B WITH TOPBAR */
0x0184, 0x0185, /* LATIN CAPITAL LETTER TONE SIX */
0x0186, 0x0254, /* LATIN CAPITAL LETTER OPEN O */
0x0187, 0x0188, /* LATIN CAPITAL LETTER C WITH HOOK */
0x0189, 0x0256, /* LATIN CAPITAL LETTER AFRICAN D */
0x018A, 0x0257, /* LATIN CAPITAL LETTER D WITH HOOK */
0x018B, 0x018C, /* LATIN CAPITAL LETTER D WITH TOPBAR */
0x018E, 0x01DD, /* LATIN CAPITAL LETTER REVERSED E */
0x018F, 0x0259, /* LATIN CAPITAL LETTER SCHWA */
0x0190, 0x025B, /* LATIN CAPITAL LETTER OPEN E */
0x0191, 0x0192, /* LATIN CAPITAL LETTER F WITH HOOK */
0x0193, 0x0260, /* LATIN CAPITAL LETTER G WITH HOOK */
0x0194, 0x0263, /* LATIN CAPITAL LETTER GAMMA */
0x0196, 0x0269, /* LATIN CAPITAL LETTER IOTA */
0x0197, 0x0268, /* LATIN CAPITAL LETTER I WITH STROKE */
0x0198, 0x0199, /* LATIN CAPITAL LETTER K WITH HOOK */
0x019C, 0x026F, /* LATIN CAPITAL LETTER TURNED M */
0x019D, 0x0272, /* LATIN CAPITAL LETTER N WITH LEFT HOOK */
0x019F, 0x0275, /* LATIN CAPITAL LETTER O WITH MIDDLE TILDE */
0x01A0, 0x01A1, /* LATIN CAPITAL LETTER O WITH HORN */
0x01A2, 0x01A3, /* LATIN CAPITAL LETTER OI */
0x01A4, 0x01A5, /* LATIN CAPITAL LETTER P WITH HOOK */
0x01A6, 0x0280, /* LATIN LETTER YR */
0x01A7, 0x01A8, /* LATIN CAPITAL LETTER TONE TWO */
0x01A9, 0x0283, /* LATIN CAPITAL LETTER ESH */
0x01AC, 0x01AD, /* LATIN CAPITAL LETTER T WITH HOOK */
0x01AE, 0x0288, /* LATIN CAPITAL LETTER T WITH RETROFLEX HOOK */
0x01AF, 0x01B0, /* LATIN CAPITAL LETTER U WITH HORN */
0x01B1, 0x028A, /* LATIN CAPITAL LETTER UPSILON */
0x01B2, 0x028B, /* LATIN CAPITAL LETTER V WITH HOOK */
0x01B3, 0x01B4, /* LATIN CAPITAL LETTER Y WITH HOOK */
0x01B5, 0x01B6, /* LATIN CAPITAL LETTER Z WITH STROKE */
0x01B7, 0x0292, /* LATIN CAPITAL LETTER EZH */
0x01B8, 0x01B9, /* LATIN CAPITAL LETTER EZH REVERSED */
0x01BC, 0x01BD, /* LATIN CAPITAL LETTER TONE FIVE */
0x01C4, 0x01C6, /* LATIN CAPITAL LETTER DZ WITH CARON */
0x01C5, 0x01C6, /* LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON */
0x01C7, 0x01C9, /* LATIN CAPITAL LETTER LJ */
0x01C8, 0x01C9, /* LATIN CAPITAL LETTER L WITH SMALL LETTER J */
0x01CA, 0x01CC, /* LATIN CAPITAL LETTER NJ */
0x01CB, 0x01CC, /* LATIN CAPITAL LETTER N WITH SMALL LETTER J */
0x01CD, 0x01CE, /* LATIN CAPITAL LETTER A WITH CARON */
0x01CF, 0x01D0, /* LATIN CAPITAL LETTER I WITH CARON */
0x01D1, 0x01D2, /* LATIN CAPITAL LETTER O WITH CARON */
0x01D3, 0x01D4, /* LATIN CAPITAL LETTER U WITH CARON */
0x01D5, 0x01D6, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON */
0x01D7, 0x01D8, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE */
0x01D9, 0x01DA, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON */
0x01DB, 0x01DC, /* LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE */
0x01DE, 0x01DF, /* LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON */
0x01E0, 0x01E1, /* LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON */
0x01E2, 0x01E3, /* LATIN CAPITAL LETTER AE WITH MACRON */
0x01E4, 0x01E5, /* LATIN CAPITAL LETTER G WITH STROKE */
0x01E6, 0x01E7, /* LATIN CAPITAL LETTER G WITH CARON */
0x01E8, 0x01E9, /* LATIN CAPITAL LETTER K WITH CARON */
0x01EA, 0x01EB, /* LATIN CAPITAL LETTER O WITH OGONEK */
0x01EC, 0x01ED, /* LATIN CAPITAL LETTER O WITH OGONEK AND MACRON */
0x01EE, 0x01EF, /* LATIN CAPITAL LETTER EZH WITH CARON */
0x01F1, 0x01F3, /* LATIN CAPITAL LETTER DZ */
0x01F2, 0x01F3, /* LATIN CAPITAL LETTER D WITH SMALL LETTER Z */
0x01F4, 0x01F5, /* LATIN CAPITAL LETTER G WITH ACUTE */
0x01F6, 0x0195, /* LATIN CAPITAL LETTER HWAIR */
0x01F7, 0x01BF, /* LATIN CAPITAL LETTER WYNN */
0x01F8, 0x01F9, /* LATIN CAPITAL LETTER N WITH GRAVE */
0x01FA, 0x01FB, /* LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE */
0x01FC, 0x01FD, /* LATIN CAPITAL LETTER AE WITH ACUTE */
0x01FE, 0x01FF, /* LATIN CAPITAL LETTER O WITH STROKE AND ACUTE */
0x0200, 0x0201, /* LATIN CAPITAL LETTER A WITH DOUBLE GRAVE */
0x0202, 0x0203, /* LATIN CAPITAL LETTER A WITH INVERTED BREVE */
0x0204, 0x0205, /* LATIN CAPITAL LETTER E WITH DOUBLE GRAVE */
0x0206, 0x0207, /* LATIN CAPITAL LETTER E WITH INVERTED BREVE */
0x0208, 0x0209, /* LATIN CAPITAL LETTER I WITH DOUBLE GRAVE */
0x020A, 0x020B, /* LATIN CAPITAL LETTER I WITH INVERTED BREVE */
0x020C, 0x020D, /* LATIN CAPITAL LETTER O WITH DOUBLE GRAVE */
0x020E, 0x020F, /* LATIN CAPITAL LETTER O WITH INVERTED BREVE */
0x0210, 0x0211, /* LATIN CAPITAL LETTER R WITH DOUBLE GRAVE */
0x0212, 0x0213, /* LATIN CAPITAL LETTER R WITH INVERTED BREVE */
0x0214, 0x0215, /* LATIN CAPITAL LETTER U WITH DOUBLE GRAVE */
0x0216, 0x0217, /* LATIN CAPITAL LETTER U WITH INVERTED BREVE */
0x0218, 0x0219, /* LATIN CAPITAL LETTER S WITH COMMA BELOW */
0x021A, 0x021B, /* LATIN CAPITAL LETTER T WITH COMMA BELOW */
0x021C, 0x021D, /* LATIN CAPITAL LETTER YOGH */
0x021E, 0x021F, /* LATIN CAPITAL LETTER H WITH CARON */
0x0220, 0x019E, /* LATIN CAPITAL LETTER N WITH LONG RIGHT LEG */
0x0222, 0x0223, /* LATIN CAPITAL LETTER OU */
0x0224, 0x0225, /* LATIN CAPITAL LETTER Z WITH HOOK */
0x0226, 0x0227, /* LATIN CAPITAL LETTER A WITH DOT ABOVE */
0x0228, 0x0229, /* LATIN CAPITAL LETTER E WITH CEDILLA */
0x022A, 0x022B, /* LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON */
0x022C, 0x022D, /* LATIN CAPITAL LETTER O WITH TILDE AND MACRON */
0x022E, 0x022F, /* LATIN CAPITAL LETTER O WITH DOT ABOVE */
0x0230, 0x0231, /* LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON */
0x0232, 0x0233, /* LATIN CAPITAL LETTER Y WITH MACRON */
0x023A, 0x2C65, /* LATIN CAPITAL LETTER A WITH STROKE */
0x023B, 0x023C, /* LATIN CAPITAL LETTER C WITH STROKE */
0x023D, 0x019A, /* LATIN CAPITAL LETTER L WITH BAR */
0x023E, 0x2C66, /* LATIN CAPITAL LETTER T WITH DIAGONAL STROKE */
0x0241, 0x0242, /* LATIN CAPITAL LETTER GLOTTAL STOP */
0x0243, 0x0180, /* LATIN CAPITAL LETTER B WITH STROKE */
0x0244, 0x0289, /* LATIN CAPITAL LETTER U BAR */
0x0245, 0x028C, /* LATIN CAPITAL LETTER TURNED V */
0x0246, 0x0247, /* LATIN CAPITAL LETTER E WITH STROKE */
0x0248, 0x0249, /* LATIN CAPITAL LETTER J WITH STROKE */
0x024A, 0x024B, /* LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL */
0x024C, 0x024D, /* LATIN CAPITAL LETTER R WITH STROKE */
0x024E, 0x024F, /* LATIN CAPITAL LETTER Y WITH STROKE */
0x0345, 0x03B9, /* COMBINING GREEK YPOGEGRAMMENI */
0x0386, 0x03AC, /* GREEK CAPITAL LETTER ALPHA WITH TONOS */
0x0388, 0x03AD, /* GREEK CAPITAL LETTER EPSILON WITH TONOS */
0x0389, 0x03AE, /* GREEK CAPITAL LETTER ETA WITH TONOS */
0x038A, 0x03AF, /* GREEK CAPITAL LETTER IOTA WITH TONOS */
0x038C, 0x03CC, /* GREEK CAPITAL LETTER OMICRON WITH TONOS */
0x038E, 0x03CD, /* GREEK CAPITAL LETTER UPSILON WITH TONOS */
0x038F, 0x03CE, /* GREEK CAPITAL LETTER OMEGA WITH TONOS */
0x0391, 0x03B1, /* GREEK CAPITAL LETTER ALPHA */
0x0392, 0x03B2, /* GREEK CAPITAL LETTER BETA */
0x0393, 0x03B3, /* GREEK CAPITAL LETTER GAMMA */
0x0394, 0x03B4, /* GREEK CAPITAL LETTER DELTA */
0x0395, 0x03B5, /* GREEK CAPITAL LETTER EPSILON */
0x0396, 0x03B6, /* GREEK CAPITAL LETTER ZETA */
0x0397, 0x03B7, /* GREEK CAPITAL LETTER ETA */
0x0398, 0x03B8, /* GREEK CAPITAL LETTER THETA */
0x0399, 0x03B9, /* GREEK CAPITAL LETTER IOTA */
0x039A, 0x03BA, /* GREEK CAPITAL LETTER KAPPA */
0x039B, 0x03BB, /* GREEK CAPITAL LETTER LAMDA */
0x039C, 0x03BC, /* GREEK CAPITAL LETTER MU */
0x039D, 0x03BD, /* GREEK CAPITAL LETTER NU */
0x039E, 0x03BE, /* GREEK CAPITAL LETTER XI */
0x039F, 0x03BF, /* GREEK CAPITAL LETTER OMICRON */
0x03A0, 0x03C0, /* GREEK CAPITAL LETTER PI */
0x03A1, 0x03C1, /* GREEK CAPITAL LETTER RHO */
0x03A3, 0x03C3, /* GREEK CAPITAL LETTER SIGMA */
0x03A4, 0x03C4, /* GREEK CAPITAL LETTER TAU */
0x03A5, 0x03C5, /* GREEK CAPITAL LETTER UPSILON */
0x03A6, 0x03C6, /* GREEK CAPITAL LETTER PHI */
0x03A7, 0x03C7, /* GREEK CAPITAL LETTER CHI */
0x03A8, 0x03C8, /* GREEK CAPITAL LETTER PSI */
0x03A9, 0x03C9, /* GREEK CAPITAL LETTER OMEGA */
0x03AA, 0x03CA, /* GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
0x03AB, 0x03CB, /* GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
0x03C2, 0x03C3, /* GREEK SMALL LETTER FINAL SIGMA */
0x03D0, 0x03B2, /* GREEK BETA SYMBOL */
0x03D1, 0x03B8, /* GREEK THETA SYMBOL */
0x03D5, 0x03C6, /* GREEK PHI SYMBOL */
0x03D6, 0x03C0, /* GREEK PI SYMBOL */
0x03D8, 0x03D9, /* GREEK LETTER ARCHAIC KOPPA */
0x03DA, 0x03DB, /* GREEK LETTER STIGMA */
0x03DC, 0x03DD, /* GREEK LETTER DIGAMMA */
0x03DE, 0x03DF, /* GREEK LETTER KOPPA */
0x03E0, 0x03E1, /* GREEK LETTER SAMPI */
0x03E2, 0x03E3, /* COPTIC CAPITAL LETTER SHEI */
0x03E4, 0x03E5, /* COPTIC CAPITAL LETTER FEI */
0x03E6, 0x03E7, /* COPTIC CAPITAL LETTER KHEI */
0x03E8, 0x03E9, /* COPTIC CAPITAL LETTER HORI */
0x03EA, 0x03EB, /* COPTIC CAPITAL LETTER GANGIA */
0x03EC, 0x03ED, /* COPTIC CAPITAL LETTER SHIMA */
0x03EE, 0x03EF, /* COPTIC CAPITAL LETTER DEI */
0x03F0, 0x03BA, /* GREEK KAPPA SYMBOL */
0x03F1, 0x03C1, /* GREEK RHO SYMBOL */
0x03F4, 0x03B8, /* GREEK CAPITAL THETA SYMBOL */
0x03F5, 0x03B5, /* GREEK LUNATE EPSILON SYMBOL */
0x03F7, 0x03F8, /* GREEK CAPITAL LETTER SHO */
0x03F9, 0x03F2, /* GREEK CAPITAL LUNATE SIGMA SYMBOL */
0x03FA, 0x03FB, /* GREEK CAPITAL LETTER SAN */
0x03FD, 0x037B, /* GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL */
0x03FE, 0x037C, /* GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL */
0x03FF, 0x037D, /* GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL */
0x0400, 0x0450, /* CYRILLIC CAPITAL LETTER IE WITH GRAVE */
0x0401, 0x0451, /* CYRILLIC CAPITAL LETTER IO */
0x0402, 0x0452, /* CYRILLIC CAPITAL LETTER DJE */
0x0403, 0x0453, /* CYRILLIC CAPITAL LETTER GJE */
0x0404, 0x0454, /* CYRILLIC CAPITAL LETTER UKRAINIAN IE */
0x0405, 0x0455, /* CYRILLIC CAPITAL LETTER DZE */
0x0406, 0x0456, /* CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */
0x0407, 0x0457, /* CYRILLIC CAPITAL LETTER YI */
0x0408, 0x0458, /* CYRILLIC CAPITAL LETTER JE */
0x0409, 0x0459, /* CYRILLIC CAPITAL LETTER LJE */
0x040A, 0x045A, /* CYRILLIC CAPITAL LETTER NJE */
0x040B, 0x045B, /* CYRILLIC CAPITAL LETTER TSHE */
0x040C, 0x045C, /* CYRILLIC CAPITAL LETTER KJE */
0x040D, 0x045D, /* CYRILLIC CAPITAL LETTER I WITH GRAVE */
0x040E, 0x045E, /* CYRILLIC CAPITAL LETTER SHORT U */
0x040F, 0x045F, /* CYRILLIC CAPITAL LETTER DZHE */
0x0410, 0x0430, /* CYRILLIC CAPITAL LETTER A */
0x0411, 0x0431, /* CYRILLIC CAPITAL LETTER BE */
0x0412, 0x0432, /* CYRILLIC CAPITAL LETTER VE */
0x0413, 0x0433, /* CYRILLIC CAPITAL LETTER GHE */
0x0414, 0x0434, /* CYRILLIC CAPITAL LETTER DE */
0x0415, 0x0435, /* CYRILLIC CAPITAL LETTER IE */
0x0416, 0x0436, /* CYRILLIC CAPITAL LETTER ZHE */
0x0417, 0x0437, /* CYRILLIC CAPITAL LETTER ZE */
0x0418, 0x0438, /* CYRILLIC CAPITAL LETTER I */
0x0419, 0x0439, /* CYRILLIC CAPITAL LETTER SHORT I */
0x041A, 0x043A, /* CYRILLIC CAPITAL LETTER KA */
0x041B, 0x043B, /* CYRILLIC CAPITAL LETTER EL */
0x041C, 0x043C, /* CYRILLIC CAPITAL LETTER EM */
0x041D, 0x043D, /* CYRILLIC CAPITAL LETTER EN */
0x041E, 0x043E, /* CYRILLIC CAPITAL LETTER O */
0x041F, 0x043F, /* CYRILLIC CAPITAL LETTER PE */
0x0420, 0x0440, /* CYRILLIC CAPITAL LETTER ER */
0x0421, 0x0441, /* CYRILLIC CAPITAL LETTER ES */
0x0422, 0x0442, /* CYRILLIC CAPITAL LETTER TE */
0x0423, 0x0443, /* CYRILLIC CAPITAL LETTER U */
0x0424, 0x0444, /* CYRILLIC CAPITAL LETTER EF */
0x0425, 0x0445, /* CYRILLIC CAPITAL LETTER HA */
0x0426, 0x0446, /* CYRILLIC CAPITAL LETTER TSE */
0x0427, 0x0447, /* CYRILLIC CAPITAL LETTER CHE */
0x0428, 0x0448, /* CYRILLIC CAPITAL LETTER SHA */
0x0429, 0x0449, /* CYRILLIC CAPITAL LETTER SHCHA */
0x042A, 0x044A, /* CYRILLIC CAPITAL LETTER HARD SIGN */
0x042B, 0x044B, /* CYRILLIC CAPITAL LETTER YERU */
0x042C, 0x044C, /* CYRILLIC CAPITAL LETTER SOFT SIGN */
0x042D, 0x044D, /* CYRILLIC CAPITAL LETTER E */
0x042E, 0x044E, /* CYRILLIC CAPITAL LETTER YU */
0x042F, 0x044F, /* CYRILLIC CAPITAL LETTER YA */
0x0460, 0x0461, /* CYRILLIC CAPITAL LETTER OMEGA */
0x0462, 0x0463, /* CYRILLIC CAPITAL LETTER YAT */
0x0464, 0x0465, /* CYRILLIC CAPITAL LETTER IOTIFIED E */
0x0466, 0x0467, /* CYRILLIC CAPITAL LETTER LITTLE YUS */
0x0468, 0x0469, /* CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS */
0x046A, 0x046B, /* CYRILLIC CAPITAL LETTER BIG YUS */
0x046C, 0x046D, /* CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS */
0x046E, 0x046F, /* CYRILLIC CAPITAL LETTER KSI */
0x0470, 0x0471, /* CYRILLIC CAPITAL LETTER PSI */
0x0472, 0x0473, /* CYRILLIC CAPITAL LETTER FITA */
0x0474, 0x0475, /* CYRILLIC CAPITAL LETTER IZHITSA */
0x0476, 0x0477, /* CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT */
0x0478, 0x0479, /* CYRILLIC CAPITAL LETTER UK */
0x047A, 0x047B, /* CYRILLIC CAPITAL LETTER ROUND OMEGA */
0x047C, 0x047D, /* CYRILLIC CAPITAL LETTER OMEGA WITH TITLO */
0x047E, 0x047F, /* CYRILLIC CAPITAL LETTER OT */
0x0480, 0x0481, /* CYRILLIC CAPITAL LETTER KOPPA */
0x048A, 0x048B, /* CYRILLIC CAPITAL LETTER SHORT I WITH TAIL */
0x048C, 0x048D, /* CYRILLIC CAPITAL LETTER SEMISOFT SIGN */
0x048E, 0x048F, /* CYRILLIC CAPITAL LETTER ER WITH TICK */
0x0490, 0x0491, /* CYRILLIC CAPITAL LETTER GHE WITH UPTURN */
0x0492, 0x0493, /* CYRILLIC CAPITAL LETTER GHE WITH STROKE */
0x0494, 0x0495, /* CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK */
0x0496, 0x0497, /* CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER */
0x0498, 0x0499, /* CYRILLIC CAPITAL LETTER ZE WITH DESCENDER */
0x049A, 0x049B, /* CYRILLIC CAPITAL LETTER KA WITH DESCENDER */
0x049C, 0x049D, /* CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE */
0x049E, 0x049F, /* CYRILLIC CAPITAL LETTER KA WITH STROKE */
0x04A0, 0x04A1, /* CYRILLIC CAPITAL LETTER BASHKIR KA */
0x04A2, 0x04A3, /* CYRILLIC CAPITAL LETTER EN WITH DESCENDER */
0x04A4, 0x04A5, /* CYRILLIC CAPITAL LIGATURE EN GHE */
0x04A6, 0x04A7, /* CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK */
0x04A8, 0x04A9, /* CYRILLIC CAPITAL LETTER ABKHASIAN HA */
0x04AA, 0x04AB, /* CYRILLIC CAPITAL LETTER ES WITH DESCENDER */
0x04AC, 0x04AD, /* CYRILLIC CAPITAL LETTER TE WITH DESCENDER */
0x04AE, 0x04AF, /* CYRILLIC CAPITAL LETTER STRAIGHT U */
0x04B0, 0x04B1, /* CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE */
0x04B2, 0x04B3, /* CYRILLIC CAPITAL LETTER HA WITH DESCENDER */
0x04B4, 0x04B5, /* CYRILLIC CAPITAL LIGATURE TE TSE */
0x04B6, 0x04B7, /* CYRILLIC CAPITAL LETTER CHE WITH DESCENDER */
0x04B8, 0x04B9, /* CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE */
0x04BA, 0x04BB, /* CYRILLIC CAPITAL LETTER SHHA */
0x04BC, 0x04BD, /* CYRILLIC CAPITAL LETTER ABKHASIAN CHE */
0x04BE, 0x04BF, /* CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER */
0x04C0, 0x04CF, /* CYRILLIC LETTER PALOCHKA */
0x04C1, 0x04C2, /* CYRILLIC CAPITAL LETTER ZHE WITH BREVE */
0x04C3, 0x04C4, /* CYRILLIC CAPITAL LETTER KA WITH HOOK */
0x04C5, 0x04C6, /* CYRILLIC CAPITAL LETTER EL WITH TAIL */
0x04C7, 0x04C8, /* CYRILLIC CAPITAL LETTER EN WITH HOOK */
0x04C9, 0x04CA, /* CYRILLIC CAPITAL LETTER EN WITH TAIL */
0x04CB, 0x04CC, /* CYRILLIC CAPITAL LETTER KHAKASSIAN CHE */
0x04CD, 0x04CE, /* CYRILLIC CAPITAL LETTER EM WITH TAIL */
0x04D0, 0x04D1, /* CYRILLIC CAPITAL LETTER A WITH BREVE */
0x04D2, 0x04D3, /* CYRILLIC CAPITAL LETTER A WITH DIAERESIS */
0x04D4, 0x04D5, /* CYRILLIC CAPITAL LIGATURE A IE */
0x04D6, 0x04D7, /* CYRILLIC CAPITAL LETTER IE WITH BREVE */
0x04D8, 0x04D9, /* CYRILLIC CAPITAL LETTER SCHWA */
0x04DA, 0x04DB, /* CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS */
0x04DC, 0x04DD, /* CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS */
0x04DE, 0x04DF, /* CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS */
0x04E0, 0x04E1, /* CYRILLIC CAPITAL LETTER ABKHASIAN DZE */
0x04E2, 0x04E3, /* CYRILLIC CAPITAL LETTER I WITH MACRON */
0x04E4, 0x04E5, /* CYRILLIC CAPITAL LETTER I WITH DIAERESIS */
0x04E6, 0x04E7, /* CYRILLIC CAPITAL LETTER O WITH DIAERESIS */
0x04E8, 0x04E9, /* CYRILLIC CAPITAL LETTER BARRED O */
0x04EA, 0x04EB, /* CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS */
0x04EC, 0x04ED, /* CYRILLIC CAPITAL LETTER E WITH DIAERESIS */
0x04EE, 0x04EF, /* CYRILLIC CAPITAL LETTER U WITH MACRON */
0x04F0, 0x04F1, /* CYRILLIC CAPITAL LETTER U WITH DIAERESIS */
0x04F2, 0x04F3, /* CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE */
0x04F4, 0x04F5, /* CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS */
0x04F6, 0x04F7, /* CYRILLIC CAPITAL LETTER GHE WITH DESCENDER */
0x04F8, 0x04F9, /* CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS */
0x04FA, 0x04FB, /* CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK */
0x04FC, 0x04FD, /* CYRILLIC CAPITAL LETTER HA WITH HOOK */
0x04FE, 0x04FF, /* CYRILLIC CAPITAL LETTER HA WITH STROKE */
0x0500, 0x0501, /* CYRILLIC CAPITAL LETTER KOMI DE */
0x0502, 0x0503, /* CYRILLIC CAPITAL LETTER KOMI DJE */
0x0504, 0x0505, /* CYRILLIC CAPITAL LETTER KOMI ZJE */
0x0506, 0x0507, /* CYRILLIC CAPITAL LETTER KOMI DZJE */
0x0508, 0x0509, /* CYRILLIC CAPITAL LETTER KOMI LJE */
0x050A, 0x050B, /* CYRILLIC CAPITAL LETTER KOMI NJE */
0x050C, 0x050D, /* CYRILLIC CAPITAL LETTER KOMI SJE */
0x050E, 0x050F, /* CYRILLIC CAPITAL LETTER KOMI TJE */
0x0510, 0x0511, /* CYRILLIC CAPITAL LETTER REVERSED ZE */
0x0512, 0x0513, /* CYRILLIC CAPITAL LETTER EL WITH HOOK */
0x0531, 0x0561, /* ARMENIAN CAPITAL LETTER AYB */
0x0532, 0x0562, /* ARMENIAN CAPITAL LETTER BEN */
0x0533, 0x0563, /* ARMENIAN CAPITAL LETTER GIM */
0x0534, 0x0564, /* ARMENIAN CAPITAL LETTER DA */
0x0535, 0x0565, /* ARMENIAN CAPITAL LETTER ECH */
0x0536, 0x0566, /* ARMENIAN CAPITAL LETTER ZA */
0x0537, 0x0567, /* ARMENIAN CAPITAL LETTER EH */
0x0538, 0x0568, /* ARMENIAN CAPITAL LETTER ET */
0x0539, 0x0569, /* ARMENIAN CAPITAL LETTER TO */
0x053A, 0x056A, /* ARMENIAN CAPITAL LETTER ZHE */
0x053B, 0x056B, /* ARMENIAN CAPITAL LETTER INI */
0x053C, 0x056C, /* ARMENIAN CAPITAL LETTER LIWN */
0x053D, 0x056D, /* ARMENIAN CAPITAL LETTER XEH */
0x053E, 0x056E, /* ARMENIAN CAPITAL LETTER CA */
0x053F, 0x056F, /* ARMENIAN CAPITAL LETTER KEN */
0x0540, 0x0570, /* ARMENIAN CAPITAL LETTER HO */
0x0541, 0x0571, /* ARMENIAN CAPITAL LETTER JA */
0x0542, 0x0572, /* ARMENIAN CAPITAL LETTER GHAD */
0x0543, 0x0573, /* ARMENIAN CAPITAL LETTER CHEH */
0x0544, 0x0574, /* ARMENIAN CAPITAL LETTER MEN */
0x0545, 0x0575, /* ARMENIAN CAPITAL LETTER YI */
0x0546, 0x0576, /* ARMENIAN CAPITAL LETTER NOW */
0x0547, 0x0577, /* ARMENIAN CAPITAL LETTER SHA */
0x0548, 0x0578, /* ARMENIAN CAPITAL LETTER VO */
0x0549, 0x0579, /* ARMENIAN CAPITAL LETTER CHA */
0x054A, 0x057A, /* ARMENIAN CAPITAL LETTER PEH */
0x054B, 0x057B, /* ARMENIAN CAPITAL LETTER JHEH */
0x054C, 0x057C, /* ARMENIAN CAPITAL LETTER RA */
0x054D, 0x057D, /* ARMENIAN CAPITAL LETTER SEH */
0x054E, 0x057E, /* ARMENIAN CAPITAL LETTER VEW */
0x054F, 0x057F, /* ARMENIAN CAPITAL LETTER TIWN */
0x0550, 0x0580, /* ARMENIAN CAPITAL LETTER REH */
0x0551, 0x0581, /* ARMENIAN CAPITAL LETTER CO */
0x0552, 0x0582, /* ARMENIAN CAPITAL LETTER YIWN */
0x0553, 0x0583, /* ARMENIAN CAPITAL LETTER PIWR */
0x0554, 0x0584, /* ARMENIAN CAPITAL LETTER KEH */
0x0555, 0x0585, /* ARMENIAN CAPITAL LETTER OH */
0x0556, 0x0586, /* ARMENIAN CAPITAL LETTER FEH */
0x10A0, 0x2D00, /* GEORGIAN CAPITAL LETTER AN */
0x10A1, 0x2D01, /* GEORGIAN CAPITAL LETTER BAN */
0x10A2, 0x2D02, /* GEORGIAN CAPITAL LETTER GAN */
0x10A3, 0x2D03, /* GEORGIAN CAPITAL LETTER DON */
0x10A4, 0x2D04, /* GEORGIAN CAPITAL LETTER EN */
0x10A5, 0x2D05, /* GEORGIAN CAPITAL LETTER VIN */
0x10A6, 0x2D06, /* GEORGIAN CAPITAL LETTER ZEN */
0x10A7, 0x2D07, /* GEORGIAN CAPITAL LETTER TAN */
0x10A8, 0x2D08, /* GEORGIAN CAPITAL LETTER IN */
0x10A9, 0x2D09, /* GEORGIAN CAPITAL LETTER KAN */
0x10AA, 0x2D0A, /* GEORGIAN CAPITAL LETTER LAS */
0x10AB, 0x2D0B, /* GEORGIAN CAPITAL LETTER MAN */
0x10AC, 0x2D0C, /* GEORGIAN CAPITAL LETTER NAR */
0x10AD, 0x2D0D, /* GEORGIAN CAPITAL LETTER ON */
0x10AE, 0x2D0E, /* GEORGIAN CAPITAL LETTER PAR */
0x10AF, 0x2D0F, /* GEORGIAN CAPITAL LETTER ZHAR */
0x10B0, 0x2D10, /* GEORGIAN CAPITAL LETTER RAE */
0x10B1, 0x2D11, /* GEORGIAN CAPITAL LETTER SAN */
0x10B2, 0x2D12, /* GEORGIAN CAPITAL LETTER TAR */
0x10B3, 0x2D13, /* GEORGIAN CAPITAL LETTER UN */
0x10B4, 0x2D14, /* GEORGIAN CAPITAL LETTER PHAR */
0x10B5, 0x2D15, /* GEORGIAN CAPITAL LETTER KHAR */
0x10B6, 0x2D16, /* GEORGIAN CAPITAL LETTER GHAN */
0x10B7, 0x2D17, /* GEORGIAN CAPITAL LETTER QAR */
0x10B8, 0x2D18, /* GEORGIAN CAPITAL LETTER SHIN */
0x10B9, 0x2D19, /* GEORGIAN CAPITAL LETTER CHIN */
0x10BA, 0x2D1A, /* GEORGIAN CAPITAL LETTER CAN */
0x10BB, 0x2D1B, /* GEORGIAN CAPITAL LETTER JIL */
0x10BC, 0x2D1C, /* GEORGIAN CAPITAL LETTER CIL */
0x10BD, 0x2D1D, /* GEORGIAN CAPITAL LETTER CHAR */
0x10BE, 0x2D1E, /* GEORGIAN CAPITAL LETTER XAN */
0x10BF, 0x2D1F, /* GEORGIAN CAPITAL LETTER JHAN */
0x10C0, 0x2D20, /* GEORGIAN CAPITAL LETTER HAE */
0x10C1, 0x2D21, /* GEORGIAN CAPITAL LETTER HE */
0x10C2, 0x2D22, /* GEORGIAN CAPITAL LETTER HIE */
0x10C3, 0x2D23, /* GEORGIAN CAPITAL LETTER WE */
0x10C4, 0x2D24, /* GEORGIAN CAPITAL LETTER HAR */
0x10C5, 0x2D25, /* GEORGIAN CAPITAL LETTER HOE */
0x1E00, 0x1E01, /* LATIN CAPITAL LETTER A WITH RING BELOW */
0x1E02, 0x1E03, /* LATIN CAPITAL LETTER B WITH DOT ABOVE */
0x1E04, 0x1E05, /* LATIN CAPITAL LETTER B WITH DOT BELOW */
0x1E06, 0x1E07, /* LATIN CAPITAL LETTER B WITH LINE BELOW */
0x1E08, 0x1E09, /* LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE */
0x1E0A, 0x1E0B, /* LATIN CAPITAL LETTER D WITH DOT ABOVE */
0x1E0C, 0x1E0D, /* LATIN CAPITAL LETTER D WITH DOT BELOW */
0x1E0E, 0x1E0F, /* LATIN CAPITAL LETTER D WITH LINE BELOW */
0x1E10, 0x1E11, /* LATIN CAPITAL LETTER D WITH CEDILLA */
0x1E12, 0x1E13, /* LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW */
0x1E14, 0x1E15, /* LATIN CAPITAL LETTER E WITH MACRON AND GRAVE */
0x1E16, 0x1E17, /* LATIN CAPITAL LETTER E WITH MACRON AND ACUTE */
0x1E18, 0x1E19, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW */
0x1E1A, 0x1E1B, /* LATIN CAPITAL LETTER E WITH TILDE BELOW */
0x1E1C, 0x1E1D, /* LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE */
0x1E1E, 0x1E1F, /* LATIN CAPITAL LETTER F WITH DOT ABOVE */
0x1E20, 0x1E21, /* LATIN CAPITAL LETTER G WITH MACRON */
0x1E22, 0x1E23, /* LATIN CAPITAL LETTER H WITH DOT ABOVE */
0x1E24, 0x1E25, /* LATIN CAPITAL LETTER H WITH DOT BELOW */
0x1E26, 0x1E27, /* LATIN CAPITAL LETTER H WITH DIAERESIS */
0x1E28, 0x1E29, /* LATIN CAPITAL LETTER H WITH CEDILLA */
0x1E2A, 0x1E2B, /* LATIN CAPITAL LETTER H WITH BREVE BELOW */
0x1E2C, 0x1E2D, /* LATIN CAPITAL LETTER I WITH TILDE BELOW */
0x1E2E, 0x1E2F, /* LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE */
0x1E30, 0x1E31, /* LATIN CAPITAL LETTER K WITH ACUTE */
0x1E32, 0x1E33, /* LATIN CAPITAL LETTER K WITH DOT BELOW */
0x1E34, 0x1E35, /* LATIN CAPITAL LETTER K WITH LINE BELOW */
0x1E36, 0x1E37, /* LATIN CAPITAL LETTER L WITH DOT BELOW */
0x1E38, 0x1E39, /* LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON */
0x1E3A, 0x1E3B, /* LATIN CAPITAL LETTER L WITH LINE BELOW */
0x1E3C, 0x1E3D, /* LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW */
0x1E3E, 0x1E3F, /* LATIN CAPITAL LETTER M WITH ACUTE */
0x1E40, 0x1E41, /* LATIN CAPITAL LETTER M WITH DOT ABOVE */
0x1E42, 0x1E43, /* LATIN CAPITAL LETTER M WITH DOT BELOW */
0x1E44, 0x1E45, /* LATIN CAPITAL LETTER N WITH DOT ABOVE */
0x1E46, 0x1E47, /* LATIN CAPITAL LETTER N WITH DOT BELOW */
0x1E48, 0x1E49, /* LATIN CAPITAL LETTER N WITH LINE BELOW */
0x1E4A, 0x1E4B, /* LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW */
0x1E4C, 0x1E4D, /* LATIN CAPITAL LETTER O WITH TILDE AND ACUTE */
0x1E4E, 0x1E4F, /* LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS */
0x1E50, 0x1E51, /* LATIN CAPITAL LETTER O WITH MACRON AND GRAVE */
0x1E52, 0x1E53, /* LATIN CAPITAL LETTER O WITH MACRON AND ACUTE */
0x1E54, 0x1E55, /* LATIN CAPITAL LETTER P WITH ACUTE */
0x1E56, 0x1E57, /* LATIN CAPITAL LETTER P WITH DOT ABOVE */
0x1E58, 0x1E59, /* LATIN CAPITAL LETTER R WITH DOT ABOVE */
0x1E5A, 0x1E5B, /* LATIN CAPITAL LETTER R WITH DOT BELOW */
0x1E5C, 0x1E5D, /* LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON */
0x1E5E, 0x1E5F, /* LATIN CAPITAL LETTER R WITH LINE BELOW */
0x1E60, 0x1E61, /* LATIN CAPITAL LETTER S WITH DOT ABOVE */
0x1E62, 0x1E63, /* LATIN CAPITAL LETTER S WITH DOT BELOW */
0x1E64, 0x1E65, /* LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE */
0x1E66, 0x1E67, /* LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE */
0x1E68, 0x1E69, /* LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE */
0x1E6A, 0x1E6B, /* LATIN CAPITAL LETTER T WITH DOT ABOVE */
0x1E6C, 0x1E6D, /* LATIN CAPITAL LETTER T WITH DOT BELOW */
0x1E6E, 0x1E6F, /* LATIN CAPITAL LETTER T WITH LINE BELOW */
0x1E70, 0x1E71, /* LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW */
0x1E72, 0x1E73, /* LATIN CAPITAL LETTER U WITH DIAERESIS BELOW */
0x1E74, 0x1E75, /* LATIN CAPITAL LETTER U WITH TILDE BELOW */
0x1E76, 0x1E77, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW */
0x1E78, 0x1E79, /* LATIN CAPITAL LETTER U WITH TILDE AND ACUTE */
0x1E7A, 0x1E7B, /* LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS */
0x1E7C, 0x1E7D, /* LATIN CAPITAL LETTER V WITH TILDE */
0x1E7E, 0x1E7F, /* LATIN CAPITAL LETTER V WITH DOT BELOW */
0x1E80, 0x1E81, /* LATIN CAPITAL LETTER W WITH GRAVE */
0x1E82, 0x1E83, /* LATIN CAPITAL LETTER W WITH ACUTE */
0x1E84, 0x1E85, /* LATIN CAPITAL LETTER W WITH DIAERESIS */
0x1E86, 0x1E87, /* LATIN CAPITAL LETTER W WITH DOT ABOVE */
0x1E88, 0x1E89, /* LATIN CAPITAL LETTER W WITH DOT BELOW */
0x1E8A, 0x1E8B, /* LATIN CAPITAL LETTER X WITH DOT ABOVE */
0x1E8C, 0x1E8D, /* LATIN CAPITAL LETTER X WITH DIAERESIS */
0x1E8E, 0x1E8F, /* LATIN CAPITAL LETTER Y WITH DOT ABOVE */
0x1E90, 0x1E91, /* LATIN CAPITAL LETTER Z WITH CIRCUMFLEX */
0x1E92, 0x1E93, /* LATIN CAPITAL LETTER Z WITH DOT BELOW */
0x1E94, 0x1E95, /* LATIN CAPITAL LETTER Z WITH LINE BELOW */
0x1E9B, 0x1E61, /* LATIN SMALL LETTER LONG S WITH DOT ABOVE */
0x1EA0, 0x1EA1, /* LATIN CAPITAL LETTER A WITH DOT BELOW */
0x1EA2, 0x1EA3, /* LATIN CAPITAL LETTER A WITH HOOK ABOVE */
0x1EA4, 0x1EA5, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */
0x1EA6, 0x1EA7, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */
0x1EA8, 0x1EA9, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */
0x1EAA, 0x1EAB, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */
0x1EAC, 0x1EAD, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW */
0x1EAE, 0x1EAF, /* LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */
0x1EB0, 0x1EB1, /* LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */
0x1EB2, 0x1EB3, /* LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */
0x1EB4, 0x1EB5, /* LATIN CAPITAL LETTER A WITH BREVE AND TILDE */
0x1EB6, 0x1EB7, /* LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW */
0x1EB8, 0x1EB9, /* LATIN CAPITAL LETTER E WITH DOT BELOW */
0x1EBA, 0x1EBB, /* LATIN CAPITAL LETTER E WITH HOOK ABOVE */
0x1EBC, 0x1EBD, /* LATIN CAPITAL LETTER E WITH TILDE */
0x1EBE, 0x1EBF, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */
0x1EC0, 0x1EC1, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */
0x1EC2, 0x1EC3, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */
0x1EC4, 0x1EC5, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */
0x1EC6, 0x1EC7, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW */
0x1EC8, 0x1EC9, /* LATIN CAPITAL LETTER I WITH HOOK ABOVE */
0x1ECA, 0x1ECB, /* LATIN CAPITAL LETTER I WITH DOT BELOW */
0x1ECC, 0x1ECD, /* LATIN CAPITAL LETTER O WITH DOT BELOW */
0x1ECE, 0x1ECF, /* LATIN CAPITAL LETTER O WITH HOOK ABOVE */
0x1ED0, 0x1ED1, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */
0x1ED2, 0x1ED3, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */
0x1ED4, 0x1ED5, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */
0x1ED6, 0x1ED7, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */
0x1ED8, 0x1ED9, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW */
0x1EDA, 0x1EDB, /* LATIN CAPITAL LETTER O WITH HORN AND ACUTE */
0x1EDC, 0x1EDD, /* LATIN CAPITAL LETTER O WITH HORN AND GRAVE */
0x1EDE, 0x1EDF, /* LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE */
0x1EE0, 0x1EE1, /* LATIN CAPITAL LETTER O WITH HORN AND TILDE */
0x1EE2, 0x1EE3, /* LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW */
0x1EE4, 0x1EE5, /* LATIN CAPITAL LETTER U WITH DOT BELOW */
0x1EE6, 0x1EE7, /* LATIN CAPITAL LETTER U WITH HOOK ABOVE */
0x1EE8, 0x1EE9, /* LATIN CAPITAL LETTER U WITH HORN AND ACUTE */
0x1EEA, 0x1EEB, /* LATIN CAPITAL LETTER U WITH HORN AND GRAVE */
0x1EEC, 0x1EED, /* LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE */
0x1EEE, 0x1EEF, /* LATIN CAPITAL LETTER U WITH HORN AND TILDE */
0x1EF0, 0x1EF1, /* LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW */
0x1EF2, 0x1EF3, /* LATIN CAPITAL LETTER Y WITH GRAVE */
0x1EF4, 0x1EF5, /* LATIN CAPITAL LETTER Y WITH DOT BELOW */
0x1EF6, 0x1EF7, /* LATIN CAPITAL LETTER Y WITH HOOK ABOVE */
0x1EF8, 0x1EF9, /* LATIN CAPITAL LETTER Y WITH TILDE */
0x1F08, 0x1F00, /* GREEK CAPITAL LETTER ALPHA WITH PSILI */
0x1F09, 0x1F01, /* GREEK CAPITAL LETTER ALPHA WITH DASIA */
0x1F0A, 0x1F02, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA */
0x1F0B, 0x1F03, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA */
0x1F0C, 0x1F04, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA */
0x1F0D, 0x1F05, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA */
0x1F0E, 0x1F06, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI */
0x1F0F, 0x1F07, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI */
0x1F18, 0x1F10, /* GREEK CAPITAL LETTER EPSILON WITH PSILI */
0x1F19, 0x1F11, /* GREEK CAPITAL LETTER EPSILON WITH DASIA */
0x1F1A, 0x1F12, /* GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA */
0x1F1B, 0x1F13, /* GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA */
0x1F1C, 0x1F14, /* GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA */
0x1F1D, 0x1F15, /* GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA */
0x1F28, 0x1F20, /* GREEK CAPITAL LETTER ETA WITH PSILI */
0x1F29, 0x1F21, /* GREEK CAPITAL LETTER ETA WITH DASIA */
0x1F2A, 0x1F22, /* GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA */
0x1F2B, 0x1F23, /* GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA */
0x1F2C, 0x1F24, /* GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA */
0x1F2D, 0x1F25, /* GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA */
0x1F2E, 0x1F26, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI */
0x1F2F, 0x1F27, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI */
0x1F38, 0x1F30, /* GREEK CAPITAL LETTER IOTA WITH PSILI */
0x1F39, 0x1F31, /* GREEK CAPITAL LETTER IOTA WITH DASIA */
0x1F3A, 0x1F32, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA */
0x1F3B, 0x1F33, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA */
0x1F3C, 0x1F34, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA */
0x1F3D, 0x1F35, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA */
0x1F3E, 0x1F36, /* GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI */
0x1F3F, 0x1F37, /* GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI */
0x1F48, 0x1F40, /* GREEK CAPITAL LETTER OMICRON WITH PSILI */
0x1F49, 0x1F41, /* GREEK CAPITAL LETTER OMICRON WITH DASIA */
0x1F4A, 0x1F42, /* GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA */
0x1F4B, 0x1F43, /* GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA */
0x1F4C, 0x1F44, /* GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA */
0x1F4D, 0x1F45, /* GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA */
0x1F59, 0x1F51, /* GREEK CAPITAL LETTER UPSILON WITH DASIA */
0x1F5B, 0x1F53, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA */
0x1F5D, 0x1F55, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA */
0x1F5F, 0x1F57, /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI */
0x1F68, 0x1F60, /* GREEK CAPITAL LETTER OMEGA WITH PSILI */
0x1F69, 0x1F61, /* GREEK CAPITAL LETTER OMEGA WITH DASIA */
0x1F6A, 0x1F62, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA */
0x1F6B, 0x1F63, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA */
0x1F6C, 0x1F64, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA */
0x1F6D, 0x1F65, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA */
0x1F6E, 0x1F66, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI */
0x1F6F, 0x1F67, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI */
0x1F88, 0x1F80, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI */
0x1F89, 0x1F81, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI */
0x1F8A, 0x1F82, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI */
0x1F8B, 0x1F83, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI */
0x1F8C, 0x1F84, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI */
0x1F8D, 0x1F85, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI */
0x1F8E, 0x1F86, /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */
0x1F8F, 0x1F87, /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */
0x1F98, 0x1F90, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI */
0x1F99, 0x1F91, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI */
0x1F9A, 0x1F92, /* GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI */
0x1F9B, 0x1F93, /* GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI */
0x1F9C, 0x1F94, /* GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI */
0x1F9D, 0x1F95, /* GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI */
0x1F9E, 0x1F96, /* GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */
0x1F9F, 0x1F97, /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */
0x1FA8, 0x1FA0, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI */
0x1FA9, 0x1FA1, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI */
0x1FAA, 0x1FA2, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI */
0x1FAB, 0x1FA3, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI */
0x1FAC, 0x1FA4, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI */
0x1FAD, 0x1FA5, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI */
0x1FAE, 0x1FA6, /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */
0x1FAF, 0x1FA7, /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */
0x1FB8, 0x1FB0, /* GREEK CAPITAL LETTER ALPHA WITH VRACHY */
0x1FB9, 0x1FB1, /* GREEK CAPITAL LETTER ALPHA WITH MACRON */
0x1FBA, 0x1F70, /* GREEK CAPITAL LETTER ALPHA WITH VARIA */
0x1FBB, 0x1F71, /* GREEK CAPITAL LETTER ALPHA WITH OXIA */
0x1FBC, 0x1FB3, /* GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI */
0x1FBE, 0x03B9, /* GREEK PROSGEGRAMMENI */
0x1FC8, 0x1F72, /* GREEK CAPITAL LETTER EPSILON WITH VARIA */
0x1FC9, 0x1F73, /* GREEK CAPITAL LETTER EPSILON WITH OXIA */
0x1FCA, 0x1F74, /* GREEK CAPITAL LETTER ETA WITH VARIA */
0x1FCB, 0x1F75, /* GREEK CAPITAL LETTER ETA WITH OXIA */
0x1FCC, 0x1FC3, /* GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI */
0x1FD8, 0x1FD0, /* GREEK CAPITAL LETTER IOTA WITH VRACHY */
0x1FD9, 0x1FD1, /* GREEK CAPITAL LETTER IOTA WITH MACRON */
0x1FDA, 0x1F76, /* GREEK CAPITAL LETTER IOTA WITH VARIA */
0x1FDB, 0x1F77, /* GREEK CAPITAL LETTER IOTA WITH OXIA */
0x1FE8, 0x1FE0, /* GREEK CAPITAL LETTER UPSILON WITH VRACHY */
0x1FE9, 0x1FE1, /* GREEK CAPITAL LETTER UPSILON WITH MACRON */
0x1FEA, 0x1F7A, /* GREEK CAPITAL LETTER UPSILON WITH VARIA */
0x1FEB, 0x1F7B, /* GREEK CAPITAL LETTER UPSILON WITH OXIA */
0x1FEC, 0x1FE5, /* GREEK CAPITAL LETTER RHO WITH DASIA */
0x1FF8, 0x1F78, /* GREEK CAPITAL LETTER OMICRON WITH VARIA */
0x1FF9, 0x1F79, /* GREEK CAPITAL LETTER OMICRON WITH OXIA */
0x1FFA, 0x1F7C, /* GREEK CAPITAL LETTER OMEGA WITH VARIA */
0x1FFB, 0x1F7D, /* GREEK CAPITAL LETTER OMEGA WITH OXIA */
0x1FFC, 0x1FF3, /* GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI */
0x2126, 0x03C9, /* OHM SIGN */
0x212A, 0x006B, /* KELVIN SIGN */
0x212B, 0x00E5, /* ANGSTROM SIGN */
0x2132, 0x214E, /* TURNED CAPITAL F */
0x2160, 0x2170, /* ROMAN NUMERAL ONE */
0x2161, 0x2171, /* ROMAN NUMERAL TWO */
0x2162, 0x2172, /* ROMAN NUMERAL THREE */
0x2163, 0x2173, /* ROMAN NUMERAL FOUR */
0x2164, 0x2174, /* ROMAN NUMERAL FIVE */
0x2165, 0x2175, /* ROMAN NUMERAL SIX */
0x2166, 0x2176, /* ROMAN NUMERAL SEVEN */
0x2167, 0x2177, /* ROMAN NUMERAL EIGHT */
0x2168, 0x2178, /* ROMAN NUMERAL NINE */
0x2169, 0x2179, /* ROMAN NUMERAL TEN */
0x216A, 0x217A, /* ROMAN NUMERAL ELEVEN */
0x216B, 0x217B, /* ROMAN NUMERAL TWELVE */
0x216C, 0x217C, /* ROMAN NUMERAL FIFTY */
0x216D, 0x217D, /* ROMAN NUMERAL ONE HUNDRED */
0x216E, 0x217E, /* ROMAN NUMERAL FIVE HUNDRED */
0x216F, 0x217F, /* ROMAN NUMERAL ONE THOUSAND */
0x2183, 0x2184, /* ROMAN NUMERAL REVERSED ONE HUNDRED */
0x24B6, 0x24D0, /* CIRCLED LATIN CAPITAL LETTER A */
0x24B7, 0x24D1, /* CIRCLED LATIN CAPITAL LETTER B */
0x24B8, 0x24D2, /* CIRCLED LATIN CAPITAL LETTER C */
0x24B9, 0x24D3, /* CIRCLED LATIN CAPITAL LETTER D */
0x24BA, 0x24D4, /* CIRCLED LATIN CAPITAL LETTER E */
0x24BB, 0x24D5, /* CIRCLED LATIN CAPITAL LETTER F */
0x24BC, 0x24D6, /* CIRCLED LATIN CAPITAL LETTER G */
0x24BD, 0x24D7, /* CIRCLED LATIN CAPITAL LETTER H */
0x24BE, 0x24D8, /* CIRCLED LATIN CAPITAL LETTER I */
0x24BF, 0x24D9, /* CIRCLED LATIN CAPITAL LETTER J */
0x24C0, 0x24DA, /* CIRCLED LATIN CAPITAL LETTER K */
0x24C1, 0x24DB, /* CIRCLED LATIN CAPITAL LETTER L */
0x24C2, 0x24DC, /* CIRCLED LATIN CAPITAL LETTER M */
0x24C3, 0x24DD, /* CIRCLED LATIN CAPITAL LETTER N */
0x24C4, 0x24DE, /* CIRCLED LATIN CAPITAL LETTER O */
0x24C5, 0x24DF, /* CIRCLED LATIN CAPITAL LETTER P */
0x24C6, 0x24E0, /* CIRCLED LATIN CAPITAL LETTER Q */
0x24C7, 0x24E1, /* CIRCLED LATIN CAPITAL LETTER R */
0x24C8, 0x24E2, /* CIRCLED LATIN CAPITAL LETTER S */
0x24C9, 0x24E3, /* CIRCLED LATIN CAPITAL LETTER T */
0x24CA, 0x24E4, /* CIRCLED LATIN CAPITAL LETTER U */
0x24CB, 0x24E5, /* CIRCLED LATIN CAPITAL LETTER V */
0x24CC, 0x24E6, /* CIRCLED LATIN CAPITAL LETTER W */
0x24CD, 0x24E7, /* CIRCLED LATIN CAPITAL LETTER X */
0x24CE, 0x24E8, /* CIRCLED LATIN CAPITAL LETTER Y */
0x24CF, 0x24E9, /* CIRCLED LATIN CAPITAL LETTER Z */
0x2C00, 0x2C30, /* GLAGOLITIC CAPITAL LETTER AZU */
0x2C01, 0x2C31, /* GLAGOLITIC CAPITAL LETTER BUKY */
0x2C02, 0x2C32, /* GLAGOLITIC CAPITAL LETTER VEDE */
0x2C03, 0x2C33, /* GLAGOLITIC CAPITAL LETTER GLAGOLI */
0x2C04, 0x2C34, /* GLAGOLITIC CAPITAL LETTER DOBRO */
0x2C05, 0x2C35, /* GLAGOLITIC CAPITAL LETTER YESTU */
0x2C06, 0x2C36, /* GLAGOLITIC CAPITAL LETTER ZHIVETE */
0x2C07, 0x2C37, /* GLAGOLITIC CAPITAL LETTER DZELO */
0x2C08, 0x2C38, /* GLAGOLITIC CAPITAL LETTER ZEMLJA */
0x2C09, 0x2C39, /* GLAGOLITIC CAPITAL LETTER IZHE */
0x2C0A, 0x2C3A, /* GLAGOLITIC CAPITAL LETTER INITIAL IZHE */
0x2C0B, 0x2C3B, /* GLAGOLITIC CAPITAL LETTER I */
0x2C0C, 0x2C3C, /* GLAGOLITIC CAPITAL LETTER DJERVI */
0x2C0D, 0x2C3D, /* GLAGOLITIC CAPITAL LETTER KAKO */
0x2C0E, 0x2C3E, /* GLAGOLITIC CAPITAL LETTER LJUDIJE */
0x2C0F, 0x2C3F, /* GLAGOLITIC CAPITAL LETTER MYSLITE */
0x2C10, 0x2C40, /* GLAGOLITIC CAPITAL LETTER NASHI */
0x2C11, 0x2C41, /* GLAGOLITIC CAPITAL LETTER ONU */
0x2C12, 0x2C42, /* GLAGOLITIC CAPITAL LETTER POKOJI */
0x2C13, 0x2C43, /* GLAGOLITIC CAPITAL LETTER RITSI */
0x2C14, 0x2C44, /* GLAGOLITIC CAPITAL LETTER SLOVO */
0x2C15, 0x2C45, /* GLAGOLITIC CAPITAL LETTER TVRIDO */
0x2C16, 0x2C46, /* GLAGOLITIC CAPITAL LETTER UKU */
0x2C17, 0x2C47, /* GLAGOLITIC CAPITAL LETTER FRITU */
0x2C18, 0x2C48, /* GLAGOLITIC CAPITAL LETTER HERU */
0x2C19, 0x2C49, /* GLAGOLITIC CAPITAL LETTER OTU */
0x2C1A, 0x2C4A, /* GLAGOLITIC CAPITAL LETTER PE */
0x2C1B, 0x2C4B, /* GLAGOLITIC CAPITAL LETTER SHTA */
0x2C1C, 0x2C4C, /* GLAGOLITIC CAPITAL LETTER TSI */
0x2C1D, 0x2C4D, /* GLAGOLITIC CAPITAL LETTER CHRIVI */
0x2C1E, 0x2C4E, /* GLAGOLITIC CAPITAL LETTER SHA */
0x2C1F, 0x2C4F, /* GLAGOLITIC CAPITAL LETTER YERU */
0x2C20, 0x2C50, /* GLAGOLITIC CAPITAL LETTER YERI */
0x2C21, 0x2C51, /* GLAGOLITIC CAPITAL LETTER YATI */
0x2C22, 0x2C52, /* GLAGOLITIC CAPITAL LETTER SPIDERY HA */
0x2C23, 0x2C53, /* GLAGOLITIC CAPITAL LETTER YU */
0x2C24, 0x2C54, /* GLAGOLITIC CAPITAL LETTER SMALL YUS */
0x2C25, 0x2C55, /* GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL */
0x2C26, 0x2C56, /* GLAGOLITIC CAPITAL LETTER YO */
0x2C27, 0x2C57, /* GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS */
0x2C28, 0x2C58, /* GLAGOLITIC CAPITAL LETTER BIG YUS */
0x2C29, 0x2C59, /* GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS */
0x2C2A, 0x2C5A, /* GLAGOLITIC CAPITAL LETTER FITA */
0x2C2B, 0x2C5B, /* GLAGOLITIC CAPITAL LETTER IZHITSA */
0x2C2C, 0x2C5C, /* GLAGOLITIC CAPITAL LETTER SHTAPIC */
0x2C2D, 0x2C5D, /* GLAGOLITIC CAPITAL LETTER TROKUTASTI A */
0x2C2E, 0x2C5E, /* GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE */
0x2C60, 0x2C61, /* LATIN CAPITAL LETTER L WITH DOUBLE BAR */
0x2C62, 0x026B, /* LATIN CAPITAL LETTER L WITH MIDDLE TILDE */
0x2C63, 0x1D7D, /* LATIN CAPITAL LETTER P WITH STROKE */
0x2C64, 0x027D, /* LATIN CAPITAL LETTER R WITH TAIL */
0x2C67, 0x2C68, /* LATIN CAPITAL LETTER H WITH DESCENDER */
0x2C69, 0x2C6A, /* LATIN CAPITAL LETTER K WITH DESCENDER */
0x2C6B, 0x2C6C, /* LATIN CAPITAL LETTER Z WITH DESCENDER */
0x2C75, 0x2C76, /* LATIN CAPITAL LETTER HALF H */
0x2C80, 0x2C81, /* COPTIC CAPITAL LETTER ALFA */
0x2C82, 0x2C83, /* COPTIC CAPITAL LETTER VIDA */
0x2C84, 0x2C85, /* COPTIC CAPITAL LETTER GAMMA */
0x2C86, 0x2C87, /* COPTIC CAPITAL LETTER DALDA */
0x2C88, 0x2C89, /* COPTIC CAPITAL LETTER EIE */
0x2C8A, 0x2C8B, /* COPTIC CAPITAL LETTER SOU */
0x2C8C, 0x2C8D, /* COPTIC CAPITAL LETTER ZATA */
0x2C8E, 0x2C8F, /* COPTIC CAPITAL LETTER HATE */
0x2C90, 0x2C91, /* COPTIC CAPITAL LETTER THETHE */
0x2C92, 0x2C93, /* COPTIC CAPITAL LETTER IAUDA */
0x2C94, 0x2C95, /* COPTIC CAPITAL LETTER KAPA */
0x2C96, 0x2C97, /* COPTIC CAPITAL LETTER LAULA */
0x2C98, 0x2C99, /* COPTIC CAPITAL LETTER MI */
0x2C9A, 0x2C9B, /* COPTIC CAPITAL LETTER NI */
0x2C9C, 0x2C9D, /* COPTIC CAPITAL LETTER KSI */
0x2C9E, 0x2C9F, /* COPTIC CAPITAL LETTER O */
0x2CA0, 0x2CA1, /* COPTIC CAPITAL LETTER PI */
0x2CA2, 0x2CA3, /* COPTIC CAPITAL LETTER RO */
0x2CA4, 0x2CA5, /* COPTIC CAPITAL LETTER SIMA */
0x2CA6, 0x2CA7, /* COPTIC CAPITAL LETTER TAU */
0x2CA8, 0x2CA9, /* COPTIC CAPITAL LETTER UA */
0x2CAA, 0x2CAB, /* COPTIC CAPITAL LETTER FI */
0x2CAC, 0x2CAD, /* COPTIC CAPITAL LETTER KHI */
0x2CAE, 0x2CAF, /* COPTIC CAPITAL LETTER PSI */
0x2CB0, 0x2CB1, /* COPTIC CAPITAL LETTER OOU */
0x2CB2, 0x2CB3, /* COPTIC CAPITAL LETTER DIALECT-P ALEF */
0x2CB4, 0x2CB5, /* COPTIC CAPITAL LETTER OLD COPTIC AIN */
0x2CB6, 0x2CB7, /* COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE */
0x2CB8, 0x2CB9, /* COPTIC CAPITAL LETTER DIALECT-P KAPA */
0x2CBA, 0x2CBB, /* COPTIC CAPITAL LETTER DIALECT-P NI */
0x2CBC, 0x2CBD, /* COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI */
0x2CBE, 0x2CBF, /* COPTIC CAPITAL LETTER OLD COPTIC OOU */
0x2CC0, 0x2CC1, /* COPTIC CAPITAL LETTER SAMPI */
0x2CC2, 0x2CC3, /* COPTIC CAPITAL LETTER CROSSED SHEI */
0x2CC4, 0x2CC5, /* COPTIC CAPITAL LETTER OLD COPTIC SHEI */
0x2CC6, 0x2CC7, /* COPTIC CAPITAL LETTER OLD COPTIC ESH */
0x2CC8, 0x2CC9, /* COPTIC CAPITAL LETTER AKHMIMIC KHEI */
0x2CCA, 0x2CCB, /* COPTIC CAPITAL LETTER DIALECT-P HORI */
0x2CCC, 0x2CCD, /* COPTIC CAPITAL LETTER OLD COPTIC HORI */
0x2CCE, 0x2CCF, /* COPTIC CAPITAL LETTER OLD COPTIC HA */
0x2CD0, 0x2CD1, /* COPTIC CAPITAL LETTER L-SHAPED HA */
0x2CD2, 0x2CD3, /* COPTIC CAPITAL LETTER OLD COPTIC HEI */
0x2CD4, 0x2CD5, /* COPTIC CAPITAL LETTER OLD COPTIC HAT */
0x2CD6, 0x2CD7, /* COPTIC CAPITAL LETTER OLD COPTIC GANGIA */
0x2CD8, 0x2CD9, /* COPTIC CAPITAL LETTER OLD COPTIC DJA */
0x2CDA, 0x2CDB, /* COPTIC CAPITAL LETTER OLD COPTIC SHIMA */
0x2CDC, 0x2CDD, /* COPTIC CAPITAL LETTER OLD NUBIAN SHIMA */
0x2CDE, 0x2CDF, /* COPTIC CAPITAL LETTER OLD NUBIAN NGI */
0x2CE0, 0x2CE1, /* COPTIC CAPITAL LETTER OLD NUBIAN NYI */
0x2CE2, 0x2CE3, /* COPTIC CAPITAL LETTER OLD NUBIAN WAU */
0xFF21, 0xFF41, /* FULLWIDTH LATIN CAPITAL LETTER A */
0xFF22, 0xFF42, /* FULLWIDTH LATIN CAPITAL LETTER B */
0xFF23, 0xFF43, /* FULLWIDTH LATIN CAPITAL LETTER C */
0xFF24, 0xFF44, /* FULLWIDTH LATIN CAPITAL LETTER D */
0xFF25, 0xFF45, /* FULLWIDTH LATIN CAPITAL LETTER E */
0xFF26, 0xFF46, /* FULLWIDTH LATIN CAPITAL LETTER F */
0xFF27, 0xFF47, /* FULLWIDTH LATIN CAPITAL LETTER G */
0xFF28, 0xFF48, /* FULLWIDTH LATIN CAPITAL LETTER H */
0xFF29, 0xFF49, /* FULLWIDTH LATIN CAPITAL LETTER I */
0xFF2A, 0xFF4A, /* FULLWIDTH LATIN CAPITAL LETTER J */
0xFF2B, 0xFF4B, /* FULLWIDTH LATIN CAPITAL LETTER K */
0xFF2C, 0xFF4C, /* FULLWIDTH LATIN CAPITAL LETTER L */
0xFF2D, 0xFF4D, /* FULLWIDTH LATIN CAPITAL LETTER M */
0xFF2E, 0xFF4E, /* FULLWIDTH LATIN CAPITAL LETTER N */
0xFF2F, 0xFF4F, /* FULLWIDTH LATIN CAPITAL LETTER O */
0xFF30, 0xFF50, /* FULLWIDTH LATIN CAPITAL LETTER P */
0xFF31, 0xFF51, /* FULLWIDTH LATIN CAPITAL LETTER Q */
0xFF32, 0xFF52, /* FULLWIDTH LATIN CAPITAL LETTER R */
0xFF33, 0xFF53, /* FULLWIDTH LATIN CAPITAL LETTER S */
0xFF34, 0xFF54, /* FULLWIDTH LATIN CAPITAL LETTER T */
0xFF35, 0xFF55, /* FULLWIDTH LATIN CAPITAL LETTER U */
0xFF36, 0xFF56, /* FULLWIDTH LATIN CAPITAL LETTER V */
0xFF37, 0xFF57, /* FULLWIDTH LATIN CAPITAL LETTER W */
0xFF38, 0xFF58, /* FULLWIDTH LATIN CAPITAL LETTER X */
0xFF39, 0xFF59, /* FULLWIDTH LATIN CAPITAL LETTER Y */
0xFF3A, 0xFF5A, /* FULLWIDTH LATIN CAPITAL LETTER Z */
};
size_t msdosfs_unicode_foldmap_entries = __arraycount(msdosfs_unicode_foldmap);

View File

@ -1,4 +1,4 @@
/* $NetBSD: msdosfs_vfsops.c,v 1.118 2015/03/28 19:24:05 maxv Exp $ */ /* $NetBSD: msdosfs_vfsops.c,v 1.136 2021/02/11 00:15:55 ryoon Exp $ */
/*- /*-
* Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@ -48,7 +48,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: msdosfs_vfsops.c,v 1.118 2015/03/28 19:24:05 maxv Exp $"); __KERNEL_RCSID(0, "$NetBSD: msdosfs_vfsops.c,v 1.136 2021/02/11 00:15:55 ryoon Exp $");
#if defined(_KERNEL_OPT) #if defined(_KERNEL_OPT)
#include "opt_compat_netbsd.h" #include "opt_compat_netbsd.h"
@ -69,7 +69,6 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_vfsops.c,v 1.118 2015/03/28 19:24:05 maxv Ex
#include <sys/device.h> #include <sys/device.h>
#include <sys/disklabel.h> #include <sys/disklabel.h>
#include <sys/disk.h> #include <sys/disk.h>
#include <sys/fstrans.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/dirent.h> #include <sys/dirent.h>
@ -107,8 +106,6 @@ MALLOC_JUSTDEFINE(M_MSDOSFSMNT, "MSDOSFS mount", "MSDOS FS mount structure");
MALLOC_JUSTDEFINE(M_MSDOSFSFAT, "MSDOSFS FAT", "MSDOS FS FAT table"); MALLOC_JUSTDEFINE(M_MSDOSFSFAT, "MSDOSFS FAT", "MSDOS FS FAT table");
MALLOC_JUSTDEFINE(M_MSDOSFSTMP, "MSDOSFS temp", "MSDOS FS temp. structures"); MALLOC_JUSTDEFINE(M_MSDOSFSTMP, "MSDOSFS temp", "MSDOS FS temp. structures");
static struct sysctllog *msdosfs_sysctl_log;
extern const struct vnodeopv_desc msdosfs_vnodeop_opv_desc; extern const struct vnodeopv_desc msdosfs_vnodeop_opv_desc;
const struct vnodeopv_desc * const msdosfs_vnodeopv_descs[] = { const struct vnodeopv_desc * const msdosfs_vnodeopv_descs[] = {
@ -136,13 +133,28 @@ struct vfsops msdosfs_vfsops = {
.vfs_mountroot = msdosfs_mountroot, .vfs_mountroot = msdosfs_mountroot,
.vfs_snapshot = (void *)eopnotsupp, .vfs_snapshot = (void *)eopnotsupp,
.vfs_extattrctl = vfs_stdextattrctl, .vfs_extattrctl = vfs_stdextattrctl,
.vfs_suspendctl = msdosfs_suspendctl, .vfs_suspendctl = genfs_suspendctl,
.vfs_renamelock_enter = genfs_renamelock_enter, .vfs_renamelock_enter = genfs_renamelock_enter,
.vfs_renamelock_exit = genfs_renamelock_exit, .vfs_renamelock_exit = genfs_renamelock_exit,
.vfs_fsync = (void *)eopnotsupp, .vfs_fsync = (void *)eopnotsupp,
.vfs_opv_descs = msdosfs_vnodeopv_descs .vfs_opv_descs = msdosfs_vnodeopv_descs
}; };
SYSCTL_SETUP(msdosfs_sysctl_setup, "msdosfs sysctl")
{
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_NODE, "msdosfs",
SYSCTL_DESCR("MS-DOS file system"),
NULL, 0, NULL, 0,
CTL_VFS, 4, CTL_EOL);
/*
* XXX the "4" above could be dynamic, thereby eliminating one
* more instance of the "number to vfs" mapping problem, but
* "4" is the order as taken from sys/mount.h
*/
}
static int static int
msdos_modcmd(modcmd_t cmd, void *arg) msdos_modcmd(modcmd_t cmd, void *arg)
{ {
@ -153,23 +165,11 @@ msdos_modcmd(modcmd_t cmd, void *arg)
error = vfs_attach(&msdosfs_vfsops); error = vfs_attach(&msdosfs_vfsops);
if (error != 0) if (error != 0)
break; break;
sysctl_createv(&msdosfs_sysctl_log, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_NODE, "msdosfs",
SYSCTL_DESCR("MS-DOS file system"),
NULL, 0, NULL, 0,
CTL_VFS, 4, CTL_EOL);
/*
* XXX the "4" above could be dynamic, thereby eliminating one
* more instance of the "number to vfs" mapping problem, but
* "4" is the order as taken from sys/mount.h
*/
break; break;
case MODULE_CMD_FINI: case MODULE_CMD_FINI:
error = vfs_detach(&msdosfs_vfsops); error = vfs_detach(&msdosfs_vfsops);
if (error != 0) if (error != 0)
break; break;
sysctl_teardown(&msdosfs_sysctl_log);
break; break;
default: default:
error = ENOTTY; error = ENOTTY;
@ -210,7 +210,8 @@ update_mp(struct mount *mp, struct msdosfs_args *argp)
if (FAT32(pmp)) if (FAT32(pmp))
pmp->pm_flags |= MSDOSFSMNT_LONGNAME; pmp->pm_flags |= MSDOSFSMNT_LONGNAME;
else { else {
if ((error = msdosfs_root(mp, &rtvp)) != 0) error = msdosfs_root(mp, LK_EXCLUSIVE, &rtvp);
if (error != 0)
return error; return error;
pmp->pm_flags |= findwin95(VTODE(rtvp)) pmp->pm_flags |= findwin95(VTODE(rtvp))
? MSDOSFSMNT_LONGNAME ? MSDOSFSMNT_LONGNAME
@ -248,22 +249,22 @@ msdosfs_mountroot(void)
args.dirmask = 0777; args.dirmask = 0777;
if ((error = msdosfs_mountfs(rootvp, mp, l, &args)) != 0) { if ((error = msdosfs_mountfs(rootvp, mp, l, &args)) != 0) {
vfs_unbusy(mp, false, NULL); vfs_unbusy(mp);
vfs_destroy(mp); vfs_rele(mp);
return (error); return (error);
} }
if ((error = update_mp(mp, &args)) != 0) { if ((error = update_mp(mp, &args)) != 0) {
(void)msdosfs_unmount(mp, 0); (void)msdosfs_unmount(mp, 0);
vfs_unbusy(mp, false, NULL); vfs_unbusy(mp);
vfs_destroy(mp); vfs_rele(mp);
vrele(rootvp); vrele(rootvp);
return (error); return (error);
} }
mountlist_append(mp); mountlist_append(mp);
(void)msdosfs_statvfs(mp, &mp->mnt_stat); (void)msdosfs_statvfs(mp, &mp->mnt_stat);
vfs_unbusy(mp, false, NULL); vfs_unbusy(mp);
return (0); return (0);
} }
@ -468,6 +469,7 @@ msdosfs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l, struct msd
int ronly, error, BlkPerSec; int ronly, error, BlkPerSec;
uint64_t psize; uint64_t psize;
unsigned secsize; unsigned secsize;
u_long fatbytes, fatblocksecs;
/* Flush out any old buffers remaining from a previous use. */ /* Flush out any old buffers remaining from a previous use. */
if ((error = vinvalbuf(devvp, V_SAVE, l->l_cred, l, 0, 0)) != 0) if ((error = vinvalbuf(devvp, V_SAVE, l->l_cred, l, 0, 0)) != 0)
@ -478,10 +480,6 @@ msdosfs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l, struct msd
bp = NULL; /* both used in error_exit */ bp = NULL; /* both used in error_exit */
pmp = NULL; pmp = NULL;
error = fstrans_mount(mp);
if (error)
goto error_exit;
error = getdisksize(devvp, &psize, &secsize); error = getdisksize(devvp, &psize, &secsize);
if (error) { if (error) {
if (argp->flags & MSDOSFSMNT_GEMDOSFS) if (argp->flags & MSDOSFSMNT_GEMDOSFS)
@ -522,6 +520,13 @@ msdosfs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l, struct msd
b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB; b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB;
b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB; b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB;
#if 0
/*
* Some FAT partition, for example Raspberry Pi Pico's
* USB mass storage, does not have exptected BOOTSIGs.
* According to FreeBSD's comment, some PC-9800/9821
* FAT floppy disks have similar problems.
*/
if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) { if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
if (bsp->bs50.bsBootSectSig0 != BOOTSIG0 if (bsp->bs50.bsBootSectSig0 != BOOTSIG0
|| bsp->bs50.bsBootSectSig1 != BOOTSIG1) { || bsp->bs50.bsBootSectSig1 != BOOTSIG1) {
@ -532,6 +537,7 @@ msdosfs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l, struct msd
goto error_exit; goto error_exit;
} }
} }
#endif
pmp = malloc(sizeof(*pmp), M_MSDOSFSMNT, M_WAITOK|M_ZERO); pmp = malloc(sizeof(*pmp), M_MSDOSFSMNT, M_WAITOK|M_ZERO);
pmp->pm_mountp = mp; pmp->pm_mountp = mp;
@ -715,12 +721,40 @@ msdosfs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l, struct msd
pmp->pm_fatdiv = 1; pmp->pm_fatdiv = 1;
} }
} }
if (FAT12(pmp))
pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec;
else
pmp->pm_fatblocksize = MAXBSIZE;
pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec; /* validate cluster count against FAT */
if ((pmp->pm_maxcluster & pmp->pm_fatmask) != pmp->pm_maxcluster) {
DPRINTF("maxcluster %lu outside of mask %#lx\n",
pmp->pm_maxcluster, pmp->pm_fatmask);
error = EINVAL;
goto error_exit;
}
/* validate FAT size */
fatbytes = (pmp->pm_maxcluster+1) * pmp->pm_fatmult / pmp->pm_fatdiv;
fatblocksecs = howmany(fatbytes, pmp->pm_BytesPerSec);
if (pmp->pm_FATsecs < fatblocksecs) {
DPRINTF("FATsecs %lu < real %lu\n", pmp->pm_FATsecs,
fatblocksecs);
error = EINVAL;
goto error_exit;
}
if (FAT12(pmp)) {
/*
* limit block size to what is needed to read a FAT block
* to not exceed MAXBSIZE
*/
pmp->pm_fatblocksec = uimin(3, fatblocksecs);
pmp->pm_fatblocksize = pmp->pm_fatblocksec
* pmp->pm_BytesPerSec;
} else {
pmp->pm_fatblocksize = MAXBSIZE;
pmp->pm_fatblocksec = pmp->pm_fatblocksize
/ pmp->pm_BytesPerSec;
}
pmp->pm_bnshift = ffs(pmp->pm_BytesPerSec) - 1; pmp->pm_bnshift = ffs(pmp->pm_BytesPerSec) - 1;
/* /*
@ -842,6 +876,7 @@ msdosfs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l, struct msd
mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0]; mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
mp->mnt_stat.f_namemax = MSDOSFS_NAMEMAX(pmp); mp->mnt_stat.f_namemax = MSDOSFS_NAMEMAX(pmp);
mp->mnt_flag |= MNT_LOCAL; mp->mnt_flag |= MNT_LOCAL;
mp->mnt_iflag |= IMNT_SHRLOOKUP;
mp->mnt_dev_bshift = pmp->pm_bnshift; mp->mnt_dev_bshift = pmp->pm_bnshift;
mp->mnt_fs_bshift = pmp->pm_cnshift; mp->mnt_fs_bshift = pmp->pm_cnshift;
@ -858,7 +893,6 @@ msdosfs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l, struct msd
return (0); return (0);
error_exit: error_exit:
fstrans_unmount(mp);
if (bp) if (bp)
brelse(bp, BC_AGE); brelse(bp, BC_AGE);
if (pmp) { if (pmp) {
@ -900,13 +934,10 @@ msdosfs_unmount(struct mount *mp, int mntflags)
printf("msdosfs_umount(): just before calling VOP_CLOSE()\n"); printf("msdosfs_umount(): just before calling VOP_CLOSE()\n");
printf("flag %08x, usecount %d, writecount %d, holdcnt %d\n", printf("flag %08x, usecount %d, writecount %d, holdcnt %d\n",
vp->v_vflag | vp->v_iflag | vp->v_uflag, vp->v_usecount, vp->v_vflag | vp->v_iflag | vp->v_uflag, vrefcnt(vp),
vp->v_writecount, vp->v_holdcnt); vp->v_writecount, vp->v_holdcnt);
printf("mount %p, op %p\n", printf("mount %p, op %p\n",
vp->v_mount, vp->v_op); vp->v_mount, vp->v_op);
printf("freef %p, freeb %p, mount %p\n",
vp->v_freelist.tqe_next, vp->v_freelist.tqe_prev,
vp->v_mount);
printf("cleanblkhd %p, dirtyblkhd %p, numoutput %d, type %d\n", printf("cleanblkhd %p, dirtyblkhd %p, numoutput %d, type %d\n",
vp->v_cleanblkhd.lh_first, vp->v_cleanblkhd.lh_first,
vp->v_dirtyblkhd.lh_first, vp->v_dirtyblkhd.lh_first,
@ -926,12 +957,11 @@ msdosfs_unmount(struct mount *mp, int mntflags)
free(pmp, M_MSDOSFSMNT); free(pmp, M_MSDOSFSMNT);
mp->mnt_data = NULL; mp->mnt_data = NULL;
mp->mnt_flag &= ~MNT_LOCAL; mp->mnt_flag &= ~MNT_LOCAL;
fstrans_unmount(mp);
return (0); return (0);
} }
int int
msdosfs_root(struct mount *mp, struct vnode **vpp) msdosfs_root(struct mount *mp, int lktype, struct vnode **vpp)
{ {
struct msdosfsmount *pmp = VFSTOMSDOSFS(mp); struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
int error; int error;
@ -941,7 +971,7 @@ msdosfs_root(struct mount *mp, struct vnode **vpp)
#endif #endif
if ((error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, vpp)) != 0) if ((error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, vpp)) != 0)
return error; return error;
error = vn_lock(*vpp, LK_EXCLUSIVE); error = vn_lock(*vpp, lktype);
if (error) { if (error) {
vrele(*vpp); vrele(*vpp);
*vpp = NULL; *vpp = NULL;
@ -981,12 +1011,14 @@ msdosfs_sync_selector(void *cl, struct vnode *vp)
struct msdosfs_sync_ctx *c = cl; struct msdosfs_sync_ctx *c = cl;
struct denode *dep; struct denode *dep;
KASSERT(mutex_owned(vp->v_interlock));
dep = VTODE(vp); dep = VTODE(vp);
if (c->waitfor == MNT_LAZY || vp->v_type == VNON || if (c->waitfor == MNT_LAZY || vp->v_type == VNON ||
dep == NULL || (((dep->de_flag & dep == NULL || (((dep->de_flag &
(DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0) && (DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0) &&
(LIST_EMPTY(&vp->v_dirtyblkhd) && (LIST_EMPTY(&vp->v_dirtyblkhd) &&
UVM_OBJ_IS_CLEAN(&vp->v_uobj)))) (vp->v_iflag & VI_ONWORKLST) == 0)))
return false; return false;
return true; return true;
} }
@ -1011,7 +1043,6 @@ msdosfs_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
/* update FATs here */ /* update FATs here */
} }
} }
fstrans_start(mp, FSTRANS_SHARED);
/* /*
* Write back each (modified) denode. * Write back each (modified) denode.
*/ */
@ -1035,15 +1066,16 @@ msdosfs_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
/* /*
* Force stale file system control information to be flushed. * Force stale file system control information to be flushed.
*/ */
vn_lock(pmp->pm_devvp, LK_EXCLUSIVE | LK_RETRY);
if ((error = VOP_FSYNC(pmp->pm_devvp, cred, if ((error = VOP_FSYNC(pmp->pm_devvp, cred,
waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0)) != 0) waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0)) != 0)
allerror = error; allerror = error;
fstrans_done(mp); VOP_UNLOCK(pmp->pm_devvp);
return (allerror); return (allerror);
} }
int int
msdosfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) msdosfs_fhtovp(struct mount *mp, struct fid *fhp, int lktype, struct vnode **vpp)
{ {
struct msdosfsmount *pmp = VFSTOMSDOSFS(mp); struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
struct defid defh; struct defid defh;
@ -1069,7 +1101,7 @@ msdosfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
*vpp = NULLVP; *vpp = NULLVP;
return error; return error;
} }
error = vn_lock(*vpp, LK_EXCLUSIVE); error = vn_lock(*vpp, lktype);
if (error) { if (error) {
vrele(*vpp); vrele(*vpp);
*vpp = NULLVP; *vpp = NULLVP;
@ -1104,36 +1136,9 @@ msdosfs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size)
} }
int int
msdosfs_vget(struct mount *mp, ino_t ino, msdosfs_vget(struct mount *mp, ino_t ino, int lktype,
struct vnode **vpp) struct vnode **vpp)
{ {
return (EOPNOTSUPP); return (EOPNOTSUPP);
} }
int
msdosfs_suspendctl(struct mount *mp, int cmd)
{
int error;
struct lwp *l = curlwp;
switch (cmd) {
case SUSPEND_SUSPEND:
if ((error = fstrans_setstate(mp, FSTRANS_SUSPENDING)) != 0)
return error;
error = msdosfs_sync(mp, MNT_WAIT, l->l_proc->p_cred);
if (error == 0)
error = fstrans_setstate(mp, FSTRANS_SUSPENDED);
if (error != 0) {
(void) fstrans_setstate(mp, FSTRANS_NORMAL);
return error;
}
return 0;
case SUSPEND_RESUME:
return fstrans_setstate(mp, FSTRANS_NORMAL);
default:
return EINVAL;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: msdosfs_vnops.c,v 1.93 2015/04/04 12:34:44 riastradh Exp $ */ /* $NetBSD: msdosfs_vnops.c,v 1.104 2020/06/27 17:29:18 christos Exp $ */
/*- /*-
* Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@ -48,7 +48,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.93 2015/04/04 12:34:44 riastradh Exp $"); __KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.104 2020/06/27 17:29:18 christos Exp $");
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -60,7 +60,6 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.93 2015/04/04 12:34:44 riastradh
#include <sys/buf.h> #include <sys/buf.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/fstrans.h>
#include <sys/vnode.h> #include <sys/vnode.h>
#include <sys/signalvar.h> #include <sys/signalvar.h>
#include <sys/malloc.h> #include <sys/malloc.h>
@ -120,7 +119,6 @@ msdosfs_create(void *v)
printf("msdosfs_create(cnp %p, vap %p\n", cnp, ap->a_vap); printf("msdosfs_create(cnp %p, vap %p\n", cnp, ap->a_vap);
#endif #endif
fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED);
/* /*
* If this is the root directory and there is no space left we * If this is the root directory and there is no space left we
* can't do anything. This is because the root directory can not * can't do anything. This is because the root directory can not
@ -153,13 +151,13 @@ msdosfs_create(void *v)
DETIMES(&ndirent, NULL, NULL, NULL, pdep->de_pmp->pm_gmtoff); DETIMES(&ndirent, NULL, NULL, NULL, pdep->de_pmp->pm_gmtoff);
if ((error = createde(&ndirent, pdep, &dep, cnp)) != 0) if ((error = createde(&ndirent, pdep, &dep, cnp)) != 0)
goto bad; goto bad;
fstrans_done(ap->a_dvp->v_mount);
VN_KNOTE(ap->a_dvp, NOTE_WRITE); VN_KNOTE(ap->a_dvp, NOTE_WRITE);
*ap->a_vpp = DETOV(dep); *ap->a_vpp = DETOV(dep);
cache_enter(ap->a_dvp, *ap->a_vpp, cnp->cn_nameptr, cnp->cn_namelen,
cnp->cn_flags);
return (0); return (0);
bad: bad:
fstrans_done(ap->a_dvp->v_mount);
return (error); return (error);
} }
@ -174,17 +172,15 @@ msdosfs_close(void *v)
struct vnode *vp = ap->a_vp; struct vnode *vp = ap->a_vp;
struct denode *dep = VTODE(vp); struct denode *dep = VTODE(vp);
fstrans_start(vp->v_mount, FSTRANS_SHARED);
mutex_enter(vp->v_interlock); mutex_enter(vp->v_interlock);
if (vp->v_usecount > 1) if (vrefcnt(vp) > 1)
DETIMES(dep, NULL, NULL, NULL, dep->de_pmp->pm_gmtoff); DETIMES(dep, NULL, NULL, NULL, dep->de_pmp->pm_gmtoff);
mutex_exit(vp->v_interlock); mutex_exit(vp->v_interlock);
fstrans_done(vp->v_mount);
return (0); return (0);
} }
static int static int
msdosfs_check_possible(struct vnode *vp, struct denode *dep, mode_t mode) msdosfs_check_possible(struct vnode *vp, struct denode *dep, accmode_t accmode)
{ {
/* /*
@ -192,7 +188,7 @@ msdosfs_check_possible(struct vnode *vp, struct denode *dep, mode_t mode)
* unless the file is a socket, fifo, or a block or * unless the file is a socket, fifo, or a block or
* character device resident on the file system. * character device resident on the file system.
*/ */
if (mode & VWRITE) { if (accmode & VWRITE) {
switch (vp->v_type) { switch (vp->v_type) {
case VDIR: case VDIR:
case VLNK: case VLNK:
@ -208,7 +204,7 @@ msdosfs_check_possible(struct vnode *vp, struct denode *dep, mode_t mode)
} }
static int static int
msdosfs_check_permitted(struct vnode *vp, struct denode *dep, mode_t mode, msdosfs_check_permitted(struct vnode *vp, struct denode *dep, accmode_t accmode,
kauth_cred_t cred) kauth_cred_t cred)
{ {
struct msdosfsmount *pmp = dep->de_pmp; struct msdosfsmount *pmp = dep->de_pmp;
@ -221,9 +217,9 @@ msdosfs_check_permitted(struct vnode *vp, struct denode *dep, mode_t mode,
file_mode &= (vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask); file_mode &= (vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask);
return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
vp->v_type, file_mode), vp, NULL, genfs_can_access(vp->v_type, vp->v_type, file_mode), vp, NULL, genfs_can_access(vp, cred,
file_mode, pmp->pm_uid, pmp->pm_gid, mode, cred)); pmp->pm_uid, pmp->pm_gid, file_mode, NULL, accmode));
} }
int int
@ -231,18 +227,18 @@ msdosfs_access(void *v)
{ {
struct vop_access_args /* { struct vop_access_args /* {
struct vnode *a_vp; struct vnode *a_vp;
int a_mode; accmode_t a_accmode;
kauth_cred_t a_cred; kauth_cred_t a_cred;
} */ *ap = v; } */ *ap = v;
struct vnode *vp = ap->a_vp; struct vnode *vp = ap->a_vp;
struct denode *dep = VTODE(vp); struct denode *dep = VTODE(vp);
int error; int error;
error = msdosfs_check_possible(vp, dep, ap->a_mode); error = msdosfs_check_possible(vp, dep, ap->a_accmode);
if (error) if (error)
return error; return error;
error = msdosfs_check_permitted(vp, dep, ap->a_mode, ap->a_cred); error = msdosfs_check_permitted(vp, dep, ap->a_accmode, ap->a_cred);
return error; return error;
} }
@ -262,7 +258,6 @@ msdosfs_getattr(void *v)
u_long dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry); u_long dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry);
ino_t fileid; ino_t fileid;
fstrans_start(ap->a_vp->v_mount, FSTRANS_SHARED);
DETIMES(dep, NULL, NULL, NULL, pmp->pm_gmtoff); DETIMES(dep, NULL, NULL, NULL, pmp->pm_gmtoff);
vap->va_fsid = dep->de_dev; vap->va_fsid = dep->de_dev;
/* /*
@ -313,7 +308,6 @@ msdosfs_getattr(void *v)
vap->va_bytes = vap->va_bytes =
(dep->de_FileSize + pmp->pm_crbomask) & ~pmp->pm_crbomask; (dep->de_FileSize + pmp->pm_crbomask) & ~pmp->pm_crbomask;
vap->va_type = ap->a_vp->v_type; vap->va_type = ap->a_vp->v_type;
fstrans_done(ap->a_vp->v_mount);
return (0); return (0);
} }
@ -361,7 +355,6 @@ msdosfs_setattr(void *v)
if (ap->a_vp->v_type == VDIR) if (ap->a_vp->v_type == VDIR)
return 0; return 0;
fstrans_start(vp->v_mount, FSTRANS_SHARED);
if (vap->va_size != VNOVAL) { if (vap->va_size != VNOVAL) {
if (vp->v_mount->mnt_flag & MNT_RDONLY) { if (vp->v_mount->mnt_flag & MNT_RDONLY) {
error = EROFS; error = EROFS;
@ -378,8 +371,8 @@ msdosfs_setattr(void *v)
goto bad; goto bad;
} }
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES,
ap->a_vp, NULL, genfs_can_chtimes(ap->a_vp, vap->va_vaflags, ap->a_vp, NULL, genfs_can_chtimes(ap->a_vp, cred,
pmp->pm_uid, cred)); pmp->pm_uid, vap->va_vaflags));
if (error) if (error)
goto bad; goto bad;
if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 && if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 &&
@ -402,7 +395,7 @@ msdosfs_setattr(void *v)
goto bad; goto bad;
} }
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_FLAGS, vp, error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_FLAGS, vp,
NULL, genfs_can_chflags(cred, vp->v_type, pmp->pm_uid, false)); NULL, genfs_can_chflags(vp, cred, pmp->pm_uid, false));
if (error) if (error)
goto bad; goto bad;
/* We ignore the read and execute bits. */ /* We ignore the read and execute bits. */
@ -422,7 +415,7 @@ msdosfs_setattr(void *v)
goto bad; goto bad;
} }
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_FLAGS, vp, error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_FLAGS, vp,
NULL, genfs_can_chflags(cred, vp->v_type, pmp->pm_uid, false)); NULL, genfs_can_chflags(vp, cred, pmp->pm_uid, false));
if (error) if (error)
goto bad; goto bad;
if (vap->va_flags & SF_ARCHIVED) if (vap->va_flags & SF_ARCHIVED)
@ -441,7 +434,6 @@ msdosfs_setattr(void *v)
} }
bad: bad:
fstrans_done(vp->v_mount);
return error; return error;
} }
@ -478,7 +470,6 @@ msdosfs_read(void *v)
if (uio->uio_offset >= dep->de_FileSize) if (uio->uio_offset >= dep->de_FileSize)
return (0); return (0);
fstrans_start(vp->v_mount, FSTRANS_SHARED);
if (vp->v_type == VREG) { if (vp->v_type == VREG) {
const int advice = IO_ADV_DECODE(ap->a_ioflag); const int advice = IO_ADV_DECODE(ap->a_ioflag);
@ -489,7 +480,7 @@ msdosfs_read(void *v)
if (bytelen == 0) if (bytelen == 0)
break; break;
error = ubc_uiomove(&vp->v_uobj, uio, bytelen, advice, error = ubc_uiomove(&vp->v_uobj, uio, bytelen, advice,
UBC_READ | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp)); UBC_READ | UBC_PARTIALOK | UBC_VNODE_FLAGS(vp));
if (error) if (error)
break; break;
} }
@ -503,7 +494,6 @@ msdosfs_read(void *v)
on = uio->uio_offset & pmp->pm_crbomask; on = uio->uio_offset & pmp->pm_crbomask;
n = MIN(pmp->pm_bpcluster - on, uio->uio_resid); n = MIN(pmp->pm_bpcluster - on, uio->uio_resid);
if (uio->uio_offset >= dep->de_FileSize) { if (uio->uio_offset >= dep->de_FileSize) {
fstrans_done(vp->v_mount);
return (0); return (0);
} }
/* file size (and hence diff) may be up to 4GB */ /* file size (and hence diff) may be up to 4GB */
@ -540,7 +530,6 @@ out:
error = uerror; error = uerror;
} }
bad: bad:
fstrans_done(vp->v_mount);
return (error); return (error);
} }
@ -599,7 +588,6 @@ msdosfs_write(void *v)
if (uio->uio_offset + uio->uio_resid > MSDOSFS_FILESIZE_MAX) if (uio->uio_offset + uio->uio_resid > MSDOSFS_FILESIZE_MAX)
return (EFBIG); return (EFBIG);
fstrans_start(vp->v_mount, FSTRANS_SHARED);
/* /*
* If the offset we are starting the write at is beyond the end of * If the offset we are starting the write at is beyond the end of
* the file, then they've done a seek. Unix filesystems allow * the file, then they've done a seek. Unix filesystems allow
@ -608,7 +596,6 @@ msdosfs_write(void *v)
*/ */
if (uio->uio_offset > dep->de_FileSize) { if (uio->uio_offset > dep->de_FileSize) {
if ((error = deextend(dep, uio->uio_offset, cred)) != 0) { if ((error = deextend(dep, uio->uio_offset, cred)) != 0) {
fstrans_done(vp->v_mount);
return (error); return (error);
} }
} }
@ -637,7 +624,7 @@ msdosfs_write(void *v)
rem = round_page(dep->de_FileSize) - dep->de_FileSize; rem = round_page(dep->de_FileSize) - dep->de_FileSize;
if (rem > 0) if (rem > 0)
ubc_zerorange(&vp->v_uobj, (off_t)dep->de_FileSize, ubc_zerorange(&vp->v_uobj, (off_t)dep->de_FileSize,
rem, UBC_UNMAP_FLAG(vp)); rem, UBC_VNODE_FLAGS(vp));
extended = 1; extended = 1;
} }
@ -646,7 +633,7 @@ msdosfs_write(void *v)
bytelen = uio->uio_resid; bytelen = uio->uio_resid;
error = ubc_uiomove(&vp->v_uobj, uio, bytelen, error = ubc_uiomove(&vp->v_uobj, uio, bytelen,
IO_ADV_DECODE(ioflag), UBC_WRITE | UBC_UNMAP_FLAG(vp)); IO_ADV_DECODE(ioflag), UBC_WRITE | UBC_VNODE_FLAGS(vp));
if (error) if (error)
break; break;
@ -656,7 +643,7 @@ msdosfs_write(void *v)
*/ */
if (!async && oldoff >> 16 != uio->uio_offset >> 16) { if (!async && oldoff >> 16 != uio->uio_offset >> 16) {
mutex_enter(vp->v_interlock); rw_enter(vp->v_uobj.vmobjlock, RW_WRITER);
error = VOP_PUTPAGES(vp, (oldoff >> 16) << 16, error = VOP_PUTPAGES(vp, (oldoff >> 16) << 16,
(uio->uio_offset >> 16) << 16, (uio->uio_offset >> 16) << 16,
PGO_CLEANIT | PGO_LAZY); PGO_CLEANIT | PGO_LAZY);
@ -666,7 +653,7 @@ msdosfs_write(void *v)
/* set final size */ /* set final size */
uvm_vnp_setsize(vp, dep->de_FileSize); uvm_vnp_setsize(vp, dep->de_FileSize);
if (error == 0 && ioflag & IO_SYNC) { if (error == 0 && ioflag & IO_SYNC) {
mutex_enter(vp->v_interlock); rw_enter(vp->v_uobj.vmobjlock, RW_WRITER);
error = VOP_PUTPAGES(vp, trunc_page(oldoff), error = VOP_PUTPAGES(vp, trunc_page(oldoff),
round_page(oldoff + bytelen), PGO_CLEANIT | PGO_SYNCIO); round_page(oldoff + bytelen), PGO_CLEANIT | PGO_SYNCIO);
} }
@ -685,7 +672,6 @@ errexit:
uio->uio_resid = resid; uio->uio_resid = resid;
} else if ((ioflag & IO_SYNC) == IO_SYNC) } else if ((ioflag & IO_SYNC) == IO_SYNC)
error = deupdat(dep, 1); error = deupdat(dep, 1);
fstrans_done(vp->v_mount);
KASSERT(vp->v_size == dep->de_FileSize); KASSERT(vp->v_size == dep->de_FileSize);
return (error); return (error);
} }
@ -731,7 +717,7 @@ msdosfs_update(struct vnode *vp, const struct timespec *acc,
int int
msdosfs_remove(void *v) msdosfs_remove(void *v)
{ {
struct vop_remove_args /* { struct vop_remove_v2_args /* {
struct vnode *a_dvp; struct vnode *a_dvp;
struct vnode *a_vp; struct vnode *a_vp;
struct componentname *a_cnp; struct componentname *a_cnp;
@ -740,14 +726,13 @@ msdosfs_remove(void *v)
struct denode *ddep = VTODE(ap->a_dvp); struct denode *ddep = VTODE(ap->a_dvp);
int error; int error;
fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED);
if (ap->a_vp->v_type == VDIR) if (ap->a_vp->v_type == VDIR)
error = EPERM; error = EPERM;
else else
error = removede(ddep, dep); error = removede(ddep, dep);
#ifdef MSDOSFS_DEBUG #ifdef MSDOSFS_DEBUG
printf("msdosfs_remove(), dep %p, v_usecount %d\n", printf("msdosfs_remove(), dep %p, usecount %d\n",
dep, ap->a_vp->v_usecount); dep, vrefcnt(ap->a_vp));
#endif #endif
VN_KNOTE(ap->a_vp, NOTE_DELETE); VN_KNOTE(ap->a_vp, NOTE_DELETE);
VN_KNOTE(ap->a_dvp, NOTE_WRITE); VN_KNOTE(ap->a_dvp, NOTE_WRITE);
@ -756,8 +741,7 @@ msdosfs_remove(void *v)
else else
vput(ap->a_vp); /* causes msdosfs_inactive() to be called vput(ap->a_vp); /* causes msdosfs_inactive() to be called
* via vrele() */ * via vrele() */
vput(ap->a_dvp);
fstrans_done(ap->a_dvp->v_mount);
return (error); return (error);
} }
@ -832,7 +816,6 @@ msdosfs_rename(void *v)
struct vnode *tdvp = ap->a_tdvp; struct vnode *tdvp = ap->a_tdvp;
struct vnode *fvp = ap->a_fvp; struct vnode *fvp = ap->a_fvp;
struct vnode *fdvp = ap->a_fdvp; struct vnode *fdvp = ap->a_fdvp;
struct mount *mp = fdvp->v_mount;
struct componentname *tcnp = ap->a_tcnp; struct componentname *tcnp = ap->a_tcnp;
struct componentname *fcnp = ap->a_fcnp; struct componentname *fcnp = ap->a_fcnp;
struct denode *ip, *xp, *dp, *zp; struct denode *ip, *xp, *dp, *zp;
@ -910,7 +893,6 @@ abortit:
} }
VN_KNOTE(fdvp, NOTE_WRITE); /* XXXLUKEM/XXX: right place? */ VN_KNOTE(fdvp, NOTE_WRITE); /* XXXLUKEM/XXX: right place? */
fstrans_start(mp, FSTRANS_SHARED);
/* /*
* When the target exists, both the directory * When the target exists, both the directory
* and target vnodes are returned locked. * and target vnodes are returned locked.
@ -997,7 +979,6 @@ abortit:
* file/directory. * file/directory.
*/ */
if ((error = uniqdosname(VTODE(tdvp), tcnp, toname)) != 0) { if ((error = uniqdosname(VTODE(tdvp), tcnp, toname)) != 0) {
fstrans_done(mp);
goto abortit; goto abortit;
} }
@ -1013,7 +994,6 @@ abortit:
VOP_UNLOCK(fdvp); VOP_UNLOCK(fdvp);
vrele(ap->a_fvp); vrele(ap->a_fvp);
vrele(tdvp); vrele(tdvp);
fstrans_done(mp);
return (error); return (error);
} }
if (fvp == NULL) { if (fvp == NULL) {
@ -1025,7 +1005,6 @@ abortit:
vput(fdvp); vput(fdvp);
vrele(ap->a_fvp); vrele(ap->a_fvp);
vrele(tdvp); vrele(tdvp);
fstrans_done(mp);
return 0; return 0;
} }
VOP_UNLOCK(fdvp); VOP_UNLOCK(fdvp);
@ -1140,7 +1119,6 @@ bad:
ip->de_flag &= ~DE_RENAME; ip->de_flag &= ~DE_RENAME;
vrele(fdvp); vrele(fdvp);
vrele(fvp); vrele(fvp);
fstrans_done(mp);
return (error); return (error);
/* XXX: uuuh */ /* XXX: uuuh */
@ -1197,7 +1175,6 @@ msdosfs_mkdir(void *v)
struct buf *bp; struct buf *bp;
int async = pdep->de_pmp->pm_mountp->mnt_flag & MNT_ASYNC; int async = pdep->de_pmp->pm_mountp->mnt_flag & MNT_ASYNC;
fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED);
/* /*
* If this is the root directory and there is no space left we * If this is the root directory and there is no space left we
* can't do anything. This is because the root directory can not * can't do anything. This is because the root directory can not
@ -1280,27 +1257,24 @@ msdosfs_mkdir(void *v)
goto bad; goto bad;
VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK); VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK);
*ap->a_vpp = DETOV(dep); *ap->a_vpp = DETOV(dep);
fstrans_done(ap->a_dvp->v_mount);
return (0); return (0);
bad: bad:
clusterfree(pmp, newcluster, NULL); clusterfree(pmp, newcluster, NULL);
bad2: bad2:
fstrans_done(ap->a_dvp->v_mount);
return (error); return (error);
} }
int int
msdosfs_rmdir(void *v) msdosfs_rmdir(void *v)
{ {
struct vop_rmdir_args /* { struct vop_rmdir_v2_args /* {
struct vnode *a_dvp; struct vnode *a_dvp;
struct vnode *a_vp; struct vnode *a_vp;
struct componentname *a_cnp; struct componentname *a_cnp;
} */ *ap = v; } */ *ap = v;
struct vnode *vp = ap->a_vp; struct vnode *vp = ap->a_vp;
struct vnode *dvp = ap->a_dvp; struct vnode *dvp = ap->a_dvp;
struct mount *mp = dvp->v_mount;
struct componentname *cnp = ap->a_cnp; struct componentname *cnp = ap->a_cnp;
struct denode *ip, *dp; struct denode *ip, *dp;
int error; int error;
@ -1311,11 +1285,9 @@ msdosfs_rmdir(void *v)
* No rmdir "." please. * No rmdir "." please.
*/ */
if (dp == ip) { if (dp == ip) {
vrele(dvp); vrele(vp);
vput(vp);
return (EINVAL); return (EINVAL);
} }
fstrans_start(mp, FSTRANS_SHARED);
/* /*
* Verify the directory is empty (and valid). * Verify the directory is empty (and valid).
* (Rmdir ".." won't be valid since * (Rmdir ".." won't be valid since
@ -1345,8 +1317,6 @@ msdosfs_rmdir(void *v)
*/ */
VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
cache_purge(dvp); cache_purge(dvp);
vput(dvp);
dvp = NULL;
/* /*
* Truncate the directory that is being deleted. * Truncate the directory that is being deleted.
*/ */
@ -1354,10 +1324,7 @@ msdosfs_rmdir(void *v)
cache_purge(vp); cache_purge(vp);
out: out:
VN_KNOTE(vp, NOTE_DELETE); VN_KNOTE(vp, NOTE_DELETE);
if (dvp)
vput(dvp);
vput(vp); vput(vp);
fstrans_done(mp);
return (error); return (error);
} }
@ -1394,6 +1361,7 @@ msdosfs_readdir(void *v)
int ncookies = 0, nc = 0; int ncookies = 0, nc = 0;
off_t offset, uio_off; off_t offset, uio_off;
int chksum = -1; int chksum = -1;
uint16_t namlen;
#ifdef MSDOSFS_DEBUG #ifdef MSDOSFS_DEBUG
printf("msdosfs_readdir(): vp %p, uio %p, cred %p, eofflagp %p\n", printf("msdosfs_readdir(): vp %p, uio %p, cred %p, eofflagp %p\n",
@ -1423,7 +1391,6 @@ msdosfs_readdir(void *v)
uio->uio_resid = count; uio->uio_resid = count;
uio_off = uio->uio_offset; uio_off = uio->uio_offset;
fstrans_start(ap->a_vp->v_mount, FSTRANS_SHARED);
/* Allocate a temporary dirent buffer. */ /* Allocate a temporary dirent buffer. */
dirbuf = malloc(sizeof(struct dirent), M_MSDOSFSTMP, M_WAITOK | M_ZERO); dirbuf = malloc(sizeof(struct dirent), M_MSDOSFSTMP, M_WAITOK | M_ZERO);
@ -1541,7 +1508,10 @@ msdosfs_readdir(void *v)
if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME)
continue; continue;
chksum = win2unixfn((struct winentry *)dentp, chksum = win2unixfn((struct winentry *)dentp,
dirbuf, chksum); dirbuf, chksum, &namlen,
pmp->pm_flags & MSDOSFSMNT_UTF8);
if (chksum != -1)
dirbuf->d_namlen = namlen;
continue; continue;
} }
@ -1584,6 +1554,7 @@ msdosfs_readdir(void *v)
pmp->pm_flags & MSDOSFSMNT_SHORTNAME); pmp->pm_flags & MSDOSFSMNT_SHORTNAME);
else else
dirbuf->d_name[dirbuf->d_namlen] = 0; dirbuf->d_name[dirbuf->d_namlen] = 0;
namlen = dirbuf->d_namlen;
chksum = -1; chksum = -1;
dirbuf->d_reclen = _DIRENT_SIZE(dirbuf); dirbuf->d_reclen = _DIRENT_SIZE(dirbuf);
if (uio->uio_resid < dirbuf->d_reclen) { if (uio->uio_resid < dirbuf->d_reclen) {
@ -1627,7 +1598,6 @@ out:
bad: bad:
free(dirbuf, M_MSDOSFSTMP); free(dirbuf, M_MSDOSFSTMP);
fstrans_done(ap->a_vp->v_mount);
return (error); return (error);
} }
@ -1795,7 +1765,7 @@ msdosfs_pathconf(void *v)
*ap->a_retval = 32; *ap->a_retval = 32;
return (0); return (0);
default: default:
return (EINVAL); return genfs_pathconf(ap);
} }
/* NOTREACHED */ /* NOTREACHED */
} }
@ -1814,7 +1784,6 @@ msdosfs_fsync(void *v)
int wait; int wait;
int error; int error;
fstrans_start(vp->v_mount, FSTRANS_LAZY);
wait = (ap->a_flags & FSYNC_WAIT) != 0; wait = (ap->a_flags & FSYNC_WAIT) != 0;
error = vflushbuf(vp, ap->a_flags); error = vflushbuf(vp, ap->a_flags);
if (error == 0 && (ap->a_flags & FSYNC_DATAONLY) == 0) if (error == 0 && (ap->a_flags & FSYNC_DATAONLY) == 0)
@ -1828,7 +1797,6 @@ msdosfs_fsync(void *v)
error = VOP_IOCTL(devvp, DIOCCACHESYNC, &l, FWRITE, error = VOP_IOCTL(devvp, DIOCCACHESYNC, &l, FWRITE,
curlwp->l_cred); curlwp->l_cred);
} }
fstrans_done(vp->v_mount);
return (error); return (error);
} }
@ -1879,6 +1847,7 @@ const struct vnodeopv_entry_desc msdosfs_vnodeop_entries[] = {
{ &vop_open_desc, genfs_nullop }, /* open */ { &vop_open_desc, genfs_nullop }, /* open */
{ &vop_close_desc, msdosfs_close }, /* close */ { &vop_close_desc, msdosfs_close }, /* close */
{ &vop_access_desc, msdosfs_access }, /* access */ { &vop_access_desc, msdosfs_access }, /* access */
{ &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, msdosfs_getattr }, /* getattr */ { &vop_getattr_desc, msdosfs_getattr }, /* getattr */
{ &vop_setattr_desc, msdosfs_setattr }, /* setattr */ { &vop_setattr_desc, msdosfs_setattr }, /* setattr */
{ &vop_read_desc, msdosfs_read }, /* read */ { &vop_read_desc, msdosfs_read }, /* read */

View File

@ -1,4 +1,4 @@
/* $NetBSD: msdosfsmount.h,v 1.20 2014/07/08 09:21:52 hannken Exp $ */ /* $NetBSD: msdosfsmount.h,v 1.21 2016/01/30 09:59:27 mlelstv Exp $ */
/*- /*-
* Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@ -78,11 +78,12 @@ struct msdosfs_args {
#define MSDOSFSMNT_NOWIN95 4 /* Completely ignore Win95 entries */ #define MSDOSFSMNT_NOWIN95 4 /* Completely ignore Win95 entries */
#define MSDOSFSMNT_GEMDOSFS 8 /* This is a GEMDOS-flavour */ #define MSDOSFSMNT_GEMDOSFS 8 /* This is a GEMDOS-flavour */
#define MSDOSFSMNT_VERSIONED 16 /* Struct is versioned */ #define MSDOSFSMNT_VERSIONED 16 /* Struct is versioned */
#define MSDOSFSMNT_UTF8 32 /* Use UTF8 filenames */
/* All flags above: */ /* All flags above: */
#define MSDOSFSMNT_MNTOPT \ #define MSDOSFSMNT_MNTOPT \
(MSDOSFSMNT_SHORTNAME|MSDOSFSMNT_LONGNAME|MSDOSFSMNT_NOWIN95 \ (MSDOSFSMNT_SHORTNAME|MSDOSFSMNT_LONGNAME|MSDOSFSMNT_NOWIN95 \
|MSDOSFSMNT_GEMDOSFS|MSDOSFSMNT_VERSIONED) |MSDOSFSMNT_GEMDOSFS|MSDOSFSMNT_VERSIONED|MSDOSFSMNT_UTF8)
#define MSDOSFSMNT_RONLY 0x80000000 /* mounted read-only */ #define MSDOSFSMNT_RONLY 0x80000000 /* mounted read-only */
#define MSDOSFSMNT_WAITONFAT 0x40000000 /* mounted synchronous */ #define MSDOSFSMNT_WAITONFAT 0x40000000 /* mounted synchronous */
@ -90,7 +91,7 @@ struct msdosfs_args {
#define MSDOSFSMNT_BITS "\177\20" \ #define MSDOSFSMNT_BITS "\177\20" \
"b\00shortname\0b\01longname\0b\02nowin95\0b\03gemdosfs\0b\04mntversioned\0" \ "b\00shortname\0b\01longname\0b\02nowin95\0b\03gemdosfs\0b\04mntversioned\0" \
"b\037ronly\0b\036waitonfat\0b\035fatmirror\0" "b\05utf8\0b\037ronly\0b\036waitonfat\0b\035fatmirror\0"
#ifdef _KERNEL #ifdef _KERNEL
#include <sys/mallocvar.h> #include <sys/mallocvar.h>

View File

@ -1,8 +1,8 @@
/* $NetBSD: ecma167-udf.h,v 1.14 2011/07/07 17:45:38 reinoud Exp $ */ /* $NetBSD: ecma167-udf.h,v 1.16 2018/08/09 13:49:30 reinoud Exp $ */
/*- /*-
* Copyright (c) 2003, 2004, 2005, 2006, 2008, 2009 * Copyright (c) 2003, 2004, 2005, 2006, 2008, 2009, 2017, 2018
* Reinoud Zandijk * <reinoud@NetBSD.org> * Reinoud Zandijk <reinoud@NetBSD.org>
* Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org> * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
* All rights reserved. * All rights reserved.
* *
@ -203,14 +203,14 @@ union icb {
/* short/long/ext extent have flags encoded in length */ /* short/long/ext extent have flags encoded in length */
#define UDF_EXT_ALLOCATED (0<<30) #define UDF_EXT_ALLOCATED (0U<<30)
#define UDF_EXT_FREED (1<<30) #define UDF_EXT_FREED (1U<<30)
#define UDF_EXT_ALLOCATED_BUT_NOT_USED (1<<30) #define UDF_EXT_ALLOCATED_BUT_NOT_USED (1U<<30)
#define UDF_EXT_FREE (2<<30) #define UDF_EXT_FREE (2U<<30)
#define UDF_EXT_REDIRECT (3<<30) #define UDF_EXT_REDIRECT (3U<<30)
#define UDF_EXT_FLAGS(len) ((len) & (3<<30)) #define UDF_EXT_FLAGS(len) ((len) & (3U<<30))
#define UDF_EXT_LEN(len) ((len) & ((1<<30)-1)) #define UDF_EXT_LEN(len) ((len) & ((1U<<30)-1))
#define UDF_EXT_MAXLEN ((1<<30)-1) #define UDF_EXT_MAXLEN ((1U<<30)-1)
/* Character set spec [1/7.2.1] */ /* Character set spec [1/7.2.1] */
@ -264,7 +264,10 @@ struct regid {
struct icb_tag { struct icb_tag {
uint32_t prev_num_dirs; uint32_t prev_num_dirs;
uint16_t strat_type; uint16_t strat_type;
uint8_t strat_param[2]; union {
uint8_t strat_param[2];
uint16_t strat_param16;
};
uint16_t max_num_entries; uint16_t max_num_entries;
uint8_t reserved; uint8_t reserved;
uint8_t file_type; uint8_t file_type;
@ -682,7 +685,10 @@ struct impl_extattr_entry {
struct extattr_entry hdr; struct extattr_entry hdr;
uint32_t iu_l; uint32_t iu_l;
struct regid imp_id; struct regid imp_id;
uint8_t data[1]; union {
uint8_t data[1];
uint16_t data16;
};
} __packed; } __packed;
@ -832,4 +838,3 @@ union dscrptr {
#endif /* !_FS_UDF_ECMA167_UDF_H_ */ #endif /* !_FS_UDF_ECMA167_UDF_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf.h,v 1.50 2015/08/24 08:31:56 hannken Exp $ */ /* $NetBSD: udf.h,v 1.52 2016/05/24 09:55:57 reinoud Exp $ */
/* /*
* Copyright (c) 2006, 2008 Reinoud Zandijk * Copyright (c) 2006, 2008 Reinoud Zandijk
@ -76,7 +76,7 @@ extern int udf_verbose;
#define UDF_DEBUG_RESERVE 0x1000000 #define UDF_DEBUG_RESERVE 0x1000000
/* initial value of udf_verbose */ /* initial value of udf_verbose */
#define UDF_DEBUGGING 0 #define UDF_DEBUGGING (0)
#ifdef UDF_DEBUG #ifdef UDF_DEBUG
#define DPRINTF(name, arg) { \ #define DPRINTF(name, arg) { \
@ -252,6 +252,7 @@ struct udf_strategy {
int (*read_logvol_dscr) (struct udf_strat_args *args); int (*read_logvol_dscr) (struct udf_strat_args *args);
int (*write_logvol_dscr) (struct udf_strat_args *args); int (*write_logvol_dscr) (struct udf_strat_args *args);
void (*queuebuf) (struct udf_strat_args *args); void (*queuebuf) (struct udf_strat_args *args);
void (*sync_caches) (struct udf_strat_args *args);
void (*discstrat_init) (struct udf_strat_args *args); void (*discstrat_init) (struct udf_strat_args *args);
void (*discstrat_finish) (struct udf_strat_args *args); void (*discstrat_finish) (struct udf_strat_args *args);
}; };
@ -417,11 +418,12 @@ struct udf_node {
#define IN_SYNCED 0x0200 /* node is being used by sync */ #define IN_SYNCED 0x0200 /* node is being used by sync */
#define IN_CALLBACK_ULK 0x0400 /* node will be unlocked by callback */ #define IN_CALLBACK_ULK 0x0400 /* node will be unlocked by callback */
#define IN_NODE_REBUILD 0x0800 /* node is rebuild */ #define IN_NODE_REBUILD 0x0800 /* node is rebuild */
#define IN_NO_DELETE 0x1000 /* node is not to be deleted */
#define IN_FLAGBITS \ #define IN_FLAGBITS \
"\10\1IN_ACCESS\2IN_CHANGE\3IN_UPDATE\4IN_MODIFY\5IN_MODIFIED" \ "\10\1IN_ACCESS\2IN_CHANGE\3IN_UPDATE\4IN_MODIFY\5IN_MODIFIED" \
"\6IN_ACCESSED\7IN_RENAME\10IN_DELETED\11IN_LOCKED\12IN_SYNCED" \ "\6IN_ACCESSED\7IN_RENAME\10IN_DELETED\11IN_LOCKED\12IN_SYNCED" \
"\13IN_CALLBACK_ULK\14IN_NODE_REBUILD" "\13IN_CALLBACK_ULK\14IN_NODE_REBUILD\15IN_NO_DELETE"
#endif /* !_FS_UDF_UDF_H_ */ #endif /* !_FS_UDF_UDF_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_allocation.c,v 1.38 2015/08/24 08:30:17 hannken Exp $ */ /* $NetBSD: udf_allocation.c,v 1.41 2020/04/23 21:47:08 ad Exp $ */
/* /*
* Copyright (c) 2006, 2008 Reinoud Zandijk * Copyright (c) 2006, 2008 Reinoud Zandijk
@ -28,7 +28,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#ifndef lint #ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_allocation.c,v 1.38 2015/08/24 08:30:17 hannken Exp $"); __KERNEL_RCSID(0, "$NetBSD: udf_allocation.c,v 1.41 2020/04/23 21:47:08 ad Exp $");
#endif /* not lint */ #endif /* not lint */
@ -1001,7 +1001,7 @@ udf_bitmap_check_trunc_free(struct udf_bitmap *bitmap, uint32_t to_trunc)
bitval = (1 << bit); bitval = (1 << bit);
if (!(*bpos & bitval)) if (!(*bpos & bitval))
seq_free = 0; seq_free = 0;
offset++; to_trunc--; to_trunc--;
bit++; bit++;
if (bit == 8) { if (bit == 8) {
bpos++; bpos++;
@ -1540,8 +1540,7 @@ udf_trunc_metadatapart(struct udf_mount *ump, uint32_t num_lb)
*sizepos = udf_rw32(*sizepos) - to_trunc; *sizepos = udf_rw32(*sizepos) - to_trunc;
/* realloc bitmap for better memory usage */ /* realloc bitmap for better memory usage */
new_sbd = realloc(sbd, inf_len, M_UDFVOLD, new_sbd = realloc(sbd, inf_len, M_UDFVOLD, M_WAITOK);
M_CANFAIL | M_WAITOK);
if (new_sbd) { if (new_sbd) {
/* update pointers */ /* update pointers */
ump->metadata_unalloc_dscr = new_sbd; ump->metadata_unalloc_dscr = new_sbd;
@ -2679,7 +2678,7 @@ udf_grow_node(struct udf_node *udf_node, uint64_t new_size)
#if 0 #if 0
/* zero append space in buffer */ /* zero append space in buffer */
ubc_zerorange(&vp->v_uobj, old_size, ubc_zerorange(&vp->v_uobj, old_size,
new_size - old_size, UBC_UNMAP_FLAG(vp)); new_size - old_size, UBC_VNODE_FLAGS(vp));
#endif #endif
udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec);
@ -2785,7 +2784,7 @@ udf_grow_node(struct udf_node *udf_node, uint64_t new_size)
/* TODO zero appened space in buffer! */ /* TODO zero appened space in buffer! */
/* using ubc_zerorange(&vp->v_uobj, old_size, */ /* using ubc_zerorange(&vp->v_uobj, old_size, */
/* new_size - old_size, UBC_UNMAP_FLAG(vp)); ? */ /* new_size - old_size, UBC_VNODE_FLAGS(vp)); ? */
} }
memset(&s_ad, 0, sizeof(struct long_ad)); memset(&s_ad, 0, sizeof(struct long_ad));
@ -2956,7 +2955,7 @@ udf_shrink_node(struct udf_node *udf_node, uint64_t new_size)
/* TODO zero appened space in buffer! */ /* TODO zero appened space in buffer! */
/* using ubc_zerorange(&vp->v_uobj, old_size, */ /* using ubc_zerorange(&vp->v_uobj, old_size, */
/* old_size - new_size, UBC_UNMAP_FLAG(vp)); ? */ /* old_size - new_size, UBC_VNODE_FLAGS(vp)); ? */
/* set new size for uvm */ /* set new size for uvm */
uvm_vnp_setsize(vp, new_size); uvm_vnp_setsize(vp, new_size);

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_mount.h,v 1.3 2006/02/02 15:52:23 reinoud Exp $ */ /* $NetBSD: udf_mount.h,v 1.4 2019/10/16 21:52:22 maya Exp $ */
/* /*
* Copyright (c) 2006 Reinoud Zandijk * Copyright (c) 2006 Reinoud Zandijk
@ -12,13 +12,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 for the
* NetBSD Project. See http://www.NetBSD.org/ for
* information about NetBSD.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_readwrite.c,v 1.11 2011/06/12 03:35:55 rmind Exp $ */ /* $NetBSD: udf_readwrite.c,v 1.12 2016/05/24 09:55:57 reinoud Exp $ */
/* /*
* Copyright (c) 2007, 2008 Reinoud Zandijk * Copyright (c) 2007, 2008 Reinoud Zandijk
@ -28,7 +28,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#ifndef lint #ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_readwrite.c,v 1.11 2011/06/12 03:35:55 rmind Exp $"); __KERNEL_RCSID(0, "$NetBSD: udf_readwrite.c,v 1.12 2016/05/24 09:55:57 reinoud Exp $");
#endif /* not lint */ #endif /* not lint */
@ -695,6 +695,19 @@ udf_discstrat_queuebuf(struct udf_mount *ump, struct buf *nestbuf)
} }
void
udf_synchronise_caches(struct udf_mount *ump)
{
struct udf_strategy *strategy = ump->strategy;
struct udf_strat_args args;
KASSERT(strategy);
args.ump = ump;
(strategy->sync_caches)(&args);
}
void void
udf_discstrat_init(struct udf_mount *ump) udf_discstrat_init(struct udf_mount *ump)
{ {

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_rename.c,v 1.12 2014/11/10 19:44:08 riz Exp $ */ /* $NetBSD: udf_rename.c,v 1.13 2020/01/17 20:08:08 ad Exp $ */
/* /*
* Copyright (c) 2013 Reinoud Zandijk * Copyright (c) 2013 Reinoud Zandijk
@ -28,7 +28,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: udf_rename.c,v 1.12 2014/11/10 19:44:08 riz Exp $"); __KERNEL_RCSID(0, "$NetBSD: udf_rename.c,v 1.13 2020/01/17 20:08:08 ad Exp $");
#include <sys/param.h> #include <sys/param.h>
#include <sys/errno.h> #include <sys/errno.h>
@ -465,7 +465,7 @@ udf_gro_lookup(struct mount *mp, struct vnode *dvp,
return ENOENT; return ENOENT;
DPRINTF(LOOKUP, ("udf_gro_lookup found '%s'\n", name)); DPRINTF(LOOKUP, ("udf_gro_lookup found '%s'\n", name));
error = udf_get_node(dir_node->ump, &icb_loc, &res_node); error = udf_get_node(dir_node->ump, &icb_loc, &res_node, LK_EXCLUSIVE);
if (error) if (error)
return error; return error;
*vp_ret = res_node->vnode; *vp_ret = res_node->vnode;
@ -598,7 +598,8 @@ udf_gro_genealogy(struct mount *mp, kauth_cred_t cred,
*/ */
DPRINTF(NODE, ("\tgetting the parent node\n")); DPRINTF(NODE, ("\tgetting the parent node\n"));
VOP_UNLOCK(vp); VOP_UNLOCK(vp);
error = udf_get_node(ump, &parent_loc, &parent_node); error = udf_get_node(ump, &parent_loc, &parent_node,
LK_EXCLUSIVE);
vrele(vp); vrele(vp);
if (error) if (error)
return error; return error;

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_strat_bootstrap.c,v 1.4 2014/11/10 18:46:33 maxv Exp $ */ /* $NetBSD: udf_strat_bootstrap.c,v 1.5 2016/05/24 09:55:57 reinoud Exp $ */
/* /*
* Copyright (c) 2006, 2008 Reinoud Zandijk * Copyright (c) 2006, 2008 Reinoud Zandijk
@ -28,7 +28,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#ifndef lint #ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_strat_bootstrap.c,v 1.4 2014/11/10 18:46:33 maxv Exp $"); __KERNEL_RCSID(0, "$NetBSD: udf_strat_bootstrap.c,v 1.5 2016/05/24 09:55:57 reinoud Exp $");
#endif /* not lint */ #endif /* not lint */
@ -115,6 +115,14 @@ udf_queuebuf_bootstrap(struct udf_strat_args *args)
VOP_STRATEGY(ump->devvp, buf); VOP_STRATEGY(ump->devvp, buf);
} }
static void
udf_sync_caches_bootstrap(struct udf_strat_args *args)
{
/* empty */
}
static void static void
udf_discstrat_init_bootstrap(struct udf_strat_args *args) udf_discstrat_init_bootstrap(struct udf_strat_args *args)
{ {
@ -137,6 +145,7 @@ struct udf_strategy udf_strat_bootstrap =
udf_read_logvol_dscr_bootstrap, udf_read_logvol_dscr_bootstrap,
udf_write_logvol_dscr_bootstrap, udf_write_logvol_dscr_bootstrap,
udf_queuebuf_bootstrap, udf_queuebuf_bootstrap,
udf_sync_caches_bootstrap,
udf_discstrat_init_bootstrap, udf_discstrat_init_bootstrap,
udf_discstrat_finish_bootstrap udf_discstrat_finish_bootstrap
}; };

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_strat_direct.c,v 1.13 2015/10/06 08:57:34 hannken Exp $ */ /* $NetBSD: udf_strat_direct.c,v 1.14 2016/05/24 09:55:57 reinoud Exp $ */
/* /*
* Copyright (c) 2006, 2008 Reinoud Zandijk * Copyright (c) 2006, 2008 Reinoud Zandijk
@ -28,7 +28,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#ifndef lint #ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_strat_direct.c,v 1.13 2015/10/06 08:57:34 hannken Exp $"); __KERNEL_RCSID(0, "$NetBSD: udf_strat_direct.c,v 1.14 2016/05/24 09:55:57 reinoud Exp $");
#endif /* not lint */ #endif /* not lint */
@ -392,6 +392,15 @@ udf_queue_buf_direct(struct udf_strat_args *args)
} }
static void
udf_sync_caches_direct(struct udf_strat_args *args)
{
struct udf_mount *ump = args->ump;
udf_mmc_synchronise_caches(ump);
}
static void static void
udf_discstrat_init_direct(struct udf_strat_args *args) udf_discstrat_init_direct(struct udf_strat_args *args)
{ {
@ -441,6 +450,7 @@ struct udf_strategy udf_strat_direct =
udf_read_nodedscr_direct, udf_read_nodedscr_direct,
udf_write_nodedscr_direct, udf_write_nodedscr_direct,
udf_queue_buf_direct, udf_queue_buf_direct,
udf_sync_caches_direct,
udf_discstrat_init_direct, udf_discstrat_init_direct,
udf_discstrat_finish_direct udf_discstrat_finish_direct
}; };

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_strat_rmw.c,v 1.27 2015/10/06 08:57:34 hannken Exp $ */ /* $NetBSD: udf_strat_rmw.c,v 1.28 2016/05/24 09:55:57 reinoud Exp $ */
/* /*
* Copyright (c) 2006, 2008 Reinoud Zandijk * Copyright (c) 2006, 2008 Reinoud Zandijk
@ -28,7 +28,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#ifndef lint #ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_strat_rmw.c,v 1.27 2015/10/06 08:57:34 hannken Exp $"); __KERNEL_RCSID(0, "$NetBSD: udf_strat_rmw.c,v 1.28 2016/05/24 09:55:57 reinoud Exp $");
#endif /* not lint */ #endif /* not lint */
@ -1005,6 +1005,16 @@ udf_queuebuf_rmw(struct udf_strat_args *args)
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
static void
udf_sync_caches_rmw(struct udf_strat_args *args)
{
struct udf_mount *ump = args->ump;
udf_mmc_synchronise_caches(ump);
}
/* --------------------------------------------------------------------- */
static void static void
udf_shedule_read_callback(struct buf *buf) udf_shedule_read_callback(struct buf *buf)
{ {
@ -1495,6 +1505,7 @@ struct udf_strategy udf_strat_rmw =
udf_read_nodedscr_rmw, udf_read_nodedscr_rmw,
udf_write_nodedscr_rmw, udf_write_nodedscr_rmw,
udf_queuebuf_rmw, udf_queuebuf_rmw,
udf_sync_caches_rmw,
udf_discstrat_init_rmw, udf_discstrat_init_rmw,
udf_discstrat_finish_rmw udf_discstrat_finish_rmw
}; };

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_strat_sequential.c,v 1.14 2015/10/06 08:57:34 hannken Exp $ */ /* $NetBSD: udf_strat_sequential.c,v 1.15 2016/05/24 09:55:57 reinoud Exp $ */
/* /*
* Copyright (c) 2006, 2008 Reinoud Zandijk * Copyright (c) 2006, 2008 Reinoud Zandijk
@ -28,7 +28,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#ifndef lint #ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_strat_sequential.c,v 1.14 2015/10/06 08:57:34 hannken Exp $"); __KERNEL_RCSID(0, "$NetBSD: udf_strat_sequential.c,v 1.15 2016/05/24 09:55:57 reinoud Exp $");
#endif /* not lint */ #endif /* not lint */
@ -86,6 +86,7 @@ struct strat_private {
kmutex_t discstrat_mutex; /* disc strategy */ kmutex_t discstrat_mutex; /* disc strategy */
int run_thread; /* thread control */ int run_thread; /* thread control */
int sync_req; /* thread control */
int cur_queue; int cur_queue;
struct disk_strategy old_strategy_setting; struct disk_strategy old_strategy_setting;
@ -287,6 +288,30 @@ udf_queuebuf_seq(struct udf_strat_args *args)
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
static void
udf_sync_caches_seq(struct udf_strat_args *args)
{
struct udf_mount *ump = args->ump;
struct strat_private *priv = PRIV(ump);
/* we might be called during unmount inadvertedly, be on safe side */
if (!priv)
return;
/* signal our thread that there might be something to do */
priv->sync_req = 1;
cv_signal(&priv->discstrat_cv);
mutex_enter(&priv->discstrat_mutex);
while (priv->sync_req) {
cv_timedwait(&priv->discstrat_cv,
&priv->discstrat_mutex, hz/8);
}
mutex_exit(&priv->discstrat_mutex);
}
/* --------------------------------------------------------------------- */
/* TODO convert to lb_size */ /* TODO convert to lb_size */
static void static void
udf_VAT_mapping_update(struct udf_mount *ump, struct buf *buf, uint32_t lb_map) udf_VAT_mapping_update(struct udf_mount *ump, struct buf *buf, uint32_t lb_map)
@ -539,7 +564,7 @@ udf_discstrat_thread(void *arg)
empty = 1; empty = 1;
mutex_enter(&priv->discstrat_mutex); mutex_enter(&priv->discstrat_mutex);
while (priv->run_thread || !empty) { while (priv->run_thread || !empty || priv->sync_req) {
/* process the current selected queue */ /* process the current selected queue */
udf_doshedule(ump); udf_doshedule(ump);
empty = (bufq_peek(priv->queues[UDF_SHED_READING]) == NULL); empty = (bufq_peek(priv->queues[UDF_SHED_READING]) == NULL);
@ -547,9 +572,16 @@ udf_discstrat_thread(void *arg)
empty &= (bufq_peek(priv->queues[UDF_SHED_SEQWRITING]) == NULL); empty &= (bufq_peek(priv->queues[UDF_SHED_SEQWRITING]) == NULL);
/* wait for more if needed */ /* wait for more if needed */
if (empty) if (empty) {
if (priv->sync_req) {
/* on sync, we need to simulate a read->write transition */
udf_mmc_synchronise_caches(ump);
priv->cur_queue = UDF_SHED_READING;
priv->sync_req = 0;
}
cv_timedwait(&priv->discstrat_cv, cv_timedwait(&priv->discstrat_cv,
&priv->discstrat_mutex, hz/8); &priv->discstrat_mutex, hz/8);
}
} }
mutex_exit(&priv->discstrat_mutex); mutex_exit(&priv->discstrat_mutex);
@ -621,6 +653,7 @@ udf_discstrat_init_seq(struct udf_strat_args *args)
/* create our disk strategy thread */ /* create our disk strategy thread */
priv->run_thread = 1; priv->run_thread = 1;
priv->sync_req = 0;
if (kthread_create(PRI_NONE, 0 /* KTHREAD_MPSAFE*/, NULL /* cpu_info*/, if (kthread_create(PRI_NONE, 0 /* KTHREAD_MPSAFE*/, NULL /* cpu_info*/,
udf_discstrat_thread, ump, &priv->queue_lwp, udf_discstrat_thread, ump, &priv->queue_lwp,
"%s", "udf_rw")) { "%s", "udf_rw")) {
@ -673,6 +706,7 @@ struct udf_strategy udf_strat_sequential =
udf_read_logvol_dscr_seq, udf_read_logvol_dscr_seq,
udf_write_logvol_dscr_seq, udf_write_logvol_dscr_seq,
udf_queuebuf_seq, udf_queuebuf_seq,
udf_sync_caches_seq,
udf_discstrat_init_seq, udf_discstrat_init_seq,
udf_discstrat_finish_seq udf_discstrat_finish_seq
}; };

View File

@ -1,9 +1,9 @@
/* $NetBSD: udf_subr.c,v 1.132 2015/08/24 08:31:56 hannken Exp $ */ /* $NetBSD: udf_subr.c,v 1.152 2021/01/11 22:02:28 skrll Exp $ */
/* /*
* Copyright (c) 2006, 2008 Reinoud Zandijk * Copyright (c) 2006, 2008 Reinoud Zandijk
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
@ -12,7 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
@ -23,13 +23,13 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
#ifndef lint #ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.132 2015/08/24 08:31:56 hannken Exp $"); __KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.152 2021/01/11 22:02:28 skrll Exp $");
#endif /* not lint */ #endif /* not lint */
@ -319,27 +319,25 @@ udf_setup_writeparams(struct udf_mount *ump)
} }
int void
udf_synchronise_caches(struct udf_mount *ump) udf_mmc_synchronise_caches(struct udf_mount *ump)
{ {
struct mmc_op mmc_op; struct mmc_op mmc_op;
DPRINTF(CALL, ("udf_synchronise_caches()\n")); DPRINTF(CALL, ("udf_mcc_synchronise_caches()\n"));
if (ump->vfs_mountp->mnt_flag & MNT_RDONLY) if (ump->vfs_mountp->mnt_flag & MNT_RDONLY)
return 0; return;
/* discs are done now */ /* discs are done now */
if (ump->discinfo.mmc_class == MMC_CLASS_DISC) if (ump->discinfo.mmc_class == MMC_CLASS_DISC)
return 0; return;
memset(&mmc_op, 0, sizeof(struct mmc_op)); memset(&mmc_op, 0, sizeof(struct mmc_op));
mmc_op.operation = MMC_OP_SYNCHRONISECACHE; mmc_op.operation = MMC_OP_SYNCHRONISECACHE;
/* ignore return code */ /* ignore return code */
(void) VOP_IOCTL(ump->devvp, MMCOP, &mmc_op, FKIOCTL, NOCRED); (void) VOP_IOCTL(ump->devvp, MMCOP, &mmc_op, FKIOCTL, NOCRED);
return 0;
} }
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
@ -811,7 +809,7 @@ udf_lock_node(struct udf_node *udf_node, int flag, char const *fname, const int
if (ret == EWOULDBLOCK) { if (ret == EWOULDBLOCK) {
DPRINTF(LOCKING, ( "udf_lock_node: udf_node %p would block " DPRINTF(LOCKING, ( "udf_lock_node: udf_node %p would block "
"wanted at %s:%d, previously locked at %s:%d\n", "wanted at %s:%d, previously locked at %s:%d\n",
udf_node, fname, lineno, udf_node, fname, lineno,
udf_node->lock_fname, udf_node->lock_lineno)); udf_node->lock_fname, udf_node->lock_lineno));
} }
} }
@ -930,7 +928,7 @@ udf_read_anchors(struct udf_mount *ump)
positions[1] = track_end-256; positions[1] = track_end-256;
positions[2] = track_end; positions[2] = track_end;
positions[3] = track_start+512; /* [UDF 2.60/6.11.2] */ positions[3] = track_start+512; /* [UDF 2.60/6.11.2] */
/* XXX shouldn't +512 be prefered above +256 for compat with Roxio CD */ /* XXX shouldn't +512 be preferred over +256 for compat with Roxio CD */
ok = 0; ok = 0;
anchorsp = ump->anchors; anchorsp = ump->anchors;
@ -946,7 +944,7 @@ udf_read_anchors(struct udf_mount *ump)
/* VATs are only recorded on sequential media, but initialise */ /* VATs are only recorded on sequential media, but initialise */
ump->first_possible_vat_location = track_start + 2; ump->first_possible_vat_location = track_start + 2;
ump->last_possible_vat_location = track_end + last_track.packet_size; ump->last_possible_vat_location = track_end;
return ok; return ok;
} }
@ -984,7 +982,7 @@ udf_get_record_vpart(struct udf_mount *ump, int udf_c_type)
} }
/* /*
* BUGALERT: some rogue implementations use random physical partition * BUGALERT: some rogue implementations use random physical partition
* numbers to break other implementations so lookup the number. * numbers to break other implementations so lookup the number.
*/ */
@ -1235,7 +1233,7 @@ udf_retrieve_lvint(struct udf_mount *ump)
/* are we linking to a new piece? */ /* are we linking to a new piece? */
if (dscr && lvint->next_extent.len) { if (dscr && lvint->next_extent.len) {
len = udf_rw32(lvint->next_extent.len); len = udf_rw32(lvint->next_extent.len);
lbnum = udf_rw32(lvint->next_extent.loc); lbnum = udf_rw32(lvint->next_extent.loc);
if (trace_len >= UDF_LVDINT_SEGMENTS-1) { if (trace_len >= UDF_LVDINT_SEGMENTS-1) {
@ -1281,7 +1279,7 @@ udf_loose_lvint_history(struct udf_mount *ump)
uint32_t out_ext, out_wpos, out_len; uint32_t out_ext, out_wpos, out_len;
uint32_t lb_num; uint32_t lb_num;
uint32_t len, start; uint32_t len, start;
int ext, minext, extlen, cnt, cpy_len, dscr_type; int ext, sumext, extlen, cnt, cpy_len, dscr_type;
int losing; int losing;
int error; int error;
@ -1289,18 +1287,29 @@ udf_loose_lvint_history(struct udf_mount *ump)
/* search smallest extent */ /* search smallest extent */
trace = &ump->lvint_trace[0]; trace = &ump->lvint_trace[0];
minext = trace->end - trace->start; sumext = trace->end - trace->start;
for (ext = 1; ext < UDF_LVDINT_SEGMENTS; ext++) { for (ext = 1; ext < UDF_LVDINT_SEGMENTS; ext++) {
trace = &ump->lvint_trace[ext]; trace = &ump->lvint_trace[ext];
extlen = trace->end - trace->start; extlen = trace->end - trace->start;
if (extlen == 0) if (extlen == 0)
break; break;
minext = MIN(minext, extlen); sumext += extlen;
} }
losing = MIN(minext, UDF_LVINT_LOSSAGE);
/* no sense wiping all */ /* just one element? its not legal but be bug compatible */
if (losing == minext) if (sumext == 1) {
losing--; /* overwrite the only entry */
DPRINTF(VOLUMES, ("\tLinux bugcompat overwriting sole entry\n"));
trace = &ump->lvint_trace[0];
trace->wpos = 0;
return 0;
}
losing = MIN(sumext, UDF_LVINT_LOSSAGE);
/* no sense wiping too much */
if (sumext == UDF_LVINT_LOSSAGE)
losing = UDF_LVINT_LOSSAGE/2;
DPRINTF(VOLUMES, ("\tlosing %d entries\n", losing)); DPRINTF(VOLUMES, ("\tlosing %d entries\n", losing));
@ -1437,7 +1446,6 @@ udf_writeout_lvint(struct udf_mount *ump, int lvflag)
DPRINTF(VOLUMES, ("writing out logvol integrity descriptor\n")); DPRINTF(VOLUMES, ("writing out logvol integrity descriptor\n"));
again:
/* get free space in last chunk */ /* get free space in last chunk */
trace = ump->lvint_trace; trace = ump->lvint_trace;
while (trace->wpos > (trace->end - trace->start)) { while (trace->wpos > (trace->end - trace->start)) {
@ -1465,11 +1473,20 @@ again:
if (space < 1) { if (space < 1) {
if (lvflag & UDF_APPENDONLY_LVINT) if (lvflag & UDF_APPENDONLY_LVINT)
return EROFS; return EROFS;
/* loose history by re-writing extents */ /* loose history by re-writing extents */
error = udf_loose_lvint_history(ump); error = udf_loose_lvint_history(ump);
if (error) if (error)
return error; return error;
goto again;
trace = ump->lvint_trace;
while (trace->wpos > (trace->end - trace->start))
trace++;
space = (trace->end - trace->start) - trace->wpos;
DPRINTF(VOLUMES, ("new try: write start = %d, end = %d, "
"pos = %d, wpos = %d, "
"space = %d\n", trace->start, trace->end,
trace->pos, trace->wpos, space));
} }
/* update our integrity descriptor to identify us and timestamp it */ /* update our integrity descriptor to identify us and timestamp it */
@ -1573,7 +1590,7 @@ udf_read_physical_partition_spacetables(struct udf_mount *ump)
if (partd == NULL) if (partd == NULL)
continue; continue;
parthdr = &partd->_impl_use.part_hdr; parthdr = &partd->_impl_use.part_hdr;
len = udf_rw32(parthdr->unalloc_space_table.len); len = udf_rw32(parthdr->unalloc_space_table.len);
if (len) { if (len) {
printf("UDF mount: space tables not supported\n"); printf("UDF mount: space tables not supported\n");
@ -1632,7 +1649,7 @@ udf_read_physical_partition_spacetables(struct udf_mount *ump)
if (partd == NULL) if (partd == NULL)
continue; continue;
parthdr = &partd->_impl_use.part_hdr; parthdr = &partd->_impl_use.part_hdr;
len = udf_rw32(parthdr->freed_space_table.len); len = udf_rw32(parthdr->freed_space_table.len);
if (len) { if (len) {
printf("UDF mount: space tables not supported\n"); printf("UDF mount: space tables not supported\n");
@ -1673,6 +1690,14 @@ udf_write_physical_partition_spacetables(struct udf_mount *ump, int waitfor)
DPRINTF(VOLUMES, ("Write unalloc. space bitmap %d\n", DPRINTF(VOLUMES, ("Write unalloc. space bitmap %d\n",
lb_num + ptov)); lb_num + ptov));
dscr = (union dscrptr *) ump->part_unalloc_dscr[phys_part]; dscr = (union dscrptr *) ump->part_unalloc_dscr[phys_part];
/* force a sane minimum for descriptors CRC length */
/* see UDF 2.3.1.2 and 2.3.8.1 */
KASSERT(udf_rw16(dscr->sbd.tag.id) == TAGID_SPACE_BITMAP);
if (udf_rw16(dscr->sbd.tag.desc_crc_len) == 0)
dscr->sbd.tag.desc_crc_len = udf_rw16(8);
/* write out space bitmap */
error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR, error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR,
(union dscrptr *) dscr, (union dscrptr *) dscr,
ptov + lb_num, lb_num); ptov + lb_num, lb_num);
@ -1699,6 +1724,14 @@ udf_write_physical_partition_spacetables(struct udf_mount *ump, int waitfor)
DPRINTF(VOLUMES, ("Write freed space bitmap %d\n", DPRINTF(VOLUMES, ("Write freed space bitmap %d\n",
lb_num + ptov)); lb_num + ptov));
dscr = (union dscrptr *) ump->part_freed_dscr[phys_part]; dscr = (union dscrptr *) ump->part_freed_dscr[phys_part];
/* force a sane minimum for descriptors CRC length */
/* see UDF 2.3.1.2 and 2.3.8.1 */
KASSERT(udf_rw16(dscr->sbd.tag.id) == TAGID_SPACE_BITMAP);
if (udf_rw16(dscr->sbd.tag.desc_crc_len) == 0)
dscr->sbd.tag.desc_crc_len = udf_rw16(8);
/* write out space bitmap */
error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR, error = udf_write_phys_dscr_sync(ump, NULL, UDF_C_DSCR,
(union dscrptr *) dscr, (union dscrptr *) dscr,
ptov + lb_num, lb_num); ptov + lb_num, lb_num);
@ -1738,7 +1771,7 @@ udf_read_metadata_partition_spacetable(struct udf_mount *ump)
"%"PRIu64" bytes\n", inflen)); "%"PRIu64" bytes\n", inflen));
/* allocate space for bitmap */ /* allocate space for bitmap */
dscr = malloc(inflen, M_UDFVOLD, M_CANFAIL | M_WAITOK); dscr = malloc(inflen, M_UDFVOLD, M_WAITOK);
if (!dscr) if (!dscr)
return ENOMEM; return ENOMEM;
@ -1981,7 +2014,7 @@ udf_process_vds(struct udf_mount *ump) {
DPRINTF(VOLUMES, ("\t%d -> %d(%d) type %d\n", log_part, DPRINTF(VOLUMES, ("\t%d -> %d(%d) type %d\n", log_part,
raw_phys_part, phys_part, pmap_type)); raw_phys_part, phys_part, pmap_type));
if (phys_part == UDF_PARTITIONS) if (phys_part == UDF_PARTITIONS)
return EINVAL; return EINVAL;
if (pmap_type == UDF_VTOP_TYPE_UNKNOWN) if (pmap_type == UDF_VTOP_TYPE_UNKNOWN)
@ -2097,7 +2130,7 @@ udf_process_vds(struct udf_mount *ump) {
snprintb(bits, sizeof(bits), UDFONERROR_BITS, ump->lvreadwrite); snprintb(bits, sizeof(bits), UDFONERROR_BITS, ump->lvreadwrite);
DPRINTF(VOLUMES, ("\tactions on logvol errors %s\n", bits)); DPRINTF(VOLUMES, ("\tactions on logvol errors %s\n", bits));
DPRINTF(VOLUMES, ("\tselected sheduler `%s`\n", DPRINTF(VOLUMES, ("\tselected sheduler `%s`\n",
(ump->strategy == &udf_strat_direct) ? "Direct" : (ump->strategy == &udf_strat_direct) ? "Direct" :
(ump->strategy == &udf_strat_sequential) ? "Sequential" : (ump->strategy == &udf_strat_sequential) ? "Sequential" :
(ump->strategy == &udf_strat_rmw) ? "RMW" : "UNKNOWN!")); (ump->strategy == &udf_strat_rmw) ? "RMW" : "UNKNOWN!"));
@ -2281,12 +2314,12 @@ udf_create_parentfid(struct udf_mount *ump, struct fileid_desc *fid,
* (a) inside the file's (e)fe in the length of the extended attribute area * (a) inside the file's (e)fe in the length of the extended attribute area
* before the allocation descriptors/filedata * before the allocation descriptors/filedata
* *
* (b) in a file referenced by (e)fe->ext_attr_icb and * (b) in a file referenced by (e)fe->ext_attr_icb and
* *
* (c) in the e(fe)'s associated stream directory that can hold various * (c) in the e(fe)'s associated stream directory that can hold various
* sub-files. In the stream directory a few fixed named subfiles are reserved * sub-files. In the stream directory a few fixed named subfiles are reserved
* for NT/Unix ACL's and OS/2 attributes. * for NT/Unix ACL's and OS/2 attributes.
* *
* NOTE: Extended attributes are read randomly but allways written * NOTE: Extended attributes are read randomly but allways written
* *atomicaly*. For ACL's this interface is propably different but not known * *atomicaly*. For ACL's this interface is propably different but not known
* to me yet. * to me yet.
@ -2554,7 +2587,7 @@ udf_extattr_insert_internal(struct udf_mount *ump, union dscrptr *dscr,
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
static int static int
udf_update_lvid_from_vat_extattr(struct udf_node *vat_node) udf_update_lvid_from_vat_extattr(struct udf_node *vat_node)
{ {
struct udf_mount *ump; struct udf_mount *ump;
@ -2590,7 +2623,7 @@ udf_update_lvid_from_vat_extattr(struct udf_node *vat_node)
return error; return error;
/* paranoia */ /* paranoia */
if (a_l != sizeof(*implext) -1 + udf_rw32(implext->iu_l) + sizeof(lvext)) { if (a_l != sizeof(*implext) -2 + udf_rw32(implext->iu_l) + sizeof(lvext)) {
DPRINTF(VOLUMES, ("VAT LVExtension size doesn't compute\n")); DPRINTF(VOLUMES, ("VAT LVExtension size doesn't compute\n"));
return EINVAL; return EINVAL;
} }
@ -2621,7 +2654,7 @@ udf_update_lvid_from_vat_extattr(struct udf_node *vat_node)
} }
static int static int
udf_update_vat_extattr_from_lvid(struct udf_node *vat_node) udf_update_vat_extattr_from_lvid(struct udf_node *vat_node)
{ {
struct udf_mount *ump; struct udf_mount *ump;
@ -2706,7 +2739,7 @@ udf_vat_write(struct udf_node *vat_node, uint8_t *blob, int size, uint32_t offse
/* realloc */ /* realloc */
new_vat_table = realloc(ump->vat_table, new_vat_table = realloc(ump->vat_table,
ump->vat_table_alloc_len + UDF_VAT_CHUNKSIZE, ump->vat_table_alloc_len + UDF_VAT_CHUNKSIZE,
M_UDFVOLD, M_WAITOK | M_CANFAIL); M_UDFVOLD, M_WAITOK);
if (!new_vat_table) { if (!new_vat_table) {
printf("udf_vat_write: can't extent VAT, out of mem\n"); printf("udf_vat_write: can't extent VAT, out of mem\n");
return ENOMEM; return ENOMEM;
@ -2833,7 +2866,6 @@ udf_writeout_vat(struct udf_mount *ump)
if (error) if (error)
printf("udf_writeout_vat: error writing VAT node!\n"); printf("udf_writeout_vat: error writing VAT node!\n");
out: out:
return error; return error;
} }
@ -2904,8 +2936,7 @@ udf_check_for_vat(struct udf_node *vat_node)
((vat_length + UDF_VAT_CHUNKSIZE-1) / UDF_VAT_CHUNKSIZE) ((vat_length + UDF_VAT_CHUNKSIZE-1) / UDF_VAT_CHUNKSIZE)
* UDF_VAT_CHUNKSIZE; * UDF_VAT_CHUNKSIZE;
vat_table = malloc(vat_table_alloc_len, M_UDFVOLD, vat_table = malloc(vat_table_alloc_len, M_UDFVOLD, M_WAITOK);
M_CANFAIL | M_WAITOK);
if (vat_table == NULL) { if (vat_table == NULL) {
printf("allocation of %d bytes failed for VAT\n", printf("allocation of %d bytes failed for VAT\n",
vat_table_alloc_len); vat_table_alloc_len);
@ -2974,7 +3005,7 @@ udf_check_for_vat(struct udf_node *vat_node)
lvinfo->min_udf_readver = vat->min_udf_readver; lvinfo->min_udf_readver = vat->min_udf_readver;
lvinfo->min_udf_writever = vat->min_udf_writever; lvinfo->min_udf_writever = vat->min_udf_writever;
lvinfo->max_udf_writever = vat->max_udf_writever; lvinfo->max_udf_writever = vat->max_udf_writever;
udf_update_logvolname(ump, vat->logvol_id); udf_update_logvolname(ump, vat->logvol_id);
} }
@ -2995,6 +3026,10 @@ udf_check_for_vat(struct udf_node *vat_node)
ump->logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_CLOSED); ump->logvol_integrity->integrity_type = udf_rw32(UDF_INTEGRITY_CLOSED);
ump->logvol_integrity->time = *mtime; ump->logvol_integrity->time = *mtime;
/* if we're updating, free old allocated space */
if (ump->vat_table)
free(ump->vat_table, M_UDFVOLD);
ump->vat_table_len = vat_length; ump->vat_table_len = vat_length;
ump->vat_table_alloc_len = vat_table_alloc_len; ump->vat_table_alloc_len = vat_table_alloc_len;
ump->vat_table = vat_table; ump->vat_table = vat_table;
@ -3017,49 +3052,71 @@ out:
static int static int
udf_search_vat(struct udf_mount *ump, union udf_pmap *mapping) udf_search_vat(struct udf_mount *ump, union udf_pmap *mapping)
{ {
struct udf_node *vat_node; struct udf_node *vat_node, *accepted_vat_node;
struct long_ad icb_loc; struct long_ad icb_loc;
uint32_t early_vat_loc, vat_loc; uint32_t early_vat_loc, late_vat_loc, vat_loc;
int error; int error;
/* mapping info not needed */ /* mapping info not needed */
mapping = mapping; mapping = mapping;
vat_loc = ump->last_possible_vat_location; DPRINTF(VOLUMES, ("Searching VAT\n"));
early_vat_loc = vat_loc - 256; /* 8 blocks of 32 sectors */
DPRINTF(VOLUMES, ("1) last possible %d, early_vat_loc %d \n", /*
vat_loc, early_vat_loc)); * Start reading forward in blocks from the first possible vat
early_vat_loc = MAX(early_vat_loc, ump->first_possible_vat_location); * location. If not found in this block, start again a bit before
* until we get a hit.
*/
late_vat_loc = ump->last_possible_vat_location;
early_vat_loc = MAX(late_vat_loc - 64, ump->first_possible_vat_location);
DPRINTF(VOLUMES, ("2) last possible %d, early_vat_loc %d \n", DPRINTF(VOLUMES, ("\tfull range %d to %d\n", early_vat_loc, late_vat_loc));
vat_loc, early_vat_loc)); accepted_vat_node = NULL;
/* start looking from the end of the range */
do { do {
DPRINTF(VOLUMES, ("Checking for VAT at sector %d\n", vat_loc)); vat_loc = early_vat_loc;
icb_loc.loc.part_num = udf_rw16(UDF_VTOP_RAWPART); DPRINTF(VOLUMES, ("\tchecking range %d to %d\n",
icb_loc.loc.lb_num = udf_rw32(vat_loc); early_vat_loc, late_vat_loc));
do {
DPRINTF(VOLUMES, ("\t\tChecking for VAT at sector %d\n",
vat_loc));
icb_loc.loc.part_num = udf_rw16(UDF_VTOP_RAWPART);
icb_loc.loc.lb_num = udf_rw32(vat_loc);
error = udf_get_node(ump, &icb_loc, &vat_node); error = udf_get_node(ump, &icb_loc, &vat_node,
if (!error) { LK_EXCLUSIVE);
error = udf_check_for_vat(vat_node); if (!error) {
DPRINTFIF(VOLUMES, !error, error = udf_check_for_vat(vat_node);
("VAT accepted at %d\n", vat_loc)); vat_node->i_flags = 0; /* reset access */
if (!error) }
break; if (!error) {
} DPRINTFIF(VOLUMES, !error,
if (vat_node) { ("VAT candidate accepted at %d\n",
vput(vat_node->vnode); vat_loc));
vat_node = NULL; if (accepted_vat_node)
} vput(accepted_vat_node->vnode);
vat_loc--; /* walk backwards */ accepted_vat_node = vat_node;
} while (vat_loc >= early_vat_loc); accepted_vat_node->i_flags |= IN_NO_DELETE;
vat_node = NULL;
}
if (vat_node)
vput(vat_node->vnode);
vat_loc++; /* walk forward */
} while (vat_loc < late_vat_loc);
if (accepted_vat_node)
break;
/* keep our VAT node around */ early_vat_loc = MAX(early_vat_loc - 64, ump->first_possible_vat_location);
if (vat_node) { late_vat_loc = MIN(early_vat_loc + 64, ump->last_possible_vat_location);
UDF_SET_SYSTEMFILE(vat_node->vnode); } while (late_vat_loc > ump->first_possible_vat_location);
ump->vat_node = vat_node;
/* keep our last accepted VAT node around */
if (accepted_vat_node) {
/* revert no delete flag again to avoid potential side effects */
accepted_vat_node->i_flags &= ~IN_NO_DELETE;
UDF_SET_SYSTEMFILE(accepted_vat_node->vnode);
ump->vat_node = accepted_vat_node;
return 0;
} }
return error; return error;
@ -3141,7 +3198,8 @@ udf_read_metadata_nodes(struct udf_mount *ump, union udf_pmap *mapping)
DPRINTF(VOLUMES, ("Metadata file\n")); DPRINTF(VOLUMES, ("Metadata file\n"));
icb_loc.loc.lb_num = pmm->meta_file_lbn; icb_loc.loc.lb_num = pmm->meta_file_lbn;
error = udf_get_node(ump, &icb_loc, &ump->metadata_node); error = udf_get_node(ump, &icb_loc, &ump->metadata_node,
LK_EXCLUSIVE);
if (ump->metadata_node) { if (ump->metadata_node) {
vp = ump->metadata_node->vnode; vp = ump->metadata_node->vnode;
UDF_SET_SYSTEMFILE(vp); UDF_SET_SYSTEMFILE(vp);
@ -3150,7 +3208,8 @@ udf_read_metadata_nodes(struct udf_mount *ump, union udf_pmap *mapping)
icb_loc.loc.lb_num = pmm->meta_mirror_file_lbn; icb_loc.loc.lb_num = pmm->meta_mirror_file_lbn;
if (icb_loc.loc.lb_num != -1) { if (icb_loc.loc.lb_num != -1) {
DPRINTF(VOLUMES, ("Metadata copy file\n")); DPRINTF(VOLUMES, ("Metadata copy file\n"));
error = udf_get_node(ump, &icb_loc, &ump->metadatamirror_node); error = udf_get_node(ump, &icb_loc, &ump->metadatamirror_node,
LK_EXCLUSIVE);
if (ump->metadatamirror_node) { if (ump->metadatamirror_node) {
vp = ump->metadatamirror_node->vnode; vp = ump->metadatamirror_node->vnode;
UDF_SET_SYSTEMFILE(vp); UDF_SET_SYSTEMFILE(vp);
@ -3160,7 +3219,8 @@ udf_read_metadata_nodes(struct udf_mount *ump, union udf_pmap *mapping)
icb_loc.loc.lb_num = pmm->meta_bitmap_file_lbn; icb_loc.loc.lb_num = pmm->meta_bitmap_file_lbn;
if (icb_loc.loc.lb_num != -1) { if (icb_loc.loc.lb_num != -1) {
DPRINTF(VOLUMES, ("Metadata bitmap file\n")); DPRINTF(VOLUMES, ("Metadata bitmap file\n"));
error = udf_get_node(ump, &icb_loc, &ump->metadatabitmap_node); error = udf_get_node(ump, &icb_loc, &ump->metadatabitmap_node,
LK_EXCLUSIVE);
if (ump->metadatabitmap_node) { if (ump->metadatabitmap_node) {
vp = ump->metadatabitmap_node->vnode; vp = ump->metadatabitmap_node->vnode;
UDF_SET_SYSTEMFILE(vp); UDF_SET_SYSTEMFILE(vp);
@ -3341,7 +3401,7 @@ udf_read_rootdirs(struct udf_mount *ump)
/* try to read in the rootdir */ /* try to read in the rootdir */
dir_loc = &ump->fileset_desc->rootdir_icb; dir_loc = &ump->fileset_desc->rootdir_icb;
error = udf_get_node(ump, dir_loc, &rootdir_node); error = udf_get_node(ump, dir_loc, &rootdir_node, LK_EXCLUSIVE);
if (error) if (error)
return ENOENT; return ENOENT;
@ -3354,7 +3414,8 @@ udf_read_rootdirs(struct udf_mount *ump)
dir_loc = &ump->fileset_desc->streamdir_icb; dir_loc = &ump->fileset_desc->streamdir_icb;
if (udf_rw32(dir_loc->len)) { if (udf_rw32(dir_loc->len)) {
printf("udf_read_rootdirs: streamdir defined "); printf("udf_read_rootdirs: streamdir defined ");
error = udf_get_node(ump, dir_loc, &streamdir_node); error = udf_get_node(ump, dir_loc, &streamdir_node,
LK_EXCLUSIVE);
if (error) { if (error) {
printf("but error in streamdir reading\n"); printf("but error in streamdir reading\n");
} else { } else {
@ -3674,6 +3735,21 @@ udf_open_logvol(struct udf_mount *ump)
/* determine data and metadata tracks again */ /* determine data and metadata tracks again */
error = udf_search_writing_tracks(ump); error = udf_search_writing_tracks(ump);
if (ump->lvclose & UDF_WRITE_VAT) {
/*
* we writeout the VAT to get a self-sustained session
* for fsck
*/
DPRINTF(VOLUMES, ("lvclose & UDF_WRITE_VAT\n"));
/* write out the VAT data and all its descriptors */
DPRINTF(VOLUMES, ("writeout vat_node\n"));
udf_writeout_vat(ump);
/* force everything to be synchronized on the device */
(void) udf_synchronise_caches(ump);
}
} }
/* mark it open */ /* mark it open */
@ -3722,15 +3798,6 @@ udf_close_logvol(struct udf_mount *ump, int mntflags)
/* write out the VAT data and all its descriptors */ /* write out the VAT data and all its descriptors */
DPRINTF(VOLUMES, ("writeout vat_node\n")); DPRINTF(VOLUMES, ("writeout vat_node\n"));
udf_writeout_vat(ump); udf_writeout_vat(ump);
(void) vflushbuf(ump->vat_node->vnode, FSYNC_WAIT);
(void) VOP_FSYNC(ump->vat_node->vnode,
FSCRED, FSYNC_WAIT, 0, 0);
if (ump->lvclose & UDF_CLOSE_SESSION) {
DPRINTF(VOLUMES, ("udf_close_logvol: closing session "
"as requested\n"));
}
/* at least two DVD packets and 3 CD-R packets */ /* at least two DVD packets and 3 CD-R packets */
nvats = 32; nvats = 32;
@ -3765,6 +3832,9 @@ udf_close_logvol(struct udf_mount *ump, int mntflags)
if (!error) if (!error)
nok++; nok++;
} }
/* force everything to be synchronized on the device */
(void) udf_synchronise_caches(ump);
if (nok < 14) { if (nok < 14) {
/* arbitrary; but at least one or two CD frames */ /* arbitrary; but at least one or two CD frames */
printf("writeout of at least 14 VATs failed\n"); printf("writeout of at least 14 VATs failed\n");
@ -3776,6 +3846,8 @@ udf_close_logvol(struct udf_mount *ump, int mntflags)
/* finish closing of session */ /* finish closing of session */
if (ump->lvclose & UDF_CLOSE_SESSION) { if (ump->lvclose & UDF_CLOSE_SESSION) {
DPRINTF(VOLUMES, ("udf_close_logvol: closing session "
"as requested\n"));
error = udf_validate_session_start(ump); error = udf_validate_session_start(ump);
if (error) if (error)
return error; return error;
@ -3995,6 +4067,7 @@ static const struct genfs_ops udf_genfsops = {
.gop_alloc = udf_gop_alloc, .gop_alloc = udf_gop_alloc,
.gop_write = genfs_gop_write_rwmap, .gop_write = genfs_gop_write_rwmap,
.gop_markupdate = udf_gop_markupdate, .gop_markupdate = udf_gop_markupdate,
.gop_putrange = genfs_gop_putrange,
}; };
@ -4046,7 +4119,7 @@ static uint32_t
unix_mode_to_udf_perm(mode_t mode) unix_mode_to_udf_perm(mode_t mode)
{ {
uint32_t perm; uint32_t perm;
perm = ((mode & S_IRWXO) ); perm = ((mode & S_IRWXO) );
perm |= ((mode & S_IRWXG) << 2); perm |= ((mode & S_IRWXG) << 2);
perm |= ((mode & S_IRWXU) << 4); perm |= ((mode & S_IRWXU) << 4);
@ -4350,7 +4423,7 @@ udf_getownership(struct udf_node *udf_node, uid_t *uidp, gid_t *gidp)
uid = (uid_t)udf_rw32(efe->uid); uid = (uid_t)udf_rw32(efe->uid);
gid = (gid_t)udf_rw32(efe->gid); gid = (gid_t)udf_rw32(efe->gid);
} }
/* do the uid/gid translation game */ /* do the uid/gid translation game */
if (uid == (uid_t) -1) if (uid == (uid_t) -1)
uid = ump->mount_args.anon_uid; uid = ump->mount_args.anon_uid;
@ -4478,7 +4551,7 @@ udf_dirhash_fill(struct udf_node *dir_node)
* *
*/ */
int int
udf_lookup_name_in_dir(struct vnode *vp, const char *name, int namelen, udf_lookup_name_in_dir(struct vnode *vp, const char *name, int namelen,
struct long_ad *icb_loc, int *found) struct long_ad *icb_loc, int *found)
{ {
@ -4486,7 +4559,8 @@ udf_lookup_name_in_dir(struct vnode *vp, const char *name, int namelen,
struct dirhash *dirh; struct dirhash *dirh;
struct dirhash_entry *dirh_ep; struct dirhash_entry *dirh_ep;
struct fileid_desc *fid; struct fileid_desc *fid;
struct dirent *dirent; struct dirent *dirent, *s_dirent;
struct charspec osta_charspec;
uint64_t diroffset; uint64_t diroffset;
uint32_t lb_size; uint32_t lb_size;
int hit, error; int hit, error;
@ -4504,18 +4578,28 @@ udf_lookup_name_in_dir(struct vnode *vp, const char *name, int namelen,
dirh = dir_node->dir_hash; dirh = dir_node->dir_hash;
/* allocate temporary space for fid */ /* allocate temporary space for fid */
lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size); lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size);
fid = malloc(lb_size, M_UDFTEMP, M_WAITOK); fid = malloc(lb_size, M_UDFTEMP, M_WAITOK);
dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK); dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK);
s_dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK);
DPRINTF(DIRHASH, ("dirhash_lookup looking for `%*.*s`\n", DPRINTF(DIRHASH, ("dirhash_lookup looking for `%*.*s`\n",
namelen, namelen, name)); namelen, namelen, name));
/* convert given unix name to canonical unix name */
udf_osta_charset(&osta_charspec);
unix_to_udf_name((char *) fid->data, &fid->l_fi,
name, namelen, &osta_charspec);
udf_to_unix_name(s_dirent->d_name, NAME_MAX,
(char *) fid->data, fid->l_fi,
&osta_charspec);
s_dirent->d_namlen = strlen(s_dirent->d_name);
/* search our dirhash hits */ /* search our dirhash hits */
memset(icb_loc, 0, sizeof(*icb_loc)); memset(icb_loc, 0, sizeof(*icb_loc));
dirh_ep = NULL; dirh_ep = NULL;
for (;;) { for (;;) {
hit = dirhash_lookup(dirh, name, namelen, &dirh_ep); hit = dirhash_lookup(dirh, s_dirent->d_name, s_dirent->d_namlen, &dirh_ep);
/* if no hit, abort the search */ /* if no hit, abort the search */
if (!hit) if (!hit)
break; break;
@ -4532,16 +4616,7 @@ udf_lookup_name_in_dir(struct vnode *vp, const char *name, int namelen,
dirent->d_namlen, dirent->d_namlen, dirent->d_name)); dirent->d_namlen, dirent->d_namlen, dirent->d_name));
/* see if its our entry */ /* see if its our entry */
#ifdef DIAGNOSTIC if (strncmp(dirent->d_name, s_dirent->d_name, s_dirent->d_namlen) == 0) {
if (dirent->d_namlen != namelen) {
printf("WARNING: dirhash_lookup() returned wrong "
"d_namelen: %d and ought to be %d\n",
dirent->d_namlen, namelen);
printf("\tlooked for `%s' and got `%s'\n",
name, dirent->d_name);
}
#endif
if (strncmp(dirent->d_name, name, namelen) == 0) {
*found = 1; *found = 1;
*icb_loc = fid->icb; *icb_loc = fid->icb;
break; break;
@ -4549,6 +4624,7 @@ udf_lookup_name_in_dir(struct vnode *vp, const char *name, int namelen,
} }
free(fid, M_UDFTEMP); free(fid, M_UDFTEMP);
free(dirent, M_UDFTEMP); free(dirent, M_UDFTEMP);
free(s_dirent, M_UDFTEMP);
dirhash_put(dir_node->dir_hash); dirhash_put(dir_node->dir_hash);
@ -4718,12 +4794,11 @@ udf_dir_detach(struct udf_mount *ump, struct udf_node *dir_node,
struct dirhash_entry *dirh_ep; struct dirhash_entry *dirh_ep;
struct file_entry *fe = dir_node->fe; struct file_entry *fe = dir_node->fe;
struct fileid_desc *fid; struct fileid_desc *fid;
struct dirent *dirent; struct dirent *dirent, *s_dirent;
struct charspec osta_charspec;
uint64_t diroffset; uint64_t diroffset;
uint32_t lb_size, fidsize; uint32_t lb_size, fidsize;
int found, error; int found, error;
char const *name = cnp->cn_nameptr;
int namelen = cnp->cn_namelen;
int hit, refcnt; int hit, refcnt;
/* get our dirhash and make sure its read in */ /* get our dirhash and make sure its read in */
@ -4740,16 +4815,26 @@ udf_dir_detach(struct udf_mount *ump, struct udf_node *dir_node,
assert(dir_node->efe); assert(dir_node->efe);
} }
/* allocate temporary space for fid */ /* allocate temporary space for fid and dirents */
lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size); lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size);
fid = malloc(lb_size, M_UDFTEMP, M_WAITOK); fid = malloc(lb_size, M_UDFTEMP, M_WAITOK);
dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK); dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK);
s_dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK);
/* convert given unix name to canonical unix name */
udf_osta_charset(&osta_charspec);
unix_to_udf_name((char *) fid->data, &fid->l_fi,
cnp->cn_nameptr, cnp->cn_namelen, &osta_charspec);
udf_to_unix_name(s_dirent->d_name, NAME_MAX,
(char *) fid->data, fid->l_fi,
&osta_charspec);
s_dirent->d_namlen = strlen(s_dirent->d_name);
/* search our dirhash hits */ /* search our dirhash hits */
found = 0; found = 0;
dirh_ep = NULL; dirh_ep = NULL;
for (;;) { for (;;) {
hit = dirhash_lookup(dirh, name, namelen, &dirh_ep); hit = dirhash_lookup(dirh, s_dirent->d_name, s_dirent->d_namlen, &dirh_ep);
/* if no hit, abort the search */ /* if no hit, abort the search */
if (!hit) if (!hit)
break; break;
@ -4763,8 +4848,8 @@ udf_dir_detach(struct udf_mount *ump, struct udf_node *dir_node,
break; break;
/* see if its our entry */ /* see if its our entry */
KASSERT(dirent->d_namlen == namelen); KASSERT(dirent->d_namlen == s_dirent->d_namlen);
if (strncmp(dirent->d_name, name, namelen) == 0) { if (strncmp(dirent->d_name, s_dirent->d_name, s_dirent->d_namlen) == 0) {
found = 1; found = 1;
break; break;
} }
@ -4788,7 +4873,7 @@ udf_dir_detach(struct udf_mount *ump, struct udf_node *dir_node,
/* write out */ /* write out */
error = vn_rdwr(UIO_WRITE, dir_node->vnode, error = vn_rdwr(UIO_WRITE, dir_node->vnode,
fid, fidsize, diroffset, fid, fidsize, diroffset,
UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED,
FSCRED, NULL, NULL); FSCRED, NULL, NULL);
if (error) if (error)
@ -4845,6 +4930,7 @@ udf_dir_detach(struct udf_mount *ump, struct udf_node *dir_node,
error_out: error_out:
free(fid, M_UDFTEMP); free(fid, M_UDFTEMP);
free(dirent, M_UDFTEMP); free(dirent, M_UDFTEMP);
free(s_dirent, M_UDFTEMP);
dirhash_put(dir_node->dir_hash); dirhash_put(dir_node->dir_hash);
@ -4950,7 +5036,7 @@ udf_dir_update_rootentry(struct udf_mount *ump, struct udf_node *dir_node,
/* write out */ /* write out */
error = vn_rdwr(UIO_WRITE, dir_node->vnode, error = vn_rdwr(UIO_WRITE, dir_node->vnode,
fid, fidsize, diroffset, fid, fidsize, diroffset,
UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED,
FSCRED, NULL, NULL); FSCRED, NULL, NULL);
@ -5154,7 +5240,7 @@ udf_dir_attach(struct udf_mount *ump, struct udf_node *dir_node,
/* writeout FID/update parent directory */ /* writeout FID/update parent directory */
error = vn_rdwr(UIO_WRITE, dvp, error = vn_rdwr(UIO_WRITE, dvp,
fid, chosen_size, chosen_fid_pos, fid, chosen_size, chosen_fid_pos,
UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED,
FSCRED, NULL, NULL); FSCRED, NULL, NULL);
@ -5336,7 +5422,7 @@ udf_loadvnode(struct mount *mp, struct vnode *vp,
/* choose this one */ /* choose this one */
last_fe_icb_loc = icb_loc; last_fe_icb_loc = icb_loc;
/* record and process/update (ext)fentry */ /* record and process/update (ext)fentry */
if (dscr_type == TAGID_FENTRY) { if (dscr_type == TAGID_FENTRY) {
if (udf_node->fe) if (udf_node->fe)
@ -5544,16 +5630,18 @@ udf_loadvnode(struct mount *mp, struct vnode *vp,
int int
udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc, udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc,
struct udf_node **udf_noderes) struct udf_node **udf_noderes, int lktype)
{ {
int error; int error;
struct vnode *vp; struct vnode *vp;
*udf_noderes = NULL;
error = vcache_get(ump->vfs_mountp, &node_icb_loc->loc, error = vcache_get(ump->vfs_mountp, &node_icb_loc->loc,
sizeof(node_icb_loc->loc), &vp); sizeof(node_icb_loc->loc), &vp);
if (error) if (error)
return error; return error;
error = vn_lock(vp, LK_EXCLUSIVE); error = vn_lock(vp, lktype);
if (error) { if (error) {
vrele(vp); vrele(vp);
return error; return error;
@ -5696,7 +5784,7 @@ udf_dispose_node(struct udf_node *udf_node)
int int
udf_newvnode(struct mount *mp, struct vnode *dvp, struct vnode *vp, udf_newvnode(struct mount *mp, struct vnode *dvp, struct vnode *vp,
struct vattr *vap, kauth_cred_t cred, struct vattr *vap, kauth_cred_t cred, void *extra,
size_t *key_len, const void **new_key) size_t *key_len, const void **new_key)
{ {
union dscrptr *dscr; union dscrptr *dscr;
@ -5840,7 +5928,7 @@ udf_newvnode(struct mount *mp, struct vnode *dvp, struct vnode *vp,
gid = parent_gid; gid = parent_gid;
udf_setownership(udf_node, uid, gid); udf_setownership(udf_node, uid, gid);
*key_len = sizeof(udf_node->loc.loc);; *key_len = sizeof(udf_node->loc.loc);
*new_key = &udf_node->loc.loc; *new_key = &udf_node->loc.loc;
return 0; return 0;
@ -5855,7 +5943,7 @@ udf_create_node(struct vnode *dvp, struct vnode **vpp, struct vattr *vap,
struct udf_mount *ump = dir_node->ump; struct udf_mount *ump = dir_node->ump;
int error; int error;
error = vcache_new(dvp->v_mount, dvp, vap, cnp->cn_cred, vpp); error = vcache_new(dvp->v_mount, dvp, vap, cnp->cn_cred, NULL, vpp);
if (error) if (error)
return error; return error;
@ -5880,6 +5968,7 @@ udf_create_node(struct vnode *dvp, struct vnode **vpp, struct vattr *vap,
/* adjust file count */ /* adjust file count */
udf_adjust_filecount(udf_node, 1); udf_adjust_filecount(udf_node, 1);
cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags);
return 0; return 0;
} }
@ -5914,6 +6003,9 @@ udf_delete_node(struct udf_node *udf_node)
struct long_ad *loc; struct long_ad *loc;
int extnr, lvint, dummy; int extnr, lvint, dummy;
if (udf_node->i_flags & IN_NO_DELETE)
return;
/* paranoia check on integrity; should be open!; we could panic */ /* paranoia check on integrity; should be open!; we could panic */
lvint = udf_rw32(udf_node->ump->logvol_integrity->integrity_type); lvint = udf_rw32(udf_node->ump->logvol_integrity->integrity_type);
if (lvint == UDF_INTEGRITY_CLOSED) if (lvint == UDF_INTEGRITY_CLOSED)
@ -6342,7 +6434,11 @@ udf_sync_pass(struct udf_mount *ump, kauth_cred_t cred, int pass, int *ndirty)
static bool static bool
udf_sync_selector(void *cl, struct vnode *vp) udf_sync_selector(void *cl, struct vnode *vp)
{ {
struct udf_node *udf_node = VTOI(vp); struct udf_node *udf_node;
KASSERT(mutex_owned(vp->v_interlock));
udf_node = VTOI(vp);
if (vp->v_vflag & VV_SYSTEM) if (vp->v_vflag & VV_SYSTEM)
return false; return false;
@ -6352,7 +6448,7 @@ udf_sync_selector(void *cl, struct vnode *vp)
return false; return false;
if ((udf_node->i_flags & (IN_ACCESSED | IN_UPDATE | IN_MODIFIED)) == 0) if ((udf_node->i_flags & (IN_ACCESSED | IN_UPDATE | IN_MODIFIED)) == 0)
return false; return false;
if (LIST_EMPTY(&vp->v_dirtyblkhd) && UVM_OBJ_IS_CLEAN(&vp->v_uobj)) if (LIST_EMPTY(&vp->v_dirtyblkhd) && (vp->v_iflag & VI_ONWORKLST) == 0)
return false; return false;
return true; return true;
@ -6398,7 +6494,7 @@ recount:
udf_sync_pass(ump, cred, 3, &ndirty); udf_sync_pass(ump, cred, 3, &ndirty);
DPRINTF(SYNC, ("counted num dirty pending blocks %d\n", DPRINTF(SYNC, ("counted num dirty pending blocks %d\n",
ndirty)); ndirty));
if (ndirty) { if (ndirty) {
/* 1/4 second wait */ /* 1/4 second wait */
kpause("udfsync2", false, hz/4, NULL); kpause("udfsync2", false, hz/4, NULL);
@ -6424,7 +6520,7 @@ recount:
/* /*
* Read and write file extent in/from the buffer. * Read and write file extent in/from the buffer.
* *
* The splitup of the extent into seperate request-buffers is to minimise * The splitup of the extent into separate request-buffers is to minimise
* copying around as much as possible. * copying around as much as possible.
* *
* block based file reading and writing * block based file reading and writing
@ -6438,21 +6534,26 @@ udf_read_internal(struct udf_node *node, uint8_t *blob)
struct extfile_entry *efe = node->efe; struct extfile_entry *efe = node->efe;
uint64_t inflen; uint64_t inflen;
uint32_t sector_size; uint32_t sector_size;
uint8_t *pos; uint8_t *srcpos;
int icbflags, addr_type; int icbflags, addr_type;
/* get extent and do some paranoia checks */ /* get extent and do some paranoia checks */
ump = node->ump; ump = node->ump;
sector_size = ump->discinfo.sector_size; sector_size = ump->discinfo.sector_size;
/*
* XXX there should be real bounds-checking logic here,
* in case ->l_ea or ->inf_len contains nonsense.
*/
if (fe) { if (fe) {
inflen = udf_rw64(fe->inf_len); inflen = udf_rw64(fe->inf_len);
pos = &fe->data[0] + udf_rw32(fe->l_ea); srcpos = &fe->data[0] + udf_rw32(fe->l_ea);
icbflags = udf_rw16(fe->icbtag.flags); icbflags = udf_rw16(fe->icbtag.flags);
} else { } else {
assert(node->efe); assert(node->efe);
inflen = udf_rw64(efe->inf_len); inflen = udf_rw64(efe->inf_len);
pos = &efe->data[0] + udf_rw32(efe->l_ea); srcpos = &efe->data[0] + udf_rw32(efe->l_ea);
icbflags = udf_rw16(efe->icbtag.flags); icbflags = udf_rw16(efe->icbtag.flags);
} }
addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;
@ -6462,8 +6563,8 @@ udf_read_internal(struct udf_node *node, uint8_t *blob)
assert(inflen < sector_size); assert(inflen < sector_size);
/* copy out info */ /* copy out info */
memset(blob, 0, sector_size); memcpy(blob, srcpos, inflen);
memcpy(blob, pos, inflen); memset(&blob[inflen], 0, sector_size - inflen);
return 0; return 0;
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_subr.h,v 1.19 2013/07/07 19:49:44 reinoud Exp $ */ /* $NetBSD: udf_subr.h,v 1.21 2020/01/17 20:08:08 ad Exp $ */
/* /*
* Copyright (c) 2006, 2008 Reinoud Zandijk * Copyright (c) 2006, 2008 Reinoud Zandijk
@ -40,7 +40,8 @@ int udf_search_tracks(struct udf_mount *ump, struct udf_args *args,
int *first_tracknr, int *last_tracknr); int *first_tracknr, int *last_tracknr);
int udf_search_writing_tracks(struct udf_mount *ump); int udf_search_writing_tracks(struct udf_mount *ump);
int udf_setup_writeparams(struct udf_mount *ump); int udf_setup_writeparams(struct udf_mount *ump);
int udf_synchronise_caches(struct udf_mount *ump); void udf_mmc_synchronise_caches(struct udf_mount *ump);
void udf_synchronise_caches(struct udf_mount *ump);
/* tags operations */ /* tags operations */
int udf_fidsize(struct fileid_desc *fid); int udf_fidsize(struct fileid_desc *fid);
@ -131,7 +132,7 @@ uint64_t udf_advance_uniqueid(struct udf_mount *ump);
void udf_lock_node(struct udf_node *udf_node, int flag, char const *fname, const int lineno); void udf_lock_node(struct udf_node *udf_node, int flag, char const *fname, const int lineno);
void udf_unlock_node(struct udf_node *udf_node, int flag); void udf_unlock_node(struct udf_node *udf_node, int flag);
int udf_get_node(struct udf_mount *ump, struct long_ad *icbloc, struct udf_node **noderes); int udf_get_node(struct udf_mount *ump, struct long_ad *icbloc, struct udf_node **noderes, int);
int udf_writeout_node(struct udf_node *udf_node, int waitfor); int udf_writeout_node(struct udf_node *udf_node, int waitfor);
int udf_dispose_node(struct udf_node *node); int udf_dispose_node(struct udf_node *node);

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_vfsops.c,v 1.71 2015/08/24 08:31:56 hannken Exp $ */ /* $NetBSD: udf_vfsops.c,v 1.80 2020/04/14 12:47:44 reinoud Exp $ */
/* /*
* Copyright (c) 2006, 2008 Reinoud Zandijk * Copyright (c) 2006, 2008 Reinoud Zandijk
@ -28,7 +28,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#ifndef lint #ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_vfsops.c,v 1.71 2015/08/24 08:31:56 hannken Exp $"); __KERNEL_RCSID(0, "$NetBSD: udf_vfsops.c,v 1.80 2020/04/14 12:47:44 reinoud Exp $");
#endif /* not lint */ #endif /* not lint */
@ -79,8 +79,6 @@ MALLOC_JUSTDEFINE(M_UDFVOLD, "UDF volspace", "UDF volume space descriptors");
MALLOC_JUSTDEFINE(M_UDFTEMP, "UDF temp", "UDF scrap space"); MALLOC_JUSTDEFINE(M_UDFTEMP, "UDF temp", "UDF scrap space");
struct pool udf_node_pool; struct pool udf_node_pool;
static struct sysctllog *udf_sysctl_log;
/* internal functions */ /* internal functions */
static int udf_mountfs(struct vnode *, struct mount *, struct lwp *, struct udf_args *); static int udf_mountfs(struct vnode *, struct mount *, struct lwp *, struct udf_args *);
@ -118,7 +116,7 @@ struct vfsops udf_vfsops = {
.vfs_mountroot = udf_mountroot, .vfs_mountroot = udf_mountroot,
.vfs_snapshot = udf_snapshot, .vfs_snapshot = udf_snapshot,
.vfs_extattrctl = vfs_stdextattrctl, .vfs_extattrctl = vfs_stdextattrctl,
.vfs_suspendctl = (void *)eopnotsupp, .vfs_suspendctl = genfs_suspendctl,
.vfs_renamelock_enter = genfs_renamelock_enter, .vfs_renamelock_enter = genfs_renamelock_enter,
.vfs_renamelock_exit = genfs_renamelock_exit, .vfs_renamelock_exit = genfs_renamelock_exit,
.vfs_fsync = (void *)eopnotsupp, .vfs_fsync = (void *)eopnotsupp,
@ -169,10 +167,34 @@ udf_done(void)
*/ */
#define UDF_VERBOSE_SYSCTLOPT 1 #define UDF_VERBOSE_SYSCTLOPT 1
/*
* XXX the "24" below could be dynamic, thereby eliminating one
* more instance of the "number to vfs" mapping problem, but
* "24" is the order as taken from sys/mount.h
*/
SYSCTL_SETUP(udf_sysctl_setup, "udf sysctl")
{
const struct sysctlnode *node;
sysctl_createv(clog, 0, NULL, &node,
CTLFLAG_PERMANENT,
CTLTYPE_NODE, "udf",
SYSCTL_DESCR("OSTA Universal File System"),
NULL, 0, NULL, 0,
CTL_VFS, 24, CTL_EOL);
#ifdef DEBUG
sysctl_createv(clog, 0, NULL, &node,
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
CTLTYPE_INT, "verbose",
SYSCTL_DESCR("Bitmask for filesystem debugging"),
NULL, 0, &udf_verbose, 0,
CTL_VFS, 24, UDF_VERBOSE_SYSCTLOPT, CTL_EOL);
#endif
}
static int static int
udf_modcmd(modcmd_t cmd, void *arg) udf_modcmd(modcmd_t cmd, void *arg)
{ {
const struct sysctlnode *node;
int error; int error;
switch (cmd) { switch (cmd) {
@ -180,31 +202,11 @@ udf_modcmd(modcmd_t cmd, void *arg)
error = vfs_attach(&udf_vfsops); error = vfs_attach(&udf_vfsops);
if (error != 0) if (error != 0)
break; break;
/*
* XXX the "24" below could be dynamic, thereby eliminating one
* more instance of the "number to vfs" mapping problem, but
* "24" is the order as taken from sys/mount.h
*/
sysctl_createv(&udf_sysctl_log, 0, NULL, &node,
CTLFLAG_PERMANENT,
CTLTYPE_NODE, "udf",
SYSCTL_DESCR("OSTA Universal File System"),
NULL, 0, NULL, 0,
CTL_VFS, 24, CTL_EOL);
#ifdef DEBUG
sysctl_createv(&udf_sysctl_log, 0, NULL, &node,
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
CTLTYPE_INT, "verbose",
SYSCTL_DESCR("Bitmask for filesystem debugging"),
NULL, 0, &udf_verbose, 0,
CTL_VFS, 24, UDF_VERBOSE_SYSCTLOPT, CTL_EOL);
#endif
break; break;
case MODULE_CMD_FINI: case MODULE_CMD_FINI:
error = vfs_detach(&udf_vfsops); error = vfs_detach(&udf_vfsops);
if (error != 0) if (error != 0)
break; break;
sysctl_teardown(&udf_sysctl_log);
break; break;
default: default:
error = ENOTTY; error = ENOTTY;
@ -277,7 +279,6 @@ static void
udf_release_system_nodes(struct mount *mp) udf_release_system_nodes(struct mount *mp)
{ {
struct udf_mount *ump = VFSTOUDF(mp); struct udf_mount *ump = VFSTOUDF(mp);
int error;
/* if we haven't even got an ump, dont bother */ /* if we haven't even got an ump, dont bother */
if (!ump) if (!ump)
@ -294,10 +295,6 @@ udf_release_system_nodes(struct mount *mp)
vrele(ump->metadatamirror_node->vnode); vrele(ump->metadatamirror_node->vnode);
if (ump->metadatabitmap_node) if (ump->metadatabitmap_node)
vrele(ump->metadatabitmap_node->vnode); vrele(ump->metadatabitmap_node->vnode);
/* This flush should NOT write anything nor allow any node to remain */
if ((error = vflush(ump->vfs_mountp, NULLVP, 0)) != 0)
panic("Failure to flush UDF system vnodes\n");
} }
@ -361,7 +358,7 @@ udf_mount(struct mount *mp, const char *path,
} }
if (bdevsw_lookup(devvp->v_rdev) == NULL) { if (bdevsw_lookup(devvp->v_rdev) == NULL) {
vrele(devvp); vrele(devvp);
return ENXIO; return ENXIO;
} }
/* /*
@ -442,12 +439,14 @@ static bool
udf_sanity_selector(void *cl, struct vnode *vp) udf_sanity_selector(void *cl, struct vnode *vp)
{ {
KASSERT(mutex_owned(vp->v_interlock));
vprint("", vp); vprint("", vp);
if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE) { if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE) {
printf(" is locked\n"); printf(" is locked\n");
} }
if (vp->v_usecount > 1) if (vrefcnt(vp) > 1)
printf(" more than one usecount %d\n", vp->v_usecount); printf(" more than one usecount %d\n", vrefcnt(vp));
return false; return false;
} }
@ -518,6 +517,10 @@ udf_unmount(struct mount *mp, int mntflags)
/* NOTE release system nodes should NOT write anything */ /* NOTE release system nodes should NOT write anything */
udf_release_system_nodes(mp); udf_release_system_nodes(mp);
/* This flush should NOT write anything nor allow any node to remain */
if ((error = vflush(ump->vfs_mountp, NULLVP, 0)) != 0)
panic("Failure to flush UDF system vnodes\n");
/* finalise disc strategy */ /* finalise disc strategy */
udf_discstrat_finish(ump); udf_discstrat_finish(ump);
@ -743,7 +746,7 @@ udf_start(struct mount *mp, int flags)
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
int int
udf_root(struct mount *mp, struct vnode **vpp) udf_root(struct mount *mp, int lktype, struct vnode **vpp)
{ {
struct vnode *vp; struct vnode *vp;
struct long_ad *dir_loc; struct long_ad *dir_loc;
@ -754,12 +757,13 @@ udf_root(struct mount *mp, struct vnode **vpp)
DPRINTF(CALL, ("udf_root called\n")); DPRINTF(CALL, ("udf_root called\n"));
dir_loc = &ump->fileset_desc->rootdir_icb; dir_loc = &ump->fileset_desc->rootdir_icb;
error = udf_get_node(ump, dir_loc, &root_dir); error = udf_get_node(ump, dir_loc, &root_dir, lktype);
if (error)
return error;
if (!root_dir) if (!root_dir)
error = ENOENT; error = ENOENT;
if (error)
return error;
vp = root_dir->vnode; vp = root_dir->vnode;
KASSERT(vp->v_vflag & VV_ROOT); KASSERT(vp->v_vflag & VV_ROOT);
@ -893,7 +897,7 @@ udf_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
* (optional) TODO lookup why some sources state NFSv3 * (optional) TODO lookup why some sources state NFSv3
*/ */
int int
udf_vget(struct mount *mp, ino_t ino, udf_vget(struct mount *mp, ino_t ino, int lktype,
struct vnode **vpp) struct vnode **vpp)
{ {
DPRINTF(NOTIMPL, ("udf_vget called\n")); DPRINTF(NOTIMPL, ("udf_vget called\n"));
@ -906,7 +910,7 @@ udf_vget(struct mount *mp, ino_t ino,
* Lookup vnode for file handle specified * Lookup vnode for file handle specified
*/ */
int int
udf_fhtovp(struct mount *mp, struct fid *fhp, udf_fhtovp(struct mount *mp, struct fid *fhp, int lktype,
struct vnode **vpp) struct vnode **vpp)
{ {
DPRINTF(NOTIMPL, ("udf_fhtovp called\n")); DPRINTF(NOTIMPL, ("udf_fhtovp called\n"));

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf_vnops.c,v 1.101 2015/04/20 23:03:08 riastradh Exp $ */ /* $NetBSD: udf_vnops.c,v 1.114 2020/06/27 17:29:18 christos Exp $ */
/* /*
* Copyright (c) 2006, 2008 Reinoud Zandijk * Copyright (c) 2006, 2008 Reinoud Zandijk
@ -32,7 +32,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#ifndef lint #ifndef lint
__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.101 2015/04/20 23:03:08 riastradh Exp $"); __KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.114 2020/06/27 17:29:18 christos Exp $");
#endif /* not lint */ #endif /* not lint */
@ -71,16 +71,13 @@ __KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.101 2015/04/20 23:03:08 riastradh Ex
static int udf_do_readlink(struct udf_node *udf_node, uint64_t filesize, static int udf_do_readlink(struct udf_node *udf_node, uint64_t filesize,
uint8_t *targetbuf, int *length); uint8_t *targetbuf, int *length);
/* externs */
extern int prtactive;
/* implementations of vnode functions; table follows at end */ /* implementations of vnode functions; table follows at end */
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
int int
udf_inactive(void *v) udf_inactive(void *v)
{ {
struct vop_inactive_args /* { struct vop_inactive_v2_args /* {
struct vnode *a_vp; struct vnode *a_vp;
bool *a_recycle; bool *a_recycle;
} */ *ap = v; } */ *ap = v;
@ -92,7 +89,6 @@ udf_inactive(void *v)
if (udf_node == NULL) { if (udf_node == NULL) {
DPRINTF(NODE, ("udf_inactive: inactive NULL UDF node\n")); DPRINTF(NODE, ("udf_inactive: inactive NULL UDF node\n"));
VOP_UNLOCK(vp);
return 0; return 0;
} }
@ -115,14 +111,12 @@ udf_inactive(void *v)
*ap->a_recycle = false; *ap->a_recycle = false;
if ((refcnt == 0) && ((vp->v_vflag & VV_SYSTEM) == 0)) { if ((refcnt == 0) && ((vp->v_vflag & VV_SYSTEM) == 0)) {
*ap->a_recycle = true; *ap->a_recycle = true;
VOP_UNLOCK(vp);
return 0; return 0;
} }
/* write out its node */ /* write out its node */
if (udf_node->i_flags & (IN_CHANGE | IN_UPDATE | IN_MODIFIED)) if (udf_node->i_flags & (IN_CHANGE | IN_UPDATE | IN_MODIFIED))
udf_update(vp, NULL, NULL, NULL, 0); udf_update(vp, NULL, NULL, NULL, 0);
VOP_UNLOCK(vp);
return 0; return 0;
} }
@ -132,16 +126,16 @@ udf_inactive(void *v)
int int
udf_reclaim(void *v) udf_reclaim(void *v)
{ {
struct vop_reclaim_args /* { struct vop_reclaim_v2_args /* {
struct vnode *a_vp; struct vnode *a_vp;
} */ *ap = v; } */ *ap = v;
struct vnode *vp = ap->a_vp; struct vnode *vp = ap->a_vp;
struct udf_node *udf_node = VTOI(vp); struct udf_node *udf_node = VTOI(vp);
int refcnt; int refcnt;
VOP_UNLOCK(vp);
DPRINTF(NODE, ("udf_reclaim called for node %p\n", udf_node)); DPRINTF(NODE, ("udf_reclaim called for node %p\n", udf_node));
if (prtactive && vp->v_usecount > 1)
vprint("udf_reclaim(): pushing active", vp);
if (udf_node == NULL) { if (udf_node == NULL) {
DPRINTF(NODE, ("udf_reclaim(): null udfnode\n")); DPRINTF(NODE, ("udf_reclaim(): null udfnode\n"));
@ -174,9 +168,6 @@ udf_reclaim(void *v)
tsleep(&udf_node->outstanding_nodedscr, PRIBIO, "recl wait", hz/8); tsleep(&udf_node->outstanding_nodedscr, PRIBIO, "recl wait", hz/8);
} }
vcache_remove(vp->v_mount, &udf_node->loc.loc,
sizeof(udf_node->loc.loc));
/* dispose all node knowledge */ /* dispose all node knowledge */
udf_dispose_node(udf_node); udf_dispose_node(udf_node);
@ -257,7 +248,7 @@ udf_read(void *v)
/* ubc, here we come, prepare to trap */ /* ubc, here we come, prepare to trap */
error = ubc_uiomove(uobj, uio, len, advice, error = ubc_uiomove(uobj, uio, len, advice,
UBC_READ | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp)); UBC_READ | UBC_PARTIALOK | UBC_VNODE_FLAGS(vp));
if (error) if (error)
break; break;
} }
@ -375,7 +366,7 @@ udf_write(void *v)
/* ubc, here we come, prepare to trap */ /* ubc, here we come, prepare to trap */
error = ubc_uiomove(uobj, uio, len, advice, error = ubc_uiomove(uobj, uio, len, advice,
UBC_WRITE | UBC_UNMAP_FLAG(vp)); UBC_WRITE | UBC_VNODE_FLAGS(vp));
if (error) if (error)
break; break;
@ -388,7 +379,7 @@ udf_write(void *v)
*/ */
if ((vp->v_type != VDIR) && if ((vp->v_type != VDIR) &&
(old_offset >> 16 != uio->uio_offset >> 16)) { (old_offset >> 16 != uio->uio_offset >> 16)) {
mutex_enter(vp->v_interlock); rw_enter(vp->v_uobj.vmobjlock, RW_WRITER);
error = VOP_PUTPAGES(vp, (old_offset >> 16) << 16, error = VOP_PUTPAGES(vp, (old_offset >> 16) << 16,
(uio->uio_offset >> 16) << 16, (uio->uio_offset >> 16) << 16,
PGO_CLEANIT | PGO_LAZY); PGO_CLEANIT | PGO_LAZY);
@ -618,7 +609,7 @@ udf_readdir(void *v)
if (uio->uio_resid < _DIRENT_SIZE(dirent)) if (uio->uio_resid < _DIRENT_SIZE(dirent))
break; break;
/* remember the last entry we transfered */ /* remember the last entry we transferred */
transoffset = diroffset; transoffset = diroffset;
/* skip deleted entries */ /* skip deleted entries */
@ -759,7 +750,8 @@ udf_lookup(void *v)
if (error == 0) { if (error == 0) {
DPRINTF(LOOKUP, ("\tfound '..'\n")); DPRINTF(LOOKUP, ("\tfound '..'\n"));
/* try to create/reuse the node */ /* try to create/reuse the node */
error = udf_get_node(ump, &icb_loc, &res_node); error = udf_get_node(ump, &icb_loc, &res_node,
LK_EXCLUSIVE);
if (!error) { if (!error) {
DPRINTF(LOOKUP, DPRINTF(LOOKUP,
@ -811,7 +803,7 @@ udf_lookup(void *v)
*/ */
/* try to create/reuse the node */ /* try to create/reuse the node */
error = udf_get_node(ump, &icb_loc, &res_node); error = udf_get_node(ump, &icb_loc, &res_node, LK_EXCLUSIVE);
if (error) if (error)
goto out; goto out;
@ -834,7 +826,7 @@ udf_lookup(void *v)
udf_getownership(dir_node, &d_uid, &d_gid); udf_getownership(dir_node, &d_uid, &d_gid);
error = kauth_authorize_vnode(cnp->cn_cred, error = kauth_authorize_vnode(cnp->cn_cred,
KAUTH_VNODE_DELETE, res_node->vnode, KAUTH_VNODE_DELETE, res_node->vnode,
dir_node->vnode, genfs_can_sticky(cnp->cn_cred, dir_node->vnode, genfs_can_sticky(dvp, cnp->cn_cred,
d_uid, d_uid)); d_uid, d_uid));
if (error) { if (error) {
error = EPERM; error = EPERM;
@ -1049,7 +1041,7 @@ udf_chown(struct vnode *vp, uid_t new_uid, gid_t new_gid,
/* check permissions */ /* check permissions */
error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP,
vp, NULL, genfs_can_chown(cred, uid, gid, new_uid, new_gid)); vp, NULL, genfs_can_chown(vp, cred, uid, gid, new_uid, new_gid));
if (error) if (error)
return (error); return (error);
@ -1086,7 +1078,7 @@ udf_chmod(struct vnode *vp, mode_t mode, kauth_cred_t cred)
/* check permissions */ /* check permissions */
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp, error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp,
NULL, genfs_can_chmod(vp->v_type, cred, uid, gid, mode)); NULL, genfs_can_chmod(vp, cred, uid, gid, mode));
if (error) if (error)
return (error); return (error);
@ -1195,7 +1187,7 @@ udf_chtimes(struct vnode *vp,
/* check permissions */ /* check permissions */
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp,
NULL, genfs_can_chtimes(vp, setattrflags, uid, cred)); NULL, genfs_can_chtimes(vp, cred, uid, setattrflags));
if (error) if (error)
return (error); return (error);
@ -1334,9 +1326,9 @@ udf_pathconf(void *v)
#endif #endif
*ap->a_retval = bits; *ap->a_retval = bits;
return 0; return 0;
default:
return genfs_pathconf(ap);
} }
return EINVAL;
} }
@ -1387,15 +1379,15 @@ udf_close(void *v)
udf_node = udf_node; /* shut up gcc */ udf_node = udf_node; /* shut up gcc */
if (!async && (vp->v_type != VDIR)) { if (!async && (vp->v_type != VDIR)) {
mutex_enter(vp->v_interlock); rw_enter(vp->v_uobj.vmobjlock, RW_WRITER);
error = VOP_PUTPAGES(vp, 0, 0, PGO_CLEANIT); error = VOP_PUTPAGES(vp, 0, 0, PGO_CLEANIT);
if (error) if (error)
return error; return error;
} }
mutex_enter(vp->v_interlock); mutex_enter(vp->v_interlock);
if (vp->v_usecount > 1) if (vrefcnt(vp) > 1)
udf_itimes(udf_node, NULL, NULL, NULL); udf_itimes(udf_node, NULL, NULL, NULL);
mutex_exit(vp->v_interlock); mutex_exit(vp->v_interlock);
return 0; return 0;
@ -1445,13 +1437,13 @@ udf_check_possible(struct vnode *vp, struct vattr *vap, mode_t mode)
} }
static int static int
udf_check_permitted(struct vnode *vp, struct vattr *vap, mode_t mode, udf_check_permitted(struct vnode *vp, struct vattr *vap, accmode_t accmode,
kauth_cred_t cred) kauth_cred_t cred)
{ {
/* ask the generic genfs_can_access to advice on security */ /* ask the generic genfs_can_access to advice on security */
return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode,
vp->v_type, vap->va_mode), vp, NULL, genfs_can_access(vp->v_type, vp->v_type, vap->va_mode), vp, NULL, genfs_can_access(vp, cred,
vap->va_mode, vap->va_uid, vap->va_gid, mode, cred)); vap->va_uid, vap->va_gid, vap->va_mode, NULL, accmode));
} }
int int
@ -1459,12 +1451,12 @@ udf_access(void *v)
{ {
struct vop_access_args /* { struct vop_access_args /* {
struct vnode *a_vp; struct vnode *a_vp;
int a_mode; accmode_t a_accmode;
kauth_cred_t a_cred; kauth_cred_t a_cred;
struct proc *a_p; struct proc *a_p;
} */ *ap = v; } */ *ap = v;
struct vnode *vp = ap->a_vp; struct vnode *vp = ap->a_vp;
mode_t mode = ap->a_mode; accmode_t accmode = ap->a_accmode;
kauth_cred_t cred = ap->a_cred; kauth_cred_t cred = ap->a_cred;
/* struct udf_node *udf_node = VTOI(vp); */ /* struct udf_node *udf_node = VTOI(vp); */
struct vattr vap; struct vattr vap;
@ -1476,11 +1468,11 @@ udf_access(void *v)
if (error) if (error)
return error; return error;
error = udf_check_possible(vp, &vap, mode); error = udf_check_possible(vp, &vap, accmode);
if (error) if (error)
return error; return error;
error = udf_check_permitted(vp, &vap, mode, cred); error = udf_check_permitted(vp, &vap, accmode, cred);
return error; return error;
} }
@ -1947,7 +1939,7 @@ udf_readlink(void *v)
int int
udf_remove(void *v) udf_remove(void *v)
{ {
struct vop_remove_args /* { struct vop_remove_v2_args /* {
struct vnode *a_dvp; struct vnode *a_dvp;
struct vnode *a_vp; struct vnode *a_vp;
struct componentname *a_cnp; struct componentname *a_cnp;
@ -1978,7 +1970,6 @@ udf_remove(void *v)
vrele(vp); vrele(vp);
else else
vput(vp); vput(vp);
vput(dvp);
return error; return error;
} }
@ -1988,7 +1979,7 @@ udf_remove(void *v)
int int
udf_rmdir(void *v) udf_rmdir(void *v)
{ {
struct vop_rmdir_args /* { struct vop_rmdir_v2_args /* {
struct vnode *a_dvp; struct vnode *a_dvp;
struct vnode *a_vp; struct vnode *a_vp;
struct componentname *a_cnp; struct componentname *a_cnp;
@ -2001,12 +1992,11 @@ udf_rmdir(void *v)
struct udf_mount *ump = dir_node->ump; struct udf_mount *ump = dir_node->ump;
int error, isempty; int error, isempty;
DPRINTF(NOTIMPL, ("udf_rmdir '%s' called\n", cnp->cn_nameptr)); DPRINTF(CALL, ("udf_rmdir '%s' called\n", cnp->cn_nameptr));
/* don't allow '.' to be deleted */ /* don't allow '.' to be deleted */
if (dir_node == udf_node) { if (dir_node == udf_node) {
vrele(dvp); vrele(vp);
vput(vp);
return EINVAL; return EINVAL;
} }
@ -2023,7 +2013,6 @@ udf_rmdir(void *v)
dirhash_put(udf_node->dir_hash); dirhash_put(udf_node->dir_hash);
if (!isempty) { if (!isempty) {
vput(dvp);
vput(vp); vput(vp);
return ENOTEMPTY; return ENOTEMPTY;
} }
@ -2046,8 +2035,7 @@ udf_rmdir(void *v)
} }
DPRINTFIF(NODE, error, ("\tgot error removing dir\n")); DPRINTFIF(NODE, error, ("\tgot error removing dir\n"));
/* unput the nodes and exit */ /* put the node and exit */
vput(dvp);
vput(vp); vput(vp);
return error; return error;
@ -2191,6 +2179,7 @@ const struct vnodeopv_entry_desc udf_vnodeop_entries[] = {
{ &vop_open_desc, udf_open }, /* open */ { &vop_open_desc, udf_open }, /* open */
{ &vop_close_desc, udf_close }, /* close */ { &vop_close_desc, udf_close }, /* close */
{ &vop_access_desc, udf_access }, /* access */ { &vop_access_desc, udf_access }, /* access */
{ &vop_accessx_desc, genfs_accessx }, /* accessx */
{ &vop_getattr_desc, udf_getattr }, /* getattr */ { &vop_getattr_desc, udf_getattr }, /* getattr */
{ &vop_setattr_desc, udf_setattr }, /* setattr */ /* TODO chflags */ { &vop_setattr_desc, udf_setattr }, /* setattr */ /* TODO chflags */
{ &vop_read_desc, udf_read }, /* read */ { &vop_read_desc, udf_read }, /* read */

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.36 2013/08/05 14:41:57 reinoud Exp $ # $NetBSD: Makefile,v 1.37 2019/10/13 07:28:19 mrg Exp $
# #
WARNS?= 5 WARNS?= 5
@ -31,6 +31,12 @@ CPPFLAGS+= -I${.CURDIR} -I${MKNODSRC} -I${MTREESRC} -DMAKEFS
.if !defined(HOSTPROG) .if !defined(HOSTPROG)
DPADD+= ${LIBUTIL} DPADD+= ${LIBUTIL}
LDADD+= -lutil LDADD+= -lutil
COPTS.cd9660.c+= ${GCC_NO_STRINGOP_TRUNCATION} ${GCC_NO_FORMAT_TRUNCATION}
COPTS.cd9660_conversion.c+= ${GCC_NO_FORMAT_TRUNCATION}
COPTS.udf.c+= ${GCC_NO_STRINGOP_TRUNCATION}
COPTS.v7fs_estimate.c+= ${GCC_NO_STRINGOP_TRUNCATION}
COPTS.v7fs_populate.c+= ${GCC_NO_STRINGOP_TRUNCATION} ${GCC_NO_FORMAT_TRUNCATION}
.endif .endif
.include <bsd.prog.mk> .include <bsd.prog.mk>

View File

@ -1,4 +1,4 @@
/* $NetBSD: cd9660.c,v 1.49 2015/06/17 01:05:41 christos Exp $ */ /* $NetBSD: cd9660.c,v 1.57 2020/11/10 20:48:29 reinoud Exp $ */
/* /*
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
@ -103,7 +103,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if defined(__RCSID) && !defined(__lint) #if defined(__RCSID) && !defined(__lint)
__RCSID("$NetBSD: cd9660.c,v 1.49 2015/06/17 01:05:41 christos Exp $"); __RCSID("$NetBSD: cd9660.c,v 1.57 2020/11/10 20:48:29 reinoud Exp $");
#endif /* !__lint */ #endif /* !__lint */
#include <string.h> #include <string.h>
@ -124,7 +124,7 @@ __RCSID("$NetBSD: cd9660.c,v 1.49 2015/06/17 01:05:41 christos Exp $");
static void cd9660_finalize_PVD(iso9660_disk *); static void cd9660_finalize_PVD(iso9660_disk *);
static cd9660node *cd9660_allocate_cd9660node(void); static cd9660node *cd9660_allocate_cd9660node(void);
static void cd9660_set_defaults(iso9660_disk *); static void cd9660_set_defaults(iso9660_disk *);
static int cd9660_arguments_set_string(const char *, const char *, int, static int cd9660_arguments_set_string(const char *, const char *, size_t,
char, char *); char, char *);
static void cd9660_populate_iso_dir_record( static void cd9660_populate_iso_dir_record(
struct _iso_directory_record_cd9660 *, u_char, u_char, u_char, struct _iso_directory_record_cd9660 *, u_char, u_char, u_char,
@ -178,7 +178,7 @@ static int cd9660_add_generic_bootimage(iso9660_disk *, const char *);
/* /*
* Allocate and initalize a cd9660node * Allocate and initialize a cd9660node
* @returns struct cd9660node * Pointer to new node, or NULL on error * @returns struct cd9660node * Pointer to new node, or NULL on error
*/ */
static cd9660node * static cd9660node *
@ -298,7 +298,7 @@ cd9660_prep_opts(fsinfo_t *fsopts)
"Allow 37 char filenames (unimplemented)"), "Allow 37 char filenames (unimplemented)"),
OPT_BOOL('i', "allow-illegal-chars", allow_illegal_chars, OPT_BOOL('i', "allow-illegal-chars", allow_illegal_chars,
"Allow illegal characters in filenames"), "Allow illegal characters in filenames"),
OPT_BOOL('D', "allow-multidot", allow_multidot, OPT_BOOL('m', "allow-multidot", allow_multidot,
"Allow multiple periods in filenames"), "Allow multiple periods in filenames"),
OPT_BOOL('o', "omit-trailing-period", omit_trailing_period, OPT_BOOL('o', "omit-trailing-period", omit_trailing_period,
"Omit trailing periods in filenames"), "Omit trailing periods in filenames"),
@ -321,6 +321,7 @@ cd9660_prep_opts(fsinfo_t *fsopts)
OPT_STR('\0', "no-boot", "No boot support"), OPT_STR('\0', "no-boot", "No boot support"),
OPT_STR('\0', "hard-disk-boot", "Boot from hard disk"), OPT_STR('\0', "hard-disk-boot", "Boot from hard disk"),
OPT_STR('\0', "boot-load-segment", "Boot load segment"), OPT_STR('\0', "boot-load-segment", "Boot load segment"),
OPT_STR('\0', "platformid", "Section Header Platform ID"),
{ .name = NULL } { .name = NULL }
}; };
@ -339,10 +340,11 @@ cd9660_cleanup_opts(fsinfo_t *fsopts)
} }
static int static int
cd9660_arguments_set_string(const char *val, const char *fieldtitle, int length, cd9660_arguments_set_string(const char *val, const char *fieldtitle,
char testmode, char * dest) size_t length, char testmode, char * dest)
{ {
int len, test; size_t len;
int test;
if (val == NULL) if (val == NULL)
warnx("error: The %s requires a string argument", fieldtitle); warnx("error: The %s requires a string argument", fieldtitle);
@ -457,7 +459,8 @@ cd9660_parse_opts(const char *option, fsinfo_t *fsopts)
/* RRIP */ /* RRIP */
cd9660_eltorito_add_boot_option(diskStructure, name, 0); cd9660_eltorito_add_boot_option(diskStructure, name, 0);
rv = 1; rv = 1;
} else if (strcmp(name, "boot-load-segment") == 0) { } else if (strcmp(name, "boot-load-segment") == 0 ||
strcmp(name, "platformid") == 0) {
if (buf[0] == '\0') { if (buf[0] == '\0') {
warnx("Option `%s' doesn't contain a value", warnx("Option `%s' doesn't contain a value",
name); name);
@ -483,7 +486,7 @@ cd9660_parse_opts(const char *option, fsinfo_t *fsopts)
*/ */
void void
cd9660_makefs(const char *image, const char *dir, fsnode *root, cd9660_makefs(const char *image, const char *dir, fsnode *root,
fsinfo_t *fsopts) fsinfo_t *fsopts)
{ {
int64_t startoffset; int64_t startoffset;
int numDirectories; int numDirectories;
@ -661,7 +664,7 @@ typedef int (*cd9660node_func)(cd9660node *);
static void static void
cd9660_finalize_PVD(iso9660_disk *diskStructure) cd9660_finalize_PVD(iso9660_disk *diskStructure)
{ {
time_t tim; time_t tstamp = stampst.st_ino ? stampst.st_mtime : time(NULL);
/* root should be a fixed size of 34 bytes since it has no name */ /* root should be a fixed size of 34 bytes since it has no name */
memcpy(diskStructure->primaryDescriptor.root_directory_record, memcpy(diskStructure->primaryDescriptor.root_directory_record,
@ -710,23 +713,23 @@ cd9660_finalize_PVD(iso9660_disk *diskStructure)
diskStructure->primaryDescriptor.bibliographic_file_id, 37); diskStructure->primaryDescriptor.bibliographic_file_id, 37);
/* Setup dates */ /* Setup dates */
time(&tim);
cd9660_time_8426( cd9660_time_8426(
(unsigned char *)diskStructure->primaryDescriptor.creation_date, (unsigned char *)diskStructure->primaryDescriptor.creation_date,
tim); tstamp);
cd9660_time_8426( cd9660_time_8426(
(unsigned char *)diskStructure->primaryDescriptor.modification_date, (unsigned char *)diskStructure->primaryDescriptor.modification_date,
tim); tstamp);
/* #if 0
cd9660_set_date(diskStructure->primaryDescriptor.expiration_date, now); cd9660_set_date(diskStructure->primaryDescriptor.expiration_date,
*/ tstamp);
#endif
memset(diskStructure->primaryDescriptor.expiration_date, '0' ,16); memset(diskStructure->primaryDescriptor.expiration_date, '0' ,16);
diskStructure->primaryDescriptor.expiration_date[16] = 0; diskStructure->primaryDescriptor.expiration_date[16] = 0;
cd9660_time_8426( cd9660_time_8426(
(unsigned char *)diskStructure->primaryDescriptor.effective_date, (unsigned char *)diskStructure->primaryDescriptor.effective_date,
tim); tstamp);
} }
static void static void
@ -821,7 +824,7 @@ cd9660_fill_extended_attribute_record(cd9660node *node)
static int static int
cd9660_translate_node_common(iso9660_disk *diskStructure, cd9660node *newnode) cd9660_translate_node_common(iso9660_disk *diskStructure, cd9660node *newnode)
{ {
time_t tim; time_t tstamp = stampst.st_ino ? stampst.st_mtime : time(NULL);
u_char flag; u_char flag;
char temp[ISO_FILENAME_MAXLENGTH_WITH_PADDING]; char temp[ISO_FILENAME_MAXLENGTH_WITH_PADDING];
@ -841,9 +844,8 @@ cd9660_translate_node_common(iso9660_disk *diskStructure, cd9660node *newnode)
/* Set the various dates */ /* Set the various dates */
/* If we want to use the current date and time */ /* If we want to use the current date and time */
time(&tim);
cd9660_time_915(newnode->isoDirRecord->date, tim); cd9660_time_915(newnode->isoDirRecord->date, tstamp);
cd9660_bothendian_dword(newnode->fileDataLength, cd9660_bothendian_dword(newnode->fileDataLength,
newnode->isoDirRecord->size); newnode->isoDirRecord->size);
@ -883,7 +885,8 @@ cd9660_translate_node(iso9660_disk *diskStructure, fsnode *node,
return 0; return 0;
/* Finally, overwrite some of the values that are set by default */ /* Finally, overwrite some of the values that are set by default */
cd9660_time_915(newnode->isoDirRecord->date, node->inode->st.st_mtime); cd9660_time_915(newnode->isoDirRecord->date,
stampst.st_ino ? stampst.st_mtime : node->inode->st.st_mtime);
return 1; return 1;
} }
@ -1078,7 +1081,7 @@ cd9660_rename_filename(iso9660_disk *diskStructure, cd9660node *iter, int num,
tmp = emalloc(ISO_FILENAME_MAXLENGTH_WITH_PADDING); tmp = emalloc(ISO_FILENAME_MAXLENGTH_WITH_PADDING);
while (i < num) { while (i < num && iter) {
powers = 1; powers = 1;
count = 0; count = 0;
digits = 1; digits = 1;
@ -1281,6 +1284,8 @@ cd9660_rrip_move_directory(iso9660_disk *diskStructure, cd9660node *dir)
diskStructure->rootNode, dir); diskStructure->rootNode, dir);
if (diskStructure->rr_moved_dir == NULL) if (diskStructure->rr_moved_dir == NULL)
return 0; return 0;
cd9660_time_915(diskStructure->rr_moved_dir->isoDirRecord->date,
stampst.st_ino ? stampst.st_mtime : start_time.tv_sec);
} }
/* Create a file with the same ORIGINAL name */ /* Create a file with the same ORIGINAL name */
@ -1290,7 +1295,7 @@ cd9660_rrip_move_directory(iso9660_disk *diskStructure, cd9660node *dir)
return NULL; return NULL;
diskStructure->rock_ridge_move_count++; diskStructure->rock_ridge_move_count++;
snprintf(newname, sizeof(newname), "%08i", snprintf(newname, sizeof(newname), "%08u",
diskStructure->rock_ridge_move_count); diskStructure->rock_ridge_move_count);
/* Point to old parent */ /* Point to old parent */

View File

@ -1,4 +1,4 @@
/* $NetBSD: cd9660.h,v 1.20 2013/01/29 15:52:25 christos Exp $ */ /* $NetBSD: cd9660.h,v 1.21 2015/12/24 15:52:37 christos Exp $ */
/* /*
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
@ -308,7 +308,7 @@ typedef struct _iso9660_disk {
/************ FUNCTIONS **************/ /************ FUNCTIONS **************/
int cd9660_valid_a_chars(const char *); int cd9660_valid_a_chars(const char *);
int cd9660_valid_d_chars(const char *); int cd9660_valid_d_chars(const char *);
void cd9660_uppercase_characters(char *, int); void cd9660_uppercase_characters(char *, size_t);
/* ISO Data Types */ /* ISO Data Types */
void cd9660_721(uint16_t, unsigned char *); void cd9660_721(uint16_t, unsigned char *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: cd9660_conversion.c,v 1.4 2007/03/14 14:11:17 christos Exp $ */ /* $NetBSD: cd9660_conversion.c,v 1.5 2017/02/08 21:33:12 christos Exp $ */
/* /*
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
@ -35,7 +35,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if defined(__RCSID) && !defined(__lint) #if defined(__RCSID) && !defined(__lint)
__RCSID("$NetBSD: cd9660_conversion.c,v 1.4 2007/03/14 14:11:17 christos Exp $"); __RCSID("$NetBSD: cd9660_conversion.c,v 1.5 2017/02/08 21:33:12 christos Exp $");
#endif /* !__lint */ #endif /* !__lint */
@ -150,6 +150,9 @@ cd9660_pad_string_spaces(char *str, int len)
static char static char
cd9660_compute_gm_offset(time_t tim) cd9660_compute_gm_offset(time_t tim)
{ {
if (stampst.st_ino)
return 0;
struct tm t, gm; struct tm t, gm;
(void)localtime_r(&tim, &t); (void)localtime_r(&tim, &t);
@ -173,7 +176,10 @@ cd9660_time_8426(unsigned char *buf, time_t tim)
struct tm t; struct tm t;
char temp[18]; char temp[18];
(void)localtime_r(&tim, &t); if (stampst.st_ino)
(void)gmtime_r(&tim, &t);
else
(void)localtime_r(&tim, &t);
(void)snprintf(temp, sizeof(temp), "%04i%02i%02i%02i%02i%02i%02i", (void)snprintf(temp, sizeof(temp), "%04i%02i%02i%02i%02i%02i%02i",
1900+(int)t.tm_year, 1900+(int)t.tm_year,
(int)t.tm_mon+1, (int)t.tm_mon+1,
@ -192,7 +198,10 @@ cd9660_time_915(unsigned char *buf, time_t tim)
{ {
struct tm t; struct tm t;
(void)localtime_r(&tim, &t); if (stampst.st_ino)
(void)gmtime_r(&tim, &t);
else
(void)localtime_r(&tim, &t);
buf[0] = t.tm_year; buf[0] = t.tm_year;
buf[1] = t.tm_mon+1; buf[1] = t.tm_mon+1;
buf[2] = t.tm_mday; buf[2] = t.tm_mday;

View File

@ -1,4 +1,4 @@
/* $NetBSD: cd9660_eltorito.c,v 1.20 2013/01/28 21:03:28 christos Exp $ */ /* $NetBSD: cd9660_eltorito.c,v 1.24 2020/11/15 00:18:48 jmcneill Exp $ */
/* /*
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
@ -40,7 +40,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if defined(__RCSID) && !defined(__lint) #if defined(__RCSID) && !defined(__lint)
__RCSID("$NetBSD: cd9660_eltorito.c,v 1.20 2013/01/28 21:03:28 christos Exp $"); __RCSID("$NetBSD: cd9660_eltorito.c,v 1.24 2020/11/15 00:18:48 jmcneill Exp $");
#endif /* !__lint */ #endif /* !__lint */
#ifdef DEBUG #ifdef DEBUG
@ -56,11 +56,12 @@ static struct boot_catalog_entry *cd9660_boot_setup_validation_entry(char);
static struct boot_catalog_entry *cd9660_boot_setup_default_entry( static struct boot_catalog_entry *cd9660_boot_setup_default_entry(
struct cd9660_boot_image *); struct cd9660_boot_image *);
static struct boot_catalog_entry *cd9660_boot_setup_section_head(char); static struct boot_catalog_entry *cd9660_boot_setup_section_head(char);
static struct boot_catalog_entry *cd9660_boot_setup_validation_entry(char);
#if 0 #if 0
static u_char cd9660_boot_get_system_type(struct cd9660_boot_image *); static u_char cd9660_boot_get_system_type(struct cd9660_boot_image *);
#endif #endif
static struct cd9660_boot_image *default_boot_image;
int int
cd9660_add_boot_disk(iso9660_disk *diskStructure, const char *boot_info) cd9660_add_boot_disk(iso9660_disk *diskStructure, const char *boot_info)
{ {
@ -108,9 +109,11 @@ cd9660_add_boot_disk(iso9660_disk *diskStructure, const char *boot_info)
else if (strcmp(sysname, "macppc") == 0 || else if (strcmp(sysname, "macppc") == 0 ||
strcmp(sysname, "mac68k") == 0) strcmp(sysname, "mac68k") == 0)
new_image->system = ET_SYS_MAC; new_image->system = ET_SYS_MAC;
else if (strcmp(sysname, "efi") == 0)
new_image->system = ET_SYS_EFI;
else { else {
warnx("boot disk system must be " warnx("boot disk system must be "
"i386, powerpc, macppc, or mac68k"); "i386, powerpc, macppc, mac68k, or efi");
free(temp); free(temp);
free(new_image); free(new_image);
return 0; return 0;
@ -175,9 +178,15 @@ cd9660_add_boot_disk(iso9660_disk *diskStructure, const char *boot_info)
new_image->serialno = diskStructure->image_serialno++; new_image->serialno = diskStructure->image_serialno++;
new_image->platform_id = new_image->system;
/* TODO : Need to do anything about the boot image in the tree? */ /* TODO : Need to do anything about the boot image in the tree? */
diskStructure->is_bootable = 1; diskStructure->is_bootable = 1;
/* First boot image is initial/default entry. */
if (default_boot_image == NULL)
default_boot_image = new_image;
return 1; return 1;
} }
@ -211,6 +220,13 @@ cd9660_eltorito_add_boot_option(iso9660_disk *diskStructure,
warn("%s: strtoul", __func__); warn("%s: strtoul", __func__);
return 0; return 0;
} }
} else if (strcmp(option_string, "platformid") == 0) {
if (strcmp(value, "efi") == 0)
image->platform_id = ET_SYS_EFI;
else {
warn("%s: unknown platform: %s", __func__, value);
return 0;
}
} else { } else {
return 0; return 0;
} }
@ -233,6 +249,7 @@ cd9660_boot_setup_validation_entry(char sys)
size_t i; size_t i;
entry = cd9660_init_boot_catalog_entry(); entry = cd9660_init_boot_catalog_entry();
entry->entry_type = ET_ENTRY_VE;
ve = &entry->entry_data.VE; ve = &entry->entry_data.VE;
ve->header_id[0] = 1; ve->header_id[0] = 1;
@ -267,6 +284,7 @@ cd9660_boot_setup_default_entry(struct cd9660_boot_image *disk)
if (default_entry == NULL) if (default_entry == NULL)
return NULL; return NULL;
default_entry->entry_type = ET_ENTRY_IE;
ie = &default_entry->entry_data.IE; ie = &default_entry->entry_data.IE;
ie->boot_indicator[0] = disk->bootable; ie->boot_indicator[0] = disk->bootable;
@ -294,6 +312,7 @@ cd9660_boot_setup_section_head(char platform)
if (entry == NULL) if (entry == NULL)
return NULL; return NULL;
entry->entry_type = ET_ENTRY_SH;
sh = &entry->entry_data.SH; sh = &entry->entry_data.SH;
/* More by default. The last one will manually be set to 0x91 */ /* More by default. The last one will manually be set to 0x91 */
sh->header_indicator[0] = ET_SECTION_HEADER_MORE; sh->header_indicator[0] = ET_SECTION_HEADER_MORE;
@ -310,6 +329,7 @@ cd9660_boot_setup_section_entry(struct cd9660_boot_image *disk)
if ((entry = cd9660_init_boot_catalog_entry()) == NULL) if ((entry = cd9660_init_boot_catalog_entry()) == NULL)
return NULL; return NULL;
entry->entry_type = ET_ENTRY_SE;
se = &entry->entry_data.SE; se = &entry->entry_data.SE;
se->boot_indicator[0] = ET_BOOTABLE; se->boot_indicator[0] = ET_BOOTABLE;
@ -342,12 +362,13 @@ cd9660_setup_boot(iso9660_disk *diskStructure, int first_sector)
int used_sectors; int used_sectors;
int num_entries = 0; int num_entries = 0;
int catalog_sectors; int catalog_sectors;
struct boot_catalog_entry *x86_head, *mac_head, *ppc_head, struct boot_catalog_entry *x86_head, *mac_head, *ppc_head, *efi_head,
*valid_entry, *default_entry, *temp, *head, **headp, *next; *valid_entry, *default_entry, *temp, *head, **headp, *next;
struct cd9660_boot_image *tmp_disk; struct cd9660_boot_image *tmp_disk;
u_char system;
headp = NULL; headp = NULL;
x86_head = mac_head = ppc_head = NULL; x86_head = mac_head = ppc_head = efi_head = NULL;
/* If there are no boot disks, don't bother building boot information */ /* If there are no boot disks, don't bother building boot information */
if (TAILQ_EMPTY(&diskStructure->boot_images)) if (TAILQ_EMPTY(&diskStructure->boot_images))
@ -359,9 +380,16 @@ cd9660_setup_boot(iso9660_disk *diskStructure, int first_sector)
cd9660_bothendian_dword(first_sector, cd9660_bothendian_dword(first_sector,
diskStructure->boot_descriptor->boot_catalog_pointer); diskStructure->boot_descriptor->boot_catalog_pointer);
/*
* Use system type of default image for validation entry. Fallback to
* X86 system type if not found.
*/
system = default_boot_image != NULL ? default_boot_image->system :
ET_SYS_X86;
/* Step 1: Generate boot catalog */ /* Step 1: Generate boot catalog */
/* Step 1a: Validation entry */ /* Step 1a: Validation entry */
valid_entry = cd9660_boot_setup_validation_entry(ET_SYS_X86); valid_entry = cd9660_boot_setup_validation_entry(system);
if (valid_entry == NULL) if (valid_entry == NULL)
return -1; return -1;
@ -391,14 +419,25 @@ cd9660_setup_boot(iso9660_disk *diskStructure, int first_sector)
sector = first_sector + catalog_sectors; sector = first_sector + catalog_sectors;
TAILQ_FOREACH(tmp_disk, &diskStructure->boot_images, image_list) { TAILQ_FOREACH(tmp_disk, &diskStructure->boot_images, image_list) {
tmp_disk->sector = sector; tmp_disk->sector = sector;
sector += tmp_disk->num_sectors; sector += tmp_disk->num_sectors /
(diskStructure->sectorSize / 512);
} }
LIST_INSERT_HEAD(&diskStructure->boot_entries, valid_entry, ll_struct); LIST_INSERT_HEAD(&diskStructure->boot_entries, valid_entry, ll_struct);
/* Step 1b: Initial/default entry */ /* Step 1b: Initial/default entry */
/* TODO : PARAM */ /* TODO : PARAM */
tmp_disk = TAILQ_FIRST(&diskStructure->boot_images); if (default_boot_image != NULL) {
struct cd9660_boot_image *tcbi;
TAILQ_FOREACH(tcbi, &diskStructure->boot_images, image_list) {
if (tcbi == default_boot_image) {
tmp_disk = tcbi;
break;
}
}
}
if (tmp_disk == NULL)
tmp_disk = TAILQ_FIRST(&diskStructure->boot_images);
default_entry = cd9660_boot_setup_default_entry(tmp_disk); default_entry = cd9660_boot_setup_default_entry(tmp_disk);
if (default_entry == NULL) { if (default_entry == NULL) {
warnx("Error: memory allocation failed in cd9660_setup_boot"); warnx("Error: memory allocation failed in cd9660_setup_boot");
@ -409,14 +448,18 @@ cd9660_setup_boot(iso9660_disk *diskStructure, int first_sector)
/* Todo: multiple default entries? */ /* Todo: multiple default entries? */
tmp_disk = TAILQ_NEXT(tmp_disk, image_list); tmp_disk = TAILQ_FIRST(&diskStructure->boot_images);
head = NULL;
temp = default_entry; temp = default_entry;
/* If multiple boot images are given : */ /* If multiple boot images are given : */
while (tmp_disk != NULL) { for (; tmp_disk != NULL; tmp_disk = TAILQ_NEXT(tmp_disk, image_list)) {
if (tmp_disk == default_boot_image)
continue;
/* Step 2: Section header */ /* Step 2: Section header */
switch (tmp_disk->system) { switch (tmp_disk->platform_id) {
case ET_SYS_X86: case ET_SYS_X86:
headp = &x86_head; headp = &x86_head;
break; break;
@ -426,6 +469,9 @@ cd9660_setup_boot(iso9660_disk *diskStructure, int first_sector)
case ET_SYS_MAC: case ET_SYS_MAC:
headp = &mac_head; headp = &mac_head;
break; break;
case ET_SYS_EFI:
headp = &efi_head;
break;
default: default:
warnx("%s: internal error: unknown system type", warnx("%s: internal error: unknown system type",
__func__); __func__);
@ -434,7 +480,7 @@ cd9660_setup_boot(iso9660_disk *diskStructure, int first_sector)
if (*headp == NULL) { if (*headp == NULL) {
head = head =
cd9660_boot_setup_section_head(tmp_disk->system); cd9660_boot_setup_section_head(tmp_disk->platform_id);
if (head == NULL) { if (head == NULL) {
warnx("Error: memory allocation failed in " warnx("Error: memory allocation failed in "
"cd9660_setup_boot"); "cd9660_setup_boot");
@ -459,9 +505,17 @@ cd9660_setup_boot(iso9660_disk *diskStructure, int first_sector)
head = next; head = next;
LIST_INSERT_AFTER(head, temp, ll_struct); LIST_INSERT_AFTER(head, temp, ll_struct);
tmp_disk = TAILQ_NEXT(tmp_disk, image_list);
} }
/* Find the last Section Header entry and mark it as the last. */
head = NULL;
LIST_FOREACH(next, &diskStructure->boot_entries, ll_struct) {
if (next->entry_type == ET_ENTRY_SH)
head = next;
}
if (head != NULL)
head->entry_data.SH.header_indicator[0] = ET_SECTION_HEADER_LAST;
/* TODO: Remaining boot disks when implemented */ /* TODO: Remaining boot disks when implemented */
return first_sector + used_sectors; return first_sector + used_sectors;

View File

@ -1,4 +1,4 @@
/* $NetBSD: cd9660_eltorito.h,v 1.5 2009/07/04 14:31:38 ahoka Exp $ */ /* $NetBSD: cd9660_eltorito.h,v 1.6 2017/01/24 11:22:43 nonaka Exp $ */
/* /*
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
@ -40,6 +40,7 @@
#define ET_SYS_X86 0 #define ET_SYS_X86 0
#define ET_SYS_PPC 1 #define ET_SYS_PPC 1
#define ET_SYS_MAC 2 #define ET_SYS_MAC 2
#define ET_SYS_EFI 0xef /* Platform ID at section header entry */
#define ET_BOOT_ENTRY_SIZE 0x20 #define ET_BOOT_ENTRY_SIZE 0x20
@ -145,6 +146,7 @@ struct cd9660_boot_image {
u_char targetMode; u_char targetMode;
u_char system; u_char system;
u_char bootable; u_char bootable;
u_char platform_id; /* for section header entry */
/* /*
* If the boot image exists in the filesystem * If the boot image exists in the filesystem
* already, this is a pointer to that node. For the sake * already, this is a pointer to that node. For the sake

View File

@ -1,4 +1,4 @@
/* $NetBSD: cd9660_strings.c,v 1.5 2011/03/23 13:11:51 christos Exp $ */ /* $NetBSD: cd9660_strings.c,v 1.6 2015/12/24 15:52:37 christos Exp $ */
/* /*
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
@ -46,14 +46,14 @@
#include "cd9660.h" #include "cd9660.h"
#if defined(__RCSID) && !defined(__lint) #if defined(__RCSID) && !defined(__lint)
__RCSID("$NetBSD: cd9660_strings.c,v 1.5 2011/03/23 13:11:51 christos Exp $"); __RCSID("$NetBSD: cd9660_strings.c,v 1.6 2015/12/24 15:52:37 christos Exp $");
#endif /* !__lint */ #endif /* !__lint */
void void
cd9660_uppercase_characters(char *str, int len) cd9660_uppercase_characters(char *str, size_t len)
{ {
int p; size_t p;
for (p = 0; p < len; p++) { for (p = 0; p < len; p++) {
if (islower((unsigned char)str[p]) ) if (islower((unsigned char)str[p]) )

View File

@ -43,10 +43,7 @@
#include <string.h> #include <string.h>
#include <zlib.h> #include <zlib.h>
#include <util.h> #include <util.h>
#if defined(__minix)
#include <unistd.h> #include <unistd.h>
#endif
#include "makefs.h" #include "makefs.h"
#include "chfs_makefs.h" #include "chfs_makefs.h"
@ -128,7 +125,6 @@ write_eb_header(fsinfo_t *fsopts)
if ((uint32_t)opts->pagesize < MINSIZE) if ((uint32_t)opts->pagesize < MINSIZE)
errx(EXIT_FAILURE, "pagesize cannot be less than %zu", MINSIZE); errx(EXIT_FAILURE, "pagesize cannot be less than %zu", MINSIZE);
buf = emalloc(opts->pagesize); buf = emalloc(opts->pagesize);
memset(buf, 0xFF, opts->pagesize);
ebhdr.ec_hdr.magic = htole32(CHFS_MAGIC_BITMASK); ebhdr.ec_hdr.magic = htole32(CHFS_MAGIC_BITMASK);
ebhdr.ec_hdr.erase_cnt = htole32(1); ebhdr.ec_hdr.erase_cnt = htole32(1);
@ -136,6 +132,8 @@ write_eb_header(fsinfo_t *fsopts)
(uint8_t *)&ebhdr.ec_hdr + 8, 4)); (uint8_t *)&ebhdr.ec_hdr + 8, 4));
memcpy(buf, &ebhdr.ec_hdr, CHFS_EB_EC_HDR_SIZE); memcpy(buf, &ebhdr.ec_hdr, CHFS_EB_EC_HDR_SIZE);
memset(buf + CHFS_EB_EC_HDR_SIZE, 0xFF,
opts->pagesize - CHFS_EB_EC_HDR_SIZE);
buf_write(fsopts, buf, opts->pagesize); buf_write(fsopts, buf, opts->pagesize);

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs.c,v 1.64 2015/01/12 19:50:25 christos Exp $ */ /* $NetBSD: ffs.c,v 1.70 2017/12/16 23:08:40 christos Exp $ */
/* /*
* Copyright (c) 2001 Wasabi Systems, Inc. * Copyright (c) 2001 Wasabi Systems, Inc.
@ -71,7 +71,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if defined(__RCSID) && !defined(__lint) #if defined(__RCSID) && !defined(__lint)
__RCSID("$NetBSD: ffs.c,v 1.64 2015/01/12 19:50:25 christos Exp $"); __RCSID("$NetBSD: ffs.c,v 1.70 2017/12/16 23:08:40 christos Exp $");
#endif /* !__lint */ #endif /* !__lint */
#include <sys/param.h> #include <sys/param.h>
@ -466,6 +466,7 @@ ffs_create_image(const char *image, fsinfo_t *fsopts)
char *buf; char *buf;
int i, bufsize; int i, bufsize;
off_t bufrem; off_t bufrem;
time_t tstamp;
int oflags = O_RDWR | O_CREAT; int oflags = O_RDWR | O_CREAT;
assert (image != NULL); assert (image != NULL);
@ -530,7 +531,15 @@ ffs_create_image(const char *image, fsinfo_t *fsopts)
/* make the file system */ /* make the file system */
if (debug & DEBUG_FS_CREATE_IMAGE) if (debug & DEBUG_FS_CREATE_IMAGE)
printf("calling mkfs(\"%s\", ...)\n", image); printf("calling mkfs(\"%s\", ...)\n", image);
fs = ffs_mkfs(image, fsopts);
if (stampst.st_ino)
tstamp = stampst.st_ctime;
else
tstamp = start_time.tv_sec;
srandom(tstamp);
fs = ffs_mkfs(image, fsopts, tstamp);
fsopts->superblock = (void *)fs; fsopts->superblock = (void *)fs;
if (debug & DEBUG_FS_CREATE_IMAGE) { if (debug & DEBUG_FS_CREATE_IMAGE) {
time_t t; time_t t;
@ -637,19 +646,12 @@ ffs_build_dinode1(struct ufs1_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
{ {
size_t slen; size_t slen;
void *membuf; void *membuf;
struct stat *st = stampst.st_ino ? &stampst : &cur->inode->st;
memset(dinp, 0, sizeof(*dinp)); memset(dinp, 0, sizeof(*dinp));
dinp->di_mode = cur->inode->st.st_mode; dinp->di_mode = cur->inode->st.st_mode;
dinp->di_nlink = cur->inode->nlink; dinp->di_nlink = cur->inode->nlink;
dinp->di_size = cur->inode->st.st_size; dinp->di_size = cur->inode->st.st_size;
dinp->di_atime = cur->inode->st.st_atime;
dinp->di_mtime = cur->inode->st.st_mtime;
dinp->di_ctime = cur->inode->st.st_ctime;
#if HAVE_STRUCT_STAT_ST_MTIMENSEC
dinp->di_atimensec = cur->inode->st.st_atimensec;
dinp->di_mtimensec = cur->inode->st.st_mtimensec;
dinp->di_ctimensec = cur->inode->st.st_ctimensec;
#endif
#if HAVE_STRUCT_STAT_ST_FLAGS #if HAVE_STRUCT_STAT_ST_FLAGS
dinp->di_flags = cur->inode->st.st_flags; dinp->di_flags = cur->inode->st.st_flags;
#endif #endif
@ -658,6 +660,15 @@ ffs_build_dinode1(struct ufs1_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
#endif #endif
dinp->di_uid = cur->inode->st.st_uid; dinp->di_uid = cur->inode->st.st_uid;
dinp->di_gid = cur->inode->st.st_gid; dinp->di_gid = cur->inode->st.st_gid;
dinp->di_atime = st->st_atime;
dinp->di_mtime = st->st_mtime;
dinp->di_ctime = st->st_ctime;
#if HAVE_STRUCT_STAT_ST_MTIMENSEC
dinp->di_atimensec = st->st_atimensec;
dinp->di_mtimensec = st->st_mtimensec;
dinp->di_ctimensec = st->st_ctimensec;
#endif
/* not set: di_db, di_ib, di_blocks, di_spare */ /* not set: di_db, di_ib, di_blocks, di_spare */
membuf = NULL; membuf = NULL;
@ -685,31 +696,33 @@ ffs_build_dinode2(struct ufs2_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
{ {
size_t slen; size_t slen;
void *membuf; void *membuf;
struct stat *st = stampst.st_ino ? &stampst : &cur->inode->st;
memset(dinp, 0, sizeof(*dinp)); memset(dinp, 0, sizeof(*dinp));
dinp->di_mode = cur->inode->st.st_mode; dinp->di_mode = cur->inode->st.st_mode;
dinp->di_nlink = cur->inode->nlink; dinp->di_nlink = cur->inode->nlink;
dinp->di_size = cur->inode->st.st_size; dinp->di_size = cur->inode->st.st_size;
dinp->di_atime = cur->inode->st.st_atime;
dinp->di_mtime = cur->inode->st.st_mtime;
dinp->di_ctime = cur->inode->st.st_ctime;
#if HAVE_STRUCT_STAT_ST_MTIMENSEC
dinp->di_atimensec = cur->inode->st.st_atimensec;
dinp->di_mtimensec = cur->inode->st.st_mtimensec;
dinp->di_ctimensec = cur->inode->st.st_ctimensec;
#endif
#if HAVE_STRUCT_STAT_ST_FLAGS #if HAVE_STRUCT_STAT_ST_FLAGS
dinp->di_flags = cur->inode->st.st_flags; dinp->di_flags = cur->inode->st.st_flags;
#endif #endif
#if HAVE_STRUCT_STAT_ST_GEN #if HAVE_STRUCT_STAT_ST_GEN
dinp->di_gen = cur->inode->st.st_gen; dinp->di_gen = cur->inode->st.st_gen;
#endif
#if HAVE_STRUCT_STAT_BIRTHTIME
dinp->di_birthtime = cur->inode->st.st_birthtime;
dinp->di_birthnsec = cur->inode->st.st_birthtimensec;
#endif #endif
dinp->di_uid = cur->inode->st.st_uid; dinp->di_uid = cur->inode->st.st_uid;
dinp->di_gid = cur->inode->st.st_gid; dinp->di_gid = cur->inode->st.st_gid;
dinp->di_atime = st->st_atime;
dinp->di_mtime = st->st_mtime;
dinp->di_ctime = st->st_ctime;
#if HAVE_STRUCT_STAT_ST_MTIMENSEC
dinp->di_atimensec = st->st_atimensec;
dinp->di_mtimensec = st->st_mtimensec;
dinp->di_ctimensec = st->st_ctimensec;
#endif
#if HAVE_STRUCT_STAT_BIRTHTIME
dinp->di_birthtime = st->st_birthtime;
dinp->di_birthnsec = st->st_birthtimensec;
#endif
/* not set: di_db, di_ib, di_blocks, di_spare */ /* not set: di_db, di_ib, di_blocks, di_spare */
membuf = NULL; membuf = NULL;
@ -1102,12 +1115,11 @@ ffs_write_inode(union dinode *dp, uint32_t ino, const fsinfo_t *fsopts)
* Initialize inode blocks on the fly for UFS2. * Initialize inode blocks on the fly for UFS2.
*/ */
initediblk = ufs_rw32(cgp->cg_initediblk, fsopts->needswap); initediblk = ufs_rw32(cgp->cg_initediblk, fsopts->needswap);
if (ffs_opts->version == 2 && while (ffs_opts->version == 2 &&
(uint32_t)(cgino + FFS_INOPB(fs)) > initediblk && (uint32_t)(cgino + FFS_INOPB(fs)) > initediblk &&
initediblk < ufs_rw32(cgp->cg_niblk, fsopts->needswap)) { initediblk < ufs_rw32(cgp->cg_niblk, fsopts->needswap)) {
memset(buf, 0, fs->fs_bsize); memset(buf, 0, fs->fs_bsize);
dip = (struct ufs2_dinode *)buf; dip = (struct ufs2_dinode *)buf;
srandom(time(NULL));
for (i = 0; i < FFS_INOPB(fs); i++) { for (i = 0; i < FFS_INOPB(fs); i++) {
dip->di_gen = random() / 2 + 1; dip->di_gen = random() / 2 + 1;
dip++; dip++;

View File

@ -1,4 +1,4 @@
/* $NetBSD: buf.c,v 1.22 2015/03/29 05:52:59 agc Exp $ */ /* $NetBSD: buf.c,v 1.24 2016/06/24 19:24:11 christos Exp $ */
/* /*
* Copyright (c) 2001 Wasabi Systems, Inc. * Copyright (c) 2001 Wasabi Systems, Inc.
@ -41,7 +41,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if defined(__RCSID) && !defined(__lint) #if defined(__RCSID) && !defined(__lint)
__RCSID("$NetBSD: buf.c,v 1.22 2015/03/29 05:52:59 agc Exp $"); __RCSID("$NetBSD: buf.c,v 1.24 2016/06/24 19:24:11 christos Exp $");
#endif /* !__lint */ #endif /* !__lint */
#include <sys/param.h> #include <sys/param.h>
@ -78,17 +78,17 @@ bread(struct vnode *vp, daddr_t blkno, int size, int u2 __unused,
(long long)(*bpp)->b_blkno, (long long) offset, (long long)(*bpp)->b_blkno, (long long) offset,
(*bpp)->b_bcount); (*bpp)->b_bcount);
if (lseek((*bpp)->b_fs->fd, offset, SEEK_SET) == -1) if (lseek((*bpp)->b_fs->fd, offset, SEEK_SET) == -1)
err(1, "%s: lseek %lld (%lld)", __func__, err(EXIT_FAILURE, "%s: lseek %lld (%lld)", __func__,
(long long)(*bpp)->b_blkno, (long long)offset); (long long)(*bpp)->b_blkno, (long long)offset);
rv = read((*bpp)->b_fs->fd, (*bpp)->b_data, (*bpp)->b_bcount); rv = read((*bpp)->b_fs->fd, (*bpp)->b_data, (size_t)(*bpp)->b_bcount);
if (debug & DEBUG_BUF_BREAD) if (debug & DEBUG_BUF_BREAD)
printf("bread: read %ld (%lld) returned %zd\n", printf("bread: read %ld (%lld) returned %zd\n",
(*bpp)->b_bcount, (long long)offset, rv); (*bpp)->b_bcount, (long long)offset, rv);
if (rv == -1) /* read error */ if (rv == -1) /* read error */
err(1, "%s: read %ld (%lld) returned %zd", __func__, err(EXIT_FAILURE, "%s: read %ld (%lld) returned %zd", __func__,
(*bpp)->b_bcount, (long long)offset, rv); (*bpp)->b_bcount, (long long)offset, rv);
else if (rv != (*bpp)->b_bcount) /* short read */ else if (rv != (*bpp)->b_bcount) /* short read */
err(1, "%s: read %ld (%lld) returned %zd", __func__, errx(EXIT_FAILURE, "%s: read %ld (%lld) returned %zd", __func__,
(*bpp)->b_bcount, (long long)offset, rv); (*bpp)->b_bcount, (long long)offset, rv);
else else
return (0); return (0);
@ -129,14 +129,14 @@ bwrite(struct buf *bp)
{ {
off_t offset; off_t offset;
ssize_t rv; ssize_t rv;
int bytes; size_t bytes;
fsinfo_t *fs = bp->b_fs; fsinfo_t *fs = bp->b_fs;
assert (bp != NULL); assert (bp != NULL);
offset = bp->b_blkno * fs->sectorsize + fs->offset; offset = bp->b_blkno * fs->sectorsize + fs->offset;
bytes = bp->b_bcount; bytes = (size_t)bp->b_bcount;
if (debug & DEBUG_BUF_BWRITE) if (debug & DEBUG_BUF_BWRITE)
printf("bwrite: blkno %lld offset %lld bcount %d\n", printf("bwrite: blkno %lld offset %lld bcount %zu\n",
(long long)bp->b_blkno, (long long) offset, bytes); (long long)bp->b_blkno, (long long) offset, bytes);
if (lseek(bp->b_fs->fd, offset, SEEK_SET) == -1) if (lseek(bp->b_fs->fd, offset, SEEK_SET) == -1)
return (errno); return (errno);
@ -145,7 +145,7 @@ bwrite(struct buf *bp)
printf("bwrite: write %ld (offset %lld) returned %lld\n", printf("bwrite: write %ld (offset %lld) returned %lld\n",
bp->b_bcount, (long long)offset, (long long)rv); bp->b_bcount, (long long)offset, (long long)rv);
brelse(bp, 0); brelse(bp, 0);
if (rv == bytes) if (rv == (ssize_t)bytes)
return (0); return (0);
else if (rv == -1) /* write error */ else if (rv == -1) /* write error */
return (errno); return (errno);
@ -210,8 +210,8 @@ getblk(struct vnode *vp, daddr_t blkno, int size, int u1 __unused,
} }
bp->b_bcount = size; bp->b_bcount = size;
if (bp->b_data == NULL || bp->b_bcount > bp->b_bufsize) { if (bp->b_data == NULL || bp->b_bcount > bp->b_bufsize) {
n = erealloc(bp->b_data, size); n = erealloc(bp->b_data, (size_t)size);
memset(n, 0, size); memset(n, 0, (size_t)size);
bp->b_data = n; bp->b_data = n;
bp->b_bufsize = size; bp->b_bufsize = size;
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: buf.h,v 1.10 2015/03/29 05:52:59 agc Exp $ */ /* $NetBSD: buf.h,v 1.13 2018/09/03 16:29:37 riastradh Exp $ */
/* /*
* Copyright (c) 2001 Wasabi Systems, Inc. * Copyright (c) 2001 Wasabi Systems, Inc.
@ -40,6 +40,7 @@
#include <sys/param.h> #include <sys/param.h>
#include <sys/queue.h> #include <sys/queue.h>
#include <sys/stat.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -87,7 +88,34 @@ struct buf * getblk(struct vnode *, daddr_t, int, int, int);
#define BC_AGE 0 #define BC_AGE 0
#define min(a, b) MIN((a), (b)) #define min(a, b) MIN((a), (b))
#define microtime(tv) gettimeofday((tv), NULL)
static inline unsigned int
uimin(unsigned int a, unsigned int b)
{
return (a < b ? a : b);
}
static inline unsigned int
uimax(unsigned int a, unsigned int b)
{
return (a > b ? a : b);
}
static inline void
microtime(struct timeval *tv)
{
extern struct stat stampst;
if (stampst.st_ino) {
tv->tv_sec = stampst.st_mtime;
tv->tv_usec = 0;
} else {
gettimeofday((tv), NULL);
}
}
#define KASSERT(a) #define KASSERT(a)
#define IO_SYNC 1 #define IO_SYNC 1

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs_alloc.c,v 1.28 2015/03/29 05:52:59 agc Exp $ */ /* $NetBSD: ffs_alloc.c,v 1.29 2016/06/24 19:24:11 christos Exp $ */
/* From: NetBSD: ffs_alloc.c,v 1.50 2001/09/06 02:16:01 lukem Exp */ /* From: NetBSD: ffs_alloc.c,v 1.50 2001/09/06 02:16:01 lukem Exp */
/* /*
@ -47,7 +47,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if defined(__RCSID) && !defined(__lint) #if defined(__RCSID) && !defined(__lint)
__RCSID("$NetBSD: ffs_alloc.c,v 1.28 2015/03/29 05:52:59 agc Exp $"); __RCSID("$NetBSD: ffs_alloc.c,v 1.29 2016/06/24 19:24:11 christos Exp $");
#endif /* !__lint */ #endif /* !__lint */
#include <sys/param.h> #include <sys/param.h>
@ -107,7 +107,7 @@ ffs_alloc(struct inode *ip, daddr_t lbn __unused, daddr_t bpref, int size,
*bnp = 0; *bnp = 0;
if (size > fs->fs_bsize || ffs_fragoff(fs, size) != 0) { if (size > fs->fs_bsize || ffs_fragoff(fs, size) != 0) {
errx(1, "ffs_alloc: bad size: bsize %d size %d", errx(EXIT_FAILURE, "%s: bad size: bsize %d size %d", __func__,
fs->fs_bsize, size); fs->fs_bsize, size);
} }
if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0) if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0)
@ -441,8 +441,8 @@ ffs_blkfree(struct inode *ip, daddr_t bno, long size)
if (size > fs->fs_bsize || ffs_fragoff(fs, size) != 0 || if (size > fs->fs_bsize || ffs_fragoff(fs, size) != 0 ||
ffs_fragnum(fs, bno) + ffs_numfrags(fs, size) > fs->fs_frag) { ffs_fragnum(fs, bno) + ffs_numfrags(fs, size) > fs->fs_frag) {
errx(1, "blkfree: bad size: bno %lld bsize %d size %ld", errx(EXIT_FAILURE, "%s: bad size: bno %lld bsize %d "
(long long)bno, fs->fs_bsize, size); "size %ld", __func__, (long long)bno, fs->fs_bsize, size);
} }
cg = dtog(fs, bno); cg = dtog(fs, bno);
if (bno >= fs->fs_size) { if (bno >= fs->fs_size) {
@ -465,8 +465,8 @@ ffs_blkfree(struct inode *ip, daddr_t bno, long size)
if (size == fs->fs_bsize) { if (size == fs->fs_bsize) {
fragno = ffs_fragstoblks(fs, cgbno); fragno = ffs_fragstoblks(fs, cgbno);
if (!ffs_isfreeblock(fs, cg_blksfree(cgp, needswap), fragno)) { if (!ffs_isfreeblock(fs, cg_blksfree(cgp, needswap), fragno)) {
errx(1, "blkfree: freeing free block %lld", errx(EXIT_FAILURE, "%s: freeing free block %lld",
(long long)bno); __func__, (long long)bno);
} }
ffs_setblock(fs, cg_blksfree(cgp, needswap), fragno); ffs_setblock(fs, cg_blksfree(cgp, needswap), fragno);
ffs_clusteracct(fs, cgp, fragno, 1); ffs_clusteracct(fs, cgp, fragno, 1);
@ -486,7 +486,8 @@ ffs_blkfree(struct inode *ip, daddr_t bno, long size)
frags = ffs_numfrags(fs, size); frags = ffs_numfrags(fs, size);
for (i = 0; i < frags; i++) { for (i = 0; i < frags; i++) {
if (isset(cg_blksfree(cgp, needswap), cgbno + i)) { if (isset(cg_blksfree(cgp, needswap), cgbno + i)) {
errx(1, "blkfree: freeing free frag: block %lld", errx(EXIT_FAILURE, "%s: freeing free frag: "
"block %lld", __func__,
(long long)(cgbno + i)); (long long)(cgbno + i));
} }
setbit(cg_blksfree(cgp, needswap), cgbno + i); setbit(cg_blksfree(cgp, needswap), cgbno + i);
@ -566,11 +567,10 @@ ffs_mapsearch(struct fs *fs, struct cg *cgp, daddr_t bpref, int allocsiz)
(const u_char *)fragtbl[fs->fs_frag], (const u_char *)fragtbl[fs->fs_frag],
(1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); (1 << (allocsiz - 1 + (fs->fs_frag % NBBY))));
if (loc == 0) { if (loc == 0) {
errx(1, errx(EXIT_FAILURE, "%s: map corrupted: start %d "
"ffs_alloccg: map corrupted: start %d len %d offset %d %ld", "len %d offset %d %ld", __func__, ostart, olen,
ostart, olen, ufs_rw32(cgp->cg_freeoff, needswap),
ufs_rw32(cgp->cg_freeoff, needswap), (long)cg_blksfree(cgp, needswap) - (long)cgp);
(long)cg_blksfree(cgp, needswap) - (long)cgp);
/* NOTREACHED */ /* NOTREACHED */
} }
} }
@ -592,6 +592,7 @@ ffs_mapsearch(struct fs *fs, struct cg *cgp, daddr_t bpref, int allocsiz)
subfield <<= 1; subfield <<= 1;
} }
} }
errx(1, "ffs_alloccg: block not in map: bno %lld", (long long)bno); errx(EXIT_FAILURE, "%s: block not in map: bno %lld", __func__,
(long long)bno);
return (-1); return (-1);
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs_extern.h,v 1.6 2003/08/07 11:25:33 agc Exp $ */ /* $NetBSD: ffs_extern.h,v 1.7 2017/02/09 04:42:53 kre Exp $ */
/* From: NetBSD: ffs_extern.h,v 1.19 2001/08/17 02:18:48 lukem Exp */ /* From: NetBSD: ffs_extern.h,v 1.19 2001/08/17 02:18:48 lukem Exp */
/*- /*-
@ -59,7 +59,7 @@ void ffs_clusteracct(struct fs *, struct cg *, int32_t, int);
int ffs_balloc(struct inode *, off_t, int, struct buf **); int ffs_balloc(struct inode *, off_t, int, struct buf **);
/* ffs_bswap.c */ /* ffs_bswap.c */
void ffs_sb_swap(struct fs*, struct fs *); void ffs_sb_swap(const struct fs*, struct fs *);
void ffs_dinode1_swap(struct ufs1_dinode *, struct ufs1_dinode *); void ffs_dinode1_swap(struct ufs1_dinode *, struct ufs1_dinode *);
void ffs_dinode2_swap(struct ufs2_dinode *, struct ufs2_dinode *); void ffs_dinode2_swap(struct ufs2_dinode *, struct ufs2_dinode *);
void ffs_csum_swap(struct csum *, struct csum *, int); void ffs_csum_swap(struct csum *, struct csum *, int);

View File

@ -1,4 +1,4 @@
/* $NetBSD: mkfs.c,v 1.32 2013/10/19 17:16:37 christos Exp $ */ /* $NetBSD: mkfs.c,v 1.39 2020/03/26 04:25:28 kre Exp $ */
/* /*
* Copyright (c) 2002 Networks Associates Technology, Inc. * Copyright (c) 2002 Networks Associates Technology, Inc.
@ -48,7 +48,7 @@
static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95"; static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95";
#else #else
#ifdef __RCSID #ifdef __RCSID
__RCSID("$NetBSD: mkfs.c,v 1.32 2013/10/19 17:16:37 christos Exp $"); __RCSID("$NetBSD: mkfs.c,v 1.39 2020/03/26 04:25:28 kre Exp $");
#endif #endif
#endif #endif
#endif /* not lint */ #endif /* not lint */
@ -102,7 +102,11 @@ union {
char *iobuf; char *iobuf;
int iobufsize; int iobufsize;
char writebuf[FFS_MAXBSIZE]; union {
struct fs fs;
char pad[FFS_MAXBSIZE];
} wb;
#define writebuf wb.pad
static int Oflag; /* format as an 4.3BSD file system */ static int Oflag; /* format as an 4.3BSD file system */
static int64_t fssize; /* file system size */ static int64_t fssize; /* file system size */
@ -121,8 +125,19 @@ static int sbsize; /* superblock size */
static int avgfilesize; /* expected average file size */ static int avgfilesize; /* expected average file size */
static int avgfpdir; /* expected number of files per directory */ static int avgfpdir; /* expected number of files per directory */
static void
ffs_sb_copy(struct fs *o, const struct fs *i, size_t l, const fsinfo_t *fsopts)
{
memcpy(o, i, l);
/* Zero out pointers */
o->fs_csp = NULL;
o->fs_maxcluster = NULL;
if (fsopts->needswap)
ffs_sb_swap(i, o);
}
struct fs * struct fs *
ffs_mkfs(const char *fsys, const fsinfo_t *fsopts) ffs_mkfs(const char *fsys, const fsinfo_t *fsopts, time_t tstamp)
{ {
int fragsperinode, optimalfpg, origdensity, minfpg, lastminfpg; int fragsperinode, optimalfpg, origdensity, minfpg, lastminfpg;
int32_t cylno, i, csfrags; int32_t cylno, i, csfrags;
@ -445,7 +460,7 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts)
sblock.fs_state = 0; sblock.fs_state = 0;
sblock.fs_clean = FS_ISCLEAN; sblock.fs_clean = FS_ISCLEAN;
sblock.fs_ronly = 0; sblock.fs_ronly = 0;
sblock.fs_id[0] = start_time.tv_sec; sblock.fs_id[0] = tstamp;
sblock.fs_id[1] = random(); sblock.fs_id[1] = random();
sblock.fs_fsmnt[0] = '\0'; sblock.fs_fsmnt[0] = '\0';
csfrags = howmany(sblock.fs_cssize, sblock.fs_fsize); csfrags = howmany(sblock.fs_cssize, sblock.fs_fsize);
@ -461,9 +476,9 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts)
sblock.fs_cstotal.cs_nifree = sblock.fs_ncg * sblock.fs_ipg - UFS_ROOTINO; sblock.fs_cstotal.cs_nifree = sblock.fs_ncg * sblock.fs_ipg - UFS_ROOTINO;
sblock.fs_cstotal.cs_ndir = 0; sblock.fs_cstotal.cs_ndir = 0;
sblock.fs_dsize -= csfrags; sblock.fs_dsize -= csfrags;
sblock.fs_time = start_time.tv_sec; sblock.fs_time = tstamp;
if (Oflag <= 1) { if (Oflag <= 1) {
sblock.fs_old_time = start_time.tv_sec; sblock.fs_old_time = tstamp;
sblock.fs_old_dsize = sblock.fs_dsize; sblock.fs_old_dsize = sblock.fs_dsize;
sblock.fs_old_csaddr = sblock.fs_csaddr; sblock.fs_old_csaddr = sblock.fs_csaddr;
sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir; sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir;
@ -508,14 +523,12 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts)
* Make a copy of the superblock into the buffer that we will be * Make a copy of the superblock into the buffer that we will be
* writing out in each cylinder group. * writing out in each cylinder group.
*/ */
memcpy(writebuf, &sblock, sbsize); ffs_sb_copy(&wb.fs, &sblock, sbsize, fsopts);
if (fsopts->needswap)
ffs_sb_swap(&sblock, (struct fs*)writebuf);
memcpy(iobuf, writebuf, SBLOCKSIZE); memcpy(iobuf, writebuf, SBLOCKSIZE);
printf("super-block backups (for fsck -b #) at:"); printf("super-block backups (for fsck -b #) at:");
for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
initcg(cylno, start_time.tv_sec, fsopts); initcg(cylno, tstamp, fsopts);
if (cylno % nprintcols == 0) if (cylno % nprintcols == 0)
printf("\n"); printf("\n");
printf(" %*lld,", printcolwidth, printf(" %*lld,", printcolwidth,
@ -528,7 +541,7 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts)
* Now construct the initial file system, * Now construct the initial file system,
* then write out the super-block. * then write out the super-block.
*/ */
sblock.fs_time = start_time.tv_sec; sblock.fs_time = tstamp;
if (Oflag <= 1) { if (Oflag <= 1) {
sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir; sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir;
sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree; sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree;
@ -555,9 +568,7 @@ ffs_write_superblock(struct fs *fs, const fsinfo_t *fsopts)
saveflag = fs->fs_flags & FS_INTERNAL; saveflag = fs->fs_flags & FS_INTERNAL;
fs->fs_flags &= ~FS_INTERNAL; fs->fs_flags &= ~FS_INTERNAL;
memcpy(writebuf, &sblock, sbsize); ffs_sb_copy(&wb.fs, &sblock, sbsize, fsopts);
if (fsopts->needswap)
ffs_sb_swap(fs, (struct fs*)writebuf);
ffs_wtfs(fs->fs_sblockloc / sectorsize, sbsize, writebuf, fsopts); ffs_wtfs(fs->fs_sblockloc / sectorsize, sbsize, writebuf, fsopts);
/* Write out the duplicate super blocks */ /* Write out the duplicate super blocks */
@ -787,15 +798,15 @@ ffs_rdfs(daddr_t bno, int size, void *bf, const fsinfo_t *fsopts)
offset = bno * fsopts->sectorsize + fsopts->offset; offset = bno * fsopts->sectorsize + fsopts->offset;
if (lseek(fsopts->fd, offset, SEEK_SET) < 0) if (lseek(fsopts->fd, offset, SEEK_SET) < 0)
err(1, "%s: seek error for sector %lld", __func__, err(EXIT_FAILURE, "%s: seek error for sector %lld", __func__,
(long long)bno); (long long)bno);
n = read(fsopts->fd, bf, size); n = read(fsopts->fd, bf, size);
if (n == -1) { if (n == -1) {
err(1, "%s: read error bno %lld size %d", __func__, err(EXIT_FAILURE, "%s: read error bno %lld size %d", __func__,
(long long)bno, size); (long long)bno, size);
} }
else if (n != size) else if (n != size)
errx(1, "%s: short read error for sector %lld", __func__, errx(EXIT_FAILURE, "%s: short read error for sector %lld", __func__,
(long long)bno); (long long)bno);
} }
@ -810,15 +821,15 @@ ffs_wtfs(daddr_t bno, int size, void *bf, const fsinfo_t *fsopts)
offset = bno * fsopts->sectorsize + fsopts->offset; offset = bno * fsopts->sectorsize + fsopts->offset;
if (lseek(fsopts->fd, offset, SEEK_SET) == -1) if (lseek(fsopts->fd, offset, SEEK_SET) == -1)
err(1, "%s: seek error for sector %lld", __func__, err(EXIT_FAILURE, "%s: seek error @%jd for sector %jd",
(long long)bno); __func__, (intmax_t)offset, (intmax_t)bno);
n = write(fsopts->fd, bf, size); n = write(fsopts->fd, bf, size);
if (n == -1) if (n == -1)
err(1, "%s: write error for sector %lld", __func__, err(EXIT_FAILURE, "%s: write error for sector %jd", __func__,
(long long)bno); (intmax_t)bno);
else if (n != size) else if (n != size)
errx(1, "%s: short write error for sector %lld", __func__, errx(EXIT_FAILURE, "%s: short write error for sector %jd",
(long long)bno); __func__, (intmax_t)bno);
} }
@ -841,5 +852,5 @@ ilog2(int val)
for (n = 0; n < sizeof(n) * CHAR_BIT; n++) for (n = 0; n < sizeof(n) * CHAR_BIT; n++)
if (1 << n == val) if (1 << n == val)
return (n); return (n);
errx(1, "%s: %d is not a power of 2", __func__, val); errx(EXIT_FAILURE, "%s: %d is not a power of 2", __func__, val);
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: newfs_extern.h,v 1.3 2009/10/21 01:07:47 snj Exp $ */ /* $NetBSD: newfs_extern.h,v 1.4 2015/12/21 00:58:08 christos Exp $ */
/* From: NetBSD: extern.h,v 1.3 2000/12/01 12:03:27 simonb Exp $ */ /* From: NetBSD: extern.h,v 1.3 2000/12/01 12:03:27 simonb Exp $ */
/* /*
@ -26,7 +26,7 @@
*/ */
/* prototypes */ /* prototypes */
struct fs *ffs_mkfs(const char *, const fsinfo_t *); struct fs *ffs_mkfs(const char *, const fsinfo_t *, time_t);
void ffs_write_superblock(struct fs *, const fsinfo_t *); void ffs_write_superblock(struct fs *, const fsinfo_t *);
void ffs_rdfs(daddr_t, int, void *, const fsinfo_t *); void ffs_rdfs(daddr_t, int, void *, const fsinfo_t *);
void ffs_wtfs(daddr_t, int, void *, const fsinfo_t *); void ffs_wtfs(daddr_t, int, void *, const fsinfo_t *);

View File

@ -1,4 +1,4 @@
.\" $NetBSD: makefs.8,v 1.53 2013/08/06 20:16:54 wiz Exp $ .\" $NetBSD: makefs.8,v 1.66 2020/11/15 00:18:48 jmcneill Exp $
.\" .\"
.\" Copyright (c) 2001-2003 Wasabi Systems, Inc. .\" Copyright (c) 2001-2003 Wasabi Systems, Inc.
.\" All rights reserved. .\" All rights reserved.
@ -33,7 +33,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE. .\" POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.Dd August 6, 2013 .Dd November 14, 2020
.Dt MAKEFS 8 .Dt MAKEFS 8
.Os .Os
.Sh NAME .Sh NAME
@ -54,6 +54,7 @@
.Op Fl o Ar fs-options .Op Fl o Ar fs-options
.Op Fl S Ar sector-size .Op Fl S Ar sector-size
.Op Fl s Ar image-size .Op Fl s Ar image-size
.Op Fl T Ar timestamp
.Op Fl t Ar fs-type .Op Fl t Ar fs-type
.Ar image-file .Ar image-file
.Ar directory .Ar directory
@ -178,7 +179,7 @@ and
.Xr getgrnam 3 .Xr getgrnam 3
(and related) library calls. (and related) library calls.
.It Fl O Ar offset .It Fl O Ar offset
Instead of creating the filesystem at the beginning of the file, start Instead of creating the file system at the beginning of the file, start
at offset. at offset.
Valid only for Valid only for
.Sy ffs .Sy ffs
@ -199,24 +200,58 @@ Defaults to 512.
.It Fl s Ar image-size .It Fl s Ar image-size
Set the size of the file system image to Set the size of the file system image to
.Ar image-size . .Ar image-size .
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 file system files and directories
created so that repeatable builds are possible.
The
.Ar timestamp
can be a
.Pa pathname ,
where the timestamps are derived from that file, a parseable date
for
.Xr parsedate 3
(this option is not yet available in the tools build), or an integer
value interpreted as the number of seconds from the Epoch.
Note that timestamps specified in an
.Xr mtree 5
spec file, override the default timestamp.
When this option is enabled, file systems that regularly use
.Xr localtime 3
to convert times to the native format (such as udf and cd9660), use
.Xr gmtime 3
instead with the specified timestamps so that they are immune to
timezone changes and get consistent timestamps.
.It Fl t Ar fs-type .It Fl t Ar fs-type
Create an Create an
.Ar fs-type .Ar fs-type
file system image. file system image.
The following file system types are supported: The following file system types are supported:
.Bl -tag -width cd9660 -offset indent .Bl -tag -width cd9660 -offset indent
.It Sy ffs
BSD fast file system (default).
.It Sy cd9660 .It Sy cd9660
ISO 9660 file system. ISO 9660 file system.
.It Sy chfs .It Sy chfs
Chip flash file system. Chip flash file system.
.It Sy ffs
BSD fast file system (default).
.It Sy msdos .It Sy msdos
FAT12, FAT16, or FAT32 file system. FAT12, FAT16, or FAT32 file system.
.It Sy v7fs
7th Edition(V7) file system.
.It Sy udf .It Sy udf
ISO/Ecma UDF file system. ISO/Ecma UDF file system.
.It Sy v7fs
7th Edition(V7) file system.
.El .El
.It Fl x .It Fl x
Exclude file system nodes not explicitly listed in the specfile. Exclude file system nodes not explicitly listed in the specfile.
@ -228,7 +263,7 @@ This is useful for virtual machine images.
.Pp .Pp
Where sizes are specified, a decimal number of bytes is expected. Where sizes are specified, a decimal number of bytes is expected.
Two or more numbers may be separated by an Two or more numbers may be separated by an
.Dq x .Sq x
to indicate a product. to indicate a product.
Each number may have one of the following optional suffixes: Each number may have one of the following optional suffixes:
.Bl -tag -width 3n -offset indent -compact .Bl -tag -width 3n -offset indent -compact
@ -264,10 +299,14 @@ Expected number of files per directory.
Block size. Block size.
.It Sy density .It Sy density
Bytes per inode. Bytes per inode.
.It Sy extent
Maximum extent size.
.It Sy fsize .It Sy fsize
Fragment size. Fragment size.
.It Sy label .It Sy label
Label name of the image. Label name of the image.
.It Sy maxbpcg
Maximum total number of blocks in a cylinder group.
.It Sy maxbpg .It Sy maxbpg
Maximum blocks per file in a cylinder group. Maximum blocks per file in a cylinder group.
.It Sy minfree .It Sy minfree
@ -277,10 +316,6 @@ Optimization preference; one of
.Ql space .Ql space
or or
.Ql time . .Ql time .
.It Sy extent
Maximum extent size.
.It Sy maxbpcg
Maximum total number of blocks in a cylinder group.
.It Sy version .It Sy version
UFS version. UFS version.
1 for FFS (default), 2 for UFS2. 1 for FFS (default), 2 for UFS2.
@ -304,7 +339,7 @@ the spec.
.\" Unknown .\" Unknown
.It Sy allow-max-name .It Sy allow-max-name
Allow 37 instead of 33 characters for filenames by omitting the Allow 37 instead of 33 characters for filenames by omitting the
version id. version ID.
.It Sy allow-multidot .It Sy allow-multidot
Allow multiple dots in a filename. Allow multiple dots in a filename.
.It Sy applicationid .It Sy applicationid
@ -315,9 +350,6 @@ Use the
extension to encode extension to encode
.Tn RISC OS .Tn RISC OS
metadata. metadata.
.It Sy chrp-boot
Write an MBR partition table to the image to allow older CHRP hardware to
boot.
.It Sy boot-load-segment .It Sy boot-load-segment
Set load segment for the boot image. Set load segment for the boot image.
.It Sy bootimage .It Sy bootimage
@ -326,11 +358,15 @@ Filename of a boot image in the format
where where
.Dq sysid .Dq sysid
is one of is one of
.Ql efi ,
.Ql i386 , .Ql i386 ,
.Ql mac68k , .Ql mac68k ,
.Ql macppc , .Ql macppc ,
or or
.Ql powerpc . .Ql powerpc .
.It Sy chrp-boot
Write an MBR partition table to the image to allow older CHRP hardware to
boot.
.It Sy generic-bootimage .It Sy generic-bootimage
Load a generic boot image into the first 32K of the cd9660 image. Load a generic boot image into the first 32K of the cd9660 image.
.It Sy hard-disk-boot .It Sy hard-disk-boot
@ -350,6 +386,8 @@ ElTorito image.
Do not pad the image (apparently Linux needs the padding). Do not pad the image (apparently Linux needs the padding).
.\" .It Sy omit-trailing-period .\" .It Sy omit-trailing-period
.\" Unknown .\" Unknown
.It Sy platformid
Set platform ID of section header entry of the boot image.
.It Sy preparer .It Sy preparer
Preparer ID of the image. Preparer ID of the image.
.It Sy publisher .It Sy publisher
@ -377,9 +415,63 @@ Type of the media.
NOR: 0 or NAND: 1. NOR: 0 or NAND: 1.
.El .El
.Ss msdos-specific options .Ss msdos-specific options
See .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 .Xr newfs_msdos 8
for fs specific options. 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.
.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
.Ss V7FS-specific options .Ss V7FS-specific options
The following keywords are supported: The following keywords are supported:
.Pp .Pp
@ -398,7 +490,7 @@ Each of the options consists of a keyword, an equal sign
and a value. and a value.
The following keywords are supported: The following keywords are supported:
.Pp .Pp
.Bl -tag -width optimization -compact .Bl -tag -width optimization -offset indent -compact
.It Sy disctype .It Sy disctype
This can have the following values: This can have the following values:
.Bl -tag -width cdromXdvdromXbdromXXX -compact .Bl -tag -width cdromXdvdromXbdromXXX -compact
@ -453,8 +545,8 @@ utility appeared in
.An UCHIYAMA Yasushi .An UCHIYAMA Yasushi
(v7fs support), (v7fs support),
.An Tamas Toth .An Tamas Toth
(chfs support). (chfs support),
.An Christos Zoulas .An Christos Zoulas
(msdos support). (msdos support),
.An Reinoud Zandijk .An Reinoud Zandijk
(udf support). (udf support).

View File

@ -1,4 +1,4 @@
/* $NetBSD: makefs.c,v 1.50 2013/08/05 14:41:57 reinoud Exp $ */ /* $NetBSD: makefs.c,v 1.53 2015/11/27 15:10:32 joerg Exp $ */
/* /*
* Copyright (c) 2001-2003 Wasabi Systems, Inc. * Copyright (c) 2001-2003 Wasabi Systems, Inc.
@ -41,7 +41,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if defined(__RCSID) && !defined(__lint) #if defined(__RCSID) && !defined(__lint)
__RCSID("$NetBSD: makefs.c,v 1.50 2013/08/05 14:41:57 reinoud Exp $"); __RCSID("$NetBSD: makefs.c,v 1.53 2015/11/27 15:10:32 joerg Exp $");
#endif /* !__lint */ #endif /* !__lint */
#include <assert.h> #include <assert.h>
@ -87,8 +87,10 @@ static fstype_t fstypes[] = {
u_int debug; u_int debug;
struct timespec start_time; struct timespec start_time;
struct stat stampst;
static fstype_t *get_fstype(const char *); static fstype_t *get_fstype(const char *);
static int get_tstamp(const char *, struct stat *);
static void usage(fstype_t *, fsinfo_t *) __dead; static void usage(fstype_t *, fsinfo_t *) __dead;
int int
@ -116,13 +118,18 @@ main(int argc, char *argv[])
fstype->prepare_options(&fsoptions); fstype->prepare_options(&fsoptions);
specfile = NULL; specfile = NULL;
if (gettimeofday(&start, NULL) == -1) #ifdef CLOCK_REALTIME
err(1, "Unable to get system time"); ch = clock_gettime(CLOCK_REALTIME, &start_time);
#else
ch = gettimeofday(&start, NULL);
start_time.tv_sec = start.tv_sec; start_time.tv_sec = start.tv_sec;
start_time.tv_nsec = start.tv_usec * 1000; start_time.tv_nsec = start.tv_usec * 1000;
#endif
if (ch == -1)
err(1, "Unable to get system time");
while ((ch = getopt(argc, argv, "B:b:d:f:F:M:m:N:O:o:rs:S:t:xZ")) != -1) {
while ((ch = getopt(argc, argv, "B:b:d:f:F:M:m:N:O:o:rs:S:t:T:xZ")) != -1) {
switch (ch) { switch (ch) {
case 'B': case 'B':
@ -240,6 +247,12 @@ main(int argc, char *argv[])
fstype->prepare_options(&fsoptions); fstype->prepare_options(&fsoptions);
break; break;
case 'T':
if (get_tstamp(optarg, &stampst) == -1)
errx(1, "Cannot get timestamp from `%s'",
optarg);
break;
case 'x': case 'x':
fsoptions.onlyspec = 1; fsoptions.onlyspec = 1;
break; break;
@ -409,6 +422,36 @@ copy_opts(const option_t *o)
return memcpy(ecalloc(i, sizeof(*o)), o, i * sizeof(*o)); return memcpy(ecalloc(i, sizeof(*o)), o, i * sizeof(*o));
} }
static int
get_tstamp(const char *b, struct stat *st)
{
time_t when;
char *eb;
long long l;
if (stat(b, st) != -1)
return 0;
#ifndef HAVE_NBTOOL_CONFIG_H
errno = 0;
if ((when = parsedate(b, NULL, NULL)) == -1 && errno != 0)
#endif
{
errno = 0;
l = strtoll(b, &eb, 0);
if (b == eb || *eb || errno)
return -1;
when = (time_t)l;
}
st->st_ino = 1;
#if HAVE_STRUCT_STAT_BIRTHTIME
st->st_birthtime =
#endif
st->st_mtime = st->st_ctime = st->st_atime = when;
return 0;
}
static void static void
usage(fstype_t *fstype, fsinfo_t *fsoptions) usage(fstype_t *fstype, fsinfo_t *fsoptions)
{ {
@ -419,7 +462,8 @@ usage(fstype_t *fstype, fsinfo_t *fsoptions)
"Usage: %s [-rxZ] [-B endian] [-b free-blocks] [-d debug-mask]\n" "Usage: %s [-rxZ] [-B endian] [-b free-blocks] [-d debug-mask]\n"
"\t[-F mtree-specfile] [-f free-files] [-M minimum-size] [-m maximum-size]\n" "\t[-F mtree-specfile] [-f free-files] [-M minimum-size] [-m maximum-size]\n"
"\t[-N userdb-dir] [-O offset] [-o fs-options] [-S sector-size]\n" "\t[-N userdb-dir] [-O offset] [-o fs-options] [-S sector-size]\n"
"\t[-s image-size] [-t fs-type] image-file directory [extra-directory ...]\n", "\t[-s image-size] [-T <timestamp/file>] [-t fs-type]"
" image-file directory [extra-directory ...]\n",
prog); prog);
if (fstype) { if (fstype) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: makefs.h,v 1.35 2013/08/05 14:41:57 reinoud Exp $ */ /* $NetBSD: makefs.h,v 1.36 2015/11/25 00:48:49 christos Exp $ */
/* /*
* Copyright (c) 2001 Wasabi Systems, Inc. * Copyright (c) 2001 Wasabi Systems, Inc.
@ -199,6 +199,7 @@ DECLARE_FUN(udf);
extern u_int debug; extern u_int debug;
extern struct timespec start_time; extern struct timespec start_time;
extern struct stat stampst;
/* /*
* If -x is specified, we want to exclude nodes which do not appear * If -x is specified, we want to exclude nodes which do not appear

View File

@ -1,4 +1,4 @@
/* $NetBSD: msdos.c,v 1.14 2013/02/03 03:21:21 christos Exp $ */ /* $NetBSD: msdos.c,v 1.20 2017/04/14 15:40:35 christos Exp $ */
/*- /*-
* Copyright (c) 2013 The NetBSD Foundation, Inc. * Copyright (c) 2013 The NetBSD Foundation, Inc.
@ -15,9 +15,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@ -37,7 +34,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if defined(__RCSID) && !defined(__lint) #if defined(__RCSID) && !defined(__lint)
__RCSID("$NetBSD: msdos.c,v 1.14 2013/02/03 03:21:21 christos Exp $"); __RCSID("$NetBSD: msdos.c,v 1.20 2017/04/14 15:40:35 christos Exp $");
#endif /* !__lint */ #endif /* !__lint */
#include <sys/param.h> #include <sys/param.h>
@ -58,7 +55,9 @@ __RCSID("$NetBSD: msdos.c,v 1.14 2013/02/03 03:21:21 christos Exp $");
#include <util.h> #include <util.h>
#include <ffs/buf.h> #include <ffs/buf.h>
#include <fs/msdosfs/bpb.h>
#include <fs/msdosfs/denode.h> #include <fs/msdosfs/denode.h>
#include <fs/msdosfs/msdosfsmount.h>
#include "makefs.h" #include "makefs.h"
#include "msdos.h" #include "msdos.h"
#include "mkfs_msdos.h" #include "mkfs_msdos.h"
@ -66,10 +65,15 @@ __RCSID("$NetBSD: msdos.c,v 1.14 2013/02/03 03:21:21 christos Exp $");
static int msdos_populate_dir(const char *, struct denode *, fsnode *, static int msdos_populate_dir(const char *, struct denode *, fsnode *,
fsnode *, fsinfo_t *); fsnode *, fsinfo_t *);
struct msdos_options_ex {
struct msdos_options options;
bool utf8;
};
void void
msdos_prep_opts(fsinfo_t *fsopts) msdos_prep_opts(fsinfo_t *fsopts)
{ {
struct msdos_options *msdos_opt = ecalloc(1, sizeof(*msdos_opt)); struct msdos_options_ex *msdos_opt = ecalloc(1, sizeof(*msdos_opt));
const option_t msdos_options[] = { const option_t msdos_options[] = {
#define AOPT(_opt, _type, _name, _min, _desc) { \ #define AOPT(_opt, _type, _name, _min, _desc) { \
.letter = _opt, \ .letter = _opt, \
@ -79,7 +83,7 @@ msdos_prep_opts(fsinfo_t *fsopts)
(sizeof(_type) == 1 ? OPT_INT8 : \ (sizeof(_type) == 1 ? OPT_INT8 : \
(sizeof(_type) == 2 ? OPT_INT16 : \ (sizeof(_type) == 2 ? OPT_INT16 : \
(sizeof(_type) == 4 ? OPT_INT32 : OPT_INT64)))), \ (sizeof(_type) == 4 ? OPT_INT32 : OPT_INT64)))), \
.value = &msdos_opt->_name, \ .value = &msdos_opt->options._name, \
.minimum = _min, \ .minimum = _min, \
.maximum = sizeof(_type) == 1 ? 0xff : \ .maximum = sizeof(_type) == 1 ? 0xff : \
(sizeof(_type) == 2 ? 0xffff : \ (sizeof(_type) == 2 ? 0xffff : \
@ -88,6 +92,8 @@ msdos_prep_opts(fsinfo_t *fsopts)
}, },
ALLOPTS ALLOPTS
#undef AOPT #undef AOPT
{ 'U', "utf8", &msdos_opt->utf8, OPT_BOOL,
0, 1, "Use UTF8 names" },
{ .name = NULL } { .name = NULL }
}; };
@ -127,6 +133,12 @@ msdos_parse_opts(const char *option, fsinfo_t *fsopts)
msdos_opt->media_descriptor_set = 1; msdos_opt->media_descriptor_set = 1;
else if (strcmp(msdos_options[rv].name, "hidden_sectors") == 0) else if (strcmp(msdos_options[rv].name, "hidden_sectors") == 0)
msdos_opt->hidden_sectors_set = 1; msdos_opt->hidden_sectors_set = 1;
if (stampst.st_ino) {
msdos_opt->timestamp_set = 1;
msdos_opt->timestamp = stampst.st_mtime;
}
return 1; return 1;
} }
@ -134,45 +146,48 @@ msdos_parse_opts(const char *option, fsinfo_t *fsopts)
void void
msdos_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts) msdos_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts)
{ {
struct msdos_options *msdos_opt = fsopts->fs_specific; struct msdos_options_ex *msdos_opt = fsopts->fs_specific;
struct vnode vp, rootvp; struct vnode vp, rootvp;
struct timeval start; struct timeval start;
struct msdosfsmount *pmp; struct msdosfsmount *pmp;
uint32_t flags;
assert(image != NULL); assert(image != NULL);
assert(dir != NULL); assert(dir != NULL);
assert(root != NULL); assert(root != NULL);
assert(fsopts != NULL); assert(fsopts != NULL);
/* fsopts->size = fsopts->maxsize;
* XXX: pick up other options from the msdos specific ones? msdos_opt->options.create_size = MAX(msdos_opt->options.create_size,
* Is minsize right here? fsopts->offset + fsopts->size);
*/ msdos_opt->options.offset = fsopts->offset;
msdos_opt->create_size = MAX(msdos_opt->create_size, fsopts->minsize); if (msdos_opt->options.bytes_per_sector == 0) {
msdos_opt->offset = fsopts->offset;
if (msdos_opt->bytes_per_sector == 0) {
if (fsopts->sectorsize == -1) if (fsopts->sectorsize == -1)
fsopts->sectorsize = 512; fsopts->sectorsize = 512;
msdos_opt->bytes_per_sector = fsopts->sectorsize; msdos_opt->options.bytes_per_sector = fsopts->sectorsize;
} else if (fsopts->sectorsize == -1) { } else if (fsopts->sectorsize == -1) {
fsopts->sectorsize = msdos_opt->bytes_per_sector; fsopts->sectorsize = msdos_opt->options.bytes_per_sector;
} else if (fsopts->sectorsize != msdos_opt->bytes_per_sector) { } else if (fsopts->sectorsize != msdos_opt->options.bytes_per_sector) {
err(1, "inconsistent sectorsize -S %u" err(1, "inconsistent sectorsize -S %u"
"!= -o bytes_per_sector %u", "!= -o bytes_per_sector %u",
fsopts->sectorsize, msdos_opt->bytes_per_sector); fsopts->sectorsize, msdos_opt->options.bytes_per_sector);
} }
/* create image */ /* create image */
printf("Creating `%s'\n", image); printf("Creating `%s'\n", image);
TIMER_START(start); TIMER_START(start);
if (mkfs_msdos(image, NULL, msdos_opt) == -1) if (mkfs_msdos(image, NULL, &msdos_opt->options) == -1)
return; return;
TIMER_RESULTS(start, "mkfs_msdos"); TIMER_RESULTS(start, "mkfs_msdos");
fsopts->fd = open(image, O_RDWR); fsopts->fd = open(image, O_RDWR);
vp.fs = fsopts; vp.fs = fsopts;
if ((pmp = msdosfs_mount(&vp, 0)) == NULL) flags = 0;
if (msdos_opt->utf8)
flags |= MSDOSFSMNT_UTF8;
if ((pmp = msdosfs_mount(&vp, flags)) == NULL)
err(1, "msdosfs_mount"); err(1, "msdosfs_mount");
if (msdosfs_root(pmp, &rootvp) != 0) if (msdosfs_root(pmp, &rootvp) != 0)

View File

@ -1,4 +1,4 @@
/* $NetBSD: msdos.h,v 1.2 2013/01/26 00:31:49 christos Exp $ */ /* $NetBSD: msdos.h,v 1.3 2015/10/16 16:40:02 christos Exp $ */
/*- /*-
* Copyright (c) 2013 The NetBSD Foundation, Inc. * Copyright (c) 2013 The NetBSD Foundation, Inc.
@ -15,9 +15,6 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile.inc,v 1.6 2014/09/01 09:09:47 martin Exp $ # $NetBSD: Makefile.inc,v 1.7 2016/02/06 10:40:58 mlelstv Exp $
# #
MSDOS= ${NETBSDSRCDIR}/sys/fs/msdosfs MSDOS= ${NETBSDSRCDIR}/sys/fs/msdosfs
@ -12,5 +12,5 @@ CPPFLAGS+= -I${NETBSDSRCDIR}/sys
.endif .endif
SRCS+= mkfs_msdos.c msdosfs_fat.c msdosfs_conv.c msdosfs_vfsops.c SRCS+= mkfs_msdos.c msdosfs_fat.c msdosfs_conv.c msdosfs_vfsops.c
SRCS+= msdosfs_lookup.c msdosfs_denode.c msdosfs_vnops.c SRCS+= msdosfs_lookup.c msdosfs_denode.c msdosfs_vnops.c msdosfs_unicode.c
SRCS+= clock_subr.c SRCS+= clock_subr.c

View File

@ -50,7 +50,7 @@
#endif #endif
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: msdosfs_vfsops.c,v 1.9 2015/03/29 05:52:59 agc Exp $"); __KERNEL_RCSID(0, "$NetBSD: msdosfs_vfsops.c,v 1.11 2018/01/27 02:07:33 sevan Exp $");
#include <sys/param.h> #include <sys/param.h>
@ -68,6 +68,7 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_vfsops.c,v 1.9 2015/03/29 05:52:59 agc Exp $
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <util.h> #include <util.h>
#include <strings.h>
#include "makefs.h" #include "makefs.h"
#include "msdos.h" #include "msdos.h"
@ -152,6 +153,12 @@ msdosfs_mount(struct vnode *devvp, int flags)
} }
} }
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) { if (pmp->pm_Sectors == 0) {
pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs); pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);
pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors); pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors);

View File

@ -1,4 +1,4 @@
/* $NetBSD: msdosfs_vnops.c,v 1.16 2015/03/29 05:52:59 agc Exp $ */ /* $NetBSD: msdosfs_vnops.c,v 1.19 2017/04/13 17:10:12 christos Exp $ */
/*- /*-
* Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@ -51,7 +51,7 @@
#endif #endif
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.16 2015/03/29 05:52:59 agc Exp $"); __KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.19 2017/04/13 17:10:12 christos Exp $");
#include <sys/param.h> #include <sys/param.h>
#include <sys/mman.h> #include <sys/mman.h>
@ -98,12 +98,20 @@ static void
msdosfs_times(struct msdosfsmount *pmp, struct denode *dep, msdosfs_times(struct msdosfsmount *pmp, struct denode *dep,
const struct stat *st) const struct stat *st)
{ {
struct timespec at;
struct timespec mt;
if (stampst.st_ino)
st = &stampst;
#ifndef HAVE_NBTOOL_CONFIG_H #ifndef HAVE_NBTOOL_CONFIG_H
struct timespec at = st->st_atimespec; at = st->st_atimespec;
struct timespec mt = st->st_mtimespec; mt = st->st_mtimespec;
#else #else
struct timespec at = { st->st_atime, 0 }; at.tv_sec = st->st_atime;
struct timespec mt = { st->st_mtime, 0 }; at.tv_nsec = 0;
mt.tv_sec = st->st_mtime;
mt.tv_nsec = 0;
#endif #endif
unix2dostime(&at, pmp->pm_gmtoff, &dep->de_ADate, NULL, NULL); unix2dostime(&at, pmp->pm_gmtoff, &dep->de_ADate, NULL, NULL);
unix2dostime(&mt, pmp->pm_gmtoff, &dep->de_MDate, &dep->de_MTime, NULL); unix2dostime(&mt, pmp->pm_gmtoff, &dep->de_MDate, &dep->de_MTime, NULL);
@ -154,12 +162,12 @@ msdosfs_findslot(struct denode *dp, struct componentname *cnp)
break; break;
case 2: case 2:
wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr,
cnp->cn_namelen) + 1; cnp->cn_namelen, pmp->pm_flags & MSDOSFSMNT_UTF8) + 1;
break; break;
case 3: case 3:
olddos = 0; olddos = 0;
wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr,
cnp->cn_namelen) + 1; cnp->cn_namelen, pmp->pm_flags & MSDOSFSMNT_UTF8) + 1;
break; break;
} }
@ -243,7 +251,8 @@ msdosfs_findslot(struct denode *dp, struct componentname *cnp)
chksum = winChkName((const u_char *)cnp->cn_nameptr, chksum = winChkName((const u_char *)cnp->cn_nameptr,
cnp->cn_namelen, cnp->cn_namelen,
(struct winentry *)dep, (struct winentry *)dep,
chksum); chksum,
pmp->pm_flags & MSDOSFSMNT_UTF8);
continue; continue;
} }
@ -431,31 +440,29 @@ msdosfs_wfile(const char *path, struct denode *dep, fsnode *node)
return 0; return 0;
/* Don't bother to try to write files larger than the fs limit */ /* Don't bother to try to write files larger than the fs limit */
if (st->st_size > MSDOSFS_FILESIZE_MAX) { if (st->st_size > MSDOSFS_FILESIZE_MAX)
errno = EFBIG; return EFBIG;
return -1;
}
nsize = st->st_size; nsize = st->st_size;
DPRINTF(("%s(nsize=%zu, osize=%zu)\n", __func__, nsize, osize)); DPRINTF(("%s(nsize=%zu, osize=%zu)\n", __func__, nsize, osize));
if (nsize > osize) { if (nsize > osize) {
if ((error = deextend(dep, nsize, NULL)) != 0) { if ((error = deextend(dep, nsize, NULL)) != 0)
errno = error; return error;
return -1; if ((error = msdosfs_updatede(dep)) != 0)
} return error;
if ((error = msdosfs_updatede(dep)) != 0) {
errno = error;
return -1;
}
} }
if ((fd = open(path, O_RDONLY)) == -1) if ((fd = open(path, O_RDONLY)) == -1) {
err(1, "open %s", path); error = errno;
DPRINTF((1, "open %s: %s", path, strerror(error)));
return error;
}
if ((dat = mmap(0, nsize, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0)) if ((dat = mmap(0, nsize, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0))
== MAP_FAILED) { == MAP_FAILED) {
DPRINTF(("%s: mmap %s %s", __func__, node->name, error = errno;
strerror(errno))); DPRINTF(("%s: mmap %s: %s", __func__, node->name,
strerror(error)));
close(fd); close(fd);
goto out; goto out;
} }
@ -469,6 +476,7 @@ msdosfs_wfile(const char *path, struct denode *dep, fsnode *node)
cn = dep->de_StartCluster; cn = dep->de_StartCluster;
if (cn == MSDOSFSROOT) { if (cn == MSDOSFSROOT) {
DPRINTF(("%s: bad lbn %lu", __func__, cn)); DPRINTF(("%s: bad lbn %lu", __func__, cn));
error = EINVAL;
goto out; goto out;
} }
bn = cntobn(pmp, cn); bn = cntobn(pmp, cn);

View File

@ -1,4 +1,4 @@
/* $NetBSD: udf.c,v 1.17 2015/06/16 23:04:14 christos Exp $ */ /* $NetBSD: udf.c,v 1.21 2020/04/18 12:25:01 martin Exp $ */
/* /*
* Copyright (c) 2006, 2008, 2013 Reinoud Zandijk * Copyright (c) 2006, 2008, 2013 Reinoud Zandijk
@ -30,7 +30,7 @@
#endif #endif
#include <sys/cdefs.h> #include <sys/cdefs.h>
__RCSID("$NetBSD: udf.c,v 1.17 2015/06/16 23:04:14 christos Exp $"); __RCSID("$NetBSD: udf.c,v 1.21 2020/04/18 12:25:01 martin Exp $");
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -201,7 +201,7 @@ udf_emulate_discinfo(fsinfo_t *fsopts, struct mmc_discinfo *di,
case 0x10: /* DVDROM */ case 0x10: /* DVDROM */
case 0x40: /* BDROM */ case 0x40: /* BDROM */
req_enable |= FORMAT_READONLY; req_enable |= FORMAT_READONLY;
/* FALLTROUGH */ /* FALLTHROUGH */
case 0x01: /* disc */ case 0x01: /* disc */
/* set up a disc info profile for partitions/files */ /* set up a disc info profile for partitions/files */
di->mmc_class = MMC_CLASS_DISC; di->mmc_class = MMC_CLASS_DISC;
@ -290,9 +290,6 @@ udf_update_trackinfo(struct mmc_discinfo *di, struct mmc_trackinfo *ti)
void void
udf_prep_opts(fsinfo_t *fsopts) udf_prep_opts(fsinfo_t *fsopts)
{ {
struct tm *tm;
time_t now;
const option_t udf_options[] = { const option_t udf_options[] = {
OPT_STR('T', "disctype", "disc type (cdrom,dvdrom,bdrom," OPT_STR('T', "disctype", "disc type (cdrom,dvdrom,bdrom,"
"dvdram,bdre,disk,cdr,dvdr,bdr,cdrw,dvdrw)"), "dvdram,bdre,disk,cdr,dvdr,bdr,cdrw,dvdrw)"),
@ -330,13 +327,16 @@ udf_prep_opts(fsinfo_t *fsopts)
context.max_udf = 0x201; /* 0x250 and 0x260 are not ready */ context.max_udf = 0x201; /* 0x250 and 0x260 are not ready */
/* use user's time zone as default */ /* use user's time zone as default */
(void)time(&now);
tm = localtime(&now);
#ifdef HAVE_STRUCT_TM_TM_GMTOFF #ifdef HAVE_STRUCT_TM_TM_GMTOFF
context.gmtoff = tm->tm_gmtoff; if (!stampst.st_ino) {
#else struct tm tm;
context.gmtoff = 0; time_t now;
(void)time(&now);
(void)localtime_r(&now, &tm);
context.gmtoff = tm.tm_gmtoff;
} else
#endif #endif
context.gmtoff = 0;
/* return info */ /* return info */
fsopts->fs_specific = NULL; fsopts->fs_specific = NULL;
@ -514,6 +514,7 @@ static uint32_t
udf_datablocks(off_t sz) udf_datablocks(off_t sz)
{ {
/* predictor if it can be written inside the node */ /* predictor if it can be written inside the node */
/* XXX the predictor assumes NO extended attributes in the node */
if (sz < context.sector_size - UDF_EXTFENTRY_SIZE - 16) if (sz < context.sector_size - UDF_EXTFENTRY_SIZE - 16)
return 0; return 0;
@ -561,7 +562,6 @@ udf_file_inject_blob(union dscrptr *dscr, uint8_t *blob, off_t size)
struct extfile_entry *efe; struct extfile_entry *efe;
uint64_t inf_len, obj_size; uint64_t inf_len, obj_size;
uint32_t l_ea, l_ad; uint32_t l_ea, l_ad;
uint32_t free_space, desc_size;
uint16_t crclen; uint16_t crclen;
uint8_t *data, *pos; uint8_t *data, *pos;
@ -575,7 +575,6 @@ udf_file_inject_blob(union dscrptr *dscr, uint8_t *blob, off_t size)
icb = &fe->icbtag; icb = &fe->icbtag;
inf_len = udf_rw64(fe->inf_len); inf_len = udf_rw64(fe->inf_len);
obj_size = 0; obj_size = 0;
desc_size = sizeof(struct file_entry);
} else if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) { } else if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) {
efe = &dscr->efe; efe = &dscr->efe;
data = efe->data; data = efe->data;
@ -584,39 +583,22 @@ udf_file_inject_blob(union dscrptr *dscr, uint8_t *blob, off_t size)
icb = &efe->icbtag; icb = &efe->icbtag;
inf_len = udf_rw64(efe->inf_len); inf_len = udf_rw64(efe->inf_len);
obj_size = udf_rw64(efe->obj_size); obj_size = udf_rw64(efe->obj_size);
desc_size = sizeof(struct extfile_entry);
} else { } else {
errx(1, "Bad tag passed to udf_file_inject_blob"); errx(1, "Bad tag passed to udf_file_inject_blob");
} }
crclen = udf_rw16(dscr->tag.desc_crc_len); crclen = udf_rw16(dscr->tag.desc_crc_len);
/* calculate free space */ /* check if it will fit internally */
free_space = context.sector_size - (l_ea + l_ad) - desc_size;
if (udf_datablocks(size)) { if (udf_datablocks(size)) {
#if !defined(NDEBUG) && defined(__minix) /* the predictor tells it won't fit internally */
assert(free_space < size);
#else
if (!(free_space < size)) {
printf("%s:%d not enough free space\n", __FILE__, __LINE__);
abort();
}
#endif /* !defined(NDEBUG) && defined(__minix) */
return 1; return 1;
} }
/* going internal */ /* going internal */
assert(l_ad == 0); assert(l_ad == 0);
#if !defined(NDEBUG) && defined(__minix)
assert((udf_rw16(icb->flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK) == assert((udf_rw16(icb->flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK) ==
UDF_ICB_INTERN_ALLOC); UDF_ICB_INTERN_ALLOC);
#else
if (!((udf_rw16(icb->flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK) == UDF_ICB_INTERN_ALLOC)) {
printf("%s:%d: allocation flags mismatch\n", __FILE__, __LINE__);
abort();
}
#endif /* !defined(NDEBUG) && defined(__minix) */
// assert(free_space >= size);
pos = data + l_ea + l_ad; pos = data + l_ea + l_ad;
memcpy(pos, blob, size); memcpy(pos, blob, size);
l_ad += size; l_ad += size;
@ -704,14 +686,7 @@ udf_append_file_mapping(union dscrptr *dscr, struct long_ad *piece)
last_long = NULL; last_long = NULL;
if (l_ad != 0) { if (l_ad != 0) {
if (use_shorts) { if (use_shorts) {
#if !defined(NDEBUG) && defined(__minix)
assert(cur_alloc == UDF_ICB_SHORT_ALLOC); assert(cur_alloc == UDF_ICB_SHORT_ALLOC);
#else
if (!(cur_alloc == UDF_ICB_SHORT_ALLOC)) {
printf("%s:%d: Expecting UDF_ICB_SHORT_ALLOC allocation\n", __FILE__, __LINE__);
abort();
}
#endif /* !defined(NDEBUG) && defined(__minix) */
pos += l_ad - short_len; pos += l_ad - short_len;
last_short = (struct short_ad *) pos; last_short = (struct short_ad *) pos;
last_lb_num = udf_rw32(last_short->lb_num); last_lb_num = udf_rw32(last_short->lb_num);
@ -719,14 +694,7 @@ udf_append_file_mapping(union dscrptr *dscr, struct long_ad *piece)
last_len = UDF_EXT_LEN(udf_rw32(last_short->len)); last_len = UDF_EXT_LEN(udf_rw32(last_short->len));
last_flags = UDF_EXT_FLAGS(udf_rw32(last_short->len)); last_flags = UDF_EXT_FLAGS(udf_rw32(last_short->len));
} else { } else {
#if !defined(NDEBUG) && defined(__minix)
assert(cur_alloc == UDF_ICB_LONG_ALLOC); assert(cur_alloc == UDF_ICB_LONG_ALLOC);
#else
if (!(cur_alloc == UDF_ICB_LONG_ALLOC)) {
printf("%s:%d: Expecting UDF_ICB_LONG_ALLOC allocation\n", __FILE__, __LINE__);
abort();
}
#endif /* !defined(NDEBUG) && defined(__minix) */
pos += l_ad - long_len; pos += l_ad - long_len;
last_long = (struct long_ad *) pos; last_long = (struct long_ad *) pos;
last_lb_num = udf_rw32(last_long->loc.lb_num); last_lb_num = udf_rw32(last_long->loc.lb_num);
@ -906,6 +874,7 @@ udf_estimate_walk(fsinfo_t *fsopts,
case S_IFDIR: case S_IFDIR:
if (strcmp(cur->name, ".") == 0) if (strcmp(cur->name, ".") == 0)
continue; continue;
/* FALLTHROUGH */
case S_IFLNK: case S_IFLNK:
case S_IFREG: case S_IFREG:
/* create dummy FID to see how long name will become */ /* create dummy FID to see how long name will become */

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile.inc,v 1.2 2013/08/05 18:45:00 reinoud Exp $ # $NetBSD: Makefile.inc,v 1.4 2020/09/06 07:20:31 mrg Exp $
# #
UDF= ${NETBSDSRCDIR}/sys/fs/udf UDF= ${NETBSDSRCDIR}/sys/fs/udf
@ -11,3 +11,7 @@ CPPFLAGS+= -I${UDF} -I${UDF_NEWFS} -I${FSCK}
SRCS += udf_create.c udf_write.c udf_osta.c SRCS += udf_create.c udf_write.c udf_osta.c
.if !defined(__MINIX)
CWARNFLAGS.clang+= -Wno-error=address-of-packed-member -Wno-error=constant-conversion
.endif # !defined(__MINIX)
CWARNFLAGS.gcc+= ${GCC_NO_ADDR_OF_PACKED_MEMBER}

View File

@ -132,10 +132,6 @@ estimate_size_walk(fsnode *root, char *dir, struct v7fs_geometry *geom)
int n; int n;
off_t sz; off_t sz;
#if defined(__minix)
/* LSC: -Werror=maybe-uninitialized, when compiling with -O3. */
nblk = 0;
#endif /* defined(__minix) */
for (cur = root, nentries = 0; cur != NULL; cur = cur->next, for (cur = root, nentries = 0; cur != NULL; cur = cur->next,
nentries++, geom->ninode++) { nentries++, geom->ninode++) {
switch (cur->type & S_IFMT) { switch (cur->type & S_IFMT) {
@ -261,10 +257,6 @@ v7fs_estimate(const char *dir, fsnode *root, fsinfo_t *fsopts)
v7fs_daddr_t nblk; v7fs_daddr_t nblk;
struct v7fs_geometry geom; struct v7fs_geometry geom;
#if defined(__minix)
/* LSC: -Werror=maybe-uninitialized, when compiling with -O3. */
nblk = 0;
#endif /* defined(__minix) */
memset(&geom , 0, sizeof(geom)); memset(&geom , 0, sizeof(geom));
strncpy(path, dir, sizeof(path)); strncpy(path, dir, sizeof(path));

View File

@ -1,4 +1,4 @@
/* $NetBSD: walk.c,v 1.28 2013/02/03 06:16:53 christos Exp $ */ /* $NetBSD: walk.c,v 1.29 2015/11/25 00:48:49 christos Exp $ */
/* /*
* Copyright (c) 2001 Wasabi Systems, Inc. * Copyright (c) 2001 Wasabi Systems, Inc.
@ -41,7 +41,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if defined(__RCSID) && !defined(__lint) #if defined(__RCSID) && !defined(__lint)
__RCSID("$NetBSD: walk.c,v 1.28 2013/02/03 06:16:53 christos Exp $"); __RCSID("$NetBSD: walk.c,v 1.29 2015/11/25 00:48:49 christos Exp $");
#endif /* !__lint */ #endif /* !__lint */
#include <sys/param.h> #include <sys/param.h>
@ -252,6 +252,20 @@ create_fsnode(const char *root, const char *path, const char *name,
cur->type = stbuf->st_mode & S_IFMT; cur->type = stbuf->st_mode & S_IFMT;
cur->inode->nlink = 1; cur->inode->nlink = 1;
cur->inode->st = *stbuf; cur->inode->st = *stbuf;
if (stampst.st_ino) {
cur->inode->st.st_atime = stampst.st_atime;
cur->inode->st.st_mtime = stampst.st_mtime;
cur->inode->st.st_ctime = stampst.st_ctime;
#if HAVE_STRUCT_STAT_ST_MTIMENSEC
cur->inode->st.st_atimensec = stampst.st_atimensec;
cur->inode->st.st_mtimensec = stampst.st_mtimensec;
cur->inode->st.st_ctimensec = stampst.st_ctimensec;
#endif
#if HAVE_STRUCT_STAT_BIRTHTIME
cur->inode->st.st_birthtime = stampst.st_birthtime;
cur->inode->st.st_birthtimensec = stampst.st_birthtimensec;
#endif
}
return (cur); return (cur);
} }