[patch] combine mount_udf(8) with kiconv(3)

R. Imura imura at ryu16.org
Tue Nov 4 08:45:58 PST 2003


On Tue, Nov 04, 2003 at 09:46:24AM -0700, Scott Long wrote:
> 
> Ok, looks good.  Please send me a full diff and I'll commit it.
> 
> Thanks!

I attached the patch for you.

Regards,

- R. Imura
-------------- next part --------------
Index: sbin/mount_udf/Makefile
===================================================================
RCS file: /home/ncvs/src/sbin/mount_udf/Makefile,v
retrieving revision 1.2
diff -u -r1.2 Makefile
--- sbin/mount_udf/Makefile	15 Apr 2002 20:16:48 -0000	1.2
+++ sbin/mount_udf/Makefile	1 Nov 2003 20:50:50 -0000
@@ -3,10 +3,16 @@
 PROG=	mount_udf
 SRCS=	mount_udf.c getmntopts.c
 MAN=	mount_udf.8
+DPADD=	${LIBKICONV}
+LDADD=	-lkiconv
 
 MOUNT=	${.CURDIR}/../mount
 CFLAGS+= -I${MOUNT} -I${.CURDIR}/../../sys -Wall
 .PATH:	${MOUNT}
 WARNS= 1
+
+# Needs to be dynamically linked for optional dlopen() access to
+# userland libiconv
+NOSHARED?=	NO
 
 .include <bsd.prog.mk>
Index: sbin/mount_udf/mount_udf.8
===================================================================
RCS file: /home/ncvs/src/sbin/mount_udf/mount_udf.8,v
retrieving revision 1.4
diff -u -r1.4 mount_udf.8
--- sbin/mount_udf/mount_udf.8	12 Dec 2002 05:56:36 -0000	1.4
+++ sbin/mount_udf/mount_udf.8	1 Nov 2003 20:39:47 -0000
@@ -36,6 +36,7 @@
 .Nm
 .Op Fl v
 .Op Fl o Ar options
+.Op Fl C Ar charset
 .Ar special | node
 .Sh DESCRIPTION
 The
@@ -57,6 +58,10 @@
 The following UDF specific options are available:
 .It Fl v
 Be verbose about mounting the UDF file system.
+.It Fl C Ar charset
+Specify local
+.Ar charset
+to convert Unicode file names.
 .El
 .Sh SEE ALSO
 .Xr cdcontrol 1 ,
Index: sbin/mount_udf/mount_udf.c
===================================================================
RCS file: /home/ncvs/src/sbin/mount_udf/mount_udf.c,v
retrieving revision 1.6
diff -u -r1.6 mount_udf.c
--- sbin/mount_udf/mount_udf.c	21 Aug 2002 18:11:17 -0000	1.6
+++ sbin/mount_udf/mount_udf.c	2 Nov 2003 00:29:39 -0000
@@ -46,10 +46,15 @@
 
 #include <sys/cdio.h>
 #include <sys/file.h>
+#include <sys/iconv.h>
 #include <sys/param.h>
+#include <sys/linker.h>
+#include <sys/module.h>
 #include <sys/mount.h>
 #include <sys/uio.h>
 
+#include <fs/udf/udf_mount.h>
+
 #include <err.h>
 #include <errno.h>
 #include <stdlib.h>
@@ -66,18 +71,21 @@
 	{ NULL, 0, 0, 0 }
 };
 
