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

"R. Imura" <[email protected]>
Newsgroups gmane.os.freebsd.devel.internationalization
Message-ID <20031104164554.GB8303%[email protected]>
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

_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-i18n
To unsubscribe, send any mail to "[email protected]"
udf_5_current_20031104.diff (text/plain, 22.5 KB)
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 */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.