summaryrefslogtreecommitdiffstats
path: root/sys/isofs
diff options
context:
space:
mode:
authorfjoe <fjoe@FreeBSD.org>2003-09-26 20:26:25 +0000
committerfjoe <fjoe@FreeBSD.org>2003-09-26 20:26:25 +0000
commit571ef024e3f3a472116a55a8489d77eb4f5f933e (patch)
tree5e4dbdee80eebe5477ad9c5637bb6b0ee47993d5 /sys/isofs
parent0c8bfb6d004a87cd501c13516a69b3ef59ed6c7c (diff)
downloadFreeBSD-src-571ef024e3f3a472116a55a8489d77eb4f5f933e.zip
FreeBSD-src-571ef024e3f3a472116a55a8489d77eb4f5f933e.tar.gz
- Support for multibyte charsets in LIBICONV.
- CD9660_ICONV, NTFS_ICONV and MSDOSFS_ICONV kernel options (with corresponding modules). - kiconv(3) for loadable charset conversion tables support. Submitted by: Ryuichiro Imura <imura@ryu16.org>
Diffstat (limited to 'sys/isofs')
-rw-r--r--sys/isofs/cd9660/cd9660_iconv.c36
-rw-r--r--sys/isofs/cd9660/cd9660_lookup.c7
-rw-r--r--sys/isofs/cd9660/cd9660_mount.h3
-rw-r--r--sys/isofs/cd9660/cd9660_rrip.c12
-rw-r--r--sys/isofs/cd9660/cd9660_util.c155
-rw-r--r--sys/isofs/cd9660/cd9660_vfsops.c20
-rw-r--r--sys/isofs/cd9660/cd9660_vnops.c4
-rw-r--r--sys/isofs/cd9660/iso.h10
8 files changed, 187 insertions, 60 deletions
diff --git a/sys/isofs/cd9660/cd9660_iconv.c b/sys/isofs/cd9660/cd9660_iconv.c
new file mode 100644
index 0000000..43a5a0d
--- /dev/null
+++ b/sys/isofs/cd9660/cd9660_iconv.c
@@ -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/kernel.h>
+#include <sys/module.h>
+#include <sys/mount.h>
+#include <sys/iconv.h>
+
+VFS_DECLARE_ICONV(cd9660);
diff --git a/sys/isofs/cd9660/cd9660_lookup.c b/sys/isofs/cd9660/cd9660_lookup.c
index 056e893..49308ea 100644
--- a/sys/isofs/cd9660/cd9660_lookup.c
+++ b/sys/isofs/cd9660/cd9660_lookup.c
@@ -238,7 +238,12 @@ searchloop:
if (namelen != 1
|| ep->name[0] != 0)
goto notfound;
- } else if (!(res = isofncmp(name, len, ep->name, namelen, imp->joliet_level))) {
+ } else if (!(res = isofncmp(name, len,
+ ep->name, namelen,
+ imp->joliet_level,
+ imp->im_flags,
+ imp->im_d2l,
+ imp->im_l2d))) {
if (isoflags & 2)
ino = isodirino(ep, imp);
else
diff --git a/sys/isofs/cd9660/cd9660_mount.h b/sys/isofs/cd9660/cd9660_mount.h
index 8cc6a86..0397d06 100644
--- a/sys/isofs/cd9660/cd9660_mount.h
+++ b/sys/isofs/cd9660/cd9660_mount.h
@@ -47,9 +47,12 @@ struct iso_args {
struct export_args export; /* network export info */
int flags; /* mounting flags, see below */
int ssector; /* starting sector, 0 for 1st session */
+ char *cs_disk; /* disk charset for Joliet cs conversion */
+ char *cs_local; /* local charset for Joliet cs conversion */
};
#define ISOFSMNT_NORRIP 0x00000001 /* disable Rock Ridge Ext.*/
#define ISOFSMNT_GENS 0x00000002 /* enable generation numbers */
#define ISOFSMNT_EXTATT 0x00000004 /* enable extended attributes */
#define ISOFSMNT_NOJOLIET 0x00000008 /* disable Joliet Ext.*/
#define ISOFSMNT_BROKENJOLIET 0x00000010/* allow broken Joliet disks */
+#define ISOFSMNT_KICONV 0x00000020 /* Use libiconv to convert chars */
diff --git a/sys/isofs/cd9660/cd9660_rrip.c b/sys/isofs/cd9660/cd9660_rrip.c
index 7f7ea15..1546e8d 100644
--- a/sys/isofs/cd9660/cd9660_rrip.c
+++ b/sys/isofs/cd9660/cd9660_rrip.c
@@ -293,7 +293,8 @@ cd9660_rrip_defname(isodir,ana)
{
isofntrans(isodir->name,isonum_711(isodir->name_len),
ana->outbuf,ana->outlen,
- 1,isonum_711(isodir->flags)&4, ana->imp->joliet_level);
+ 1,isonum_711(isodir->flags)&4, ana->imp->joliet_level,
+ ana->imp->im_flags, ana->imp->im_d2l);
switch (*ana->outbuf) {
default:
break;
@@ -491,7 +492,7 @@ cd9660_rrip_loop(isodir,ana,table)
register ISO_SUSP_HEADER *pend;
struct buf *bp = NULL;
char *pwhead;
- u_char c;
+ u_short c;
int result;
/*
@@ -501,7 +502,8 @@ cd9660_rrip_loop(isodir,ana,table)
pwhead = isodir->name + isonum_711(isodir->name_len);
if (!(isonum_711(isodir->name_len)&1))
pwhead++;
- isochar(isodir->name, pwhead, ana->imp->joliet_level, &c);
+ isochar(isodir->name, pwhead, ana->imp->joliet_level, &c, NULL,
+ ana->imp->im_flags, ana->imp->im_d2l);
/* If it's not the '.' entry of the root dir obey SP field */
if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent)
@@ -627,7 +629,7 @@ cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)
{
ISO_RRIP_ANALYZE analyze;
RRIP_TABLE *tab;
- u_char c;
+ u_short c;
analyze.outbuf = outbuf;
analyze.outlen = outlen;
@@ -638,7 +640,7 @@ cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)
*outlen = 0;
isochar(isodir->name, isodir->name + isonum_711(isodir->name_len),
- imp->joliet_level, &c);
+ imp->joliet_level, &c, NULL, imp->im_flags, imp->im_d2l);
tab = rrip_table_getname;
if (c == 0 || c == 1) {
cd9660_rrip_defname(isodir,&analyze);
diff --git a/sys/isofs/cd9660/cd9660_util.c b/sys/isofs/cd9660/cd9660_util.c
index 8a132c0..dccb14c 100644
--- a/sys/isofs/cd9660/cd9660_util.c
+++ b/sys/isofs/cd9660/cd9660_util.c
@@ -46,16 +46,12 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/mount.h>
#include <sys/vnode.h>
+#include <sys/iconv.h>
#include <isofs/cd9660/iso.h>
+#include <isofs/cd9660/cd9660_mount.h>
-/*
- * XXX: limited support for loading of Unicode
- * conversion routine as a kld at a run-time.
- * Should be removed when native Unicode kernel
- * interfaces have been introduced.
- */
-u_char (*cd9660_wchar2char)(u_int32_t wchar) = NULL;
+extern struct iconv_functions *cd9660_iconv;
/*
* Get one character out of an iso filename
@@ -63,29 +59,47 @@ u_char (*cd9660_wchar2char)(u_int32_t wchar) = NULL;
* Return number of bytes consumed
*/
int
-isochar(isofn, isoend, joliet_level, c)
+isochar(isofn, isoend, joliet_level, c, clen, flags, handle)
u_char *isofn;
u_char *isoend;
int joliet_level;
- u_char *c;
+ u_short *c;
+ int *clen;
+ int flags;
+ void *handle;
{
+ size_t i, j, len;
+ char inbuf[3], outbuf[3], *inp, *outp;
+
*c = *isofn++;
+ if (clen) *clen = 1;
if (joliet_level == 0 || isofn == isoend)
/* (00) and (01) are one byte in Joliet, too */
return 1;
- /* No Unicode support yet :-( */
- switch (*c) {
- default:
- *c = '?';
- break;
- case '\0':
- *c = *isofn;
- break;
+ if (flags & ISOFSMNT_KICONV && cd9660_iconv) {
+ i = j = len = 2;
+ inbuf[0]=(char)*(isofn - 1);
+ inbuf[1]=(char)*isofn;
+ inbuf[2]='\0';
+ inp = inbuf;
+ outp = outbuf;
+ cd9660_iconv->convchr(handle, (const char **)&inp, &i, &outp, &j);
+ len -= j;
+ if (clen) *clen = len;
+ *c = '\0';
+ while(len--)
+ *c |= (*(outp - len - 1) & 0xff) << (len << 3);
+ } else {
+ switch (*c) {
+ default:
+ *c = '?';
+ break;
+ case '\0':
+ *c = *isofn;
+ break;
+ }
}
- /* XXX: if Unicode conversion routine is loaded then use it */
- if (cd9660_wchar2char != NULL)
- *c = cd9660_wchar2char((*(isofn - 1) << 8) | *isofn);
return 2;
}
@@ -96,53 +110,60 @@ isochar(isofn, isoend, joliet_level, c)
* Note: Version number plus ';' may be omitted.
*/
int
-isofncmp(fn, fnlen, isofn, isolen, joliet_level)
+isofncmp(fn, fnlen, isofn, isolen, joliet_level, flags, handle, lhandle)
u_char *fn;
int fnlen;
u_char *isofn;
int isolen;
int joliet_level;
+ int flags;
+ void *handle;
+ void *lhandle;
{
int i, j;
- u_char c, *fnend = fn + fnlen, *isoend = isofn + isolen;
+ u_short c, d;
+ u_char *fnend = fn + fnlen, *isoend = isofn + isolen;
- for (; fn != fnend; fn++) {
+ for (; fn < fnend; ) {
+ d = sgetrune(fn, fnend - fn, (char const **)&fn, flags, lhandle);
if (isofn == isoend)
- return *fn;
- isofn += isochar(isofn, isoend, joliet_level, &c);
+ return d;
+ isofn += isochar(isofn, isoend, joliet_level, &c, NULL, flags, handle);
if (c == ';') {
- if (*fn++ != ';')
- return fn[-1];
- for (i = 0; fn != fnend; i = i * 10 + *fn++ - '0') {
+ if (d != ';')
+ return d;
+ for (i = 0; fn < fnend; i = i * 10 + *fn++ - '0') {
if (*fn < '0' || *fn > '9') {
return -1;
}
}
for (j = 0; isofn != isoend; j = j * 10 + c - '0')
isofn += isochar(isofn, isoend,
- joliet_level, &c);
+ joliet_level, &c,
+ NULL, flags, handle);
return i - j;
}
- if (c != *fn) {
+ if (c != d) {
if (c >= 'A' && c <= 'Z') {
- if (c + ('a' - 'A') != *fn) {
- if (*fn >= 'a' && *fn <= 'z')
- return *fn - ('a' - 'A') - c;
+ if (c + ('a' - 'A') != d) {
+ if (d >= 'a' && d <= 'z')
+ return d - ('a' - 'A') - c;
else
- return *fn - c;
+ return d - c;
}
} else
- return *fn - c;
+ return d - c;
}
}
if (isofn != isoend) {
- isofn += isochar(isofn, isoend, joliet_level, &c);
+ isofn += isochar(isofn, isoend, joliet_level, &c, NULL, flags, handle);
switch (c) {
default:
return -c;
case '.':
if (isofn != isoend) {
- isochar(isofn, isoend, joliet_level, &c);
+ isochar(isofn, isoend, joliet_level, &c,
+ NULL, flags, handle);
if (c == ';')
return 0;
}
@@ -158,7 +179,7 @@ isofncmp(fn, fnlen, isofn, isolen, joliet_level)
* translate a filename of length > 0
*/
void
-isofntrans(infn, infnlen, outfn, outfnlen, original, assoc, joliet_level)
+isofntrans(infn, infnlen, outfn, outfnlen, original, assoc, joliet_level, flags, handle)
u_char *infn;
int infnlen;
u_char *outfn;
@@ -166,25 +187,61 @@ isofntrans(infn, infnlen, outfn, outfnlen, original, assoc, joliet_level)
int original;
int assoc;
int joliet_level;
+ int flags;
+ void *handle;
{
- int fnidx = 0;
- u_char c, d = '\0', *infnend = infn + infnlen;
+ u_short c, d = '\0';
+ u_char *outp = outfn, *infnend = infn + infnlen;
+ int clen;
if (assoc) {
- *outfn++ = ASSOCCHAR;
- fnidx++;
+ *outp++ = ASSOCCHAR;
}
- for (; infn != infnend; fnidx++) {
- infn += isochar(infn, infnend, joliet_level, &c);
+ for (; infn != infnend; ) {
+ infn += isochar(infn, infnend, joliet_level, &c, &clen, flags, handle);
if (!original && !joliet_level && c >= 'A' && c <= 'Z')
- *outfn++ = c + ('a' - 'A');
+ c += ('a' - 'A');
else if (!original && c == ';') {
- fnidx -= (d == '.');
+ outp -= (d == '.');
break;
- } else
- *outfn++ = c;
+ }
d = c;
+ while(clen--)
+ *outp++ = c >> (clen << 3);
}
- *outfnlen = fnidx;
+ *outfnlen = outp - outfn;
+}
+
+/*
+ * same as sgetrune(3)
+ */
+u_short
+sgetrune(string, n, result, flags, handle)
+ const char *string;
+ size_t n;
+ char const **result;
+ int flags;
+ void *handle;
+{
+ size_t i, j, len;
+ char outbuf[3], *outp;
+ u_short c = '\0';
+
+ len = i = (n < 2) ? n : 2;
+ j = 2;
+ outp = outbuf;
+
+ if (flags & ISOFSMNT_KICONV && cd9660_iconv) {
+ cd9660_iconv->convchr(handle, (const char **)&string,
+ &i, &outp, &j);
+ len -= i;
+ } else {
+ len = 1;
+ string++;
+ }
+
+ if (result) *result = string;
+ while(len--) c |= (*(string - len - 1) & 0xff) << (len << 3);
+ return (c);
}
diff --git a/sys/isofs/cd9660/cd9660_vfsops.c b/sys/isofs/cd9660/cd9660_vfsops.c
index 8df32e0..0f8f3c9 100644
--- a/sys/isofs/cd9660/cd9660_vfsops.c
+++ b/sys/isofs/cd9660/cd9660_vfsops.c
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/stat.h>
#include <sys/syslog.h>
+#include <sys/iconv.h>
#include <isofs/cd9660/iso.h>
@@ -66,6 +67,8 @@ __FBSDID("$FreeBSD$");
MALLOC_DEFINE(M_ISOFSMNT, "ISOFS mount", "ISOFS mount structure");
MALLOC_DEFINE(M_ISOFSNODE, "ISOFS node", "ISOFS vnode private part");
+struct iconv_functions *cd9660_iconv = NULL;
+
static vfs_mount_t cd9660_mount;
static vfs_unmount_t cd9660_unmount;
static vfs_root_t cd9660_root;
@@ -471,7 +474,16 @@ iso_mountfs(devvp, mp, td, argp)
bp = NULL;
}
isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
- ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET);
+ ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET |
+ ISOFSMNT_KICONV);
+
+ if (isomp->im_flags & ISOFSMNT_KICONV && cd9660_iconv) {
+ cd9660_iconv->open(argp->cs_local, argp->cs_disk, &isomp->im_d2l);
+ cd9660_iconv->open(argp->cs_disk, argp->cs_local, &isomp->im_l2d);
+ } else {
+ isomp->im_d2l = NULL;
+ isomp->im_l2d = NULL;
+ }
if (high_sierra) {
/* this effectively ignores all the mount flags */
@@ -551,6 +563,12 @@ cd9660_unmount(mp, mntflags, td)
isomp = VFSTOISOFS(mp);
+ if (isomp->im_flags & ISOFSMNT_KICONV && cd9660_iconv) {
+ if (isomp->im_d2l)
+ cd9660_iconv->close(isomp->im_d2l);
+ if (isomp->im_l2d)
+ cd9660_iconv->close(isomp->im_l2d);
+ }
isomp->im_devvp->v_rdev->si_mountpoint = NULL;
error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, td);
vrele(isomp->im_devvp);
diff --git a/sys/isofs/cd9660/cd9660_vnops.c b/sys/isofs/cd9660/cd9660_vnops.c
index bf95bf7..c18b664 100644
--- a/sys/isofs/cd9660/cd9660_vnops.c
+++ b/sys/isofs/cd9660/cd9660_vnops.c
@@ -562,7 +562,9 @@ cd9660_readdir(ap)
idp->current.d_name, &namelen,
imp->iso_ftype == ISO_FTYPE_9660,
isonum_711(ep->flags)&4,
- imp->joliet_level);
+ imp->joliet_level,
+ imp->im_flags,
+ imp->im_d2l);
idp->current.d_namlen = (u_char)namelen;
if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
error = iso_shipdir(idp);
diff --git a/sys/isofs/cd9660/iso.h b/sys/isofs/cd9660/iso.h
index b41cd0c..15766ef 100644
--- a/sys/isofs/cd9660/iso.h
+++ b/sys/isofs/cd9660/iso.h
@@ -245,6 +245,9 @@ struct iso_mnt {
int rr_skip0;
int joliet_level;
+
+ void *im_d2l;
+ void *im_l2d;
};
#define VFSTOISOFS(mp) ((struct iso_mnt *)((mp)->mnt_data))
@@ -265,10 +268,11 @@ extern vop_t **cd9660_vnodeop_p;
extern vop_t **cd9660_specop_p;
extern vop_t **cd9660_fifoop_p;
-int isochar(u_char *, u_char *, int, u_char *);
-int isofncmp(u_char *, int, u_char *, int, int);
-void isofntrans(u_char *, int, u_char *, u_short *, int, int, int);
+int isochar(u_char *, u_char *, int, u_short *, int *, int, void *);
+int isofncmp(u_char *, int, u_char *, int, int, int, void *, void *);
+void isofntrans(u_char *, int, u_char *, u_short *, int, int, int, int, void *);
ino_t isodirino(struct iso_directory_record *, struct iso_mnt *);
+u_short sgetrune(const char *, size_t, char const **, int, void *);
#endif /* _KERNEL */
OpenPOWER on IntegriCloud