+int	set_charset(char **, char **, const char *);
 void	usage(void);
 
 int
 main(int argc, char **argv)
 {
-	struct iovec iov[6];
-	int ch, mntflags, opts;
+	struct iovec iov[12];
+	int ch, i, mntflags, opts, udf_flags;
 	char *dev, *dir, mntpath[MAXPATHLEN];
+	char *cs_disk, *cs_local;
 	int verbose;
 
-	mntflags = opts = verbose = 0;
-	while ((ch = getopt(argc, argv, "o:v")) != -1)
+	i = mntflags = opts = udf_flags = verbose = 0;
+	cs_disk = cs_local = NULL;
+	while ((ch = getopt(argc, argv, "o:vC:")) != -1)
 		switch (ch) {
 		case 'o':
 			getmntopts(optarg, mopts, &mntflags, &opts);
@@ -85,6 +93,11 @@
 		case 'v':
 			verbose++;
 			break;
+		case 'C':
+			if (set_charset(&cs_disk, &cs_local, optarg) == -1)
+				err(EX_OSERR, "udf_iconv");
+			udf_flags |= UDFMNT_KICONV;
+			break;
 		case '?':
 		default:
 			usage();
@@ -110,27 +123,70 @@
 	 */
 	mntflags |= MNT_RDONLY;
 
-	iov[0].iov_base = "fstype";
-	iov[0].iov_len = sizeof("fstype");
-	iov[1].iov_base = "udf";
-	iov[1].iov_len = strlen(iov[1].iov_base) + 1;
-	iov[2].iov_base = "fspath";
-	iov[2].iov_len = sizeof("fspath");
-	iov[3].iov_base = mntpath;
-	iov[3].iov_len = strlen(mntpath) + 1;
-	iov[4].iov_base = "from";
-	iov[4].iov_len = sizeof("from");
-	iov[5].iov_base = dev;
-	iov[5].iov_len = strlen(dev) + 1;
-	if (nmount(iov, 6, mntflags) < 0)
+	iov[i].iov_base = "fstype";
+	iov[i++].iov_len = sizeof("fstype");
+	iov[i].iov_base = "udf";
+	iov[i++].iov_len = strlen(iov[1].iov_base) + 1;
+	iov[i].iov_base = "fspath";
+	iov[i++].iov_len = sizeof("fspath");
+	iov[i].iov_base = mntpath;
+	iov[i++].iov_len = strlen(mntpath) + 1;
+	iov[i].iov_base = "from";
+	iov[i++].iov_len = sizeof("from");
+	iov[i].iov_base = dev;
+	iov[i++].iov_len = strlen(dev) + 1;
+	iov[i].iov_base = "flags";
+	iov[i++].iov_len = sizeof("flags");
+	iov[i].iov_base = &udf_flags;
+	iov[i++].iov_len = sizeof(udf_flags);
+	if (udf_flags & UDFMNT_KICONV) {
+		iov[i].iov_base = "cs_disk";
+		iov[i++].iov_len = sizeof("cs_disk") + 1;
+		iov[i].iov_base = cs_disk;
+		iov[i++].iov_len = strlen(cs_disk) + 1;
+		iov[i].iov_base = "cs_local";
+		iov[i++].iov_len = sizeof("cs_local") + 1;
+		iov[i].iov_base = cs_local;
+		iov[i++].iov_len = strlen(cs_local) + 1;
+	}
+	if (nmount(iov, i, mntflags) < 0)
 		err(1, "%s", dev);
 	exit(0);
 }
 
+int
+set_charset(char **cs_disk, char **cs_local, const char *localcs)
+{
+	int error;
+
+	if (modfind("udf_iconv") < 0)
+		if (kldload("udf_iconv") < 0 || modfind("udf_iconv") < 0) {
+			warnx( "cannot find or load \"udf_iconv\" kernel module");
+			return (-1);
+		}
+
+	if ((*cs_disk = malloc(ICONV_CSNMAXLEN)) == NULL)
+		return (-1);
+	if ((*cs_local = malloc(ICONV_CSNMAXLEN)) == NULL)
+		return (-1);
+	strncpy(*cs_disk, ENCODING_UNICODE, ICONV_CSNMAXLEN);
+	strncpy(*cs_local, localcs, ICONV_CSNMAXLEN);
+	error = kiconv_add_xlat16_cspair(*cs_local, *cs_disk, 0);
+	if (error)
+		return (-1);
+#if 0
+	error = kiconv_add_xlat16_cspair(*cs_disk, *cs_local, 0);
+	if (error)
+		return (-1);
+#endif
+
+	return (0);
+}
+
 void
 usage(void)
 {
 	(void)fprintf(stderr,
-		"usage: mount_udf [-v] [-o options] special node\n");
+		"usage: mount_udf [-v] [-o options] [-C charset] special node\n");
 	exit(EX_USAGE);
 }
