From 60c47c5ed66cd3cbfb43d32277a998191e54cb2c Mon Sep 17 00:00:00 2001 From: Alexander Polakov Date: Fri, 4 Sep 2009 01:09:33 +0400 Subject: [PATCH] libiconv: convert cd9660 to libiconv. --- sys/vfs/isofs/cd9660/Makefile | 2 + sys/vfs/isofs/cd9660/cd9660_iconv/Makefile | 6 + sys/vfs/isofs/cd9660/cd9660_iconv/cd9660_iconv.c | 35 ++++ sys/vfs/isofs/cd9660/cd9660_lookup.c | 7 +- sys/vfs/isofs/cd9660/cd9660_mount.h | 8 +- sys/vfs/isofs/cd9660/cd9660_rrip.c | 14 +- sys/vfs/isofs/cd9660/cd9660_util.c | 250 ++++++++++++++--------- sys/vfs/isofs/cd9660/cd9660_vfsops.c | 24 ++- sys/vfs/isofs/cd9660/cd9660_vnops.c | 12 +- sys/vfs/isofs/cd9660/iso.h | 49 +++-- 10 files changed, 279 insertions(+), 128 deletions(-) create mode 100644 sys/vfs/isofs/cd9660/cd9660_iconv/Makefile create mode 100644 sys/vfs/isofs/cd9660/cd9660_iconv/cd9660_iconv.c diff --git a/sys/vfs/isofs/cd9660/Makefile b/sys/vfs/isofs/cd9660/Makefile index ee552f77ba..d3c1b2af8f 100644 --- a/sys/vfs/isofs/cd9660/Makefile +++ b/sys/vfs/isofs/cd9660/Makefile @@ -6,4 +6,6 @@ KMOD= cd9660 SRCS= cd9660_bmap.c cd9660_lookup.c cd9660_node.c cd9660_rrip.c \ cd9660_util.c cd9660_vfsops.c cd9660_vnops.c +EXPORT_SYMS= cd9660_iconv + .include diff --git a/sys/vfs/isofs/cd9660/cd9660_iconv/Makefile b/sys/vfs/isofs/cd9660/cd9660_iconv/Makefile new file mode 100644 index 0000000000..172eefdb0a --- /dev/null +++ b/sys/vfs/isofs/cd9660/cd9660_iconv/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD: src/sys/modules/msdosfs_iconv/Makefile,v 1.1.30.1 2009/04/15 03:14:26 kensmith Exp $ + +KMOD= cd9660_iconv +SRCS= cd9660_iconv.c + +.include diff --git a/sys/vfs/isofs/cd9660/cd9660_iconv/cd9660_iconv.c b/sys/vfs/isofs/cd9660/cd9660_iconv/cd9660_iconv.c new file mode 100644 index 0000000000..d4150dfcaa --- /dev/null +++ b/sys/vfs/isofs/cd9660/cd9660_iconv/cd9660_iconv.c @@ -0,0 +1,35 @@ +/*- + * 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 + +#include +#include +#include +#include +#include + +VFS_DECLARE_ICONV(cd9660); diff --git a/sys/vfs/isofs/cd9660/cd9660_lookup.c b/sys/vfs/isofs/cd9660/cd9660_lookup.c index 01661ae2ee..e3c5553e5d 100644 --- a/sys/vfs/isofs/cd9660/cd9660_lookup.c +++ b/sys/vfs/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/vfs/isofs/cd9660/cd9660_mount.h b/sys/vfs/isofs/cd9660/cd9660_mount.h index 489e3fbc69..9134c3f1bb 100644 --- a/sys/vfs/isofs/cd9660/cd9660_mount.h +++ b/sys/vfs/isofs/cd9660/cd9660_mount.h @@ -39,7 +39,7 @@ * $FreeBSD: src/sys/isofs/cd9660/cd9660_mount.h,v 1.3.2.2 2001/03/14 12:03:50 bp Exp $ * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_mount.h,v 1.3 2004/08/17 18:57:33 dillon Exp $ */ - +#include /* * Arguments to mount ISO 9660 filesystems. */ @@ -48,10 +48,14 @@ 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[ICONV_CSNMAXLEN]; + /* disk charset for Joliet cs conversion */ + char cs_local[ICONV_CSNMAXLEN]; + /* 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/vfs/isofs/cd9660/cd9660_rrip.c b/sys/vfs/isofs/cd9660/cd9660_rrip.c index 5ec1a15e21..68f292be62 100644 --- a/sys/vfs/isofs/cd9660/cd9660_rrip.c +++ b/sys/vfs/isofs/cd9660/cd9660_rrip.c @@ -300,9 +300,10 @@ cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, ISO_RRIP_ANALYZE *ana) static void cd9660_rrip_defname(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana) { - isofntrans(isodir->name,isonum_711(isodir->name_len), - ana->outbuf,ana->outlen, - 1,isonum_711(isodir->flags)&4, ana->imp->joliet_level); + isofntrans(isodir->name,isonum_711(isodir->name_len), + ana->outbuf,ana->outlen, + 1,isonum_711(isodir->flags)&4, ana->imp->joliet_level, + ana->imp->im_flags, ana->imp->im_d2l); switch (*ana->outbuf) { default: break; @@ -490,7 +491,8 @@ cd9660_rrip_loop(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana, 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) @@ -619,8 +621,8 @@ cd9660_rrip_getname(struct iso_directory_record *isodir, char *outbuf, analyze.fields = ISO_SUSP_ALTNAME|ISO_SUSP_RELDIR|ISO_SUSP_CLINK|ISO_SUSP_PLINK; *outlen = 0; - isochar(isodir->name, isodir->name + isonum_711(isodir->name_len), - imp->joliet_level, &c); + isochar(isodir->name, isodir->name + isonum_711(isodir->name_len), + 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/vfs/isofs/cd9660/cd9660_util.c b/sys/vfs/isofs/cd9660/cd9660_util.c index c8181af605..43527c0cf8 100644 --- a/sys/vfs/isofs/cd9660/cd9660_util.c +++ b/sys/vfs/isofs/cd9660/cd9660_util.c @@ -44,16 +44,12 @@ #include #include #include +#include #include "iso.h" +#include "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 @@ -61,26 +57,45 @@ u_char (*cd9660_wchar2char)(u_int32_t wchar) = NULL; * Return number of bytes consumed */ int -isochar(u_char *isofn, u_char *isoend, int joliet_level, u_char *c) +isochar(isofn, isoend, joliet_level, c, clen, flags, handle) + u_char *isofn; + u_char *isoend; + int joliet_level; + 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; } @@ -90,84 +105,133 @@ isochar(u_char *isofn, u_char *isoend, int joliet_level, u_char *c) * Note: Version number plus ';' may be omitted. */ int -isofncmp(u_char *fn, int fnlen, u_char *isofn, int isolen, int 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; - - for (; fn != fnend; fn++) { - if (isofn == isoend) - return *fn; - isofn += isochar(isofn, isoend, joliet_level, &c); - if (c == ';') { - if (*fn++ != ';') - return fn[-1]; - 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); - return i - j; - } - if (c != *fn) { - if (c >= 'A' && c <= 'Z') { - if (c + ('a' - 'A') != *fn) { - if (*fn >= 'a' && *fn <= 'z') - return *fn - ('a' - 'A') - c; - else - return *fn - c; - } - } else - return *fn - c; - } - } - if (isofn != isoend) { - isofn += isochar(isofn, isoend, joliet_level, &c); - switch (c) { - default: - return -c; - case '.': - if (isofn != isoend) { - isochar(isofn, isoend, joliet_level, &c); - if (c == ';') - return 0; - } - return -1; - case ';': - return 0; - } - } - return 0; + int i, j; + u_short c, d; + u_char *fnend = fn + fnlen, *isoend = isofn + isolen; + for (; fn < fnend; ) { + d = sgetrune(fn, fnend - fn, (char const **)&fn, flags, lhandle) +; + if (isofn == isoend) + return d; + isofn += isochar(isofn, isoend, joliet_level, &c, NULL, flags, handle); + if (c == ';') { + 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, + NULL, flags, handle); + return i - j; + } + if (c != d) { + if (c >= 'A' && c <= 'Z') { + if (c + ('a' - 'A') != d) { + if (d >= 'a' && d <= 'z') + return d - ('a' - 'A') - c; + else + return d - c; + } + } else + return d - c; + } + } + if (isofn != isoend) { + 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, + NULL, flags, handle); + if (c == ';') + return 0; + } + return -1; + case ';': + return 0; + } + } + return 0; } /* * translate a filename of length > 0 */ -void -isofntrans(u_char *infn, int infnlen, u_char *outfn, u_short *outfnlen, - int original, int assoc, int joliet_level) +isofntrans(infn, infnlen, outfn, outfnlen, original, assoc, joliet_level, flags, + handle) + u_char *infn; + int infnlen; + u_char *outfn; + u_short *outfnlen; + int original; + int assoc; + int joliet_level; + int flags; + void *handle; { - int fnidx = 0; - u_char c, d = '\0', *infnend = infn + infnlen; - - if (assoc) { - *outfn++ = ASSOCCHAR; - fnidx++; - } - for (; infn != infnend; fnidx++) { - infn += isochar(infn, infnend, joliet_level, &c); + u_short c, d = '\0'; + u_char *outp = outfn, *infnend = infn + infnlen; + int clen; + if (assoc) { + *outp++ = ASSOCCHAR; + } + for (; infn != infnend; ) { + infn += isochar(infn, infnend, joliet_level, &c, &clen, flags, handle); + if (!original && !joliet_level && c >= 'A' && c <= 'Z') + c += ('a' - 'A'); + else if (!original && c == ';') { + outp -= (d == '.'); + break; + } + d = c; + while(clen--) + *outp++ = c >> (clen << 3); + } + *outfnlen = outp - outfn; +} - if (!original && !joliet_level && c >= 'A' && c <= 'Z') - *outfn++ = c + ('a' - 'A'); - else if (!original && c == ';') { - fnidx -= (d == '.'); - break; - } else - *outfn++ = c; - d = c; - } - *outfnlen = fnidx; +/* + * 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/vfs/isofs/cd9660/cd9660_vfsops.c b/sys/vfs/isofs/cd9660/cd9660_vfsops.c index cfab5def8a..9c09c56ba2 100644 --- a/sys/vfs/isofs/cd9660/cd9660_vfsops.c +++ b/sys/vfs/isofs/cd9660/cd9660_vfsops.c @@ -55,6 +55,7 @@ #include #include #include +#include #include @@ -70,6 +71,8 @@ extern struct vop_ops cd9660_fifo_vops; 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 int cd9660_mount (struct mount *, char *, caddr_t, struct ucred *); static int cd9660_unmount (struct mount *, int); static int cd9660_root (struct mount *, struct vnode **); @@ -283,6 +286,8 @@ iso_mountfs(struct vnode *devvp, struct mount *mp, struct iso_args *argp) struct iso_supplementary_descriptor *sup = NULL; struct iso_directory_record *rootp; int logical_block_size; + char cs_local[ICONV_CSNMAXLEN]; + char cs_disk[ICONV_CSNMAXLEN]; if (!(mp->mnt_flag & MNT_RDONLY)) return EROFS; @@ -467,7 +472,17 @@ iso_mountfs(struct vnode *devvp, struct mount *mp, struct iso_args *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) { + bcopy(argp->cs_local, cs_local, sizeof(cs_local)); + bcopy(argp->cs_disk, cs_disk, sizeof(cs_disk)); + cd9660_iconv->open(cs_local, cs_disk, &isomp->im_d2l); + cd9660_iconv->open(cs_disk, cs_local, &isomp->im_l2d); + } else { + isomp->im_d2l = NULL; + isomp->im_l2d = NULL; + } if (high_sierra) { /* this effectively ignores all the mount flags */ @@ -549,6 +564,13 @@ cd9660_unmount(struct mount *mp, int mntflags) 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); vrele(isomp->im_devvp); diff --git a/sys/vfs/isofs/cd9660/cd9660_vnops.c b/sys/vfs/isofs/cd9660/cd9660_vnops.c index be863c87fd..c59ec542ca 100644 --- a/sys/vfs/isofs/cd9660/cd9660_vnops.c +++ b/sys/vfs/isofs/cd9660/cd9660_vnops.c @@ -543,11 +543,13 @@ cd9660_readdir(struct vop_readdir_args *ap) idp->current.de.d_namlen = 2; error = iso_uiodir(idp,&idp->current.de,idp->curroff); } else { - isofntrans(ep->name,idp->current.de.d_namlen, - idp->current.de.d_name, &namelen, - imp->iso_ftype == ISO_FTYPE_9660, - isonum_711(ep->flags)&4, - imp->joliet_level); + isofntrans(ep->name,idp->current.de.d_namlen, + idp->current.de.d_name, &namelen, + imp->iso_ftype == ISO_FTYPE_9660, + isonum_711(ep->flags)&4, + imp->joliet_level, + imp->im_flags, + imp->im_d2l); idp->current.de.d_namlen = namelen; if (imp->iso_ftype == ISO_FTYPE_DEFAULT) error = iso_shipdir(idp); diff --git a/sys/vfs/isofs/cd9660/iso.h b/sys/vfs/isofs/cd9660/iso.h index 8407bdbff0..a1ad5951c3 100644 --- a/sys/vfs/isofs/cd9660/iso.h +++ b/sys/vfs/isofs/cd9660/iso.h @@ -247,6 +247,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)) @@ -264,10 +267,11 @@ int cd9660_uninit (struct vfsconf *); #define cd9660_sysctl ((int (*) (int *, u_int, void *, size_t *, void *, \ size_t, struct proc *))eopnotsupp) -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 */ @@ -276,34 +280,39 @@ ino_t isodirino (struct iso_directory_record *, struct iso_mnt *); * outside the kernel. Thus we don't hide them here. */ -static __inline int isonum_711 (u_char *); -static __inline int -isonum_711(u_char *p) +static __inline uint8_t +isonum_711(unsigned char *p) +{ + return p[0]; +} +static __inline uint8_t +isonum_712(unsigned char *p) { - return *p; + return p[0]; } -static __inline int isonum_712 (char *); -static __inline int -isonum_712(char *p) +static __inline uint16_t +isonum_723(unsigned char *p) { - return *p; + return (p[0] | p[1] << 8); } #ifndef UNALIGNED_ACCESS -static __inline int isonum_723 (u_char *); -static __inline int -isonum_723(u_char *p) +static __inline uint32_t +isonum_731(unsigned char *p) { - return *p|(p[1] << 8); + return (p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24); } - -static __inline int isonum_733 (u_char *); -static __inline int -isonum_733(u_char *p) +static __inline uint32_t +isonum_732(unsigned char *p) +{ + return (p[3] | p[2] << 8 | p[1] << 16 | p[0] << 24); +} +static __inline uint32_t +isonum_733(unsigned char *p) { - return *p|(p[1] << 8)|(p[2] << 16)|(p[3] << 24); + return (p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24); } #else /* UNALIGNED_ACCESS */ -- 2.11.4.GIT