From 237310012ea04b5c696cef1515d2650961a4a076 Mon Sep 17 00:00:00 2001 From: Alexander Polakov Date: Sun, 13 Sep 2009 03:22:09 +0400 Subject: [PATCH] libiconv: convert NTFS to libiconv. Partly-taken-from: FreeBSD --- sys/vfs/ntfs/Makefile | 1 + sys/vfs/ntfs/ntfs.h | 2 + sys/vfs/ntfs/ntfs_iconv/Makefile | 7 + .../ntfs/{ntfsmount.h => ntfs_iconv/ntfs_iconv.c} | 28 ++-- sys/vfs/ntfs/ntfs_subr.c | 167 +++++++++++++++++---- sys/vfs/ntfs/ntfs_subr.h | 9 +- sys/vfs/ntfs/ntfs_vfsops.c | 19 ++- sys/vfs/ntfs/ntfs_vnops.c | 17 ++- sys/vfs/ntfs/ntfsmount.h | 6 +- 9 files changed, 186 insertions(+), 70 deletions(-) create mode 100644 sys/vfs/ntfs/ntfs_iconv/Makefile copy sys/vfs/ntfs/{ntfsmount.h => ntfs_iconv/ntfs_iconv.c} (63%) diff --git a/sys/vfs/ntfs/Makefile b/sys/vfs/ntfs/Makefile index 49370d6782..91220b9594 100644 --- a/sys/vfs/ntfs/Makefile +++ b/sys/vfs/ntfs/Makefile @@ -5,4 +5,5 @@ KMOD= ntfs SRCS= ntfs_vfsops.c ntfs_vnops.c ntfs_subr.c ntfs_ihash.c \ ntfs_compr.c +SUBDIR= ntfs_iconv .include diff --git a/sys/vfs/ntfs/ntfs.h b/sys/vfs/ntfs/ntfs.h index 8dda76ffdc..516d2608f3 100644 --- a/sys/vfs/ntfs/ntfs.h +++ b/sys/vfs/ntfs/ntfs.h @@ -262,6 +262,8 @@ struct ntfsmount { struct netexport ntm_export; /* export information */ wchar * ntm_82u; /* 8bit to Unicode */ char ** ntm_u28; /* Unicode to 8 bit */ + void * ntm_ic_l2u; /* Local to Unicode (iconv) */ + void * ntm_ic_u2l; /* Unicode to Local (iconv) */ }; #define ntm_mftcn ntm_bootfile.bf_mftcn diff --git a/sys/vfs/ntfs/ntfs_iconv/Makefile b/sys/vfs/ntfs/ntfs_iconv/Makefile new file mode 100644 index 0000000000..0e79905194 --- /dev/null +++ b/sys/vfs/ntfs/ntfs_iconv/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD: src/sys/modules/ntfs_iconv/Makefile,v 1.1 2003/09/26 20:26:25 fjoe Exp $ + +.PATH: ${.CURDIR}/../../fs/ntfs +KMOD= ntfs_iconv +SRCS= ntfs_iconv.c + +.include diff --git a/sys/vfs/ntfs/ntfsmount.h b/sys/vfs/ntfs/ntfs_iconv/ntfs_iconv.c similarity index 63% copy from sys/vfs/ntfs/ntfsmount.h copy to sys/vfs/ntfs/ntfs_iconv/ntfs_iconv.c index 2f78b3805a..23d906f3bc 100644 --- a/sys/vfs/ntfs/ntfsmount.h +++ b/sys/vfs/ntfs/ntfs_iconv/ntfs_iconv.c @@ -1,7 +1,5 @@ -/* $NetBSD: ntfsmount.h,v 1.3 1999/07/26 14:02:32 jdolecek Exp $ */ - /*- - * Copyright (c) 1998, 1999 Semen Ustimenko + * Copyright (c) 2003 Ryuichiro Imura * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,21 +22,15 @@ * 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: src/sys/ntfs/ntfsmount.h,v 1.6.2.1 2001/10/12 22:08:49 semenu Exp $ - * $DragonFly: src/sys/vfs/ntfs/ntfsmount.h,v 1.2 2003/06/17 04:28:54 dillon Exp $ + * $FreeBSD: src/sys/fs/ntfs/ntfs_iconv.c,v 1.1 2003/09/26 20:26:23 fjoe Exp $ */ -#define NTFS_MFLAG_CASEINS 0x00000001 -#define NTFS_MFLAG_ALLNAMES 0x00000002 -#define NTFSMNT_U2WTABLE 0x00000004 +#include + +#include +#include +#include +#include +#include -struct ntfs_args { - char *fspec; /* block special device to mount */ - struct export_args export; /* network export information */ - uid_t uid; /* uid that owns ntfs files */ - gid_t gid; /* gid that owns ntfs files */ - mode_t mode; /* mask to be applied for ntfs perms */ - u_long flag; /* additional flags */ - u_int16_t u2w[256]; /* Unix to Wchar */ -}; +VFS_DECLARE_ICONV(ntfs); diff --git a/sys/vfs/ntfs/ntfs_subr.c b/sys/vfs/ntfs/ntfs_subr.c index 44a26a95ca..427dcdac06 100644 --- a/sys/vfs/ntfs/ntfs_subr.c +++ b/sys/vfs/ntfs/ntfs_subr.c @@ -43,6 +43,7 @@ #include #include #include +#include #include @@ -77,6 +78,7 @@ static wchar *ntfs_toupper_tab; #define NTFS_TOUPPER(ch) (ntfs_toupper_tab[(ch)]) static struct lock ntfs_toupper_lock; static signed int ntfs_toupper_usecount; +extern struct iconv_functions *ntfs_iconv; /* support macro for ntfs_ntvattrget() */ #define NTFS_AALPCMP(aalp,type,name,namelen) ( \ @@ -646,20 +648,41 @@ static int ntfs_uastricmp(struct ntfsmount *ntmp, const wchar *ustr, size_t ustrlen, const char *astr, size_t astrlen) { - size_t i; - int res; + int len; + size_t i, j, mbstrlen = astrlen; + int res; + wchar wc; + + if (ntmp->ntm_ic_l2u) { + for (i = 0, j = 0; i < ustrlen && j < astrlen; i++, j++) { + if (j < astrlen -1) { + wc = (wchar)astr[j]<<8 | (astr[j+1]&0xFF); + len = 2; + } else { + wc = (wchar)astr[j]<<8 & 0xFF00; + len = 1; + } + res = ((int) NTFS_TOUPPER(ustr[i])) - + ((int)NTFS_TOUPPER(NTFS_82U(wc, &len))); + j += len - 1; + mbstrlen -= len - 1; - /* - * XXX We use NTFS_82U(NTFS_U28(c)) to get rid of unicode - * symbols not covered by translation table - */ - for (i = 0; i < ustrlen && i < astrlen; i++) { - res = ((int) NTFS_TOUPPER(NTFS_82U(NTFS_U28(ustr[i])))) - - ((int)NTFS_TOUPPER(NTFS_82U(astr[i]))); - if (res) - return res; + if (res) + return res; + } + } else { + /* + * We use NTFS_82U(NTFS_U28(c)) to get rid of unicode + * symbols not covered by translation table + */ + for (i = 0; i < ustrlen && i < astrlen; i++) { + res = ((int) NTFS_TOUPPER(NTFS_82U(NTFS_U28(ustr[i]), &len))) - + ((int)NTFS_TOUPPER(NTFS_82U((wchar)astr[i], &len))); + if (res) + return res; + } } - return (ustrlen - astrlen); + return (ustrlen - mbstrlen); } /* @@ -669,15 +692,25 @@ static int ntfs_uastrcmp(struct ntfsmount *ntmp, const wchar *ustr, size_t ustrlen, const char *astr, size_t astrlen) { - size_t i; - int res; - - for (i = 0; (i < ustrlen) && (i < astrlen); i++) { - res = (int) (((char)NTFS_U28(ustr[i])) - astr[i]); + char u, l; + size_t i, j, mbstrlen = astrlen; + int res; + wchar wc; + + for (i = 0, j = 0; (i < ustrlen) && (j < astrlen); i++, j++) { + res = 0; + wc = NTFS_U28(ustr[i]); + u = (char)(wc>>8); + l = (char)wc; + if (u != '\0' && j < astrlen -1) { + res = (int) (u - astr[j++]); + mbstrlen--; + } + res = (res<<8) + (int) (l - astr[j]); if (res) return res; } - return (ustrlen - astrlen); + return (ustrlen - mbstrlen); } /* @@ -811,7 +844,7 @@ ntfs_ntlookupattr(struct ntfsmount *ntmp, const char *name, int namelen, */ int ntfs_ntlookupfile(struct ntfsmount *ntmp, struct vnode *vp, - struct componentname *cnp, struct vnode **vpp) + struct componentname *cnp, struct vnode **vpp) { struct fnode *fp = VTOF(vp); struct ntnode *ip = FTONT(fp); @@ -1660,7 +1693,7 @@ ntfs_readattr(struct ntfsmount *ntmp, struct ntnode *ip, u_int32_t attrnum, while (left) { error = ntfs_readattr_plain(ntmp, ip, attrnum, attrname, ntfs_cntob(cn), - ntfs_cntob(NTFS_COMPUNIT_CL), + ntfs_cntob(NTFS_COMPUNIT_CL), cup, &init, NULL); if (error) break; @@ -1905,11 +1938,17 @@ ntfs_toupper_unuse(void) } int -ntfs_u28_init(struct ntfsmount *ntmp, wchar *u2w) +ntfs_u28_init(struct ntfsmount *ntmp, wchar *u2w, char *cs_local, + char *cs_ntfs) { char ** u28; int i, j, h, l; + if (ntfs_iconv && cs_local) { + ntfs_iconv->open(cs_local, cs_ntfs, &ntmp->ntm_ic_u2l); + return (0); + } + MALLOC(u28, char **, 256 * sizeof(char*), M_TEMP, M_WAITOK | M_ZERO); for (i=0; i<256; i++) { @@ -1936,6 +1975,13 @@ ntfs_u28_uninit(struct ntfsmount *ntmp) char ** u28; int i; + if (ntmp->ntm_u28 == NULL) { + if (ntfs_iconv && ntmp->ntm_ic_u2l) { + ntfs_iconv->close(ntmp->ntm_ic_u2l); + } + return (0); + } + if (ntmp->ntm_u28 == NULL) return (0); @@ -1951,22 +1997,21 @@ ntfs_u28_uninit(struct ntfsmount *ntmp) } int -ntfs_82u_init(struct ntfsmount *ntmp, u_int16_t *u2w) +ntfs_82u_init(struct ntfsmount *ntmp, char *cs_local, char *cs_ntfs) + { wchar * _82u; int i; + if (ntfs_iconv && cs_local) { + ntfs_iconv->open(cs_ntfs, cs_local, &ntmp->ntm_ic_l2u); + return (0); + } + MALLOC(_82u, wchar *, 256 * sizeof(wchar), M_TEMP, M_WAITOK); - if (u2w == NULL) { - for (i=0; i<256; i++) - _82u[i] = i; - } else { - for (i=0; i<128; i++) - _82u[i] = i; - for (i=0; i<128; i++) - _82u[i+128] = u2w[i]; - } + for (i=0; i<256; i++) + _82u[i] = i; ntmp->ntm_82u = _82u; @@ -1976,6 +2021,13 @@ ntfs_82u_init(struct ntfsmount *ntmp, u_int16_t *u2w) int ntfs_82u_uninit(struct ntfsmount *ntmp) { + if (ntmp->ntm_82u == NULL) { + if (ntfs_iconv && ntmp->ntm_ic_l2u) { + ntfs_iconv->close(ntmp->ntm_ic_l2u); + } + return (0); + } + FREE(ntmp->ntm_82u, M_TEMP); return (0); } @@ -1986,10 +2038,28 @@ ntfs_82u_uninit(struct ntfsmount *ntmp) * and substitutes a '_' for it if the result would be '\0'; * something better has to be definitely though out */ -char +wchar ntfs_u28(struct ntfsmount *ntmp, wchar wc) { - char * p; + char *p, *outp, inbuf[3], outbuf[3]; + size_t ilen, olen; + + if (ntfs_iconv && ntmp->ntm_ic_u2l) { + ilen = olen = 2; + inbuf[0] = (char)(wc>>8); + inbuf[1] = (char)wc; + inbuf[2] = '\0'; + p = inbuf; + outp = outbuf; + ntfs_iconv->convchr(ntmp->ntm_ic_u2l, (const char **)&p, &ilen, + &outp, &olen); + if (olen == 1) { + return ((wchar)(outbuf[0]&0xFF)); + } else if (olen == 0) { + return ((wchar)((outbuf[0]<<8) | (outbuf[1]&0xFF))); + } + return ('?'); + } p = ntmp->ntm_u28[(wc>>8)&0xFF]; if (p == NULL) @@ -1997,3 +2067,34 @@ ntfs_u28(struct ntfsmount *ntmp, wchar wc) return (p[wc&0xFF]); } +wchar +ntfs_82u(struct ntfsmount *ntmp, + wchar wc, + int *len) +{ + char *p, *outp, inbuf[3], outbuf[3]; + wchar uc; + size_t ilen, olen; + + if (ntfs_iconv && ntmp->ntm_ic_l2u) { + ilen = (size_t)*len; + olen = 2; + + inbuf[0] = (char)(wc>>8); + inbuf[1] = (char)wc; + inbuf[2] = '\0'; + p = inbuf; + outp = outbuf; + ntfs_iconv->convchr(ntmp->ntm_ic_l2u, (const char **)&p, &ilen, + &outp, &olen); + *len -= (int)ilen; + uc = (wchar)((outbuf[0]<<8) | (outbuf[1]&0xFF)); + + return (uc); + } + + if (ntmp->ntm_82u != NULL) + return (ntmp->ntm_82u[wc&0xFF]); + + return ('?'); +} diff --git a/sys/vfs/ntfs/ntfs_subr.h b/sys/vfs/ntfs/ntfs_subr.h index 04962b3bc0..46de35f5cf 100644 --- a/sys/vfs/ntfs/ntfs_subr.h +++ b/sys/vfs/ntfs/ntfs_subr.h @@ -108,13 +108,14 @@ void ntfs_toupper_unuse (void); int ntfs_fget (struct ntfsmount *, struct ntnode *, int, char *, struct fnode **); void ntfs_frele (struct fnode *); -int ntfs_u28_init(struct ntfsmount *ntmp, wchar *u2w); +int ntfs_u28_init(struct ntfsmount *ntmp, wchar *u2w, char *cs_local, char *cs_ntfs); int ntfs_u28_uninit(struct ntfsmount *ntmp); -int ntfs_82u_init(struct ntfsmount *ntmp, u_int16_t *u2w); +int ntfs_82u_init(struct ntfsmount *ntmp, char *cs_local, char *cs_ntfs); int ntfs_82u_uninit(struct ntfsmount *ntmp); -char ntfs_u28(struct ntfsmount *ntmp, wchar wc); +wchar ntfs_u28(struct ntfsmount *ntmp, wchar wc); +wchar ntfs_82u(struct ntfsmount *ntmp, wchar wc, int *len); #define NTFS_U28(ch) ntfs_u28(ntmp, (ch)) -#define NTFS_82U(ch) (ntmp->ntm_82u[(ch)&0xFF]) +#define NTFS_82U(ch, len) ntfs_82u(ntmp, (ch), len) #define NTFS_UASTRCMP(ustr, ustrlen, astr, astrlen) \ ntfs_uastrcmp(ntmp, (ustr), (ustrlen), (astr), (astrlen)) #define NTFS_UASTRICMP(ustr, ustrlen, astr, astrlen) \ diff --git a/sys/vfs/ntfs/ntfs_vfsops.c b/sys/vfs/ntfs/ntfs_vfsops.c index 17fd2e8cc6..c20db7b071 100644 --- a/sys/vfs/ntfs/ntfs_vfsops.c +++ b/sys/vfs/ntfs/ntfs_vfsops.c @@ -79,6 +79,8 @@ MALLOC_DEFINE(M_NTFSFNODE,"NTFS fnode", "NTFS fnode information"); MALLOC_DEFINE(M_NTFSDIR,"NTFS dir", "NTFS dir buffer"); #endif +struct iconv_functions *ntfs_iconv = NULL; + static int ntfs_root (struct mount *, struct vnode **); static int ntfs_statfs (struct mount *, struct statfs *, struct ucred *cred); static int ntfs_unmount (struct mount *, int); @@ -397,6 +399,8 @@ ntfs_mountfs(struct vnode *devvp, struct mount *mp, struct ntfs_args *argsp, cdev_t dev; int error, ronly, ncount, i; struct vnode *vp; + char cs_local[ICONV_CSNMAXLEN]; + char cs_ntfs[ICONV_CSNMAXLEN]; /* * Disallow multiple mounts of the same device. @@ -469,16 +473,16 @@ ntfs_mountfs(struct vnode *devvp, struct mount *mp, struct ntfs_args *argsp, ntmp->ntm_mode = argsp->mode; ntmp->ntm_flag = argsp->flag; - /* Copy in the 8-bit to Unicode conversion table */ - if (argsp->flag & NTFSMNT_U2WTABLE) { - ntfs_82u_init(ntmp, argsp->u2w); + if (argsp->flag & NTFS_MFLAG_KICONV && ntfs_iconv) { + bcopy(argsp->cs_local, cs_local, sizeof(cs_local)); + bcopy(argsp->cs_ntfs, cs_ntfs, sizeof(cs_ntfs)); + ntfs_82u_init(ntmp, cs_local, cs_ntfs); + ntfs_u28_init(ntmp, NULL, cs_local, cs_ntfs); } else { - ntfs_82u_init(ntmp, NULL); + ntfs_82u_init(ntmp, NULL, NULL); + ntfs_u28_init(ntmp, ntmp->ntm_82u, NULL, NULL); } - /* Initialize Unicode to 8-bit table from 8toU table */ - ntfs_u28_init(ntmp, ntmp->ntm_82u); - mp->mnt_data = (qaddr_t)ntmp; dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n", @@ -941,6 +945,7 @@ static struct vfsops ntfs_vfsops = { .vfs_uninit = ntfs_nthash_uninit /* see ntfs_ihash.c */ }; VFS_SET(ntfs_vfsops, ntfs, 0); +MODULE_VERSION(ntfs, 1); #elif defined(__NetBSD__) extern struct vnodeopv_desc ntfs_vnodeop_opv_desc; diff --git a/sys/vfs/ntfs/ntfs_vnops.c b/sys/vfs/ntfs/ntfs_vnops.c index 92a22fcb90..e865403587 100644 --- a/sys/vfs/ntfs/ntfs_vnops.c +++ b/sys/vfs/ntfs/ntfs_vnops.c @@ -545,7 +545,8 @@ ntfs_readdir(struct vop_readdir_args *ap) struct ntnode *ip = FTONT(fp); struct uio *uio = ap->a_uio; struct ntfsmount *ntmp = ip->i_mp; - int i, error = 0; + int i, j, error = 0; + wchar c; u_int32_t faked = 0, num, off; int ncookies = 0; char convname[NTFS_MAXFILENAME + 1]; @@ -620,14 +621,16 @@ ntfs_readdir(struct vop_readdir_args *ap) { if(!ntfs_isnamepermitted(ntmp,iep)) continue; - - for (i=0; i < iep->ie_fnamelen; i++) - convname[i] = NTFS_U28(iep->ie_fname[i]); - convname[i] = '\0'; - + for(i=0, j=0; i < iep->ie_fnamelen; i++, j++) { + c = NTFS_U28(iep->ie_fname[i]); + if (c&0xFF00) + convname[j++] = (char)(c>>8); + convname[j] = (char)c&0xFF; + } + convname[j] = '\0'; if (vop_write_dirent(&error, uio, iep->ie_number, (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG, - iep->ie_fnamelen, convname)) + j, convname)) goto readdone; dprintf(("ntfs_readdir: elem: %d, fname:[%s] type: %d, " diff --git a/sys/vfs/ntfs/ntfsmount.h b/sys/vfs/ntfs/ntfsmount.h index 2f78b3805a..b51f89186d 100644 --- a/sys/vfs/ntfs/ntfsmount.h +++ b/sys/vfs/ntfs/ntfsmount.h @@ -29,9 +29,11 @@ * $DragonFly: src/sys/vfs/ntfs/ntfsmount.h,v 1.2 2003/06/17 04:28:54 dillon Exp $ */ +#include + #define NTFS_MFLAG_CASEINS 0x00000001 #define NTFS_MFLAG_ALLNAMES 0x00000002 -#define NTFSMNT_U2WTABLE 0x00000004 +#define NTFS_MFLAG_KICONV 0x00000004 struct ntfs_args { char *fspec; /* block special device to mount */ @@ -41,4 +43,6 @@ struct ntfs_args { mode_t mode; /* mask to be applied for ntfs perms */ u_long flag; /* additional flags */ u_int16_t u2w[256]; /* Unix to Wchar */ + char cs_ntfs[ICONV_CSNMAXLEN]; /* disk charset for cs conversion */ + char cs_local[ICONV_CSNMAXLEN]; /* local charset for cs conversion */ }; -- 2.11.4.GIT