Index: sys/conf/NOTES
===================================================================
RCS file: /home/ncvs/src/sys/conf/NOTES,v
retrieving revision 1.1183
diff -u -r1.1183 NOTES
--- sys/conf/NOTES	28 Oct 2003 05:47:39 -0000	1.1183
+++ sys/conf/NOTES	1 Nov 2003 21:11:04 -0000
@@ -796,6 +796,7 @@
 options		CD9660_ICONV
 options		MSDOSFS_ICONV
 options		NTFS_ICONV
+options		UDF_ICONV
 
 
 #####################################################################
Index: sys/conf/files
===================================================================
RCS file: /home/ncvs/src/sys/conf/files,v
retrieving revision 1.841
diff -u -r1.841 files
--- sys/conf/files	27 Oct 2003 11:19:08 -0000	1.841
+++ sys/conf/files	1 Nov 2003 21:10:33 -0000
@@ -939,6 +939,7 @@
 fs/smbfs/smbfs_vfsops.c		optional smbfs
 fs/smbfs/smbfs_vnops.c		optional smbfs
 fs/specfs/spec_vnops.c	standard
+fs/udf/udf_iconv.c	optional udf_iconv
 fs/udf/udf_vfsops.c	optional udf
 fs/udf/udf_vnops.c	optional udf
 fs/udf/osta.c		optional udf
Index: sys/conf/options
===================================================================
RCS file: /home/ncvs/src/sys/conf/options,v
retrieving revision 1.422
diff -u -r1.422 options
--- sys/conf/options	1 Nov 2003 00:18:29 -0000	1.422
+++ sys/conf/options	1 Nov 2003 21:10:48 -0000
@@ -202,6 +202,7 @@
 CD9660_ICONV	opt_dontuse.h
 MSDOSFS_ICONV	opt_dontuse.h
 NTFS_ICONV	opt_dontuse.h
+UDF_ICONV	opt_dontuse.h
 
 # If you are following the conditions in the copyright,
 # you can enable soft-updates which will speed up a lot of thigs
Index: sys/fs/udf/osta.c
===================================================================
RCS file: /home/ncvs/src/sys/fs/udf/osta.c,v
retrieving revision 1.2
diff -u -r1.2 osta.c
--- sys/fs/udf/osta.c	23 Aug 2002 14:10:55 -0000	1.2
+++ sys/fs/udf/osta.c	4 Nov 2003 16:27:11 -0000
@@ -73,6 +73,51 @@
 	return(returnValue);
 }
 
