diff --git a/sbin/newfs_udf/Makefile b/sbin/newfs_udf/Makefile index f9ec40c8a..96a6c850f 100644 --- a/sbin/newfs_udf/Makefile +++ b/sbin/newfs_udf/Makefile @@ -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 @@ -14,4 +14,9 @@ CPPFLAGS+= -I${MOUNT} -I${KUDF} -I${NETBSDSRCDIR}/sys DPADD+=${LIBUTIL} 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 diff --git a/sbin/newfs_udf/newfs_udf.c b/sbin/newfs_udf/newfs_udf.c index eaab2b144..94b77f9d6 100644 --- a/sbin/newfs_udf/newfs_udf.c +++ b/sbin/newfs_udf/newfs_udf.c @@ -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 @@ -72,7 +72,6 @@ int newfs_udf(int argc, char **argv); static void usage(void) __attribute__((__noreturn__)); - /* queue for temporary storage of sectors to be written out */ struct wrsect { uint64_t sectornr; @@ -121,11 +120,13 @@ udf_write_sector(void *sector, uint64_t location) if ((seekpos == NULL) || (seekpos->sectornr != location)) { pos = calloc(1, sizeof(struct wrsect)); if (pos == NULL) - return ENOMEM; + return errno; /* allocate space for copy of sector data */ pos->sector_data = calloc(1, context.sector_size); - if (pos->sector_data == NULL) - return ENOMEM; + if (pos->sector_data == NULL) { + free(pos); + return errno; + } pos->sectornr = location; if (seekpos) { diff --git a/sbin/newfs_udf/newfs_udf.h b/sbin/newfs_udf/newfs_udf.h index 1c21a0b48..2bb021d19 100644 --- a/sbin/newfs_udf/newfs_udf.h +++ b/sbin/newfs_udf/newfs_udf.h @@ -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 * All rights reserved. @@ -53,8 +55,8 @@ extern float meta_fract; /* shared structure between udf_create.c users */ -struct udf_create_context context; -struct udf_disclayout layout; +extern struct udf_create_context context; +extern struct udf_disclayout layout; /* prototypes */ int udf_write_sector(void *sector, uint64_t location); diff --git a/sbin/newfs_udf/udf_create.c b/sbin/newfs_udf/udf_create.c index ef92874af..81708d166 100644 --- a/sbin/newfs_udf/udf_create.c +++ b/sbin/newfs_udf/udf_create.c @@ -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 @@ -30,7 +30,7 @@ #endif #include -__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 #include @@ -52,6 +52,9 @@ __RCSID("$NetBSD: udf_create.c,v 1.25 2015/06/16 23:18:55 christos Exp $"); # 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. * 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) { /* note: all in backing partition space */ layout.meta_file = pos++; - layout.meta_bitmap = pos++;; + layout.meta_bitmap = pos++; layout.meta_mirror = layout.part_size_lba-1; layout.meta_alignment = MAX(blockingnr, sparable_blockingnr); 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 extattrhdr_desc *extattrhdr; struct impl_extattr_entry *implext; - uint32_t impl_attr_loc, appl_attr_loc, l_ea, a_l, exthdr_len; - uint32_t *l_eap, l_ad; + uint32_t impl_attr_loc, appl_attr_loc, l_ea, l_ad, a_l; uint16_t *spos; uint8_t *bpos, *data; + void *l_eap; if (udf_rw16(dscr->tag.id) == TAGID_FENTRY) { fe = &dscr->fe; @@ -1741,27 +1744,22 @@ udf_extattr_append_internal(union dscrptr *dscr, struct extattr_entry *extattr) /* should have a header! */ 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 !defined(NDEBUG) && defined(__minix) + uint32_t exthdr_len; 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 */ - 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); - extattrhdr->impl_attr_loc = udf_rw32(exthdr_len); - extattrhdr->appl_attr_loc = udf_rw32(exthdr_len); + extattrhdr->impl_attr_loc = exthdr_len; + extattrhdr->appl_attr_loc = exthdr_len; extattrhdr->tag.desc_crc_len = udf_rw16(8); /* record extended attribute header length */ - l_ea = exthdr_len; - *l_eap = udf_rw32(l_ea); + memcpy(l_eap, &exthdr_len, sizeof(exthdr_len)); } /* extract locations */ @@ -1794,7 +1792,7 @@ udf_extattr_append_internal(union dscrptr *dscr, struct extattr_entry *extattr) assert(appl_attr_loc == l_ea); /* 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); /* update impl. attribute locations */ @@ -1809,7 +1807,8 @@ udf_extattr_append_internal(union dscrptr *dscr, struct extattr_entry *extattr) /* copy and advance */ memcpy(bpos, extattr, 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 */ if (context.dscrver != 2) { @@ -2164,10 +2163,6 @@ udf_create_new_rootdir(union dscrptr **dscr) struct long_ad root_icb; 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)); root_icb.len = udf_rw32(context.sector_size); root_icb.loc.lb_num = udf_rw32(layout.rootdir); diff --git a/sys/fs/msdosfs/bootsect.h b/sys/fs/msdosfs/bootsect.h index 92a63093b..8c140c0f2 100644 --- a/sys/fs/msdosfs/bootsect.h +++ b/sys/fs/msdosfs/bootsect.h @@ -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) @@ -24,13 +24,13 @@ * first sector of a partitioned hard disk. */ 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 bsBPB[19]; /* BIOS parameter block */ int8_t bsDriveNumber; /* drive number (0x80) */ int8_t bsBootCode[479]; /* pad so struct is 512b */ - u_int8_t bsBootSectSig0; - u_int8_t bsBootSectSig1; + uint8_t bsBootSectSig0; + uint8_t bsBootSectSig1; #define BOOTSIG0 0x55 #define BOOTSIG1 0xaa }; @@ -46,25 +46,25 @@ struct extboot { }; 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 bsBPB[25]; /* BIOS parameter block */ int8_t bsExt[26]; /* Bootsector Extension */ int8_t bsBootCode[448]; /* pad so structure is 512b */ - u_int8_t bsBootSectSig0; - u_int8_t bsBootSectSig1; + uint8_t bsBootSectSig0; + uint8_t bsBootSectSig1; #define BOOTSIG0 0x55 #define BOOTSIG1 0xaa }; 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 bsBPB[53]; /* BIOS parameter block */ int8_t bsExt[26]; /* Bootsector Extension */ int8_t bsBootCode[420]; /* pad so structure is 512b */ - u_int8_t bsBootSectSig0; - u_int8_t bsBootSectSig1; + uint8_t bsBootSectSig0; + uint8_t bsBootSectSig1; #define BOOTSIG0 0x55 #define BOOTSIG1 0xaa }; @@ -76,7 +76,7 @@ struct bootsector710 { */ #if 0 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 bsSerial[3]; /* serial no. for mediachange */ int8_t bsBPB[19]; /* BIOS parameter block */ diff --git a/sys/fs/msdosfs/bpb.h b/sys/fs/msdosfs/bpb.h index c2937241b..c5d93e20c 100644 --- a/sys/fs/msdosfs/bpb.h +++ b/sys/fs/msdosfs/bpb.h @@ -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) @@ -23,17 +23,17 @@ * BIOS Parameter Block (BPB) for DOS 3.3 */ struct bpb33 { - u_int16_t bpbBytesPerSec; /* bytes per sector */ - u_int8_t bpbSecPerClust; /* sectors per cluster */ - u_int16_t bpbResSectors; /* number of reserved sectors */ - u_int8_t bpbFATs; /* number of FATs */ - u_int16_t bpbRootDirEnts; /* number of root directory entries */ - u_int16_t bpbSectors; /* total number of sectors */ - u_int8_t bpbMedia; /* media descriptor */ - u_int16_t bpbFATsecs; /* number of sectors per FAT */ - u_int16_t bpbSecPerTrack; /* sectors per track */ - u_int16_t bpbHeads; /* number of heads */ - u_int16_t bpbHiddenSecs; /* number of hidden sectors */ + uint16_t bpbBytesPerSec; /* bytes per sector */ + uint8_t bpbSecPerClust; /* sectors per cluster */ + uint16_t bpbResSectors; /* number of reserved sectors */ + uint8_t bpbFATs; /* number of FATs */ + uint16_t bpbRootDirEnts; /* number of root directory entries */ + uint16_t bpbSectors; /* total number of sectors */ + uint8_t bpbMedia; /* media descriptor */ + uint16_t bpbFATsecs; /* number of sectors per FAT */ + uint16_t bpbSecPerTrack; /* sectors per track */ + uint16_t bpbHeads; /* number of heads */ + uint16_t bpbHiddenSecs; /* number of hidden sectors */ }; /* @@ -41,46 +41,46 @@ struct bpb33 { * and bpbHugeSectors is not in the 3.3 bpb. */ struct bpb50 { - u_int16_t bpbBytesPerSec; /* bytes per sector */ - u_int8_t bpbSecPerClust; /* sectors per cluster */ - u_int16_t bpbResSectors; /* number of reserved sectors */ - u_int8_t bpbFATs; /* number of FATs */ - u_int16_t bpbRootDirEnts; /* number of root directory entries */ - u_int16_t bpbSectors; /* total number of sectors */ - u_int8_t bpbMedia; /* media descriptor */ - u_int16_t bpbFATsecs; /* number of sectors per FAT */ - u_int16_t bpbSecPerTrack; /* sectors per track */ - u_int16_t bpbHeads; /* number of heads */ - u_int32_t bpbHiddenSecs; /* # of hidden sectors */ - u_int32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */ + uint16_t bpbBytesPerSec; /* bytes per sector */ + uint8_t bpbSecPerClust; /* sectors per cluster */ + uint16_t bpbResSectors; /* number of reserved sectors */ + uint8_t bpbFATs; /* number of FATs */ + uint16_t bpbRootDirEnts; /* number of root directory entries */ + uint16_t bpbSectors; /* total number of sectors */ + uint8_t bpbMedia; /* media descriptor */ + uint16_t bpbFATsecs; /* number of sectors per FAT */ + uint16_t bpbSecPerTrack; /* sectors per track */ + uint16_t bpbHeads; /* number of heads */ + uint32_t bpbHiddenSecs; /* # of hidden sectors */ + uint32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */ }; /* * BPB for DOS 7.10 (FAT32). This one has a few extensions to bpb50. */ struct bpb710 { - u_int16_t bpbBytesPerSec; /* bytes per sector */ - u_int8_t bpbSecPerClust; /* sectors per cluster */ - u_int16_t bpbResSectors; /* number of reserved sectors */ - u_int8_t bpbFATs; /* number of FATs */ - u_int16_t bpbRootDirEnts; /* number of root directory entries */ - u_int16_t bpbSectors; /* total number of sectors */ - u_int8_t bpbMedia; /* media descriptor */ - u_int16_t bpbFATsecs; /* number of sectors per FAT */ - u_int16_t bpbSecPerTrack; /* sectors per track */ - u_int16_t bpbHeads; /* number of heads */ - u_int32_t bpbHiddenSecs; /* # of hidden sectors */ - u_int32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */ - u_int32_t bpbBigFATsecs; /* like bpbFATsecs for FAT32 */ - u_int16_t bpbExtFlags; /* extended flags: */ + uint16_t bpbBytesPerSec; /* bytes per sector */ + uint8_t bpbSecPerClust; /* sectors per cluster */ + uint16_t bpbResSectors; /* number of reserved sectors */ + uint8_t bpbFATs; /* number of FATs */ + uint16_t bpbRootDirEnts; /* number of root directory entries */ + uint16_t bpbSectors; /* total number of sectors */ + uint8_t bpbMedia; /* media descriptor */ + uint16_t bpbFATsecs; /* number of sectors per FAT */ + uint16_t bpbSecPerTrack; /* sectors per track */ + uint16_t bpbHeads; /* number of heads */ + uint32_t bpbHiddenSecs; /* # of hidden sectors */ + uint32_t bpbHugeSectors; /* # of sectors if bpbSectors == 0 */ + uint32_t bpbBigFATsecs; /* like bpbFATsecs for FAT32 */ + uint16_t bpbExtFlags; /* extended flags: */ #define FATNUM 0xf /* mask for numbering active FAT */ #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 */ - u_int32_t bpbRootClust; /* start cluster for root directory */ - u_int16_t bpbFSInfo; /* filesystem info structure sector */ - u_int16_t bpbBackup; /* backup boot sector */ - u_int8_t bpbReserved[12]; /* Reserved for future expansion */ + uint32_t bpbRootClust; /* start cluster for root directory */ + uint16_t bpbFSInfo; /* filesystem info structure sector */ + uint16_t bpbBackup; /* backup boot sector */ + uint8_t bpbReserved[12]; /* Reserved for future expansion */ }; #ifdef atari @@ -90,17 +90,17 @@ struct bpb710 { */ #if 0 struct bpb_a { - u_int16_t bpbBytesPerSec; /* bytes per sector */ - u_int8_t bpbSecPerClust; /* sectors per cluster */ - u_int16_t bpbResSectors; /* number of reserved sectors */ - u_int8_t bpbFATs; /* number of FATs */ - u_int16_t bpbRootDirEnts; /* number of root directory entries */ - u_int16_t bpbSectors; /* total number of sectors */ - u_int8_t bpbUseless1; /* meaningless on GEMDOS FS */ - u_int16_t bpbFATsecs; /* number of sectors per FAT */ - u_int16_t bpbUseless2; /* meaningless for harddisk fs */ - u_int16_t bpbUseless3; /* meaningless for harddisk fs */ - u_int16_t bpbHiddenSecs; /* the TOS-BIOS ignores this */ + uint16_t bpbBytesPerSec; /* bytes per sector */ + uint8_t bpbSecPerClust; /* sectors per cluster */ + uint16_t bpbResSectors; /* number of reserved sectors */ + uint8_t bpbFATs; /* number of FATs */ + uint16_t bpbRootDirEnts; /* number of root directory entries */ + uint16_t bpbSectors; /* total number of sectors */ + uint8_t bpbUseless1; /* meaningless on GEMDOS FS */ + uint16_t bpbFATsecs; /* number of sectors per FAT */ + uint16_t bpbUseless2; /* meaningless for harddisk fs */ + uint16_t bpbUseless3; /* meaningless for harddisk fs */ + uint16_t bpbHiddenSecs; /* the TOS-BIOS ignores this */ }; #endif #endif /* atari */ @@ -159,39 +159,39 @@ struct byte_bpb50 { * BPB for DOS 7.10 (FAT32). This one has a few extensions to bpb50. */ struct byte_bpb710 { - u_int8_t bpbBytesPerSec[2]; /* bytes per sector */ - u_int8_t bpbSecPerClust; /* sectors per cluster */ - u_int8_t bpbResSectors[2]; /* number of reserved sectors */ - u_int8_t bpbFATs; /* number of FATs */ - u_int8_t bpbRootDirEnts[2]; /* number of root directory entries */ - u_int8_t bpbSectors[2]; /* total number of sectors */ - u_int8_t bpbMedia; /* media descriptor */ - u_int8_t bpbFATsecs[2]; /* number of sectors per FAT */ - u_int8_t bpbSecPerTrack[2]; /* sectors per track */ - u_int8_t bpbHeads[2]; /* number of heads */ - u_int8_t bpbHiddenSecs[4]; /* # of hidden sectors */ - u_int8_t bpbHugeSectors[4]; /* # of sectors if bpbSectors == 0 */ - u_int8_t bpbBigFATsecs[4]; /* like bpbFATsecs for FAT32 */ - u_int8_t bpbExtFlags[2]; /* extended flags: */ - u_int8_t bpbFSVers[2]; /* filesystem version */ - u_int8_t bpbRootClust[4]; /* start cluster for root directory */ - u_int8_t bpbFSInfo[2]; /* filesystem info structure sector */ - u_int8_t bpbBackup[2]; /* backup boot sector */ - u_int8_t bpbReserved[12]; /* Reserved for future expansion */ + uint8_t bpbBytesPerSec[2]; /* bytes per sector */ + uint8_t bpbSecPerClust; /* sectors per cluster */ + uint8_t bpbResSectors[2]; /* number of reserved sectors */ + uint8_t bpbFATs; /* number of FATs */ + uint8_t bpbRootDirEnts[2]; /* number of root directory entries */ + uint8_t bpbSectors[2]; /* total number of sectors */ + uint8_t bpbMedia; /* media descriptor */ + uint8_t bpbFATsecs[2]; /* number of sectors per FAT */ + uint8_t bpbSecPerTrack[2]; /* sectors per track */ + uint8_t bpbHeads[2]; /* number of heads */ + uint8_t bpbHiddenSecs[4]; /* # of hidden sectors */ + uint8_t bpbHugeSectors[4]; /* # of sectors if bpbSectors == 0 */ + uint8_t bpbBigFATsecs[4]; /* like bpbFATsecs for FAT32 */ + uint8_t bpbExtFlags[2]; /* extended flags: */ + uint8_t bpbFSVers[2]; /* filesystem version */ + uint8_t bpbRootClust[4]; /* start cluster for root directory */ + uint8_t bpbFSInfo[2]; /* filesystem info structure sector */ + uint8_t bpbBackup[2]; /* backup boot sector */ + uint8_t bpbReserved[12]; /* Reserved for future expansion */ }; /* * FAT32 FSInfo block. */ struct fsinfo { - u_int8_t fsisig1[4]; - u_int8_t fsifill1[480]; - u_int8_t fsisig2[4]; - u_int8_t fsinfree[4]; - u_int8_t fsinxtfree[4]; - u_int8_t fsifill2[12]; - u_int8_t fsisig3[4]; - u_int8_t fsifill3[508]; - u_int8_t fsisig4[4]; + uint8_t fsisig1[4]; + uint8_t fsifill1[480]; + uint8_t fsisig2[4]; + uint8_t fsinfree[4]; + uint8_t fsinxtfree[4]; + uint8_t fsifill2[12]; + uint8_t fsisig3[4]; + uint8_t fsifill3[508]; + uint8_t fsisig4[4]; }; #endif /* _MSDOSFS_BPB_H_ */ diff --git a/sys/fs/msdosfs/denode.h b/sys/fs/msdosfs/denode.h index 57c13dad6..1c64d64d3 100644 --- a/sys/fs/msdosfs/denode.h +++ b/sys/fs/msdosfs/denode.h @@ -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. @@ -212,7 +212,8 @@ struct denode { #define DE_INTERNALIZE32(dep, dp) \ ((dep)->de_StartCluster |= getushort((dp)->deHighClust) << 16) #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_CHun = (dp)->deCHundredth, \ (dep)->de_CTime = getushort((dp)->deCTime), \ @@ -229,7 +230,8 @@ struct denode { #define DE_EXTERNALIZE16(dp, dep) \ putushort((dp)->deHighClust, 0) #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)->deCHundredth = (dep)->de_CHun, \ putushort((dp)->deCTime, (dep)->de_CTime), \ diff --git a/sys/fs/msdosfs/direntry.h b/sys/fs/msdosfs/direntry.h index c3d1b9b78..913e09a63 100644 --- a/sys/fs/msdosfs/direntry.h +++ b/sys/fs/msdosfs/direntry.h @@ -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. @@ -53,12 +53,12 @@ * Structure of a dos directory entry. */ 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_E5 0x05 /* the real value is 0xe5 */ #define SLOT_DELETED 0xe5 /* file in this slot deleted */ - u_int8_t deExtension[3]; /* extension, blank filled */ - u_int8_t deAttributes; /* file attributes */ + uint8_t deExtension[3]; /* extension, blank filled */ + uint8_t deAttributes; /* file attributes */ #define ATTR_NORMAL 0x00 /* normal file */ #define ATTR_READONLY 0x01 /* file is readonly */ #define ATTR_HIDDEN 0x02 /* file is hidden */ @@ -66,16 +66,16 @@ struct direntry { #define ATTR_VOLUME 0x08 /* entry is a volume label */ #define ATTR_DIRECTORY 0x10 /* entry is a directory name */ #define ATTR_ARCHIVE 0x20 /* file is new or modified */ - u_int8_t deReserved; /* reserved */ - u_int8_t deCHundredth; /* hundredth of seconds in CTime */ - u_int8_t deCTime[2]; /* create time */ - u_int8_t deCDate[2]; /* create date */ - u_int8_t deADate[2]; /* access date */ - u_int8_t deHighClust[2]; /* high bytes of cluster number */ - u_int8_t deMTime[2]; /* last update time */ - u_int8_t deMDate[2]; /* last update date */ - u_int8_t deStartCluster[2]; /* starting cluster of file */ - u_int8_t deFileSize[4]; /* size of file in bytes */ + uint8_t deReserved; /* reserved */ + uint8_t deCHundredth; /* hundredth of seconds in CTime */ + uint8_t deCTime[2]; /* create time */ + uint8_t deCDate[2]; /* create date */ + uint8_t deADate[2]; /* access date */ + uint8_t deHighClust[2]; /* high bytes of cluster number */ + uint8_t deMTime[2]; /* last update time */ + uint8_t deMDate[2]; /* last update date */ + uint8_t deStartCluster[2]; /* starting cluster of file */ + uint8_t deFileSize[4]; /* size of file in bytes */ }; 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 */ struct winentry { - u_int8_t weCnt; + uint8_t weCnt; #define WIN_LAST 0x40 #define WIN_CNT 0x3f - u_int8_t wePart1[10]; - u_int8_t weAttributes; + uint8_t wePart1[10]; + uint8_t weAttributes; #define ATTR_WIN95 0x0f - u_int8_t weReserved1; - u_int8_t weChksum; - u_int8_t wePart2[12]; - u_int16_t weReserved2; - u_int8_t wePart3[4]; + uint8_t weReserved1; + uint8_t weChksum; + uint8_t wePart2[12]; + uint16_t weReserved2; + uint8_t wePart3[4]; }; #define WIN_CHARS 13 /* Number of chars per winentry */ @@ -128,19 +128,20 @@ struct winentry { #if defined(_KERNEL) || defined(MAKEFS) struct dirent; -void unix2dostime(const struct timespec *tsp, int gmtoff, u_int16_t *ddp, - u_int16_t *dtp, u_int8_t *dhp); -void dos2unixtime(u_int dd, u_int dt, u_int dh, int gmtoff, - struct timespec *tsp); -int dos2unixfn(u_char dn[11], u_char *un, int lower); -int unix2dosfn(const u_char *un, u_char dn[12], int unlen, - u_int gen); -int unix2winfn(const u_char *un, int unlen, struct winentry *wep, - int cnt, int chksum); -int winChkName(const u_char *un, int unlen, struct winentry *wep, - int chksum); -int win2unixfn(struct winentry *wep, struct dirent *dp, int chksum); -u_int8_t winChksum(u_int8_t *name); -int winSlotCnt(const u_char *un, int unlen); +void unix2dostime(const struct timespec *tsp, int gmtoff, uint16_t *ddp, + uint16_t *dtp, uint8_t *dhp); +void dos2unixtime(unsigned int dd, unsigned int dt, unsigned int dh, + int gmtoff, struct timespec *tsp); +int dos2unixfn(unsigned char dn[11], unsigned char *un, int lower); +int unix2dosfn(const unsigned char *un, unsigned char dn[12], int unlen, + unsigned int gen); +int unix2winfn(const unsigned char *un, int unlen, struct winentry *wep, + int cnt, int chksum, int utf8); +int winChkName(const unsigned char *un, int unlen, struct winentry *wep, + int chksum, int utf8); +int win2unixfn(struct winentry *wep, struct dirent *dp, int chksum, + uint16_t *namlen, int utf8); +uint8_t winChksum(uint8_t *name); +int winSlotCnt(const unsigned char *un, int unlen, int utf8); #endif /* _KERNEL || MAKEFS */ #endif /* _MSDOSFS_DIRENTRY_H_ */ diff --git a/sys/fs/msdosfs/files.msdosfs b/sys/fs/msdosfs/files.msdosfs index 0170819ca..24e6c1f34 100644 --- a/sys/fs/msdosfs/files.msdosfs +++ b/sys/fs/msdosfs/files.msdosfs @@ -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 @@ -9,3 +9,4 @@ file fs/msdosfs/msdosfs_fat.c msdosfs file fs/msdosfs/msdosfs_lookup.c msdosfs file fs/msdosfs/msdosfs_vfsops.c msdosfs file fs/msdosfs/msdosfs_vnops.c msdosfs +file fs/msdosfs/msdosfs_unicode.c msdosfs diff --git a/sys/fs/msdosfs/msdosfs_conv.c b/sys/fs/msdosfs/msdosfs_conv.c index ba3ca918f..58a83a025 100644 --- a/sys/fs/msdosfs/msdosfs_conv.c +++ b/sys/fs/msdosfs/msdosfs_conv.c @@ -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. @@ -45,20 +45,27 @@ * any damages caused by this software. * * October 1992 + * */ #if HAVE_NBTOOL_CONFIG_H #include "nbtool_config.h" #endif +#ifndef _KERNEL +#include +#define KASSERT(x) assert(x) +#endif + #include -__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. */ #include #include +#include #ifdef _KERNEL #include #include @@ -78,6 +85,22 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_conv.c,v 1.10 2014/09/01 09:09:47 martin Exp #include #include +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 * 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 */ 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_int8_t *wcp; - int i; + u_int16_t wn[WIN_MAXLEN], *p; + int i, len; + const u_char *cp; /* * 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 */ - for (wcp = (u_int8_t *)wep, i = sizeof(*wep); --i >= 0; *wcp++ = 0xff); + memset(wep, 0xff, sizeof(*wep)); wep->weCnt = cnt; wep->weAttributes = ATTR_WIN95; wep->weReserved1 = 0; @@ -538,33 +571,18 @@ unix2winfn(const u_char *un, int unlen, struct winentry *wep, int cnt, int chksu 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;) { - if (--unlen < 0) - goto done; - *wcp++ = *un++; - *wcp++ = 0; - } - for (wcp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) { - if (--unlen < 0) - goto done; - *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; + p = &wn[i]; + memcpy(wep->wePart1, p, sizeof(wep->wePart1)); + p += sizeof(wep->wePart1) / sizeof(*p); + memcpy(wep->wePart2, p, sizeof(wep->wePart2)); + p += sizeof(wep->wePart2) / sizeof(*p); + memcpy(wep->wePart3, p, sizeof(wep->wePart3)); + + if (len > i + WIN_CHARS) + return 1; -done: - *wcp++ = 0; - *wcp++ = 0; wep->weCnt |= WIN_LAST; return 0; } @@ -574,15 +592,16 @@ done: * Returns the checksum or -1 if no match */ 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; - int i; + u_int16_t wn[WIN_MAXLEN], *p; + u_int16_t buf[WIN_CHARS]; + int i, len; /* * First compare checksums */ - if (wep->weCnt&WIN_LAST) + if (wep->weCnt & WIN_LAST) chksum = wep->weChksum; else if (chksum != wep->weChksum) chksum = -1; @@ -592,56 +611,35 @@ winChkName(const u_char *un, int unlen, struct winentry *wep, int chksum) /* * Offset of this entry */ - i = ((wep->weCnt&WIN_CNT) - 1) * WIN_CHARS; - un += i; - if ((unlen -= i) < 0) + i = ((wep->weCnt & WIN_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); + + if (i >= len + 1) + return -1; + if ((wep->weCnt & WIN_LAST) && (len - i > WIN_CHARS)) return -1; /* - * Ignore redundant winentries (those with only \0\0 on start in them). - * An appearance of such entry is a bug; unknown if in NetBSD msdosfs - * or MS Windows. + * Fetch name segment from directory entry */ - if (unlen == 0) { - if (wep->wePart1[0] == '\0' && wep->wePart1[1] == '\0') - return chksum; - else - return -1; - } - - if ((wep->weCnt&WIN_LAST) && unlen > WIN_CHARS) - return -1; + p = &buf[0]; + memcpy(p, wep->wePart1, sizeof(wep->wePart1)); + p += sizeof(wep->wePart1) / sizeof(*p); + memcpy(p, wep->wePart2, sizeof(wep->wePart2)); + p += sizeof(wep->wePart2) / sizeof(*p); + memcpy(p, wep->wePart3, sizeof(wep->wePart3)); /* - * Compare the name parts + * And compare name segment */ - for (cp = wep->wePart1, i = sizeof(wep->wePart1)/2; --i >= 0;) { - if (--unlen < 0) { - 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; - } + if (! (utf8 ? ucs2match(&wn[i], buf, WIN_CHARS) : char8match(&wn[i], buf, WIN_CHARS))) + return -1; + 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 */ 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_int8_t *np, *ep = (u_int8_t *)dp->d_name + WIN_MAXLEN; - int i; + u_int16_t wn[WIN_CHARS], *p; + u_int8_t buf[WIN_CHARS*3]; + int len; - if ((wep->weCnt&WIN_CNT) > howmany(WIN_MAXLEN, WIN_CHARS) - || !(wep->weCnt&WIN_CNT)) + if ((wep->weCnt & WIN_CNT) > howmany(WIN_MAXLEN, WIN_CHARS) + || !(wep->weCnt & WIN_CNT)) return -1; /* * First compare checksums */ - if (wep->weCnt&WIN_LAST) { + if (wep->weCnt & WIN_LAST) { chksum = wep->weChksum; - /* - * This works even though d_namlen is one byte! - */ -#ifdef __NetBSD__ - dp->d_namlen = (wep->weCnt&WIN_CNT) * WIN_CHARS; -#endif + *namlen = 0; } else if (chksum != wep->weChksum) chksum = -1; if (chksum == -1) return -1; /* - * Offset of this entry + * Fetch name segment from directory entry */ - i = ((wep->weCnt&WIN_CNT) - 1) * WIN_CHARS; - np = (u_int8_t *)dp->d_name + i; + p = &wn[0]; + memcpy(p, wep->wePart1, sizeof(wep->wePart1)); + p += sizeof(wep->wePart1) / sizeof(*p); + memcpy(p, wep->wePart2, sizeof(wep->wePart2)); + p += sizeof(wep->wePart2) / sizeof(*p); + memcpy(p, wep->wePart3, sizeof(wep->wePart3)); /* - * 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;) { - switch (*np++ = *cp++) { - case 0: -#ifdef __NetBSD__ - dp->d_namlen -= sizeof(wep->wePart2)/2 - + sizeof(wep->wePart3)/2 + i + 1; -#endif - return chksum; - case '/': - np[-1] = 0; - return -1; - } - /* - * The size comparison should result in the compiler - * optimizing the whole if away - */ - if (WIN_MAXLEN % WIN_CHARS < sizeof(wep->wePart1) / 2 - && np > ep) { - np[-1] = 0; - return -1; - } - if (*cp++) - return -1; - } - for (cp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) { - switch (*np++ = *cp++) { - case 0: -#ifdef __NetBSD__ - dp->d_namlen -= sizeof(wep->wePart3)/2 + i + 1; -#endif - return chksum; - 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; - } + if (invalidname(wn, WIN_CHARS)) + return -1; + + /* + * Translate ucs-2 to UNIX name + */ + len = utf8 ? ucs2utf8str(wn, WIN_CHARS, buf, sizeof(buf)) + : ucs2char8str(wn, WIN_CHARS, buf, sizeof(buf)); + + KASSERT(len >= 0); + KASSERT((size_t)len <= MIN(sizeof(buf), sizeof(dp->d_name)-1)); + + /* + * Prepend name segment to directory entry + * + * This ignores the slot number from the windows entry but + * assumes that segments are read in reverse order. + * + * The UCS-2 name (up to 255 chars) can overflow the UNIX + * directory entry (up to 511 bytes). Trailing characters + * are silently discarded. This could also end in multiple + * files using the same (truncated) name. + */ + *namlen += len; + if (*namlen > sizeof(dp->d_name) - 1) + *namlen = sizeof(dp->d_name) - 1; + + KASSERT(*namlen >= len); + + memmove(&dp->d_name[len], &dp->d_name[0], *namlen - len); + memcpy(dp->d_name, buf, len); + return chksum; } @@ -767,7 +728,7 @@ winChksum(u_int8_t *name) u_int8_t s; for (s = 0, i = 11; --i >= 0; s += *name++) - s = (s << 7)|(s >> 1); + s = (s << 7) | (s >> 1); return s; } @@ -775,12 +736,304 @@ winChksum(u_int8_t *name) * Determine the number of slots necessary for Win95 names */ int -winSlotCnt(const u_char *un, int unlen) +winSlotCnt(const u_char *un, int unlen, int utf8) { - for (un += unlen; unlen > 0; unlen--) - if (*--un != ' ' && *un != '.') + const u_char *cp; + int len; + + /* + * Drop trailing blanks and dots + */ + for (cp = un + unlen; unlen > 0; unlen--) + if (*--cp != ' ' && *cp != '.') break; - if (unlen > WIN_MAXLEN) - return 0; - return howmany(unlen, WIN_CHARS); + + len = utf8 ? utf8ucs2str(un, unlen, NULL, WIN_MAXLEN) : unlen; + + 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; +} + diff --git a/sys/fs/msdosfs/msdosfs_denode.c b/sys/fs/msdosfs/msdosfs_denode.c index 579a4a958..b51f36cfa 100644 --- a/sys/fs/msdosfs/msdosfs_denode.c +++ b/sys/fs/msdosfs/msdosfs_denode.c @@ -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. @@ -48,12 +48,11 @@ */ #include -__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 #include #include -#include #include #include #include @@ -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; -extern int prtactive; - struct fh_key { struct msdosfsmount *fhk_mount; uint32_t fhk_dircluster; @@ -128,6 +125,7 @@ static const struct genfs_ops msdosfs_genfsops = { .gop_alloc = msdosfs_gop_alloc, .gop_write = genfs_gop_write, .gop_markupdate = msdosfs_gop_markupdate, + .gop_putrange = genfs_gop_putrange, }; MALLOC_DECLARE(M_MSDOSFSFAT); @@ -427,7 +425,7 @@ detrunc(struct denode *dep, u_long length, int flags, kauth_cred_t cred) } else { ubc_zerorange(&DETOV(dep)->v_uobj, length, 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; ubc_zerorange(&DETOV(dep)->v_uobj, (off_t)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); return (deupdat(dep, 1)); } @@ -533,25 +531,19 @@ deextend(struct denode *dep, u_long length, kauth_cred_t cred) int msdosfs_reclaim(void *v) { - struct vop_reclaim_args /* { + struct vop_reclaim_v2_args /* { struct vnode *a_vp; } */ *ap = v; struct vnode *vp = ap->a_vp; - struct mount *mp = vp->v_mount; struct denode *dep = VTODE(vp); - fstrans_start(mp, FSTRANS_LAZY); + VOP_UNLOCK(vp); + #ifdef MSDOSFS_DEBUG printf("msdosfs_reclaim(): dep %p, file %s, refcnt %ld\n", dep, dep->de_Name, dep->de_refcnt); #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. */ @@ -570,19 +562,17 @@ msdosfs_reclaim(void *v) vp->v_data = NULL; mutex_exit(vp->v_interlock); pool_put(&msdosfs_denode_pool, dep); - fstrans_done(mp); return (0); } int msdosfs_inactive(void *v) { - struct vop_inactive_args /* { + struct vop_inactive_v2_args /* { struct vnode *a_vp; bool *a_recycle; } */ *ap = v; struct vnode *vp = ap->a_vp; - struct mount *mp = vp->v_mount; struct denode *dep = VTODE(vp); 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]); #endif - fstrans_start(mp, FSTRANS_LAZY); /* * Get rid of denodes related to stale file handles. */ @@ -622,12 +611,11 @@ out: * so that it can be reused immediately. */ #ifdef MSDOSFS_DEBUG - printf("msdosfs_inactive(): v_usecount %d, de_Name[0] %x\n", - vp->v_usecount, dep->de_Name[0]); + printf("msdosfs_inactive(): usecount %d, de_Name[0] %x\n", + vrefcnt(vp), dep->de_Name[0]); #endif *ap->a_recycle = (dep->de_Name[0] == SLOT_DELETED); - VOP_UNLOCK(vp); - fstrans_done(mp); + return (error); } diff --git a/sys/fs/msdosfs/msdosfs_fat.c b/sys/fs/msdosfs/msdosfs_fat.c index b1beb0d1a..ee93b6bab 100644 --- a/sys/fs/msdosfs/msdosfs_fat.c +++ b/sys/fs/msdosfs/msdosfs_fat.c @@ -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. @@ -52,7 +52,7 @@ #endif #include -__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. @@ -69,6 +69,7 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_fat.c,v 1.29 2015/03/28 19:24:05 maxv Exp $" #include #include /* to define vattr structure */ #else +#include #include #endif @@ -143,7 +144,7 @@ fatblock(struct msdosfsmount *pmp, u_long ofs, u_long *bnp, u_long *sizep, u_lon u_long bn, size; 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; 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) *cnp = MSDOSFSROOT; if (sp) - *sp = min(pmp->pm_bpcluster, + *sp = uimin(pmp->pm_bpcluster, dep->de_FileSize - de_cn2off(pmp, findcn)); DPRINTF(("%s(root, bn=%lu, cn=%u)\n", __func__, 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)) 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); fatblock(pmp, byteoffset, &bn, &bsize, &bo); if (bn != bp_bn) { @@ -383,7 +396,7 @@ fc_purge(struct denode *dep, u_int frcn) void updatefats(struct msdosfsmount *pmp, struct buf *bp, u_long fatbn) { - int i; + int i, error; struct buf *bpn; 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 && (pmp->pm_inusemap[cn / N_INUSEBITS] - & (1 << (cn % N_INUSEBITS)))) { + & (1U << (cn % N_INUSEBITS)))) { /* * The cluster indicated in FSInfo isn't free * 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), bp->b_bcount, 0, 0); memcpy(bpn->b_data, bp->b_data, bp->b_bcount); - if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) - bwrite(bpn); - else + if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) { + error = bwrite(bpn); + if (error) + printf("%s: copy FAT %d (error=%d)\n", + __func__, i, error); + } else bdwrite(bpn); } } @@ -458,9 +474,12 @@ updatefats(struct msdosfsmount *pmp, struct buf *bp, u_long fatbn) /* * Write out the first (or current) FAT last. */ - if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) - bwrite(bp); - else + if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) { + error = bwrite(bp); + if (error) + printf("%s: write FAT (error=%d)\n", + __func__, error); + } else bdwrite(bp); /* * Maybe update fsinfo sector here? @@ -490,7 +509,7 @@ static inline void 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--; } @@ -499,7 +518,7 @@ usemap_free(struct msdosfsmount *pmp, u_long cn) { pmp->pm_freeclustercount++; - pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1 << (cn % N_INUSEBITS)); + pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1U << (cn % N_INUSEBITS)); } int @@ -722,7 +741,7 @@ chainlength(struct msdosfsmount *pmp, u_long start, u_long count) idx = start / N_INUSEBITS; start %= N_INUSEBITS; map = pmp->pm_inusemap[idx]; - map &= ~((1 << start) - 1); + map &= ~((1U << start) - 1); if (map) { len = ffs(map) - 1 - start; 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;) { idx = cn / N_INUSEBITS; map = pmp->pm_inusemap[idx]; - map |= (1 << (cn % N_INUSEBITS)) - 1; + map |= (1U << (cn % N_INUSEBITS)) - 1; if (map != (u_int)-1) { cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1; 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;) { idx = cn / N_INUSEBITS; map = pmp->pm_inusemap[idx]; - map |= (1 << (cn % N_INUSEBITS)) - 1; + map |= (1U << (cn % N_INUSEBITS)) - 1; if (map != (u_int)-1) { cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1; 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 readcn, lbn = -1; + bn = 0; /* XXXgcc */ while (cluster >= CLUST_FIRST && cluster <= pmp->pm_maxcluster) { byteoffset = FATOFS(pmp, cluster); fatblock(pmp, byteoffset, &bn, &bsize, &bo); diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c index 84705a58b..f92969373 100644 --- a/sys/fs/msdosfs/msdosfs_lookup.c +++ b/sys/fs/msdosfs/msdosfs_lookup.c @@ -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. @@ -52,7 +52,7 @@ #endif #include -__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 @@ -161,6 +161,10 @@ msdosfs_lookup(void *v) 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, * they won't find it. DOS filesystems don't have them in the root @@ -187,12 +191,12 @@ msdosfs_lookup(void *v) break; case 2: wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, - cnp->cn_namelen) + 1; + cnp->cn_namelen, pmp->pm_flags & MSDOSFSMNT_UTF8) + 1; break; case 3: olddos = 0; wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, - cnp->cn_namelen) + 1; + cnp->cn_namelen, pmp->pm_flags & MSDOSFSMNT_UTF8) + 1; break; } if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) @@ -282,7 +286,8 @@ msdosfs_lookup(void *v) chksum = winChkName((const u_char *)cnp->cn_nameptr, cnp->cn_namelen, (struct winentry *)dep, - chksum); + chksum, + pmp->pm_flags & MSDOSFSMNT_UTF8); continue; } @@ -652,7 +657,8 @@ createde(struct denode *dep, struct denode *ddep, struct denode **depp, struct c fndoffset -= sizeof(struct direntry); } if (!unix2winfn(un, unlen, (struct winentry *)ndep, - wcnt, chksum)) + wcnt, chksum, + ddep->de_pmp->pm_flags & MSDOSFSMNT_UTF8)) break; } } diff --git a/sys/fs/msdosfs/msdosfs_unicode.c b/sys/fs/msdosfs/msdosfs_unicode.c new file mode 100644 index 000000000..53d9c7da1 --- /dev/null +++ b/sys/fs/msdosfs/msdosfs_unicode.c @@ -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 +#include + +/* + * 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); diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c index 981f3c5e2..c48f404e9 100644 --- a/sys/fs/msdosfs/msdosfs_vfsops.c +++ b/sys/fs/msdosfs/msdosfs_vfsops.c @@ -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. @@ -48,7 +48,7 @@ */ #include -__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) #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 #include #include -#include #include #include #include @@ -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_MSDOSFSTMP, "MSDOSFS temp", "MSDOS FS temp. structures"); -static struct sysctllog *msdosfs_sysctl_log; - extern const struct vnodeopv_desc msdosfs_vnodeop_opv_desc; const struct vnodeopv_desc * const msdosfs_vnodeopv_descs[] = { @@ -136,13 +133,28 @@ struct vfsops msdosfs_vfsops = { .vfs_mountroot = msdosfs_mountroot, .vfs_snapshot = (void *)eopnotsupp, .vfs_extattrctl = vfs_stdextattrctl, - .vfs_suspendctl = msdosfs_suspendctl, + .vfs_suspendctl = genfs_suspendctl, .vfs_renamelock_enter = genfs_renamelock_enter, .vfs_renamelock_exit = genfs_renamelock_exit, .vfs_fsync = (void *)eopnotsupp, .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 msdos_modcmd(modcmd_t cmd, void *arg) { @@ -153,23 +165,11 @@ msdos_modcmd(modcmd_t cmd, void *arg) error = vfs_attach(&msdosfs_vfsops); if (error != 0) 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; case MODULE_CMD_FINI: error = vfs_detach(&msdosfs_vfsops); if (error != 0) break; - sysctl_teardown(&msdosfs_sysctl_log); break; default: error = ENOTTY; @@ -210,7 +210,8 @@ update_mp(struct mount *mp, struct msdosfs_args *argp) if (FAT32(pmp)) pmp->pm_flags |= MSDOSFSMNT_LONGNAME; else { - if ((error = msdosfs_root(mp, &rtvp)) != 0) + error = msdosfs_root(mp, LK_EXCLUSIVE, &rtvp); + if (error != 0) return error; pmp->pm_flags |= findwin95(VTODE(rtvp)) ? MSDOSFSMNT_LONGNAME @@ -248,22 +249,22 @@ msdosfs_mountroot(void) args.dirmask = 0777; if ((error = msdosfs_mountfs(rootvp, mp, l, &args)) != 0) { - vfs_unbusy(mp, false, NULL); - vfs_destroy(mp); + vfs_unbusy(mp); + vfs_rele(mp); return (error); } if ((error = update_mp(mp, &args)) != 0) { (void)msdosfs_unmount(mp, 0); - vfs_unbusy(mp, false, NULL); - vfs_destroy(mp); + vfs_unbusy(mp); + vfs_rele(mp); vrele(rootvp); return (error); } mountlist_append(mp); (void)msdosfs_statvfs(mp, &mp->mnt_stat); - vfs_unbusy(mp, false, NULL); + vfs_unbusy(mp); return (0); } @@ -468,6 +469,7 @@ msdosfs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l, struct msd int ronly, error, BlkPerSec; uint64_t psize; unsigned secsize; + u_long fatbytes, fatblocksecs; /* Flush out any old buffers remaining from a previous use. */ 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 */ pmp = NULL; - error = fstrans_mount(mp); - if (error) - goto error_exit; - error = getdisksize(devvp, &psize, &secsize); if (error) { 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; 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 (bsp->bs50.bsBootSectSig0 != BOOTSIG0 || bsp->bs50.bsBootSectSig1 != BOOTSIG1) { @@ -532,6 +537,7 @@ msdosfs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l, struct msd goto error_exit; } } +#endif pmp = malloc(sizeof(*pmp), M_MSDOSFSMNT, M_WAITOK|M_ZERO); 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; } } - 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; /* @@ -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_namemax = MSDOSFS_NAMEMAX(pmp); mp->mnt_flag |= MNT_LOCAL; + mp->mnt_iflag |= IMNT_SHRLOOKUP; mp->mnt_dev_bshift = pmp->pm_bnshift; 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); error_exit: - fstrans_unmount(mp); if (bp) brelse(bp, BC_AGE); if (pmp) { @@ -900,13 +934,10 @@ msdosfs_unmount(struct mount *mp, int mntflags) printf("msdosfs_umount(): just before calling VOP_CLOSE()\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); printf("mount %p, op %p\n", 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", vp->v_cleanblkhd.lh_first, vp->v_dirtyblkhd.lh_first, @@ -926,12 +957,11 @@ msdosfs_unmount(struct mount *mp, int mntflags) free(pmp, M_MSDOSFSMNT); mp->mnt_data = NULL; mp->mnt_flag &= ~MNT_LOCAL; - fstrans_unmount(mp); return (0); } int -msdosfs_root(struct mount *mp, struct vnode **vpp) +msdosfs_root(struct mount *mp, int lktype, struct vnode **vpp) { struct msdosfsmount *pmp = VFSTOMSDOSFS(mp); int error; @@ -941,7 +971,7 @@ msdosfs_root(struct mount *mp, struct vnode **vpp) #endif if ((error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, vpp)) != 0) return error; - error = vn_lock(*vpp, LK_EXCLUSIVE); + error = vn_lock(*vpp, lktype); if (error) { vrele(*vpp); *vpp = NULL; @@ -981,12 +1011,14 @@ msdosfs_sync_selector(void *cl, struct vnode *vp) struct msdosfs_sync_ctx *c = cl; struct denode *dep; + KASSERT(mutex_owned(vp->v_interlock)); + dep = VTODE(vp); if (c->waitfor == MNT_LAZY || vp->v_type == VNON || dep == NULL || (((dep->de_flag & (DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0) && (LIST_EMPTY(&vp->v_dirtyblkhd) && - UVM_OBJ_IS_CLEAN(&vp->v_uobj)))) + (vp->v_iflag & VI_ONWORKLST) == 0))) return false; return true; } @@ -1011,7 +1043,6 @@ msdosfs_sync(struct mount *mp, int waitfor, kauth_cred_t cred) /* update FATs here */ } } - fstrans_start(mp, FSTRANS_SHARED); /* * 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. */ + vn_lock(pmp->pm_devvp, LK_EXCLUSIVE | LK_RETRY); if ((error = VOP_FSYNC(pmp->pm_devvp, cred, waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0)) != 0) allerror = error; - fstrans_done(mp); + VOP_UNLOCK(pmp->pm_devvp); return (allerror); } 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 defid defh; @@ -1069,7 +1101,7 @@ msdosfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) *vpp = NULLVP; return error; } - error = vn_lock(*vpp, LK_EXCLUSIVE); + error = vn_lock(*vpp, lktype); if (error) { vrele(*vpp); *vpp = NULLVP; @@ -1104,36 +1136,9 @@ msdosfs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size) } int -msdosfs_vget(struct mount *mp, ino_t ino, +msdosfs_vget(struct mount *mp, ino_t ino, int lktype, struct vnode **vpp) { 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; - } -} diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c index 64895abfb..a3c3c5750 100644 --- a/sys/fs/msdosfs/msdosfs_vnops.c +++ b/sys/fs/msdosfs/msdosfs_vnops.c @@ -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. @@ -48,7 +48,7 @@ */ #include -__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 #include @@ -60,7 +60,6 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.93 2015/04/04 12:34:44 riastradh #include #include #include -#include #include #include #include @@ -120,7 +119,6 @@ msdosfs_create(void *v) printf("msdosfs_create(cnp %p, vap %p\n", cnp, ap->a_vap); #endif - fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED); /* * 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 @@ -153,13 +151,13 @@ msdosfs_create(void *v) DETIMES(&ndirent, NULL, NULL, NULL, pdep->de_pmp->pm_gmtoff); if ((error = createde(&ndirent, pdep, &dep, cnp)) != 0) goto bad; - fstrans_done(ap->a_dvp->v_mount); VN_KNOTE(ap->a_dvp, NOTE_WRITE); *ap->a_vpp = DETOV(dep); + cache_enter(ap->a_dvp, *ap->a_vpp, cnp->cn_nameptr, cnp->cn_namelen, + cnp->cn_flags); return (0); bad: - fstrans_done(ap->a_dvp->v_mount); return (error); } @@ -174,17 +172,15 @@ msdosfs_close(void *v) struct vnode *vp = ap->a_vp; struct denode *dep = VTODE(vp); - fstrans_start(vp->v_mount, FSTRANS_SHARED); mutex_enter(vp->v_interlock); - if (vp->v_usecount > 1) + if (vrefcnt(vp) > 1) DETIMES(dep, NULL, NULL, NULL, dep->de_pmp->pm_gmtoff); mutex_exit(vp->v_interlock); - fstrans_done(vp->v_mount); return (0); } 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 * character device resident on the file system. */ - if (mode & VWRITE) { + if (accmode & VWRITE) { switch (vp->v_type) { case VDIR: case VLNK: @@ -208,7 +204,7 @@ msdosfs_check_possible(struct vnode *vp, struct denode *dep, mode_t mode) } 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) { 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); - return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, - vp->v_type, file_mode), vp, NULL, genfs_can_access(vp->v_type, - file_mode, pmp->pm_uid, pmp->pm_gid, mode, cred)); + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, + vp->v_type, file_mode), vp, NULL, genfs_can_access(vp, cred, + pmp->pm_uid, pmp->pm_gid, file_mode, NULL, accmode)); } int @@ -231,18 +227,18 @@ msdosfs_access(void *v) { struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + accmode_t a_accmode; kauth_cred_t a_cred; } */ *ap = v; struct vnode *vp = ap->a_vp; struct denode *dep = VTODE(vp); int error; - error = msdosfs_check_possible(vp, dep, ap->a_mode); + error = msdosfs_check_possible(vp, dep, ap->a_accmode); if (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; } @@ -262,7 +258,6 @@ msdosfs_getattr(void *v) u_long dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry); ino_t fileid; - fstrans_start(ap->a_vp->v_mount, FSTRANS_SHARED); DETIMES(dep, NULL, NULL, NULL, pmp->pm_gmtoff); vap->va_fsid = dep->de_dev; /* @@ -313,7 +308,6 @@ msdosfs_getattr(void *v) vap->va_bytes = (dep->de_FileSize + pmp->pm_crbomask) & ~pmp->pm_crbomask; vap->va_type = ap->a_vp->v_type; - fstrans_done(ap->a_vp->v_mount); return (0); } @@ -361,7 +355,6 @@ msdosfs_setattr(void *v) if (ap->a_vp->v_type == VDIR) return 0; - fstrans_start(vp->v_mount, FSTRANS_SHARED); if (vap->va_size != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) { error = EROFS; @@ -378,8 +371,8 @@ msdosfs_setattr(void *v) goto bad; } error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, - ap->a_vp, NULL, genfs_can_chtimes(ap->a_vp, vap->va_vaflags, - pmp->pm_uid, cred)); + ap->a_vp, NULL, genfs_can_chtimes(ap->a_vp, cred, + pmp->pm_uid, vap->va_vaflags)); if (error) goto bad; if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 && @@ -402,7 +395,7 @@ msdosfs_setattr(void *v) goto bad; } 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) goto bad; /* We ignore the read and execute bits. */ @@ -422,7 +415,7 @@ msdosfs_setattr(void *v) goto bad; } 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) goto bad; if (vap->va_flags & SF_ARCHIVED) @@ -441,7 +434,6 @@ msdosfs_setattr(void *v) } bad: - fstrans_done(vp->v_mount); return error; } @@ -478,7 +470,6 @@ msdosfs_read(void *v) if (uio->uio_offset >= dep->de_FileSize) return (0); - fstrans_start(vp->v_mount, FSTRANS_SHARED); if (vp->v_type == VREG) { const int advice = IO_ADV_DECODE(ap->a_ioflag); @@ -489,7 +480,7 @@ msdosfs_read(void *v) if (bytelen == 0) break; 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) break; } @@ -503,7 +494,6 @@ msdosfs_read(void *v) on = uio->uio_offset & pmp->pm_crbomask; n = MIN(pmp->pm_bpcluster - on, uio->uio_resid); if (uio->uio_offset >= dep->de_FileSize) { - fstrans_done(vp->v_mount); return (0); } /* file size (and hence diff) may be up to 4GB */ @@ -540,7 +530,6 @@ out: error = uerror; } bad: - fstrans_done(vp->v_mount); return (error); } @@ -599,7 +588,6 @@ msdosfs_write(void *v) if (uio->uio_offset + uio->uio_resid > MSDOSFS_FILESIZE_MAX) return (EFBIG); - fstrans_start(vp->v_mount, FSTRANS_SHARED); /* * 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 @@ -608,7 +596,6 @@ msdosfs_write(void *v) */ if (uio->uio_offset > dep->de_FileSize) { if ((error = deextend(dep, uio->uio_offset, cred)) != 0) { - fstrans_done(vp->v_mount); return (error); } } @@ -637,7 +624,7 @@ msdosfs_write(void *v) rem = round_page(dep->de_FileSize) - dep->de_FileSize; if (rem > 0) ubc_zerorange(&vp->v_uobj, (off_t)dep->de_FileSize, - rem, UBC_UNMAP_FLAG(vp)); + rem, UBC_VNODE_FLAGS(vp)); extended = 1; } @@ -646,7 +633,7 @@ msdosfs_write(void *v) bytelen = uio->uio_resid; 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) break; @@ -656,7 +643,7 @@ msdosfs_write(void *v) */ 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, (uio->uio_offset >> 16) << 16, PGO_CLEANIT | PGO_LAZY); @@ -666,7 +653,7 @@ msdosfs_write(void *v) /* set final size */ uvm_vnp_setsize(vp, dep->de_FileSize); 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), round_page(oldoff + bytelen), PGO_CLEANIT | PGO_SYNCIO); } @@ -685,7 +672,6 @@ errexit: uio->uio_resid = resid; } else if ((ioflag & IO_SYNC) == IO_SYNC) error = deupdat(dep, 1); - fstrans_done(vp->v_mount); KASSERT(vp->v_size == dep->de_FileSize); return (error); } @@ -731,7 +717,7 @@ msdosfs_update(struct vnode *vp, const struct timespec *acc, int msdosfs_remove(void *v) { - struct vop_remove_args /* { + struct vop_remove_v2_args /* { struct vnode *a_dvp; struct vnode *a_vp; struct componentname *a_cnp; @@ -740,14 +726,13 @@ msdosfs_remove(void *v) struct denode *ddep = VTODE(ap->a_dvp); int error; - fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED); if (ap->a_vp->v_type == VDIR) error = EPERM; else error = removede(ddep, dep); #ifdef MSDOSFS_DEBUG - printf("msdosfs_remove(), dep %p, v_usecount %d\n", - dep, ap->a_vp->v_usecount); + printf("msdosfs_remove(), dep %p, usecount %d\n", + dep, vrefcnt(ap->a_vp)); #endif VN_KNOTE(ap->a_vp, NOTE_DELETE); VN_KNOTE(ap->a_dvp, NOTE_WRITE); @@ -756,8 +741,7 @@ msdosfs_remove(void *v) else vput(ap->a_vp); /* causes msdosfs_inactive() to be called * via vrele() */ - vput(ap->a_dvp); - fstrans_done(ap->a_dvp->v_mount); + return (error); } @@ -832,7 +816,6 @@ msdosfs_rename(void *v) struct vnode *tdvp = ap->a_tdvp; struct vnode *fvp = ap->a_fvp; struct vnode *fdvp = ap->a_fdvp; - struct mount *mp = fdvp->v_mount; struct componentname *tcnp = ap->a_tcnp; struct componentname *fcnp = ap->a_fcnp; struct denode *ip, *xp, *dp, *zp; @@ -910,7 +893,6 @@ abortit: } VN_KNOTE(fdvp, NOTE_WRITE); /* XXXLUKEM/XXX: right place? */ - fstrans_start(mp, FSTRANS_SHARED); /* * When the target exists, both the directory * and target vnodes are returned locked. @@ -997,7 +979,6 @@ abortit: * file/directory. */ if ((error = uniqdosname(VTODE(tdvp), tcnp, toname)) != 0) { - fstrans_done(mp); goto abortit; } @@ -1013,7 +994,6 @@ abortit: VOP_UNLOCK(fdvp); vrele(ap->a_fvp); vrele(tdvp); - fstrans_done(mp); return (error); } if (fvp == NULL) { @@ -1025,7 +1005,6 @@ abortit: vput(fdvp); vrele(ap->a_fvp); vrele(tdvp); - fstrans_done(mp); return 0; } VOP_UNLOCK(fdvp); @@ -1140,7 +1119,6 @@ bad: ip->de_flag &= ~DE_RENAME; vrele(fdvp); vrele(fvp); - fstrans_done(mp); return (error); /* XXX: uuuh */ @@ -1197,7 +1175,6 @@ msdosfs_mkdir(void *v) struct buf *bp; 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 * can't do anything. This is because the root directory can not @@ -1280,27 +1257,24 @@ msdosfs_mkdir(void *v) goto bad; VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK); *ap->a_vpp = DETOV(dep); - fstrans_done(ap->a_dvp->v_mount); return (0); bad: clusterfree(pmp, newcluster, NULL); bad2: - fstrans_done(ap->a_dvp->v_mount); return (error); } int msdosfs_rmdir(void *v) { - struct vop_rmdir_args /* { + struct vop_rmdir_v2_args /* { struct vnode *a_dvp; struct vnode *a_vp; struct componentname *a_cnp; } */ *ap = v; struct vnode *vp = ap->a_vp; struct vnode *dvp = ap->a_dvp; - struct mount *mp = dvp->v_mount; struct componentname *cnp = ap->a_cnp; struct denode *ip, *dp; int error; @@ -1311,11 +1285,9 @@ msdosfs_rmdir(void *v) * No rmdir "." please. */ if (dp == ip) { - vrele(dvp); - vput(vp); + vrele(vp); return (EINVAL); } - fstrans_start(mp, FSTRANS_SHARED); /* * Verify the directory is empty (and valid). * (Rmdir ".." won't be valid since @@ -1345,8 +1317,6 @@ msdosfs_rmdir(void *v) */ VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); cache_purge(dvp); - vput(dvp); - dvp = NULL; /* * Truncate the directory that is being deleted. */ @@ -1354,10 +1324,7 @@ msdosfs_rmdir(void *v) cache_purge(vp); out: VN_KNOTE(vp, NOTE_DELETE); - if (dvp) - vput(dvp); vput(vp); - fstrans_done(mp); return (error); } @@ -1394,6 +1361,7 @@ msdosfs_readdir(void *v) int ncookies = 0, nc = 0; off_t offset, uio_off; int chksum = -1; + uint16_t namlen; #ifdef MSDOSFS_DEBUG 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_off = uio->uio_offset; - fstrans_start(ap->a_vp->v_mount, FSTRANS_SHARED); /* Allocate a temporary dirent buffer. */ 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) continue; chksum = win2unixfn((struct winentry *)dentp, - dirbuf, chksum); + dirbuf, chksum, &namlen, + pmp->pm_flags & MSDOSFSMNT_UTF8); + if (chksum != -1) + dirbuf->d_namlen = namlen; continue; } @@ -1584,6 +1554,7 @@ msdosfs_readdir(void *v) pmp->pm_flags & MSDOSFSMNT_SHORTNAME); else dirbuf->d_name[dirbuf->d_namlen] = 0; + namlen = dirbuf->d_namlen; chksum = -1; dirbuf->d_reclen = _DIRENT_SIZE(dirbuf); if (uio->uio_resid < dirbuf->d_reclen) { @@ -1627,7 +1598,6 @@ out: bad: free(dirbuf, M_MSDOSFSTMP); - fstrans_done(ap->a_vp->v_mount); return (error); } @@ -1795,7 +1765,7 @@ msdosfs_pathconf(void *v) *ap->a_retval = 32; return (0); default: - return (EINVAL); + return genfs_pathconf(ap); } /* NOTREACHED */ } @@ -1814,7 +1784,6 @@ msdosfs_fsync(void *v) int wait; int error; - fstrans_start(vp->v_mount, FSTRANS_LAZY); wait = (ap->a_flags & FSYNC_WAIT) != 0; error = vflushbuf(vp, ap->a_flags); if (error == 0 && (ap->a_flags & FSYNC_DATAONLY) == 0) @@ -1828,7 +1797,6 @@ msdosfs_fsync(void *v) error = VOP_IOCTL(devvp, DIOCCACHESYNC, &l, FWRITE, curlwp->l_cred); } - fstrans_done(vp->v_mount); return (error); } @@ -1879,6 +1847,7 @@ const struct vnodeopv_entry_desc msdosfs_vnodeop_entries[] = { { &vop_open_desc, genfs_nullop }, /* open */ { &vop_close_desc, msdosfs_close }, /* close */ { &vop_access_desc, msdosfs_access }, /* access */ + { &vop_accessx_desc, genfs_accessx }, /* accessx */ { &vop_getattr_desc, msdosfs_getattr }, /* getattr */ { &vop_setattr_desc, msdosfs_setattr }, /* setattr */ { &vop_read_desc, msdosfs_read }, /* read */ diff --git a/sys/fs/msdosfs/msdosfsmount.h b/sys/fs/msdosfs/msdosfsmount.h index 8539a11f1..047f1d414 100644 --- a/sys/fs/msdosfs/msdosfsmount.h +++ b/sys/fs/msdosfs/msdosfsmount.h @@ -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. @@ -78,11 +78,12 @@ struct msdosfs_args { #define MSDOSFSMNT_NOWIN95 4 /* Completely ignore Win95 entries */ #define MSDOSFSMNT_GEMDOSFS 8 /* This is a GEMDOS-flavour */ #define MSDOSFSMNT_VERSIONED 16 /* Struct is versioned */ +#define MSDOSFSMNT_UTF8 32 /* Use UTF8 filenames */ /* All flags above: */ #define MSDOSFSMNT_MNTOPT \ (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_WAITONFAT 0x40000000 /* mounted synchronous */ @@ -90,7 +91,7 @@ struct msdosfs_args { #define MSDOSFSMNT_BITS "\177\20" \ "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 #include diff --git a/sys/fs/udf/ecma167-udf.h b/sys/fs/udf/ecma167-udf.h index c52b99de8..09472266c 100644 --- a/sys/fs/udf/ecma167-udf.h +++ b/sys/fs/udf/ecma167-udf.h @@ -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 - * Reinoud Zandijk * + * Copyright (c) 2003, 2004, 2005, 2006, 2008, 2009, 2017, 2018 + * Reinoud Zandijk * Copyright (c) 2001, 2002 Scott Long * All rights reserved. * @@ -203,14 +203,14 @@ union icb { /* short/long/ext extent have flags encoded in length */ -#define UDF_EXT_ALLOCATED (0<<30) -#define UDF_EXT_FREED (1<<30) -#define UDF_EXT_ALLOCATED_BUT_NOT_USED (1<<30) -#define UDF_EXT_FREE (2<<30) -#define UDF_EXT_REDIRECT (3<<30) -#define UDF_EXT_FLAGS(len) ((len) & (3<<30)) -#define UDF_EXT_LEN(len) ((len) & ((1<<30)-1)) -#define UDF_EXT_MAXLEN ((1<<30)-1) +#define UDF_EXT_ALLOCATED (0U<<30) +#define UDF_EXT_FREED (1U<<30) +#define UDF_EXT_ALLOCATED_BUT_NOT_USED (1U<<30) +#define UDF_EXT_FREE (2U<<30) +#define UDF_EXT_REDIRECT (3U<<30) +#define UDF_EXT_FLAGS(len) ((len) & (3U<<30)) +#define UDF_EXT_LEN(len) ((len) & ((1U<<30)-1)) +#define UDF_EXT_MAXLEN ((1U<<30)-1) /* Character set spec [1/7.2.1] */ @@ -264,7 +264,10 @@ struct regid { struct icb_tag { uint32_t prev_num_dirs; uint16_t strat_type; - uint8_t strat_param[2]; + union { + uint8_t strat_param[2]; + uint16_t strat_param16; + }; uint16_t max_num_entries; uint8_t reserved; uint8_t file_type; @@ -682,7 +685,10 @@ struct impl_extattr_entry { struct extattr_entry hdr; uint32_t iu_l; struct regid imp_id; - uint8_t data[1]; + union { + uint8_t data[1]; + uint16_t data16; + }; } __packed; @@ -832,4 +838,3 @@ union dscrptr { #endif /* !_FS_UDF_ECMA167_UDF_H_ */ - diff --git a/sys/fs/udf/udf.h b/sys/fs/udf/udf.h index 8b1edb9ee..5b950094a 100644 --- a/sys/fs/udf/udf.h +++ b/sys/fs/udf/udf.h @@ -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 @@ -76,7 +76,7 @@ extern int udf_verbose; #define UDF_DEBUG_RESERVE 0x1000000 /* initial value of udf_verbose */ -#define UDF_DEBUGGING 0 +#define UDF_DEBUGGING (0) #ifdef UDF_DEBUG #define DPRINTF(name, arg) { \ @@ -252,6 +252,7 @@ struct udf_strategy { int (*read_logvol_dscr) (struct udf_strat_args *args); int (*write_logvol_dscr) (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_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_CALLBACK_ULK 0x0400 /* node will be unlocked by callback */ #define IN_NODE_REBUILD 0x0800 /* node is rebuild */ +#define IN_NO_DELETE 0x1000 /* node is not to be deleted */ #define IN_FLAGBITS \ "\10\1IN_ACCESS\2IN_CHANGE\3IN_UPDATE\4IN_MODIFY\5IN_MODIFIED" \ "\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_ */ diff --git a/sys/fs/udf/udf_allocation.c b/sys/fs/udf/udf_allocation.c index 63a5b895b..d4602c0c8 100644 --- a/sys/fs/udf/udf_allocation.c +++ b/sys/fs/udf/udf_allocation.c @@ -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 @@ -28,7 +28,7 @@ #include #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 */ @@ -1001,7 +1001,7 @@ udf_bitmap_check_trunc_free(struct udf_bitmap *bitmap, uint32_t to_trunc) bitval = (1 << bit); if (!(*bpos & bitval)) seq_free = 0; - offset++; to_trunc--; + to_trunc--; bit++; if (bit == 8) { bpos++; @@ -1540,8 +1540,7 @@ udf_trunc_metadatapart(struct udf_mount *ump, uint32_t num_lb) *sizepos = udf_rw32(*sizepos) - to_trunc; /* realloc bitmap for better memory usage */ - new_sbd = realloc(sbd, inf_len, M_UDFVOLD, - M_CANFAIL | M_WAITOK); + new_sbd = realloc(sbd, inf_len, M_UDFVOLD, M_WAITOK); if (new_sbd) { /* update pointers */ ump->metadata_unalloc_dscr = new_sbd; @@ -2679,7 +2678,7 @@ udf_grow_node(struct udf_node *udf_node, uint64_t new_size) #if 0 /* zero append space in buffer */ ubc_zerorange(&vp->v_uobj, old_size, - new_size - old_size, UBC_UNMAP_FLAG(vp)); + new_size - old_size, UBC_VNODE_FLAGS(vp)); #endif 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! */ /* 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)); @@ -2956,7 +2955,7 @@ udf_shrink_node(struct udf_node *udf_node, uint64_t new_size) /* TODO zero appened space in buffer! */ /* 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 */ uvm_vnp_setsize(vp, new_size); diff --git a/sys/fs/udf/udf_mount.h b/sys/fs/udf/udf_mount.h index bf02be7dd..897b9f90c 100644 --- a/sys/fs/udf/udf_mount.h +++ b/sys/fs/udf/udf_mount.h @@ -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 @@ -12,13 +12,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed 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 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES diff --git a/sys/fs/udf/udf_readwrite.c b/sys/fs/udf/udf_readwrite.c index 57c4ee2d0..2956133bd 100644 --- a/sys/fs/udf/udf_readwrite.c +++ b/sys/fs/udf/udf_readwrite.c @@ -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 @@ -28,7 +28,7 @@ #include #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 */ @@ -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 udf_discstrat_init(struct udf_mount *ump) { diff --git a/sys/fs/udf/udf_rename.c b/sys/fs/udf/udf_rename.c index 6f413caf1..a7be766eb 100644 --- a/sys/fs/udf/udf_rename.c +++ b/sys/fs/udf/udf_rename.c @@ -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 @@ -28,7 +28,7 @@ */ #include -__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 #include @@ -465,7 +465,7 @@ udf_gro_lookup(struct mount *mp, struct vnode *dvp, return ENOENT; 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) return error; *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")); 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); if (error) return error; diff --git a/sys/fs/udf/udf_strat_bootstrap.c b/sys/fs/udf/udf_strat_bootstrap.c index 0fcbf8fbb..f4990a135 100644 --- a/sys/fs/udf/udf_strat_bootstrap.c +++ b/sys/fs/udf/udf_strat_bootstrap.c @@ -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 @@ -28,7 +28,7 @@ #include #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 */ @@ -115,6 +115,14 @@ udf_queuebuf_bootstrap(struct udf_strat_args *args) VOP_STRATEGY(ump->devvp, buf); } + +static void +udf_sync_caches_bootstrap(struct udf_strat_args *args) +{ + /* empty */ +} + + static void 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_write_logvol_dscr_bootstrap, udf_queuebuf_bootstrap, + udf_sync_caches_bootstrap, udf_discstrat_init_bootstrap, udf_discstrat_finish_bootstrap }; diff --git a/sys/fs/udf/udf_strat_direct.c b/sys/fs/udf/udf_strat_direct.c index 251efb727..fa8a90e3a 100644 --- a/sys/fs/udf/udf_strat_direct.c +++ b/sys/fs/udf/udf_strat_direct.c @@ -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 @@ -28,7 +28,7 @@ #include #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 */ @@ -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 udf_discstrat_init_direct(struct udf_strat_args *args) { @@ -441,6 +450,7 @@ struct udf_strategy udf_strat_direct = udf_read_nodedscr_direct, udf_write_nodedscr_direct, udf_queue_buf_direct, + udf_sync_caches_direct, udf_discstrat_init_direct, udf_discstrat_finish_direct }; diff --git a/sys/fs/udf/udf_strat_rmw.c b/sys/fs/udf/udf_strat_rmw.c index dddcc829f..84171a582 100644 --- a/sys/fs/udf/udf_strat_rmw.c +++ b/sys/fs/udf/udf_strat_rmw.c @@ -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 @@ -28,7 +28,7 @@ #include #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 */ @@ -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 udf_shedule_read_callback(struct buf *buf) { @@ -1495,6 +1505,7 @@ struct udf_strategy udf_strat_rmw = udf_read_nodedscr_rmw, udf_write_nodedscr_rmw, udf_queuebuf_rmw, + udf_sync_caches_rmw, udf_discstrat_init_rmw, udf_discstrat_finish_rmw }; diff --git a/sys/fs/udf/udf_strat_sequential.c b/sys/fs/udf/udf_strat_sequential.c index 89a8aee65..aba3f138c 100644 --- a/sys/fs/udf/udf_strat_sequential.c +++ b/sys/fs/udf/udf_strat_sequential.c @@ -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 @@ -28,7 +28,7 @@ #include #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 */ @@ -86,6 +86,7 @@ struct strat_private { kmutex_t discstrat_mutex; /* disc strategy */ int run_thread; /* thread control */ + int sync_req; /* thread control */ int cur_queue; 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 */ static void 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; mutex_enter(&priv->discstrat_mutex); - while (priv->run_thread || !empty) { + while (priv->run_thread || !empty || priv->sync_req) { /* process the current selected queue */ udf_doshedule(ump); 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); /* 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, &priv->discstrat_mutex, hz/8); + } } mutex_exit(&priv->discstrat_mutex); @@ -621,6 +653,7 @@ udf_discstrat_init_seq(struct udf_strat_args *args) /* create our disk strategy thread */ priv->run_thread = 1; + priv->sync_req = 0; if (kthread_create(PRI_NONE, 0 /* KTHREAD_MPSAFE*/, NULL /* cpu_info*/, udf_discstrat_thread, ump, &priv->queue_lwp, "%s", "udf_rw")) { @@ -673,6 +706,7 @@ struct udf_strategy udf_strat_sequential = udf_read_logvol_dscr_seq, udf_write_logvol_dscr_seq, udf_queuebuf_seq, + udf_sync_caches_seq, udf_discstrat_init_seq, udf_discstrat_finish_seq }; diff --git a/sys/fs/udf/udf_subr.c b/sys/fs/udf/udf_subr.c index 9e2b9f6de..19ad2d7d4 100644 --- a/sys/fs/udf/udf_subr.c +++ b/sys/fs/udf/udf_subr.c @@ -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 * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -23,13 +23,13 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * */ #include #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 */ @@ -319,27 +319,25 @@ udf_setup_writeparams(struct udf_mount *ump) } -int -udf_synchronise_caches(struct udf_mount *ump) +void +udf_mmc_synchronise_caches(struct udf_mount *ump) { 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) - return 0; + return; /* discs are done now */ if (ump->discinfo.mmc_class == MMC_CLASS_DISC) - return 0; + return; memset(&mmc_op, 0, sizeof(struct mmc_op)); mmc_op.operation = MMC_OP_SYNCHRONISECACHE; /* ignore return code */ (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) { DPRINTF(LOCKING, ( "udf_lock_node: udf_node %p would block " "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)); } } @@ -930,7 +928,7 @@ udf_read_anchors(struct udf_mount *ump) positions[1] = track_end-256; positions[2] = track_end; 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; anchorsp = ump->anchors; @@ -946,7 +944,7 @@ udf_read_anchors(struct udf_mount *ump) /* VATs are only recorded on sequential media, but initialise */ 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; } @@ -984,7 +982,7 @@ udf_get_record_vpart(struct udf_mount *ump, int udf_c_type) } -/* +/* * BUGALERT: some rogue implementations use random physical partition * 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? */ 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); 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 lb_num; 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 error; @@ -1289,18 +1287,29 @@ udf_loose_lvint_history(struct udf_mount *ump) /* search smallest extent */ trace = &ump->lvint_trace[0]; - minext = trace->end - trace->start; + sumext = trace->end - trace->start; for (ext = 1; ext < UDF_LVDINT_SEGMENTS; ext++) { trace = &ump->lvint_trace[ext]; extlen = trace->end - trace->start; if (extlen == 0) break; - minext = MIN(minext, extlen); + sumext += extlen; } - losing = MIN(minext, UDF_LVINT_LOSSAGE); - /* no sense wiping all */ - if (losing == minext) - losing--; + + /* just one element? its not legal but be bug compatible */ + if (sumext == 1) { + /* 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)); @@ -1437,7 +1446,6 @@ udf_writeout_lvint(struct udf_mount *ump, int lvflag) DPRINTF(VOLUMES, ("writing out logvol integrity descriptor\n")); -again: /* get free space in last chunk */ trace = ump->lvint_trace; while (trace->wpos > (trace->end - trace->start)) { @@ -1465,11 +1473,20 @@ again: if (space < 1) { if (lvflag & UDF_APPENDONLY_LVINT) return EROFS; + /* loose history by re-writing extents */ error = udf_loose_lvint_history(ump); if (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 */ @@ -1573,7 +1590,7 @@ udf_read_physical_partition_spacetables(struct udf_mount *ump) if (partd == NULL) continue; parthdr = &partd->_impl_use.part_hdr; - + len = udf_rw32(parthdr->unalloc_space_table.len); if (len) { printf("UDF mount: space tables not supported\n"); @@ -1632,7 +1649,7 @@ udf_read_physical_partition_spacetables(struct udf_mount *ump) if (partd == NULL) continue; parthdr = &partd->_impl_use.part_hdr; - + len = udf_rw32(parthdr->freed_space_table.len); if (len) { 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", lb_num + ptov)); 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, (union dscrptr *) dscr, 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", lb_num + ptov)); 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, (union dscrptr *) dscr, ptov + lb_num, lb_num); @@ -1738,7 +1771,7 @@ udf_read_metadata_partition_spacetable(struct udf_mount *ump) "%"PRIu64" bytes\n", inflen)); /* allocate space for bitmap */ - dscr = malloc(inflen, M_UDFVOLD, M_CANFAIL | M_WAITOK); + dscr = malloc(inflen, M_UDFVOLD, M_WAITOK); if (!dscr) return ENOMEM; @@ -1981,7 +2014,7 @@ udf_process_vds(struct udf_mount *ump) { DPRINTF(VOLUMES, ("\t%d -> %d(%d) type %d\n", log_part, raw_phys_part, phys_part, pmap_type)); - + if (phys_part == UDF_PARTITIONS) return EINVAL; 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); 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_sequential) ? "Sequential" : (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 * 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 * sub-files. In the stream directory a few fixed named subfiles are reserved * for NT/Unix ACL's and OS/2 attributes. - * + * * NOTE: Extended attributes are read randomly but allways written * *atomicaly*. For ACL's this interface is propably different but not known * 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) { struct udf_mount *ump; @@ -2590,7 +2623,7 @@ udf_update_lvid_from_vat_extattr(struct udf_node *vat_node) return error; /* 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")); 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) { 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 */ new_vat_table = realloc(ump->vat_table, ump->vat_table_alloc_len + UDF_VAT_CHUNKSIZE, - M_UDFVOLD, M_WAITOK | M_CANFAIL); + M_UDFVOLD, M_WAITOK); if (!new_vat_table) { printf("udf_vat_write: can't extent VAT, out of mem\n"); return ENOMEM; @@ -2833,7 +2866,6 @@ udf_writeout_vat(struct udf_mount *ump) if (error) printf("udf_writeout_vat: error writing VAT node!\n"); out: - return error; } @@ -2904,8 +2936,7 @@ udf_check_for_vat(struct udf_node *vat_node) ((vat_length + UDF_VAT_CHUNKSIZE-1) / UDF_VAT_CHUNKSIZE) * UDF_VAT_CHUNKSIZE; - vat_table = malloc(vat_table_alloc_len, M_UDFVOLD, - M_CANFAIL | M_WAITOK); + vat_table = malloc(vat_table_alloc_len, M_UDFVOLD, M_WAITOK); if (vat_table == NULL) { printf("allocation of %d bytes failed for VAT\n", 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_writever = vat->min_udf_writever; lvinfo->max_udf_writever = vat->max_udf_writever; - + 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->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_alloc_len = vat_table_alloc_len; ump->vat_table = vat_table; @@ -3017,49 +3052,71 @@ out: static int 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; - uint32_t early_vat_loc, vat_loc; + uint32_t early_vat_loc, late_vat_loc, vat_loc; int error; /* mapping info not needed */ mapping = mapping; - vat_loc = ump->last_possible_vat_location; - early_vat_loc = vat_loc - 256; /* 8 blocks of 32 sectors */ + DPRINTF(VOLUMES, ("Searching VAT\n")); - DPRINTF(VOLUMES, ("1) last possible %d, early_vat_loc %d \n", - vat_loc, early_vat_loc)); - early_vat_loc = MAX(early_vat_loc, ump->first_possible_vat_location); + /* + * Start reading forward in blocks from the first possible vat + * 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", - vat_loc, early_vat_loc)); - - /* start looking from the end of the range */ + DPRINTF(VOLUMES, ("\tfull range %d to %d\n", early_vat_loc, late_vat_loc)); + accepted_vat_node = NULL; do { - DPRINTF(VOLUMES, ("Checking 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); + vat_loc = early_vat_loc; + DPRINTF(VOLUMES, ("\tchecking range %d to %d\n", + 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); - if (!error) { - error = udf_check_for_vat(vat_node); - DPRINTFIF(VOLUMES, !error, - ("VAT accepted at %d\n", vat_loc)); - if (!error) - break; - } - if (vat_node) { - vput(vat_node->vnode); - vat_node = NULL; - } - vat_loc--; /* walk backwards */ - } while (vat_loc >= early_vat_loc); + error = udf_get_node(ump, &icb_loc, &vat_node, + LK_EXCLUSIVE); + if (!error) { + error = udf_check_for_vat(vat_node); + vat_node->i_flags = 0; /* reset access */ + } + if (!error) { + DPRINTFIF(VOLUMES, !error, + ("VAT candidate accepted at %d\n", + vat_loc)); + if (accepted_vat_node) + vput(accepted_vat_node->vnode); + accepted_vat_node = vat_node; + 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 */ - if (vat_node) { - UDF_SET_SYSTEMFILE(vat_node->vnode); - ump->vat_node = vat_node; + early_vat_loc = MAX(early_vat_loc - 64, ump->first_possible_vat_location); + late_vat_loc = MIN(early_vat_loc + 64, ump->last_possible_vat_location); + } while (late_vat_loc > ump->first_possible_vat_location); + + /* 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; @@ -3141,7 +3198,8 @@ udf_read_metadata_nodes(struct udf_mount *ump, union udf_pmap *mapping) DPRINTF(VOLUMES, ("Metadata file\n")); 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) { vp = ump->metadata_node->vnode; 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; if (icb_loc.loc.lb_num != -1) { 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) { vp = ump->metadatamirror_node->vnode; 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; if (icb_loc.loc.lb_num != -1) { 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) { vp = ump->metadatabitmap_node->vnode; UDF_SET_SYSTEMFILE(vp); @@ -3341,7 +3401,7 @@ udf_read_rootdirs(struct udf_mount *ump) /* try to read in the rootdir */ 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) return ENOENT; @@ -3354,7 +3414,8 @@ udf_read_rootdirs(struct udf_mount *ump) dir_loc = &ump->fileset_desc->streamdir_icb; if (udf_rw32(dir_loc->len)) { 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) { printf("but error in streamdir reading\n"); } else { @@ -3674,6 +3735,21 @@ udf_open_logvol(struct udf_mount *ump) /* determine data and metadata tracks again */ 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 */ @@ -3722,15 +3798,6 @@ udf_close_logvol(struct udf_mount *ump, int mntflags) /* write out the VAT data and all its descriptors */ DPRINTF(VOLUMES, ("writeout vat_node\n")); 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 */ nvats = 32; @@ -3765,6 +3832,9 @@ udf_close_logvol(struct udf_mount *ump, int mntflags) if (!error) nok++; } + /* force everything to be synchronized on the device */ + (void) udf_synchronise_caches(ump); + if (nok < 14) { /* arbitrary; but at least one or two CD frames */ 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 */ if (ump->lvclose & UDF_CLOSE_SESSION) { + DPRINTF(VOLUMES, ("udf_close_logvol: closing session " + "as requested\n")); error = udf_validate_session_start(ump); if (error) return error; @@ -3995,6 +4067,7 @@ static const struct genfs_ops udf_genfsops = { .gop_alloc = udf_gop_alloc, .gop_write = genfs_gop_write_rwmap, .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) { uint32_t perm; - + perm = ((mode & S_IRWXO) ); perm |= ((mode & S_IRWXG) << 2); 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); gid = (gid_t)udf_rw32(efe->gid); } - + /* do the uid/gid translation game */ if (uid == (uid_t) -1) 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, 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_entry *dirh_ep; struct fileid_desc *fid; - struct dirent *dirent; + struct dirent *dirent, *s_dirent; + struct charspec osta_charspec; uint64_t diroffset; uint32_t lb_size; 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; /* allocate temporary space for fid */ - lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size); - fid = malloc(lb_size, M_UDFTEMP, M_WAITOK); - dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK); + lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size); + fid = malloc(lb_size, 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", 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 */ memset(icb_loc, 0, sizeof(*icb_loc)); dirh_ep = NULL; 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 (!hit) 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)); /* see if its our entry */ -#ifdef DIAGNOSTIC - 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) { + if (strncmp(dirent->d_name, s_dirent->d_name, s_dirent->d_namlen) == 0) { *found = 1; *icb_loc = fid->icb; break; @@ -4549,6 +4624,7 @@ udf_lookup_name_in_dir(struct vnode *vp, const char *name, int namelen, } free(fid, M_UDFTEMP); free(dirent, M_UDFTEMP); + free(s_dirent, M_UDFTEMP); 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 file_entry *fe = dir_node->fe; struct fileid_desc *fid; - struct dirent *dirent; + struct dirent *dirent, *s_dirent; + struct charspec osta_charspec; uint64_t diroffset; uint32_t lb_size, fidsize; int found, error; - char const *name = cnp->cn_nameptr; - int namelen = cnp->cn_namelen; int hit, refcnt; /* 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); } - /* allocate temporary space for fid */ - lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size); - fid = malloc(lb_size, M_UDFTEMP, M_WAITOK); - dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK); + /* allocate temporary space for fid and dirents */ + lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size); + fid = malloc(lb_size, 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 */ found = 0; dirh_ep = NULL; 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 (!hit) break; @@ -4763,8 +4848,8 @@ udf_dir_detach(struct udf_mount *ump, struct udf_node *dir_node, break; /* see if its our entry */ - KASSERT(dirent->d_namlen == namelen); - if (strncmp(dirent->d_name, name, namelen) == 0) { + KASSERT(dirent->d_namlen == s_dirent->d_namlen); + if (strncmp(dirent->d_name, s_dirent->d_name, s_dirent->d_namlen) == 0) { found = 1; break; } @@ -4788,7 +4873,7 @@ udf_dir_detach(struct udf_mount *ump, struct udf_node *dir_node, /* write out */ error = vn_rdwr(UIO_WRITE, dir_node->vnode, - fid, fidsize, diroffset, + fid, fidsize, diroffset, UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, FSCRED, NULL, NULL); if (error) @@ -4845,6 +4930,7 @@ udf_dir_detach(struct udf_mount *ump, struct udf_node *dir_node, error_out: free(fid, M_UDFTEMP); free(dirent, M_UDFTEMP); + free(s_dirent, M_UDFTEMP); 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 */ error = vn_rdwr(UIO_WRITE, dir_node->vnode, - fid, fidsize, diroffset, + fid, fidsize, diroffset, UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, FSCRED, NULL, NULL); @@ -5154,7 +5240,7 @@ udf_dir_attach(struct udf_mount *ump, struct udf_node *dir_node, /* writeout FID/update parent directory */ error = vn_rdwr(UIO_WRITE, dvp, - fid, chosen_size, chosen_fid_pos, + fid, chosen_size, chosen_fid_pos, UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, FSCRED, NULL, NULL); @@ -5336,7 +5422,7 @@ udf_loadvnode(struct mount *mp, struct vnode *vp, /* choose this one */ last_fe_icb_loc = icb_loc; - + /* record and process/update (ext)fentry */ if (dscr_type == TAGID_FENTRY) { if (udf_node->fe) @@ -5544,16 +5630,18 @@ udf_loadvnode(struct mount *mp, struct vnode *vp, int 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; struct vnode *vp; + *udf_noderes = NULL; + error = vcache_get(ump->vfs_mountp, &node_icb_loc->loc, sizeof(node_icb_loc->loc), &vp); if (error) return error; - error = vn_lock(vp, LK_EXCLUSIVE); + error = vn_lock(vp, lktype); if (error) { vrele(vp); return error; @@ -5696,7 +5784,7 @@ udf_dispose_node(struct udf_node *udf_node) int 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) { union dscrptr *dscr; @@ -5840,7 +5928,7 @@ udf_newvnode(struct mount *mp, struct vnode *dvp, struct vnode *vp, gid = parent_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; 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; 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) return error; @@ -5880,6 +5968,7 @@ udf_create_node(struct vnode *dvp, struct vnode **vpp, struct vattr *vap, /* adjust file count */ udf_adjust_filecount(udf_node, 1); + cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags); return 0; } @@ -5914,6 +6003,9 @@ udf_delete_node(struct udf_node *udf_node) struct long_ad *loc; int extnr, lvint, dummy; + if (udf_node->i_flags & IN_NO_DELETE) + return; + /* paranoia check on integrity; should be open!; we could panic */ lvint = udf_rw32(udf_node->ump->logvol_integrity->integrity_type); 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 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) return false; @@ -6352,7 +6448,7 @@ udf_sync_selector(void *cl, struct vnode *vp) return false; if ((udf_node->i_flags & (IN_ACCESSED | IN_UPDATE | IN_MODIFIED)) == 0) 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 true; @@ -6398,7 +6494,7 @@ recount: udf_sync_pass(ump, cred, 3, &ndirty); DPRINTF(SYNC, ("counted num dirty pending blocks %d\n", ndirty)); - + if (ndirty) { /* 1/4 second wait */ kpause("udfsync2", false, hz/4, NULL); @@ -6424,7 +6520,7 @@ recount: /* * 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. * * 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; uint64_t inflen; uint32_t sector_size; - uint8_t *pos; + uint8_t *srcpos; int icbflags, addr_type; /* get extent and do some paranoia checks */ ump = node->ump; 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) { 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); } else { assert(node->efe); 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); } 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); /* copy out info */ - memset(blob, 0, sector_size); - memcpy(blob, pos, inflen); + memcpy(blob, srcpos, inflen); + memset(&blob[inflen], 0, sector_size - inflen); return 0; } diff --git a/sys/fs/udf/udf_subr.h b/sys/fs/udf/udf_subr.h index 7146c1353..b17a5890f 100644 --- a/sys/fs/udf/udf_subr.h +++ b/sys/fs/udf/udf_subr.h @@ -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 @@ -40,7 +40,8 @@ int udf_search_tracks(struct udf_mount *ump, struct udf_args *args, int *first_tracknr, int *last_tracknr); int udf_search_writing_tracks(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 */ 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_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_dispose_node(struct udf_node *node); diff --git a/sys/fs/udf/udf_vfsops.c b/sys/fs/udf/udf_vfsops.c index 8674b7263..866aed9c7 100644 --- a/sys/fs/udf/udf_vfsops.c +++ b/sys/fs/udf/udf_vfsops.c @@ -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 @@ -28,7 +28,7 @@ #include #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 */ @@ -79,8 +79,6 @@ MALLOC_JUSTDEFINE(M_UDFVOLD, "UDF volspace", "UDF volume space descriptors"); MALLOC_JUSTDEFINE(M_UDFTEMP, "UDF temp", "UDF scrap space"); struct pool udf_node_pool; -static struct sysctllog *udf_sysctl_log; - /* internal functions */ 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_snapshot = udf_snapshot, .vfs_extattrctl = vfs_stdextattrctl, - .vfs_suspendctl = (void *)eopnotsupp, + .vfs_suspendctl = genfs_suspendctl, .vfs_renamelock_enter = genfs_renamelock_enter, .vfs_renamelock_exit = genfs_renamelock_exit, .vfs_fsync = (void *)eopnotsupp, @@ -169,10 +167,34 @@ udf_done(void) */ #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 udf_modcmd(modcmd_t cmd, void *arg) { - const struct sysctlnode *node; int error; switch (cmd) { @@ -180,31 +202,11 @@ udf_modcmd(modcmd_t cmd, void *arg) error = vfs_attach(&udf_vfsops); if (error != 0) 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; case MODULE_CMD_FINI: error = vfs_detach(&udf_vfsops); if (error != 0) break; - sysctl_teardown(&udf_sysctl_log); break; default: error = ENOTTY; @@ -277,7 +279,6 @@ static void udf_release_system_nodes(struct mount *mp) { struct udf_mount *ump = VFSTOUDF(mp); - int error; /* if we haven't even got an ump, dont bother */ if (!ump) @@ -294,10 +295,6 @@ udf_release_system_nodes(struct mount *mp) vrele(ump->metadatamirror_node->vnode); if (ump->metadatabitmap_node) 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) { vrele(devvp); - return ENXIO; + return ENXIO; } /* @@ -442,12 +439,14 @@ static bool udf_sanity_selector(void *cl, struct vnode *vp) { + KASSERT(mutex_owned(vp->v_interlock)); + vprint("", vp); if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE) { printf(" is locked\n"); } - if (vp->v_usecount > 1) - printf(" more than one usecount %d\n", vp->v_usecount); + if (vrefcnt(vp) > 1) + printf(" more than one usecount %d\n", vrefcnt(vp)); return false; } @@ -518,6 +517,10 @@ udf_unmount(struct mount *mp, int mntflags) /* NOTE release system nodes should NOT write anything */ 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 */ udf_discstrat_finish(ump); @@ -743,7 +746,7 @@ udf_start(struct mount *mp, int flags) /* --------------------------------------------------------------------- */ int -udf_root(struct mount *mp, struct vnode **vpp) +udf_root(struct mount *mp, int lktype, struct vnode **vpp) { struct vnode *vp; struct long_ad *dir_loc; @@ -754,12 +757,13 @@ udf_root(struct mount *mp, struct vnode **vpp) DPRINTF(CALL, ("udf_root called\n")); 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) error = ENOENT; - if (error) - return error; vp = root_dir->vnode; 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 */ int -udf_vget(struct mount *mp, ino_t ino, +udf_vget(struct mount *mp, ino_t ino, int lktype, struct vnode **vpp) { DPRINTF(NOTIMPL, ("udf_vget called\n")); @@ -906,7 +910,7 @@ udf_vget(struct mount *mp, ino_t ino, * Lookup vnode for file handle specified */ int -udf_fhtovp(struct mount *mp, struct fid *fhp, +udf_fhtovp(struct mount *mp, struct fid *fhp, int lktype, struct vnode **vpp) { DPRINTF(NOTIMPL, ("udf_fhtovp called\n")); diff --git a/sys/fs/udf/udf_vnops.c b/sys/fs/udf/udf_vnops.c index f6374e16d..545039898 100644 --- a/sys/fs/udf/udf_vnops.c +++ b/sys/fs/udf/udf_vnops.c @@ -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 @@ -32,7 +32,7 @@ #include #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 */ @@ -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, uint8_t *targetbuf, int *length); -/* externs */ -extern int prtactive; - /* implementations of vnode functions; table follows at end */ /* --------------------------------------------------------------------- */ int udf_inactive(void *v) { - struct vop_inactive_args /* { + struct vop_inactive_v2_args /* { struct vnode *a_vp; bool *a_recycle; } */ *ap = v; @@ -92,7 +89,6 @@ udf_inactive(void *v) if (udf_node == NULL) { DPRINTF(NODE, ("udf_inactive: inactive NULL UDF node\n")); - VOP_UNLOCK(vp); return 0; } @@ -115,14 +111,12 @@ udf_inactive(void *v) *ap->a_recycle = false; if ((refcnt == 0) && ((vp->v_vflag & VV_SYSTEM) == 0)) { *ap->a_recycle = true; - VOP_UNLOCK(vp); return 0; } /* write out its node */ if (udf_node->i_flags & (IN_CHANGE | IN_UPDATE | IN_MODIFIED)) udf_update(vp, NULL, NULL, NULL, 0); - VOP_UNLOCK(vp); return 0; } @@ -132,16 +126,16 @@ udf_inactive(void *v) int udf_reclaim(void *v) { - struct vop_reclaim_args /* { + struct vop_reclaim_v2_args /* { struct vnode *a_vp; } */ *ap = v; struct vnode *vp = ap->a_vp; struct udf_node *udf_node = VTOI(vp); int refcnt; + VOP_UNLOCK(vp); + 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) { 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); } - vcache_remove(vp->v_mount, &udf_node->loc.loc, - sizeof(udf_node->loc.loc)); - /* dispose all node knowledge */ udf_dispose_node(udf_node); @@ -257,7 +248,7 @@ udf_read(void *v) /* ubc, here we come, prepare to trap */ 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) break; } @@ -375,7 +366,7 @@ udf_write(void *v) /* ubc, here we come, prepare to trap */ error = ubc_uiomove(uobj, uio, len, advice, - UBC_WRITE | UBC_UNMAP_FLAG(vp)); + UBC_WRITE | UBC_VNODE_FLAGS(vp)); if (error) break; @@ -388,7 +379,7 @@ udf_write(void *v) */ if ((vp->v_type != VDIR) && (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, (uio->uio_offset >> 16) << 16, PGO_CLEANIT | PGO_LAZY); @@ -618,7 +609,7 @@ udf_readdir(void *v) if (uio->uio_resid < _DIRENT_SIZE(dirent)) break; - /* remember the last entry we transfered */ + /* remember the last entry we transferred */ transoffset = diroffset; /* skip deleted entries */ @@ -759,7 +750,8 @@ udf_lookup(void *v) if (error == 0) { DPRINTF(LOOKUP, ("\tfound '..'\n")); /* 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) { DPRINTF(LOOKUP, @@ -811,7 +803,7 @@ udf_lookup(void *v) */ /* 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) goto out; @@ -834,7 +826,7 @@ udf_lookup(void *v) udf_getownership(dir_node, &d_uid, &d_gid); error = kauth_authorize_vnode(cnp->cn_cred, 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)); if (error) { error = EPERM; @@ -1049,7 +1041,7 @@ udf_chown(struct vnode *vp, uid_t new_uid, gid_t new_gid, /* check permissions */ 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) return (error); @@ -1086,7 +1078,7 @@ udf_chmod(struct vnode *vp, mode_t mode, kauth_cred_t cred) /* check permissions */ 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) return (error); @@ -1195,7 +1187,7 @@ udf_chtimes(struct vnode *vp, /* check permissions */ 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) return (error); @@ -1334,9 +1326,9 @@ udf_pathconf(void *v) #endif *ap->a_retval = bits; return 0; + default: + return genfs_pathconf(ap); } - - return EINVAL; } @@ -1387,15 +1379,15 @@ udf_close(void *v) udf_node = udf_node; /* shut up gcc */ 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); if (error) return error; } mutex_enter(vp->v_interlock); - if (vp->v_usecount > 1) - udf_itimes(udf_node, NULL, NULL, NULL); + if (vrefcnt(vp) > 1) + udf_itimes(udf_node, NULL, NULL, NULL); mutex_exit(vp->v_interlock); return 0; @@ -1445,13 +1437,13 @@ udf_check_possible(struct vnode *vp, struct vattr *vap, mode_t mode) } 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) { /* ask the generic genfs_can_access to advice on security */ - return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(mode, - vp->v_type, vap->va_mode), vp, NULL, genfs_can_access(vp->v_type, - vap->va_mode, vap->va_uid, vap->va_gid, mode, cred)); + return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, + vp->v_type, vap->va_mode), vp, NULL, genfs_can_access(vp, cred, + vap->va_uid, vap->va_gid, vap->va_mode, NULL, accmode)); } int @@ -1459,12 +1451,12 @@ udf_access(void *v) { struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + accmode_t a_accmode; kauth_cred_t a_cred; struct proc *a_p; } */ *ap = v; 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; /* struct udf_node *udf_node = VTOI(vp); */ struct vattr vap; @@ -1476,11 +1468,11 @@ udf_access(void *v) if (error) return error; - error = udf_check_possible(vp, &vap, mode); + error = udf_check_possible(vp, &vap, accmode); if (error) return error; - error = udf_check_permitted(vp, &vap, mode, cred); + error = udf_check_permitted(vp, &vap, accmode, cred); return error; } @@ -1947,7 +1939,7 @@ udf_readlink(void *v) int udf_remove(void *v) { - struct vop_remove_args /* { + struct vop_remove_v2_args /* { struct vnode *a_dvp; struct vnode *a_vp; struct componentname *a_cnp; @@ -1978,7 +1970,6 @@ udf_remove(void *v) vrele(vp); else vput(vp); - vput(dvp); return error; } @@ -1988,7 +1979,7 @@ udf_remove(void *v) int udf_rmdir(void *v) { - struct vop_rmdir_args /* { + struct vop_rmdir_v2_args /* { struct vnode *a_dvp; struct vnode *a_vp; struct componentname *a_cnp; @@ -2001,12 +1992,11 @@ udf_rmdir(void *v) struct udf_mount *ump = dir_node->ump; 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 */ if (dir_node == udf_node) { - vrele(dvp); - vput(vp); + vrele(vp); return EINVAL; } @@ -2023,7 +2013,6 @@ udf_rmdir(void *v) dirhash_put(udf_node->dir_hash); if (!isempty) { - vput(dvp); vput(vp); return ENOTEMPTY; } @@ -2046,8 +2035,7 @@ udf_rmdir(void *v) } DPRINTFIF(NODE, error, ("\tgot error removing dir\n")); - /* unput the nodes and exit */ - vput(dvp); + /* put the node and exit */ vput(vp); return error; @@ -2191,6 +2179,7 @@ const struct vnodeopv_entry_desc udf_vnodeop_entries[] = { { &vop_open_desc, udf_open }, /* open */ { &vop_close_desc, udf_close }, /* close */ { &vop_access_desc, udf_access }, /* access */ + { &vop_accessx_desc, genfs_accessx }, /* accessx */ { &vop_getattr_desc, udf_getattr }, /* getattr */ { &vop_setattr_desc, udf_setattr }, /* setattr */ /* TODO chflags */ { &vop_read_desc, udf_read }, /* read */ diff --git a/usr.sbin/makefs/Makefile b/usr.sbin/makefs/Makefile index 7522fc979..143b5b72b 100644 --- a/usr.sbin/makefs/Makefile +++ b/usr.sbin/makefs/Makefile @@ -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 @@ -31,6 +31,12 @@ CPPFLAGS+= -I${.CURDIR} -I${MKNODSRC} -I${MTREESRC} -DMAKEFS .if !defined(HOSTPROG) DPADD+= ${LIBUTIL} 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 .include diff --git a/usr.sbin/makefs/cd9660.c b/usr.sbin/makefs/cd9660.c index b2499d91c..72e20f0c0 100644 --- a/usr.sbin/makefs/cd9660.c +++ b/usr.sbin/makefs/cd9660.c @@ -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 @@ -103,7 +103,7 @@ #include #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 */ #include @@ -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 cd9660node *cd9660_allocate_cd9660node(void); 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 *); static void cd9660_populate_iso_dir_record( 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 */ static cd9660node * @@ -298,7 +298,7 @@ cd9660_prep_opts(fsinfo_t *fsopts) "Allow 37 char filenames (unimplemented)"), OPT_BOOL('i', "allow-illegal-chars", allow_illegal_chars, "Allow illegal characters in filenames"), - OPT_BOOL('D', "allow-multidot", allow_multidot, + OPT_BOOL('m', "allow-multidot", allow_multidot, "Allow multiple periods in filenames"), OPT_BOOL('o', "omit-trailing-period", omit_trailing_period, "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', "hard-disk-boot", "Boot from hard disk"), OPT_STR('\0', "boot-load-segment", "Boot load segment"), + OPT_STR('\0', "platformid", "Section Header Platform ID"), { .name = NULL } }; @@ -339,10 +340,11 @@ cd9660_cleanup_opts(fsinfo_t *fsopts) } static int -cd9660_arguments_set_string(const char *val, const char *fieldtitle, int length, - char testmode, char * dest) +cd9660_arguments_set_string(const char *val, const char *fieldtitle, + size_t length, char testmode, char * dest) { - int len, test; + size_t len; + int test; if (val == NULL) warnx("error: The %s requires a string argument", fieldtitle); @@ -457,7 +459,8 @@ cd9660_parse_opts(const char *option, fsinfo_t *fsopts) /* RRIP */ cd9660_eltorito_add_boot_option(diskStructure, name, 0); 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') { warnx("Option `%s' doesn't contain a value", name); @@ -483,7 +486,7 @@ cd9660_parse_opts(const char *option, fsinfo_t *fsopts) */ void cd9660_makefs(const char *image, const char *dir, fsnode *root, - fsinfo_t *fsopts) + fsinfo_t *fsopts) { int64_t startoffset; int numDirectories; @@ -661,7 +664,7 @@ typedef int (*cd9660node_func)(cd9660node *); static void 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 */ memcpy(diskStructure->primaryDescriptor.root_directory_record, @@ -710,23 +713,23 @@ cd9660_finalize_PVD(iso9660_disk *diskStructure) diskStructure->primaryDescriptor.bibliographic_file_id, 37); /* Setup dates */ - time(&tim); cd9660_time_8426( (unsigned char *)diskStructure->primaryDescriptor.creation_date, - tim); + tstamp); cd9660_time_8426( (unsigned char *)diskStructure->primaryDescriptor.modification_date, - tim); + tstamp); - /* - cd9660_set_date(diskStructure->primaryDescriptor.expiration_date, now); - */ +#if 0 + cd9660_set_date(diskStructure->primaryDescriptor.expiration_date, + tstamp); +#endif memset(diskStructure->primaryDescriptor.expiration_date, '0' ,16); diskStructure->primaryDescriptor.expiration_date[16] = 0; cd9660_time_8426( (unsigned char *)diskStructure->primaryDescriptor.effective_date, - tim); + tstamp); } static void @@ -821,7 +824,7 @@ cd9660_fill_extended_attribute_record(cd9660node *node) static int 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; char temp[ISO_FILENAME_MAXLENGTH_WITH_PADDING]; @@ -841,9 +844,8 @@ cd9660_translate_node_common(iso9660_disk *diskStructure, cd9660node *newnode) /* Set the various dates */ /* 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, newnode->isoDirRecord->size); @@ -883,7 +885,8 @@ cd9660_translate_node(iso9660_disk *diskStructure, fsnode *node, return 0; /* 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; } @@ -1078,7 +1081,7 @@ cd9660_rename_filename(iso9660_disk *diskStructure, cd9660node *iter, int num, tmp = emalloc(ISO_FILENAME_MAXLENGTH_WITH_PADDING); - while (i < num) { + while (i < num && iter) { powers = 1; count = 0; digits = 1; @@ -1281,6 +1284,8 @@ cd9660_rrip_move_directory(iso9660_disk *diskStructure, cd9660node *dir) diskStructure->rootNode, dir); if (diskStructure->rr_moved_dir == NULL) 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 */ @@ -1290,7 +1295,7 @@ cd9660_rrip_move_directory(iso9660_disk *diskStructure, cd9660node *dir) return NULL; diskStructure->rock_ridge_move_count++; - snprintf(newname, sizeof(newname), "%08i", + snprintf(newname, sizeof(newname), "%08u", diskStructure->rock_ridge_move_count); /* Point to old parent */ diff --git a/usr.sbin/makefs/cd9660.h b/usr.sbin/makefs/cd9660.h index ef9f44f34..3d45cfa8d 100644 --- a/usr.sbin/makefs/cd9660.h +++ b/usr.sbin/makefs/cd9660.h @@ -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 @@ -308,7 +308,7 @@ typedef struct _iso9660_disk { /************ FUNCTIONS **************/ int cd9660_valid_a_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 */ void cd9660_721(uint16_t, unsigned char *); diff --git a/usr.sbin/makefs/cd9660/cd9660_conversion.c b/usr.sbin/makefs/cd9660/cd9660_conversion.c index ae1e954c8..591eae2e6 100644 --- a/usr.sbin/makefs/cd9660/cd9660_conversion.c +++ b/usr.sbin/makefs/cd9660/cd9660_conversion.c @@ -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 @@ -35,7 +35,7 @@ #include #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 */ @@ -150,6 +150,9 @@ cd9660_pad_string_spaces(char *str, int len) static char cd9660_compute_gm_offset(time_t tim) { + if (stampst.st_ino) + return 0; + struct tm t, gm; (void)localtime_r(&tim, &t); @@ -173,7 +176,10 @@ cd9660_time_8426(unsigned char *buf, time_t tim) struct tm t; 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", 1900+(int)t.tm_year, (int)t.tm_mon+1, @@ -192,7 +198,10 @@ cd9660_time_915(unsigned char *buf, time_t tim) { 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[1] = t.tm_mon+1; buf[2] = t.tm_mday; diff --git a/usr.sbin/makefs/cd9660/cd9660_eltorito.c b/usr.sbin/makefs/cd9660/cd9660_eltorito.c index dc93425a0..cc853c8d9 100644 --- a/usr.sbin/makefs/cd9660/cd9660_eltorito.c +++ b/usr.sbin/makefs/cd9660/cd9660_eltorito.c @@ -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 @@ -40,7 +40,7 @@ #include #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 */ #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( struct cd9660_boot_image *); static struct boot_catalog_entry *cd9660_boot_setup_section_head(char); -static struct boot_catalog_entry *cd9660_boot_setup_validation_entry(char); #if 0 static u_char cd9660_boot_get_system_type(struct cd9660_boot_image *); #endif +static struct cd9660_boot_image *default_boot_image; + int 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 || strcmp(sysname, "mac68k") == 0) new_image->system = ET_SYS_MAC; + else if (strcmp(sysname, "efi") == 0) + new_image->system = ET_SYS_EFI; else { warnx("boot disk system must be " - "i386, powerpc, macppc, or mac68k"); + "i386, powerpc, macppc, mac68k, or efi"); free(temp); free(new_image); 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->platform_id = new_image->system; + /* TODO : Need to do anything about the boot image in the tree? */ diskStructure->is_bootable = 1; + /* First boot image is initial/default entry. */ + if (default_boot_image == NULL) + default_boot_image = new_image; + return 1; } @@ -211,6 +220,13 @@ cd9660_eltorito_add_boot_option(iso9660_disk *diskStructure, warn("%s: strtoul", __func__); 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 { return 0; } @@ -233,6 +249,7 @@ cd9660_boot_setup_validation_entry(char sys) size_t i; entry = cd9660_init_boot_catalog_entry(); + entry->entry_type = ET_ENTRY_VE; ve = &entry->entry_data.VE; ve->header_id[0] = 1; @@ -267,6 +284,7 @@ cd9660_boot_setup_default_entry(struct cd9660_boot_image *disk) if (default_entry == NULL) return NULL; + default_entry->entry_type = ET_ENTRY_IE; ie = &default_entry->entry_data.IE; ie->boot_indicator[0] = disk->bootable; @@ -294,6 +312,7 @@ cd9660_boot_setup_section_head(char platform) if (entry == NULL) return NULL; + entry->entry_type = ET_ENTRY_SH; sh = &entry->entry_data.SH; /* More by default. The last one will manually be set to 0x91 */ 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) return NULL; + entry->entry_type = ET_ENTRY_SE; se = &entry->entry_data.SE; se->boot_indicator[0] = ET_BOOTABLE; @@ -342,12 +362,13 @@ cd9660_setup_boot(iso9660_disk *diskStructure, int first_sector) int used_sectors; int num_entries = 0; 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; struct cd9660_boot_image *tmp_disk; + u_char system; 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 (TAILQ_EMPTY(&diskStructure->boot_images)) @@ -359,9 +380,16 @@ cd9660_setup_boot(iso9660_disk *diskStructure, int first_sector) cd9660_bothendian_dword(first_sector, 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 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) return -1; @@ -391,14 +419,25 @@ cd9660_setup_boot(iso9660_disk *diskStructure, int first_sector) sector = first_sector + catalog_sectors; TAILQ_FOREACH(tmp_disk, &diskStructure->boot_images, image_list) { 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); /* Step 1b: Initial/default entry */ /* 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); if (default_entry == NULL) { 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? */ - tmp_disk = TAILQ_NEXT(tmp_disk, image_list); + tmp_disk = TAILQ_FIRST(&diskStructure->boot_images); + head = NULL; temp = default_entry; /* 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 */ - switch (tmp_disk->system) { + switch (tmp_disk->platform_id) { case ET_SYS_X86: headp = &x86_head; break; @@ -426,6 +469,9 @@ cd9660_setup_boot(iso9660_disk *diskStructure, int first_sector) case ET_SYS_MAC: headp = &mac_head; break; + case ET_SYS_EFI: + headp = &efi_head; + break; default: warnx("%s: internal error: unknown system type", __func__); @@ -434,7 +480,7 @@ cd9660_setup_boot(iso9660_disk *diskStructure, int first_sector) if (*headp == NULL) { head = - cd9660_boot_setup_section_head(tmp_disk->system); + cd9660_boot_setup_section_head(tmp_disk->platform_id); if (head == NULL) { warnx("Error: memory allocation failed in " "cd9660_setup_boot"); @@ -459,9 +505,17 @@ cd9660_setup_boot(iso9660_disk *diskStructure, int first_sector) head = next; 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 */ return first_sector + used_sectors; diff --git a/usr.sbin/makefs/cd9660/cd9660_eltorito.h b/usr.sbin/makefs/cd9660/cd9660_eltorito.h index 266148395..ef3e4a3bc 100644 --- a/usr.sbin/makefs/cd9660/cd9660_eltorito.h +++ b/usr.sbin/makefs/cd9660/cd9660_eltorito.h @@ -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 @@ -40,6 +40,7 @@ #define ET_SYS_X86 0 #define ET_SYS_PPC 1 #define ET_SYS_MAC 2 +#define ET_SYS_EFI 0xef /* Platform ID at section header entry */ #define ET_BOOT_ENTRY_SIZE 0x20 @@ -145,6 +146,7 @@ struct cd9660_boot_image { u_char targetMode; u_char system; u_char bootable; + u_char platform_id; /* for section header entry */ /* * If the boot image exists in the filesystem * already, this is a pointer to that node. For the sake diff --git a/usr.sbin/makefs/cd9660/cd9660_strings.c b/usr.sbin/makefs/cd9660/cd9660_strings.c index fa822746d..d922771f6 100644 --- a/usr.sbin/makefs/cd9660/cd9660_strings.c +++ b/usr.sbin/makefs/cd9660/cd9660_strings.c @@ -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 @@ -46,14 +46,14 @@ #include "cd9660.h" #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 */ 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++) { if (islower((unsigned char)str[p]) ) diff --git a/usr.sbin/makefs/chfs/chfs_mkfs.c b/usr.sbin/makefs/chfs/chfs_mkfs.c index 4c96f66b8..06d980a10 100644 --- a/usr.sbin/makefs/chfs/chfs_mkfs.c +++ b/usr.sbin/makefs/chfs/chfs_mkfs.c @@ -43,10 +43,7 @@ #include #include #include - -#if defined(__minix) #include -#endif #include "makefs.h" #include "chfs_makefs.h" @@ -128,7 +125,6 @@ write_eb_header(fsinfo_t *fsopts) if ((uint32_t)opts->pagesize < MINSIZE) errx(EXIT_FAILURE, "pagesize cannot be less than %zu", MINSIZE); buf = emalloc(opts->pagesize); - memset(buf, 0xFF, opts->pagesize); ebhdr.ec_hdr.magic = htole32(CHFS_MAGIC_BITMASK); ebhdr.ec_hdr.erase_cnt = htole32(1); @@ -136,6 +132,8 @@ write_eb_header(fsinfo_t *fsopts) (uint8_t *)&ebhdr.ec_hdr + 8, 4)); 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); diff --git a/usr.sbin/makefs/ffs.c b/usr.sbin/makefs/ffs.c index 44f1519fd..57d4070d8 100644 --- a/usr.sbin/makefs/ffs.c +++ b/usr.sbin/makefs/ffs.c @@ -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. @@ -71,7 +71,7 @@ #include #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 */ #include @@ -466,6 +466,7 @@ ffs_create_image(const char *image, fsinfo_t *fsopts) char *buf; int i, bufsize; off_t bufrem; + time_t tstamp; int oflags = O_RDWR | O_CREAT; assert (image != NULL); @@ -530,7 +531,15 @@ ffs_create_image(const char *image, fsinfo_t *fsopts) /* make the file system */ if (debug & DEBUG_FS_CREATE_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; if (debug & DEBUG_FS_CREATE_IMAGE) { time_t t; @@ -637,19 +646,12 @@ ffs_build_dinode1(struct ufs1_dinode *dinp, dirbuf_t *dbufp, fsnode *cur, { size_t slen; void *membuf; + struct stat *st = stampst.st_ino ? &stampst : &cur->inode->st; memset(dinp, 0, sizeof(*dinp)); dinp->di_mode = cur->inode->st.st_mode; dinp->di_nlink = cur->inode->nlink; 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 dinp->di_flags = cur->inode->st.st_flags; #endif @@ -658,6 +660,15 @@ ffs_build_dinode1(struct ufs1_dinode *dinp, dirbuf_t *dbufp, fsnode *cur, #endif dinp->di_uid = cur->inode->st.st_uid; 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 */ membuf = NULL; @@ -685,31 +696,33 @@ ffs_build_dinode2(struct ufs2_dinode *dinp, dirbuf_t *dbufp, fsnode *cur, { size_t slen; void *membuf; + struct stat *st = stampst.st_ino ? &stampst : &cur->inode->st; memset(dinp, 0, sizeof(*dinp)); dinp->di_mode = cur->inode->st.st_mode; dinp->di_nlink = cur->inode->nlink; 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 dinp->di_flags = cur->inode->st.st_flags; #endif #if HAVE_STRUCT_STAT_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 dinp->di_uid = cur->inode->st.st_uid; 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 */ 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. */ 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 && initediblk < ufs_rw32(cgp->cg_niblk, fsopts->needswap)) { memset(buf, 0, fs->fs_bsize); dip = (struct ufs2_dinode *)buf; - srandom(time(NULL)); for (i = 0; i < FFS_INOPB(fs); i++) { dip->di_gen = random() / 2 + 1; dip++; diff --git a/usr.sbin/makefs/ffs/buf.c b/usr.sbin/makefs/ffs/buf.c index 352b1dc3d..ed25432a2 100644 --- a/usr.sbin/makefs/ffs/buf.c +++ b/usr.sbin/makefs/ffs/buf.c @@ -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. @@ -41,7 +41,7 @@ #include #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 */ #include @@ -78,17 +78,17 @@ bread(struct vnode *vp, daddr_t blkno, int size, int u2 __unused, (long long)(*bpp)->b_blkno, (long long) offset, (*bpp)->b_bcount); 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); - 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) printf("bread: read %ld (%lld) returned %zd\n", (*bpp)->b_bcount, (long long)offset, rv); 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); 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); else return (0); @@ -129,14 +129,14 @@ bwrite(struct buf *bp) { off_t offset; ssize_t rv; - int bytes; + size_t bytes; fsinfo_t *fs = bp->b_fs; assert (bp != NULL); offset = bp->b_blkno * fs->sectorsize + fs->offset; - bytes = bp->b_bcount; + bytes = (size_t)bp->b_bcount; 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); if (lseek(bp->b_fs->fd, offset, SEEK_SET) == -1) return (errno); @@ -145,7 +145,7 @@ bwrite(struct buf *bp) printf("bwrite: write %ld (offset %lld) returned %lld\n", bp->b_bcount, (long long)offset, (long long)rv); brelse(bp, 0); - if (rv == bytes) + if (rv == (ssize_t)bytes) return (0); else if (rv == -1) /* write error */ return (errno); @@ -210,8 +210,8 @@ getblk(struct vnode *vp, daddr_t blkno, int size, int u1 __unused, } bp->b_bcount = size; if (bp->b_data == NULL || bp->b_bcount > bp->b_bufsize) { - n = erealloc(bp->b_data, size); - memset(n, 0, size); + n = erealloc(bp->b_data, (size_t)size); + memset(n, 0, (size_t)size); bp->b_data = n; bp->b_bufsize = size; } diff --git a/usr.sbin/makefs/ffs/buf.h b/usr.sbin/makefs/ffs/buf.h index 2f1ecc019..6a9e9d7ef 100644 --- a/usr.sbin/makefs/ffs/buf.h +++ b/usr.sbin/makefs/ffs/buf.h @@ -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. @@ -40,6 +40,7 @@ #include #include +#include #include #include @@ -87,7 +88,34 @@ struct buf * getblk(struct vnode *, daddr_t, int, int, int); #define BC_AGE 0 #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 IO_SYNC 1 diff --git a/usr.sbin/makefs/ffs/ffs_alloc.c b/usr.sbin/makefs/ffs/ffs_alloc.c index dd429ff7a..24d0df4b3 100644 --- a/usr.sbin/makefs/ffs/ffs_alloc.c +++ b/usr.sbin/makefs/ffs/ffs_alloc.c @@ -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 */ /* @@ -47,7 +47,7 @@ #include #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 */ #include @@ -107,7 +107,7 @@ ffs_alloc(struct inode *ip, daddr_t lbn __unused, daddr_t bpref, int size, *bnp = 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); } 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 || ffs_fragnum(fs, bno) + ffs_numfrags(fs, size) > fs->fs_frag) { - errx(1, "blkfree: bad size: bno %lld bsize %d size %ld", - (long long)bno, fs->fs_bsize, size); + errx(EXIT_FAILURE, "%s: bad size: bno %lld bsize %d " + "size %ld", __func__, (long long)bno, fs->fs_bsize, size); } cg = dtog(fs, bno); if (bno >= fs->fs_size) { @@ -465,8 +465,8 @@ ffs_blkfree(struct inode *ip, daddr_t bno, long size) if (size == fs->fs_bsize) { fragno = ffs_fragstoblks(fs, cgbno); if (!ffs_isfreeblock(fs, cg_blksfree(cgp, needswap), fragno)) { - errx(1, "blkfree: freeing free block %lld", - (long long)bno); + errx(EXIT_FAILURE, "%s: freeing free block %lld", + __func__, (long long)bno); } ffs_setblock(fs, cg_blksfree(cgp, needswap), fragno); 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); for (i = 0; i < frags; 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)); } 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], (1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); if (loc == 0) { - errx(1, - "ffs_alloccg: map corrupted: start %d len %d offset %d %ld", - ostart, olen, - ufs_rw32(cgp->cg_freeoff, needswap), - (long)cg_blksfree(cgp, needswap) - (long)cgp); + errx(EXIT_FAILURE, "%s: map corrupted: start %d " + "len %d offset %d %ld", __func__, ostart, olen, + ufs_rw32(cgp->cg_freeoff, needswap), + (long)cg_blksfree(cgp, needswap) - (long)cgp); /* NOTREACHED */ } } @@ -592,6 +592,7 @@ ffs_mapsearch(struct fs *fs, struct cg *cgp, daddr_t bpref, int allocsiz) 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); } diff --git a/usr.sbin/makefs/ffs/ffs_extern.h b/usr.sbin/makefs/ffs/ffs_extern.h index 53e9fe2ee..c4091a6dd 100644 --- a/usr.sbin/makefs/ffs/ffs_extern.h +++ b/usr.sbin/makefs/ffs/ffs_extern.h @@ -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 */ /*- @@ -59,7 +59,7 @@ void ffs_clusteracct(struct fs *, struct cg *, int32_t, int); int ffs_balloc(struct inode *, off_t, int, struct buf **); /* 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_dinode2_swap(struct ufs2_dinode *, struct ufs2_dinode *); void ffs_csum_swap(struct csum *, struct csum *, int); diff --git a/usr.sbin/makefs/ffs/mkfs.c b/usr.sbin/makefs/ffs/mkfs.c index c4dbc9b46..61cf74b4d 100644 --- a/usr.sbin/makefs/ffs/mkfs.c +++ b/usr.sbin/makefs/ffs/mkfs.c @@ -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. @@ -48,7 +48,7 @@ static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95"; #else #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 /* not lint */ @@ -102,7 +102,11 @@ union { char *iobuf; 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 int64_t fssize; /* file system size */ @@ -121,8 +125,19 @@ static int sbsize; /* superblock size */ static int avgfilesize; /* expected average file size */ 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 * -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; int32_t cylno, i, csfrags; @@ -445,7 +460,7 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts) sblock.fs_state = 0; sblock.fs_clean = FS_ISCLEAN; sblock.fs_ronly = 0; - sblock.fs_id[0] = start_time.tv_sec; + sblock.fs_id[0] = tstamp; sblock.fs_id[1] = random(); sblock.fs_fsmnt[0] = '\0'; 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_ndir = 0; sblock.fs_dsize -= csfrags; - sblock.fs_time = start_time.tv_sec; + sblock.fs_time = tstamp; 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_csaddr = sblock.fs_csaddr; 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 * writing out in each cylinder group. */ - memcpy(writebuf, &sblock, sbsize); - if (fsopts->needswap) - ffs_sb_swap(&sblock, (struct fs*)writebuf); + ffs_sb_copy(&wb.fs, &sblock, sbsize, fsopts); memcpy(iobuf, writebuf, SBLOCKSIZE); printf("super-block backups (for fsck -b #) at:"); for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { - initcg(cylno, start_time.tv_sec, fsopts); + initcg(cylno, tstamp, fsopts); if (cylno % nprintcols == 0) printf("\n"); printf(" %*lld,", printcolwidth, @@ -528,7 +541,7 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts) * Now construct the initial file system, * then write out the super-block. */ - sblock.fs_time = start_time.tv_sec; + sblock.fs_time = tstamp; if (Oflag <= 1) { sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir; 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; fs->fs_flags &= ~FS_INTERNAL; - memcpy(writebuf, &sblock, sbsize); - if (fsopts->needswap) - ffs_sb_swap(fs, (struct fs*)writebuf); + ffs_sb_copy(&wb.fs, &sblock, sbsize, fsopts); ffs_wtfs(fs->fs_sblockloc / sectorsize, sbsize, writebuf, fsopts); /* 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; 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); n = read(fsopts->fd, bf, size); 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); } 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); } @@ -810,15 +821,15 @@ ffs_wtfs(daddr_t bno, int size, void *bf, const fsinfo_t *fsopts) offset = bno * fsopts->sectorsize + fsopts->offset; if (lseek(fsopts->fd, offset, SEEK_SET) == -1) - err(1, "%s: seek error for sector %lld", __func__, - (long long)bno); + err(EXIT_FAILURE, "%s: seek error @%jd for sector %jd", + __func__, (intmax_t)offset, (intmax_t)bno); n = write(fsopts->fd, bf, size); if (n == -1) - err(1, "%s: write error for sector %lld", __func__, - (long long)bno); + err(EXIT_FAILURE, "%s: write error for sector %jd", __func__, + (intmax_t)bno); else if (n != size) - errx(1, "%s: short write error for sector %lld", __func__, - (long long)bno); + errx(EXIT_FAILURE, "%s: short write error for sector %jd", + __func__, (intmax_t)bno); } @@ -841,5 +852,5 @@ ilog2(int val) for (n = 0; n < sizeof(n) * CHAR_BIT; n++) if (1 << n == val) 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); } diff --git a/usr.sbin/makefs/ffs/newfs_extern.h b/usr.sbin/makefs/ffs/newfs_extern.h index d86b248dd..7e91f88ed 100644 --- a/usr.sbin/makefs/ffs/newfs_extern.h +++ b/usr.sbin/makefs/ffs/newfs_extern.h @@ -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 $ */ /* @@ -26,7 +26,7 @@ */ /* 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_rdfs(daddr_t, int, void *, const fsinfo_t *); void ffs_wtfs(daddr_t, int, void *, const fsinfo_t *); diff --git a/usr.sbin/makefs/makefs.8 b/usr.sbin/makefs/makefs.8 index 92f8fb40d..a9ffbff1a 100644 --- a/usr.sbin/makefs/makefs.8 +++ b/usr.sbin/makefs/makefs.8 @@ -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. .\" All rights reserved. @@ -33,7 +33,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd August 6, 2013 +.Dd November 14, 2020 .Dt MAKEFS 8 .Os .Sh NAME @@ -54,6 +54,7 @@ .Op Fl o Ar fs-options .Op Fl S Ar sector-size .Op Fl s Ar image-size +.Op Fl T Ar timestamp .Op Fl t Ar fs-type .Ar image-file .Ar directory @@ -178,7 +179,7 @@ and .Xr getgrnam 3 (and related) library calls. .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. Valid only for .Sy ffs @@ -199,24 +200,58 @@ Defaults to 512. .It Fl s Ar image-size Set the size of the file system image to .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 Create an .Ar fs-type file system image. The following file system types are supported: .Bl -tag -width cd9660 -offset indent -.It Sy ffs -BSD fast file system (default). .It Sy cd9660 ISO 9660 file system. .It Sy chfs Chip flash file system. +.It Sy ffs +BSD fast file system (default). .It Sy msdos FAT12, FAT16, or FAT32 file system. -.It Sy v7fs -7th Edition(V7) file system. .It Sy udf ISO/Ecma UDF file system. +.It Sy v7fs +7th Edition(V7) file system. .El .It Fl x Exclude file system nodes not explicitly listed in the specfile. @@ -228,7 +263,7 @@ This is useful for virtual machine images. .Pp Where sizes are specified, a decimal number of bytes is expected. Two or more numbers may be separated by an -.Dq x +.Sq x to indicate a product. Each number may have one of the following optional suffixes: .Bl -tag -width 3n -offset indent -compact @@ -264,10 +299,14 @@ Expected number of files per directory. Block size. .It Sy density Bytes per inode. +.It Sy extent +Maximum extent size. .It Sy fsize Fragment size. .It Sy label Label name of the image. +.It Sy maxbpcg +Maximum total number of blocks in a cylinder group. .It Sy maxbpg Maximum blocks per file in a cylinder group. .It Sy minfree @@ -277,10 +316,6 @@ Optimization preference; one of .Ql space or .Ql time . -.It Sy extent -Maximum extent size. -.It Sy maxbpcg -Maximum total number of blocks in a cylinder group. .It Sy version UFS version. 1 for FFS (default), 2 for UFS2. @@ -304,7 +339,7 @@ the spec. .\" Unknown .It Sy allow-max-name Allow 37 instead of 33 characters for filenames by omitting the -version id. +version ID. .It Sy allow-multidot Allow multiple dots in a filename. .It Sy applicationid @@ -315,9 +350,6 @@ Use the extension to encode .Tn RISC OS 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 Set load segment for the boot image. .It Sy bootimage @@ -326,11 +358,15 @@ Filename of a boot image in the format where .Dq sysid is one of +.Ql efi , .Ql i386 , .Ql mac68k , .Ql macppc , or .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 Load a generic boot image into the first 32K of the cd9660 image. .It Sy hard-disk-boot @@ -350,6 +386,8 @@ ElTorito image. Do not pad the image (apparently Linux needs the padding). .\" .It Sy omit-trailing-period .\" Unknown +.It Sy platformid +Set platform ID of section header entry of the boot image. .It Sy preparer Preparer ID of the image. .It Sy publisher @@ -377,9 +415,63 @@ Type of the media. NOR: 0 or NAND: 1. .El .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 -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 The following keywords are supported: .Pp @@ -398,7 +490,7 @@ Each of the options consists of a keyword, an equal sign and a value. The following keywords are supported: .Pp -.Bl -tag -width optimization -compact +.Bl -tag -width optimization -offset indent -compact .It Sy disctype This can have the following values: .Bl -tag -width cdromXdvdromXbdromXXX -compact @@ -453,8 +545,8 @@ utility appeared in .An UCHIYAMA Yasushi (v7fs support), .An Tamas Toth -(chfs support). +(chfs support), .An Christos Zoulas -(msdos support). +(msdos support), .An Reinoud Zandijk (udf support). diff --git a/usr.sbin/makefs/makefs.c b/usr.sbin/makefs/makefs.c index 116eceb45..508b68e2a 100644 --- a/usr.sbin/makefs/makefs.c +++ b/usr.sbin/makefs/makefs.c @@ -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. @@ -41,7 +41,7 @@ #include #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 */ #include @@ -87,8 +87,10 @@ static fstype_t fstypes[] = { u_int debug; struct timespec start_time; +struct stat stampst; static fstype_t *get_fstype(const char *); +static int get_tstamp(const char *, struct stat *); static void usage(fstype_t *, fsinfo_t *) __dead; int @@ -116,13 +118,18 @@ main(int argc, char *argv[]) fstype->prepare_options(&fsoptions); specfile = NULL; - if (gettimeofday(&start, NULL) == -1) - err(1, "Unable to get system time"); - +#ifdef CLOCK_REALTIME + ch = clock_gettime(CLOCK_REALTIME, &start_time); +#else + ch = gettimeofday(&start, NULL); start_time.tv_sec = start.tv_sec; 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) { case 'B': @@ -240,6 +247,12 @@ main(int argc, char *argv[]) fstype->prepare_options(&fsoptions); break; + case 'T': + if (get_tstamp(optarg, &stampst) == -1) + errx(1, "Cannot get timestamp from `%s'", + optarg); + break; + case 'x': fsoptions.onlyspec = 1; break; @@ -409,6 +422,36 @@ copy_opts(const option_t *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 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" "\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[-s image-size] [-t fs-type] image-file directory [extra-directory ...]\n", +"\t[-s image-size] [-T ] [-t fs-type]" +" image-file directory [extra-directory ...]\n", prog); if (fstype) { diff --git a/usr.sbin/makefs/makefs.h b/usr.sbin/makefs/makefs.h index b856d5232..2929fcb50 100644 --- a/usr.sbin/makefs/makefs.h +++ b/usr.sbin/makefs/makefs.h @@ -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. @@ -199,6 +199,7 @@ DECLARE_FUN(udf); extern u_int debug; extern struct timespec start_time; +extern struct stat stampst; /* * If -x is specified, we want to exclude nodes which do not appear diff --git a/usr.sbin/makefs/msdos.c b/usr.sbin/makefs/msdos.c index 5a7b10310..7ec46b185 100644 --- a/usr.sbin/makefs/msdos.c +++ b/usr.sbin/makefs/msdos.c @@ -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. @@ -15,9 +15,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. 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 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED @@ -37,7 +34,7 @@ #include #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 */ #include @@ -58,7 +55,9 @@ __RCSID("$NetBSD: msdos.c,v 1.14 2013/02/03 03:21:21 christos Exp $"); #include #include +#include #include +#include #include "makefs.h" #include "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 *, fsnode *, fsinfo_t *); +struct msdos_options_ex { + struct msdos_options options; + bool utf8; +}; + void 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[] = { #define AOPT(_opt, _type, _name, _min, _desc) { \ .letter = _opt, \ @@ -79,7 +83,7 @@ msdos_prep_opts(fsinfo_t *fsopts) (sizeof(_type) == 1 ? OPT_INT8 : \ (sizeof(_type) == 2 ? OPT_INT16 : \ (sizeof(_type) == 4 ? OPT_INT32 : OPT_INT64)))), \ - .value = &msdos_opt->_name, \ + .value = &msdos_opt->options._name, \ .minimum = _min, \ .maximum = sizeof(_type) == 1 ? 0xff : \ (sizeof(_type) == 2 ? 0xffff : \ @@ -88,6 +92,8 @@ msdos_prep_opts(fsinfo_t *fsopts) }, ALLOPTS #undef AOPT + { 'U', "utf8", &msdos_opt->utf8, OPT_BOOL, + 0, 1, "Use UTF8 names" }, { .name = NULL } }; @@ -127,6 +133,12 @@ msdos_parse_opts(const char *option, fsinfo_t *fsopts) msdos_opt->media_descriptor_set = 1; else if (strcmp(msdos_options[rv].name, "hidden_sectors") == 0) msdos_opt->hidden_sectors_set = 1; + + if (stampst.st_ino) { + msdos_opt->timestamp_set = 1; + msdos_opt->timestamp = stampst.st_mtime; + } + return 1; } @@ -134,45 +146,48 @@ msdos_parse_opts(const char *option, fsinfo_t *fsopts) void 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 timeval start; struct msdosfsmount *pmp; + uint32_t flags; assert(image != NULL); assert(dir != NULL); assert(root != NULL); assert(fsopts != NULL); - /* - * XXX: pick up other options from the msdos specific ones? - * Is minsize right here? - */ - msdos_opt->create_size = MAX(msdos_opt->create_size, fsopts->minsize); - msdos_opt->offset = fsopts->offset; - if (msdos_opt->bytes_per_sector == 0) { + fsopts->size = fsopts->maxsize; + msdos_opt->options.create_size = MAX(msdos_opt->options.create_size, + fsopts->offset + fsopts->size); + msdos_opt->options.offset = fsopts->offset; + if (msdos_opt->options.bytes_per_sector == 0) { if (fsopts->sectorsize == -1) fsopts->sectorsize = 512; - msdos_opt->bytes_per_sector = fsopts->sectorsize; + msdos_opt->options.bytes_per_sector = fsopts->sectorsize; } else if (fsopts->sectorsize == -1) { - fsopts->sectorsize = msdos_opt->bytes_per_sector; - } else if (fsopts->sectorsize != msdos_opt->bytes_per_sector) { + fsopts->sectorsize = msdos_opt->options.bytes_per_sector; + } else if (fsopts->sectorsize != msdos_opt->options.bytes_per_sector) { err(1, "inconsistent sectorsize -S %u" "!= -o bytes_per_sector %u", - fsopts->sectorsize, msdos_opt->bytes_per_sector); + fsopts->sectorsize, msdos_opt->options.bytes_per_sector); } /* create image */ printf("Creating `%s'\n", image); TIMER_START(start); - if (mkfs_msdos(image, NULL, msdos_opt) == -1) + if (mkfs_msdos(image, NULL, &msdos_opt->options) == -1) return; TIMER_RESULTS(start, "mkfs_msdos"); fsopts->fd = open(image, O_RDWR); 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"); if (msdosfs_root(pmp, &rootvp) != 0) diff --git a/usr.sbin/makefs/msdos.h b/usr.sbin/makefs/msdos.h index 3571bef38..0357f6d93 100644 --- a/usr.sbin/makefs/msdos.h +++ b/usr.sbin/makefs/msdos.h @@ -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. @@ -15,9 +15,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. 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 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED diff --git a/usr.sbin/makefs/msdos/Makefile.inc b/usr.sbin/makefs/msdos/Makefile.inc index 753b147ce..3f6ae8952 100644 --- a/usr.sbin/makefs/msdos/Makefile.inc +++ b/usr.sbin/makefs/msdos/Makefile.inc @@ -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 @@ -12,5 +12,5 @@ CPPFLAGS+= -I${NETBSDSRCDIR}/sys .endif 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 diff --git a/usr.sbin/makefs/msdos/msdosfs_vfsops.c b/usr.sbin/makefs/msdos/msdosfs_vfsops.c index 48f822064..5ba8ce118 100644 --- a/usr.sbin/makefs/msdos/msdosfs_vfsops.c +++ b/usr.sbin/makefs/msdos/msdosfs_vfsops.c @@ -50,7 +50,7 @@ #endif #include -__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 @@ -68,6 +68,7 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_vfsops.c,v 1.9 2015/03/29 05:52:59 agc Exp $ #include #include #include +#include #include "makefs.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) { pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs); pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors); diff --git a/usr.sbin/makefs/msdos/msdosfs_vnops.c b/usr.sbin/makefs/msdos/msdosfs_vnops.c index 4cd73b941..2695662dd 100644 --- a/usr.sbin/makefs/msdos/msdosfs_vnops.c +++ b/usr.sbin/makefs/msdos/msdosfs_vnops.c @@ -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. @@ -51,7 +51,7 @@ #endif #include -__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 #include @@ -98,12 +98,20 @@ static void msdosfs_times(struct msdosfsmount *pmp, struct denode *dep, const struct stat *st) { + struct timespec at; + struct timespec mt; + + if (stampst.st_ino) + st = &stampst; + #ifndef HAVE_NBTOOL_CONFIG_H - struct timespec at = st->st_atimespec; - struct timespec mt = st->st_mtimespec; + at = st->st_atimespec; + mt = st->st_mtimespec; #else - struct timespec at = { st->st_atime, 0 }; - struct timespec mt = { st->st_mtime, 0 }; + at.tv_sec = st->st_atime; + at.tv_nsec = 0; + mt.tv_sec = st->st_mtime; + mt.tv_nsec = 0; #endif unix2dostime(&at, pmp->pm_gmtoff, &dep->de_ADate, NULL, NULL); unix2dostime(&mt, pmp->pm_gmtoff, &dep->de_MDate, &dep->de_MTime, NULL); @@ -154,12 +162,12 @@ msdosfs_findslot(struct denode *dp, struct componentname *cnp) break; case 2: wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, - cnp->cn_namelen) + 1; + cnp->cn_namelen, pmp->pm_flags & MSDOSFSMNT_UTF8) + 1; break; case 3: olddos = 0; wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, - cnp->cn_namelen) + 1; + cnp->cn_namelen, pmp->pm_flags & MSDOSFSMNT_UTF8) + 1; break; } @@ -243,7 +251,8 @@ msdosfs_findslot(struct denode *dp, struct componentname *cnp) chksum = winChkName((const u_char *)cnp->cn_nameptr, cnp->cn_namelen, (struct winentry *)dep, - chksum); + chksum, + pmp->pm_flags & MSDOSFSMNT_UTF8); continue; } @@ -431,31 +440,29 @@ msdosfs_wfile(const char *path, struct denode *dep, fsnode *node) return 0; /* Don't bother to try to write files larger than the fs limit */ - if (st->st_size > MSDOSFS_FILESIZE_MAX) { - errno = EFBIG; - return -1; - } + if (st->st_size > MSDOSFS_FILESIZE_MAX) + return EFBIG; nsize = st->st_size; DPRINTF(("%s(nsize=%zu, osize=%zu)\n", __func__, nsize, osize)); if (nsize > osize) { - if ((error = deextend(dep, nsize, NULL)) != 0) { - errno = error; - return -1; - } - if ((error = msdosfs_updatede(dep)) != 0) { - errno = error; - return -1; - } + if ((error = deextend(dep, nsize, NULL)) != 0) + return error; + if ((error = msdosfs_updatede(dep)) != 0) + return error; } - if ((fd = open(path, O_RDONLY)) == -1) - err(1, "open %s", path); + if ((fd = open(path, O_RDONLY)) == -1) { + 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)) == MAP_FAILED) { - DPRINTF(("%s: mmap %s %s", __func__, node->name, - strerror(errno))); + error = errno; + DPRINTF(("%s: mmap %s: %s", __func__, node->name, + strerror(error))); close(fd); goto out; } @@ -469,6 +476,7 @@ msdosfs_wfile(const char *path, struct denode *dep, fsnode *node) cn = dep->de_StartCluster; if (cn == MSDOSFSROOT) { DPRINTF(("%s: bad lbn %lu", __func__, cn)); + error = EINVAL; goto out; } bn = cntobn(pmp, cn); diff --git a/usr.sbin/makefs/udf.c b/usr.sbin/makefs/udf.c index 1ff612ff9..d3d06bfec 100644 --- a/usr.sbin/makefs/udf.c +++ b/usr.sbin/makefs/udf.c @@ -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 @@ -30,7 +30,7 @@ #endif #include -__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 #include @@ -201,7 +201,7 @@ udf_emulate_discinfo(fsinfo_t *fsopts, struct mmc_discinfo *di, case 0x10: /* DVDROM */ case 0x40: /* BDROM */ req_enable |= FORMAT_READONLY; - /* FALLTROUGH */ + /* FALLTHROUGH */ case 0x01: /* disc */ /* set up a disc info profile for partitions/files */ di->mmc_class = MMC_CLASS_DISC; @@ -290,9 +290,6 @@ udf_update_trackinfo(struct mmc_discinfo *di, struct mmc_trackinfo *ti) void udf_prep_opts(fsinfo_t *fsopts) { - struct tm *tm; - time_t now; - const option_t udf_options[] = { OPT_STR('T', "disctype", "disc type (cdrom,dvdrom,bdrom," "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 */ /* use user's time zone as default */ - (void)time(&now); - tm = localtime(&now); #ifdef HAVE_STRUCT_TM_TM_GMTOFF - context.gmtoff = tm->tm_gmtoff; -#else - context.gmtoff = 0; + if (!stampst.st_ino) { + struct tm tm; + time_t now; + (void)time(&now); + (void)localtime_r(&now, &tm); + context.gmtoff = tm.tm_gmtoff; + } else #endif + context.gmtoff = 0; /* return info */ fsopts->fs_specific = NULL; @@ -514,6 +514,7 @@ static uint32_t udf_datablocks(off_t sz) { /* 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) return 0; @@ -561,7 +562,6 @@ udf_file_inject_blob(union dscrptr *dscr, uint8_t *blob, off_t size) struct extfile_entry *efe; uint64_t inf_len, obj_size; uint32_t l_ea, l_ad; - uint32_t free_space, desc_size; uint16_t crclen; uint8_t *data, *pos; @@ -575,7 +575,6 @@ udf_file_inject_blob(union dscrptr *dscr, uint8_t *blob, off_t size) icb = &fe->icbtag; inf_len = udf_rw64(fe->inf_len); obj_size = 0; - desc_size = sizeof(struct file_entry); } else if (udf_rw16(dscr->tag.id) == TAGID_EXTFENTRY) { efe = &dscr->efe; data = efe->data; @@ -584,39 +583,22 @@ udf_file_inject_blob(union dscrptr *dscr, uint8_t *blob, off_t size) icb = &efe->icbtag; inf_len = udf_rw64(efe->inf_len); obj_size = udf_rw64(efe->obj_size); - desc_size = sizeof(struct extfile_entry); } else { errx(1, "Bad tag passed to udf_file_inject_blob"); } crclen = udf_rw16(dscr->tag.desc_crc_len); - /* calculate free space */ - free_space = context.sector_size - (l_ea + l_ad) - desc_size; + /* check if it will fit internally */ if (udf_datablocks(size)) { -#if !defined(NDEBUG) && defined(__minix) - 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) */ + /* the predictor tells it won't fit internally */ return 1; } /* going internal */ assert(l_ad == 0); -#if !defined(NDEBUG) && defined(__minix) assert((udf_rw16(icb->flags) & UDF_ICB_TAG_FLAGS_ALLOC_MASK) == 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; memcpy(pos, blob, size); l_ad += size; @@ -704,14 +686,7 @@ udf_append_file_mapping(union dscrptr *dscr, struct long_ad *piece) last_long = NULL; if (l_ad != 0) { if (use_shorts) { -#if !defined(NDEBUG) && defined(__minix) 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; last_short = (struct short_ad *) pos; 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_flags = UDF_EXT_FLAGS(udf_rw32(last_short->len)); } else { -#if !defined(NDEBUG) && defined(__minix) 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; last_long = (struct long_ad *) pos; last_lb_num = udf_rw32(last_long->loc.lb_num); @@ -906,6 +874,7 @@ udf_estimate_walk(fsinfo_t *fsopts, case S_IFDIR: if (strcmp(cur->name, ".") == 0) continue; + /* FALLTHROUGH */ case S_IFLNK: case S_IFREG: /* create dummy FID to see how long name will become */ diff --git a/usr.sbin/makefs/udf/Makefile.inc b/usr.sbin/makefs/udf/Makefile.inc index 8d47e9ba7..b418226c5 100644 --- a/usr.sbin/makefs/udf/Makefile.inc +++ b/usr.sbin/makefs/udf/Makefile.inc @@ -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 @@ -11,3 +11,7 @@ CPPFLAGS+= -I${UDF} -I${UDF_NEWFS} -I${FSCK} 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} diff --git a/usr.sbin/makefs/v7fs/v7fs_estimate.c b/usr.sbin/makefs/v7fs/v7fs_estimate.c index 3e09d47e1..74b7e25a6 100644 --- a/usr.sbin/makefs/v7fs/v7fs_estimate.c +++ b/usr.sbin/makefs/v7fs/v7fs_estimate.c @@ -132,10 +132,6 @@ estimate_size_walk(fsnode *root, char *dir, struct v7fs_geometry *geom) int n; 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, nentries++, geom->ninode++) { switch (cur->type & S_IFMT) { @@ -261,10 +257,6 @@ v7fs_estimate(const char *dir, fsnode *root, fsinfo_t *fsopts) v7fs_daddr_t nblk; 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)); strncpy(path, dir, sizeof(path)); diff --git a/usr.sbin/makefs/walk.c b/usr.sbin/makefs/walk.c index 5e585ac83..77a75cf4a 100644 --- a/usr.sbin/makefs/walk.c +++ b/usr.sbin/makefs/walk.c @@ -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. @@ -41,7 +41,7 @@ #include #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 */ #include @@ -252,6 +252,20 @@ create_fsnode(const char *root, const char *path, const char *name, cur->type = stbuf->st_mode & S_IFMT; cur->inode->nlink = 1; 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); }