+/*
+ * Almost same as udf_UncompressUnicode(). The difference is that
+ * it keeps byte order of unicode string.
+ */
+int
+udf_UncompressUnicodeByte(
+	int numberOfBytes,	/* (Input) number of bytes read from media. */
+	byte *UDFCompressed,	/* (Input) bytes read from media. */
+	byte *unicode)		/* (Output) uncompressed unicode characters. */
+{
+	unsigned int compID;
+	int returnValue, unicodeIndex, byteIndex;
+
+	/* Use UDFCompressed to store current byte being read. */
+	compID = UDFCompressed[0];
+
+	/* First check for valid compID. */
+	if (compID != 8 && compID != 16) {
+		returnValue = -1;
+	} else {
+		unicodeIndex = 0;
+		byteIndex = 1;
+
+		/* Loop through all the bytes. */
+		while (byteIndex < numberOfBytes) {
+			if (compID == 16) {
+				/* Move the first byte to the high bits of the
+				 * unicode char.
+				 */
+				unicode[unicodeIndex++] =
+				    UDFCompressed[byteIndex++];
+			} else {
+				unicode[unicodeIndex++] = 0;
+			}
+			if (byteIndex < numberOfBytes) {
+				/*Then the next byte to the low bits. */
+				unicode[unicodeIndex++] =
+				    UDFCompressed[byteIndex++];
+			}
+		}
+		returnValue = unicodeIndex;
+	}
+	return(returnValue);
+}
+
 /***********************************************************************
  * DESCRIPTION:
  * Takes a string of unicode wide characters and returns an OSTA CS0
Index: sys/fs/udf/osta.h
===================================================================
RCS file: /home/ncvs/src/sys/fs/udf/osta.h,v
retrieving revision 1.1
diff -u -r1.1 osta.h
--- sys/fs/udf/osta.h	14 Apr 2002 16:52:14 -0000	1.1
+++ sys/fs/udf/osta.h	4 Nov 2003 15:49:05 -0000
@@ -21,6 +21,7 @@
 typedef unsigned char byte;
 
 int udf_UncompressUnicode(int, byte *, unicode_t *);
+int udf_UncompressUnicodeByte(int, byte *, byte *);
 int udf_CompressUnicode(int, int, unicode_t *, byte *);
 unsigned short udf_cksum(unsigned char *, int);
 unsigned short udf_unicode_cksum(unsigned short *, int);
Index: sys/fs/udf/udf.h
===================================================================
RCS file: /home/ncvs/src/sys/fs/udf/udf.h,v
retrieving revision 1.5
diff -u -r1.5 udf.h
--- sys/fs/udf/udf.h	4 May 2003 07:40:29 -0000	1.5
+++ sys/fs/udf/udf.h	1 Nov 2003 20:40:01 -0000
@@ -58,6 +58,10 @@
 	int			p_sectors;
 	int			s_table_entries;
 	struct udf_sparing_table *s_table;
+	void			*im_d2l;	/* disk->local iconv handle */
+#if 0
+	void			*im_l2d;	/* local->disk iconv handle */
+#endif
 };
 
 struct udf_dirstream {
Index: sys/fs/udf/udf_iconv.c
===================================================================
RCS file: sys/fs/udf/udf_iconv.c
diff -N sys/fs/udf/udf_iconv.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/fs/udf/udf_iconv.c	1 Nov 2003 23:05:18 -0000
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2003 Ryuichiro Imura
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/iconv.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/mount.h>
+
+VFS_DECLARE_ICONV(udf);
Index: sys/fs/udf/udf_mount.h
===================================================================
RCS file: sys/fs/udf/udf_mount.h
diff -N sys/fs/udf/udf_mount.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/fs/udf/udf_mount.h	1 Nov 2003 20:40:01 -0000
@@ -0,0 +1,29 @@
+/*-
+ * Copyright (c) 2003 Ryuichiro Imura
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define	UDFMNT_KICONV	0x00000001
Index: sys/fs/udf/udf_vfsops.c
===================================================================
RCS file: /home/ncvs/src/sys/fs/udf/udf_vfsops.c,v
retrieving revision 1.15
diff -u -r1.15 udf_vfsops.c
--- sys/fs/udf/udf_vfsops.c	7 Aug 2003 15:04:26 -0000	1.15
+++ sys/fs/udf/udf_vfsops.c	1 Nov 2003 21:01:27 -0000
@@ -79,6 +79,7 @@
 #include <sys/conf.h>
 #include <sys/dirent.h>
 #include <sys/fcntl.h>
+#include <sys/iconv.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
 #include <sys/mount.h>
@@ -90,12 +91,15 @@
 #include <vm/uma.h>
 
 #include <fs/udf/ecma167-udf.h>
-#include <fs/udf/udf.h>
 #include <fs/udf/osta.h>
+#include <fs/udf/udf.h>
+#include <fs/udf/udf_mount.h>
 
 MALLOC_DEFINE(M_UDFMOUNT, "UDF mount", "UDF mount structure");
 MALLOC_DEFINE(M_UDFFENTRY, "UDF fentry", "UDF file entry structure");
 
+struct iconv_functions *udf_iconv = NULL;
+
 /* Zones */
 uma_zone_t udf_zone_trans = NULL;
 uma_zone_t udf_zone_node = NULL;
@@ -125,6 +129,8 @@
 };
 VFS_SET(udf_vfsops, udf, VFCF_READONLY);
 
+MODULE_VERSION(udf, 1);
+
 static int udf_mountfs(struct vnode *, struct mount *, struct thread *);
 
 static int
@@ -183,9 +189,9 @@
 	struct udf_mnt *imp = 0;
 	struct export_args *export;
 	struct vfsoptlist *opts;
-	char *fspec;
+	char *fspec, *cs_disk, *cs_local;
 	size_t size;
-	int error, len;
+	int error, len, *udf_flags;
 
 	opts = mp->mnt_optnew;
 
@@ -246,6 +252,28 @@
 	}
 
 	imp = VFSTOUDFFS(mp);
+
+	udf_flags = NULL;
+	error = vfs_getopt(opts, "flags", (void **)&udf_flags, &len);
+	if (error || len != sizeof(int))
+		return (EINVAL);
+	imp->im_flags = *udf_flags;
+
+	if (imp->im_flags & UDFMNT_KICONV && udf_iconv) {
+		cs_disk = NULL;
+		error = vfs_getopt(opts, "cs_disk", (void **)&cs_disk, &len);
+		if (!error && cs_disk[len - 1] != '\0')
+			return (EINVAL);
+		cs_local = NULL;
+		error = vfs_getopt(opts, "cs_local", (void **)&cs_local, &len);
+		if (!error && cs_local[len - 1] != '\0')
+			return (EINVAL);
+		udf_iconv->open(cs_local, cs_disk, &imp->im_d2l);
+#if 0
+		udf_iconv->open(cs_disk, cs_local, &imp->im_l2d);
+#endif
+	}
+
 	copystr(fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size);
 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
 	udf_statfs(mp, &mp->mnt_stat, td);
@@ -326,6 +354,10 @@
 	udfmp->im_mountp = mp;
 	udfmp->im_dev = devvp->v_rdev;
 	udfmp->im_devvp = devvp;
+	udfmp->im_d2l = NULL;
+#if 0
+	udfmp->im_l2d = NULL;
+#endif
 
 	bsize = 2048;	/* XXX Should probe the media for it's size */
 
@@ -470,6 +502,15 @@
 
 	if ((error = vflush(mp, 0, flags)))
 		return (error);
+
+	if (udfmp->im_flags & UDFMNT_KICONV && udf_iconv) {
+		if (udfmp->im_d2l)
+			udf_iconv->close(udfmp->im_d2l);
+#if 0
+		if (udfmp->im_l2d)
+			udf_iconv->close(udfmp->im_l2d);
+#endif
+	}
 
 	udfmp->im_devvp->v_rdev->si_mountpoint = NULL;
 	error = VOP_CLOSE(udfmp->im_devvp, FREAD, NOCRED, td);
Index: sys/fs/udf/udf_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/fs/udf/udf_vnops.c,v
retrieving revision 1.31
diff -u -r1.31 udf_vnops.c
--- sys/fs/udf/udf_vnops.c	18 Oct 2003 14:10:25 -0000	1.31
+++ sys/fs/udf/udf_vnops.c	4 Nov 2003 15:49:05 -0000
@@ -37,6 +37,7 @@
 #include <sys/stat.h>
 #include <sys/bio.h>
 #include <sys/buf.h>
+#include <sys/iconv.h>
 #include <sys/mount.h>
 #include <sys/vnode.h>
 #include <sys/dirent.h>
@@ -48,6 +49,9 @@
 #include <fs/udf/ecma167-udf.h>
 #include <fs/udf/osta.h>
 #include <fs/udf/udf.h>
+#include <fs/udf/udf_mount.h>
+
+extern struct iconv_functions *udf_iconv;
 
 static int udf_access(struct vop_access_args *);
 static int udf_getattr(struct vop_getattr_args *);
@@ -446,41 +450,65 @@
 /*
  * Call the OSTA routines to translate the name from a CS0 dstring to a
  * 16-bit Unicode String.  Hooks need to be placed in here to translate from
- * Unicode to the encoding that the kernel/user expects.  For now, compact
- * the encoding to 8 bits if possible.  Return the length of the translated
- * string.
- * XXX This horribly pessimizes the 8bit case
+ * Unicode to the encoding that the kernel/user expects.  Return the length
+ * of the translated string.
  */
 static int
-udf_transname(char *cs0string, char *destname, int len)
+udf_transname(char *cs0string, char *destname, int len, struct udf_mnt *udfmp)
 {
 	unicode_t *transname;
-	int i, unilen = 0;
-
-	/* allocate a buffer big enough to hold an 8->16 bit expansion */
-	transname = uma_zalloc(udf_zone_trans, M_WAITOK);
+	char *unibuf, *unip;
+	int i, unilen = 0, destlen;
+	size_t destleft = MAXNAMLEN;
+
+	/* Convert 16-bit Unicode to destname */
+	if (udfmp->im_flags & UDFMNT_KICONV && udf_iconv) {
+		/* allocate a buffer big enough to hold an 8->16 bit expansion */
+		unibuf = uma_zalloc(udf_zone_trans, M_WAITOK);
+		unip = unibuf;
+		if ((unilen = udf_UncompressUnicodeByte(len, cs0string, unibuf)) == -1) {
+			printf("udf: Unicode translation failed\n");
+			uma_zfree(udf_zone_trans, unibuf);
+			return 0;
+		}
+
+		while (unilen > 0 && destleft > 0) {
+			udf_iconv->conv(udfmp->im_d2l, (const char **)&unibuf,
+				(size_t *)&unilen, (char **)&destname, &destleft);
+			/* Unconverted character found */
+			if (unilen > 0 && destleft > 0) {
+				*destname++ = '?';
+				destleft--;
+				unibuf += 2;
+				unilen -= 2;
+			}
+		}
+		uma_zfree(udf_zone_trans, unip);
+		*destname = '\0';
+		destlen = MAXNAMLEN - (int)destleft;
+	} else {
+		/* allocate a buffer big enough to hold an 8->16 bit expansion */
+		transname = uma_zalloc(udf_zone_trans, M_WAITOK);
 
-	if ((unilen = udf_UncompressUnicode(len, cs0string, transname)) == -1) {
-		printf("udf: Unicode translation failed\n");
-		uma_zfree(udf_zone_trans, transname);
-		return 0;
-	}
+		if ((unilen = udf_UncompressUnicode(len, cs0string, transname)) == -1) {
+			printf("udf: Unicode translation failed\n");
+			uma_zfree(udf_zone_trans, transname);
+			return 0;
+		}
 
-	/* At this point, the name is in 16-bit Unicode.  Compact it down
-	 * to 8-bit
-	 */
-	for (i = 0; i < unilen ; i++) {
-		if (transname[i] & 0xff00) {
-			destname[i] = '.';	/* Fudge the 16bit chars */
-		} else {
-			destname[i] = transname[i] & 0xff;
+		for (i = 0; i < unilen ; i++) {
+			if (transname[i] & 0xff00) {
+				destname[i] = '.';	/* Fudge the 16bit chars */
+			} else {
+				destname[i] = transname[i] & 0xff;
+			}
 		}
+		uma_zfree(udf_zone_trans, transname);
+		destname[unilen] = 0;
+		destlen = unilen;
 	}
 
-	destname[unilen] = 0;
-	uma_zfree(udf_zone_trans, transname);
-
-	return unilen;
+	return (destlen);
 }
 
 /*
@@ -489,7 +517,7 @@
  * here also.
  */
 static int
-udf_cmpname(char *cs0string, char *cmpname, int cs0len, int cmplen)
+udf_cmpname(char *cs0string, char *cmpname, int cs0len, int cmplen, struct udf_mnt *udfmp)
 {
 	char *transname;
 	int error = 0;
@@ -497,7 +525,7 @@
 	/* This is overkill, but not worth creating a new zone */
 	transname = uma_zalloc(udf_zone_trans, M_WAITOK);
 
-	cs0len = udf_transname(cs0string, transname, cs0len);
+	cs0len = udf_transname(cs0string, transname, cs0len, udfmp);
 
 	/* Easy check.  If they aren't the same length, they aren't equal */
 	if ((cs0len == 0) || (cs0len != cmplen))
@@ -686,6 +714,7 @@
 	struct uio *uio;
 	struct dirent dir;
 	struct udf_node *node;
+	struct udf_mnt *udfmp;
 	struct fileid_desc *fid;
 	struct udf_uiodir uiodir;
 	struct udf_dirstream *ds;
@@ -696,6 +725,7 @@
 	vp = a->a_vp;
 	uio = a->a_uio;
 	node = VTON(vp);
+	udfmp = node->udfmp;
 	uiodir.eofflag = 1;
 
 	if (a->a_ncookies != NULL) {
@@ -762,7 +792,7 @@
 			error = udf_uiodir(&uiodir, dir.d_reclen, uio, 2);
 		} else {
 			dir.d_namlen = udf_transname(&fid->data[fid->l_iu],
-			    &dir.d_name[0], fid->l_fi);
+			    &dir.d_name[0], fid->l_fi, udfmp);
 			dir.d_fileno = udf_getid(&fid->icb);
 			dir.d_type = (fid->file_char & UDF_FILE_CHAR_DIR) ?
 			    DT_DIR : DT_UNKNOWN;
@@ -946,7 +976,7 @@
 			}
 		} else {
 			if (!(udf_cmpname(&fid->data[fid->l_iu],
-			    nameptr, fid->l_fi, namelen))) {
+			    nameptr, fid->l_fi, namelen, udfmp))) {
 				id = udf_getid(&fid->icb);
 				break;
 			}
Index: sys/modules/Makefile
===================================================================
RCS file: /home/ncvs/src/sys/modules/Makefile,v
retrieving revision 1.352
diff -u -r1.352 Makefile
--- sys/modules/Makefile	24 Oct 2003 15:44:09 -0000	1.352
+++ sys/modules/Makefile	1 Nov 2003 20:40:36 -0000
@@ -137,6 +137,7 @@
 	ucom \
 	udbp \
 	udf \
+	udf_iconv \
 	ufm \
 	uftdi \
 	ugen \
Index: sys/modules/udf/Makefile
===================================================================
RCS file: /home/ncvs/src/sys/modules/udf/Makefile,v
retrieving revision 1.2
diff -u -r1.2 Makefile
--- sys/modules/udf/Makefile	28 Apr 2002 06:38:38 -0000	1.2
+++ sys/modules/udf/Makefile	1 Nov 2003 20:42:15 -0000
@@ -6,6 +6,7 @@
 
 SRCS=	udf_vfsops.c udf_vnops.c osta.c
 SRCS+=	vnode_if.h
+EXPORT_SYMS=	udf_iconv
 NOMAN=
 
 CLEANFILES=  .depend
Index: sys/modules/udf_iconv/Makefile
===================================================================
RCS file: sys/modules/udf_iconv/Makefile
diff -N sys/modules/udf_iconv/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/modules/udf_iconv/Makefile	1 Nov 2003 20:47:57 -0000
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH:	${.CURDIR}/../../fs/udf
+KMOD=	udf_iconv
+SRCS=	udf_iconv.c
+
+CFLAGS+= -I${.CURDIR}/../../
+
+.include <bsd.kmod.mk>
Index: sys/sys/iconv.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/iconv.h,v
retrieving revision 1.6
diff -u -r1.6 iconv.h
--- sys/sys/iconv.h	26 Sep 2003 20:26:25 -0000	1.6
+++ sys/sys/iconv.h	1 Nov 2003 20:49:09 -0000
@@ -100,6 +100,7 @@
 #else /* !_KERNEL */
 
 #include <sys/kobj.h>
+#include <sys/module.h>			/* can't avoid that */
 #include <sys/queue.h>			/* can't avoid that */
 #include <sys/sysctl.h>			/* can't avoid that */
 


More information about the freebsd-fs mailing list