Index: gnu/usr.bin/groff/tmac/mdoc.local =================================================================== RCS file: /home/ncvs/src/gnu/usr.bin/groff/tmac/mdoc.local,v retrieving revision 1.24.2.1 diff -u -r1.24.2.1 mdoc.local --- gnu/usr.bin/groff/tmac/mdoc.local 4 Jun 2003 05:37:49 -0000 1.24.2.1 +++ gnu/usr.bin/groff/tmac/mdoc.local 20 Jul 2003 18:11:04 -0000 @@ -43,6 +43,7 @@ .ds doc-str-Lb-libfetch File Transfer Library (libfetch, \-lfetch) .ds doc-str-Lb-libgeom Userland API Library for kernel GEOM subsystem (libgeom, \-lgeom) .ds doc-str-Lb-libipx IPX Address Conversion Support Library (libipx, \-lipx) +.ds doc-str-Lb-libkiconv Kernel side iconv library (libkiconv, \-lkiconv) .ds doc-str-Lb-libmd Message Digest (MD4, MD5, etc.) Support Library (libmd, \-lmd) .ds doc-str-Lb-libnetgraph Netgraph User Library (libnetgraph, \-lnetgraph) .ds doc-str-Lb-libpam PAM Library (libpam, \-lpam) Index: lib/Makefile =================================================================== RCS file: /home/ncvs/src/lib/Makefile,v retrieving revision 1.157.2.2 diff -u -r1.157.2.2 Makefile --- lib/Makefile 2 Jun 2003 22:25:10 -0000 1.157.2.2 +++ lib/Makefile 20 Jul 2003 19:01:48 -0000 @@ -26,7 +26,7 @@ ${_compat} libalias libatm ${_libbind} libbz2 libc ${_libc_r} \ libcalendar libcam libcompat libdevinfo libdevstat ${_libdisk} \ libedit libexpat libfetch libform libftpio libgeom ${_libio} libipsec \ - libipx libisc libmenu ${_libmilter} ${_libmp} ${_libncp} \ + libipx libisc libkiconv libmenu ${_libmilter} ${_libmp} ${_libncp} \ libnetgraph libopie libpam libpanel libpcap ${_libpthread} \ ${_libsm} ${_libsmb} ${_libsmdb} ${_libsmutil} \ ${_libstand} ${_libtelnet} ${_libthr} libufs libugidfw libusbhid \ Index: lib/libkiconv/Makefile =================================================================== RCS file: lib/libkiconv/Makefile diff -N lib/libkiconv/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libkiconv/Makefile 10 Sep 2003 17:02:02 -0000 @@ -0,0 +1,17 @@ +# $FreeBSD:$ + +LIB= kiconv +SRCS= xlat16_iconv.c xlat16_sysctl.c +SRCS+= quirks.c + +SHLIB_MAJOR= 1 +SHLIB_MINOR= 0 + +MAN= kiconv.3 + +MLINKS+=kiconv.3 kiconv_add_xlat16_cspair.3 \ + kiconv.3 kiconv_add_xlat16_table.3 + +CFLAGS+= -I${.CURDIR}/../../sys + +.include Index: lib/libkiconv/kiconv.3 =================================================================== RCS file: lib/libkiconv/kiconv.3 diff -N lib/libkiconv/kiconv.3 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libkiconv/kiconv.3 10 Sep 2003 17:02:02 -0000 @@ -0,0 +1,106 @@ +.\" +.\" 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$ +.\" +.Dd July 17, 2003 +.Dt KICONV 3 +.Os +.Sh NAME +.Nm kiconv_add_xlat16_cspair , +.Nm kiconv_add_xlat16_table +.Nd Kernel side iconv library +.Sh LIBRARY +.Lb libkiconv +.Sh SYNOPSIS +.In sys/iconv.h +.Ft int +.Fo kiconv_add_xlat16_cspair +.Fa "const char *tocode" +.Fa "const char *fromcode" +.Fa "int flag" +.Fc +.Ft int +.Fo kiconv_add_xlat16_table +.Fa "const char *tocode" +.Fa "const char *fromcode" +.Fa "const void *data" +.Fa "int datalen" +.Fc +.Sh DESCRIPTION +The +.Xr kiconv 3 +library provides multi-byte character conversion tables for kernel side +iconv service. +.Pp +.Fn kiconv_add_xlat16_cspair +defines a conversion table using +.Xr iconv 3 +between +.Ar fromcode +charset and +.Ar tocode +charset. You can specify +.Ar flag +to determine if +.Xr tolower 3 +/ +.Xr toupper 3 +conversion is included in the table. +The +.Ar flag +has following values. +.Pp +.Bl -tag -width "KICONV_FROM_LOWER" -compact +.It Fa KICONV_LOWER +.It Fa KICONV_FROM_LOWER +It generates a tolower table in addition to a character conversion table. +The difference between two is tolower +.Ar tocode +or tolower +.Ar fromcode . +.It Fa KICONV_UPPER +.It Fa KICONV_FROM_UPPER +It generates a toupper table in addition to a character conversion table. +The difference between two is toupper +.Ar tocode +or toupper +.Ar fromcode . +.El +.Pp +A tolower/toupper conversion is limited to single-byte characters. +.Pp +.Fn kiconv_add_xlat16_table +defines a conversion table directly pointed by +.Ar data +whose length is +.Ar datalen , +not using +.Xr iconv 3 . +.Sh SEE ALSO +.Xr iconv 3 +.Xr tolower 3 +.Xr toupper 3 +.Xr iconv 9 Index: lib/libkiconv/quirks.c =================================================================== RCS file: lib/libkiconv/quirks.c diff -N lib/libkiconv/quirks.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libkiconv/quirks.c 10 Sep 2003 17:02:02 -0000 @@ -0,0 +1,190 @@ +/*- + * 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$ + */ + +/* + * kiconv(3) requires shared linked, and reduce module size + * when statically linked. + */ + +#ifdef PIC + +/* + * Why do we need quirks? + * Since each vendors has their own Unicode mapping rules, + * we need some quirks until iconv(3) supports them. + * We can define Microsoft mappings here. + * + * For example, the eucJP and Unocode mapping rule is based on + * the JIS standard. Since Microsoft uses cp932 for Unicode mapping + * witch is not truly based on the JIS standard, reading a file + * system created by Microsoft Windows family using eucJP/Unicode + * mapping rule will cause a problem. That's why we define eucJP-ms here. + * The eucJP-ms has been defined by The Open Group Japan Vendor Coucil. + * + * Well, Apple Mac OS also has their own Unicode mappings, + * but we won't require these quirks here, because HFS doesn't have + * Unicode and HFS+ has decomposed Unicode which can not be + * handled by this xlat16 converter. + */ + +#include +#include + +#include +#include + +#include "quirks.h" + +/* + * All lists of quirk character set + */ +static struct { + int vendor; /* reserved for non MS mapping */ + const char *base_codeset, *quirk_codeset; +} quirk_list[] = { + { KICONV_VENDOR_MICSFT, "eucJP", "eucJP-ms" }, + { KICONV_VENDOR_MICSFT, "EUC-JP", "eucJP-ms" }, + { KICONV_VENDOR_MICSFT, "SJIS", "SJIS-ms" }, + { KICONV_VENDOR_MICSFT, "Shift_JIS", "SJIS-ms" }, + { KICONV_VENDOR_MICSFT, "Big5", "Big5-ms" } +}; + +/* + * The character list to replace for Japanese MS-Windows. + */ +static struct quirk_replace_list quirk_jis_cp932[] = { + { 0x00a2, 0xffe0 }, /* Cent Sign, Fullwidth Cent Sign */ + { 0x00a3, 0xffe1 }, /* Pound Sign, Fullwidth Pound Sign */ + { 0x00ac, 0xffe2 }, /* Not Sign, Fullwidth Not Sign */ + { 0x2016, 0x2225 }, /* Double Vertical Line, Parallel To */ + { 0x203e, 0x007e }, /* Overline, Tilde */ + { 0x2212, 0xff0d }, /* Minus Sign, Fullwidth Hyphenminus */ + { 0x301c, 0xff5e } /* Wave Dash, Fullwidth Tilde */ +}; + +/* + * All entries of quirks + */ +#define NumOf(n) (sizeof((n)) / sizeof((n)[0])) +static struct { + const char *quirk_codeset, *iconv_codeset, *pair_codeset; + struct quirk_replace_list (*replace_list)[]; + size_t num_of_replaces; +} quirk_table[] = { + { + "eucJP-ms", "eucJP", ENCODING_UNICODE, + &quirk_jis_cp932, NumOf(quirk_jis_cp932) + }, + { + "SJIS-ms", "CP932", ENCODING_UNICODE, + /* XXX - quirk_replace_list should be NULL */ + &quirk_jis_cp932, NumOf(quirk_jis_cp932) + }, + { + "Big5-ms", "CP950", ENCODING_UNICODE, + NULL, 0 + } +}; + + +const char * +kiconv_quirkcs(const char* base, int vendor) +{ + size_t i; + + /* + * We should compare codeset names ignoring case here, + * so that quirk could be used for all of the user input + * patterns. + */ + for (i = 0; i < NumOf(quirk_list); i++) + if (quirk_list[i].vendor == vendor && + strcasecmp(quirk_list[i].base_codeset, base) == 0) + return (quirk_list[i].quirk_codeset); + + return (base); +} + +/* + * Internal Functions + */ +const char * +search_quirk(const char *given_codeset, + const char *pair_codeset, + struct quirk_replace_list **replace_list, + size_t *num_of_replaces) +{ + size_t i; + + *replace_list = NULL; + *num_of_replaces = 0; + for (i = 0; i < NumOf(quirk_table); i++) + if (strcmp(quirk_table[i].quirk_codeset, given_codeset) == 0) { + if (strcmp(quirk_table[i].pair_codeset, pair_codeset) == 0) { + *replace_list = *quirk_table[i].replace_list; + *num_of_replaces = quirk_table[i].num_of_replaces; + } + return (quirk_table[i].iconv_codeset); + } + + return (given_codeset); +} + +uint16_t +quirk_vendor2unix(uint16_t c, struct quirk_replace_list *replace_list, size_t num) +{ + size_t i; + + for (i = 0; i < num; i++) + if (replace_list[i].vendor_code == c) + return (replace_list[i].standard_code); + + return (c); +} + +uint16_t +quirk_unix2vendor(uint16_t c, struct quirk_replace_list *replace_list, size_t num) +{ + size_t i; + + for (i = 0; i < num; i++) + if (replace_list[i].standard_code == c) + return (replace_list[i].vendor_code); + + return (c); +} + +#else /* statically linked */ + +const char * +kiconv_quirkcs(const char* base, int vendor) +{ + return (base); +} + +#endif /* PIC */ Index: lib/libkiconv/quirks.h =================================================================== RCS file: lib/libkiconv/quirks.h diff -N lib/libkiconv/quirks.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libkiconv/quirks.h 10 Sep 2003 17:02:02 -0000 @@ -0,0 +1,45 @@ +/*- + * 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$ + */ + +#ifndef _KICONV_QUIRKS_H_ +#define _KICONV_QUIRKS_H_ + +struct quirk_replace_list { + uint16_t standard_code, vendor_code; +}; + +const char *search_quirk(const char *, const char *, + struct quirk_replace_list **, size_t *); +uint16_t quirk_vendor2unix(uint16_t, + struct quirk_replace_list *, + size_t); +uint16_t quirk_unix2vendor(uint16_t, + struct quirk_replace_list *, + size_t); + +#endif /* _KICONV_QUIRKS_H_ */ Index: lib/libkiconv/xlat16_iconv.c =================================================================== RCS file: lib/libkiconv/xlat16_iconv.c diff -N lib/libkiconv/xlat16_iconv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libkiconv/xlat16_iconv.c 10 Sep 2003 17:02:02 -0000 @@ -0,0 +1,374 @@ +/*- + * 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$ + */ + +/* + * kiconv(3) requires shared linked, and reduce module size + * when statically linked. + */ + +#ifdef PIC + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "quirks.h" + +typedef void *iconv_t; + +struct xlat16_table { + uint32_t * idx[0x200]; + void * data; + size_t size; +}; + +static struct xlat16_table kiconv_xlat16_open(const char *, const char *, int); + +static int my_iconv_init(void); +static iconv_t (*my_iconv_open)(const char *, const char *); +static size_t (*my_iconv)(iconv_t, const char **, size_t *, char **, size_t *); +static int (*my_iconv_close)(iconv_t); +static size_t my_iconv_char(iconv_t, const u_char **, size_t *, u_char **, size_t *); + +int +kiconv_add_xlat16_cspair(const char *tocode, const char *fromcode, int flag) +{ + int error; + size_t i, size, idxsize; + struct iconv_cspair_info *csi; + struct xlat16_table xt; + void *data, *p; + + if (sysctlbyname("kern.iconv.cslist", NULL, &size, NULL, 0) == -1) + return (-1); + if (size > 0) { + csi = malloc(size); + if (csi == NULL) + return (-1); + if (sysctlbyname("kern.iconv.cslist", csi, &size, NULL, 0) == -1) { + free(csi); + return (-1); + } + for (i = 0; i < (size/sizeof(*csi)); i++, csi++){ + if (strcmp(csi->cs_to, tocode) == 0 && + strcmp(csi->cs_from, fromcode) == 0) + return (0); + } + } + + xt = kiconv_xlat16_open(tocode, fromcode, flag); + if (xt.size == 0) + return (-1); + + idxsize = sizeof(xt.idx); + + if ((idxsize + xt.size) > ICONV_CSMAXDATALEN) { + errno = E2BIG; + return (-1); + } + + if ((data = malloc(idxsize + xt.size)) != NULL) { + p = data; + memcpy(p, xt.idx, idxsize); + p += idxsize; + memcpy(p, xt.data, xt.size); + error = kiconv_add_xlat16_table(tocode, fromcode, data, + (int)(idxsize + xt.size)); + return (error); + } + + return (-1); +} + +static struct xlat16_table +kiconv_xlat16_open(const char *tocode, const char *fromcode, int lcase) +{ + u_char src[3], dst[4], *srcp, *dstp, ud, ld; + int us, ls, ret; + uint16_t c; + uint32_t table[0x80]; + size_t inbytesleft, outbytesleft, pre_q_size, post_q_size; + struct xlat16_table xt; + struct quirk_replace_list *pre_q_list, *post_q_list; + iconv_t cd; + void *p; + + xt.data = NULL; + xt.size = 0; + + src[2] = NULL; + dst[3] = NULL; + + ret = my_iconv_init(); + if (ret) + return (xt); + + cd = my_iconv_open(search_quirk(tocode, fromcode, &pre_q_list, &pre_q_size), + search_quirk(fromcode, tocode, &post_q_list, &post_q_size)); + if (cd == (iconv_t) (-1)) + return (xt); + + if ((xt.data = malloc(0x200 * 0x80 * sizeof(uint32_t))) == NULL) + return (xt); + + p = xt.data; + + for (ls = 0 ; ls < 0x200 ; ls++) { + xt.idx[ls] = NULL; + for (us = 0 ; us < 0x80 ; us++) { + srcp = src; + dstp = dst; + + inbytesleft = 2; + outbytesleft = 3; + bzero(dst, outbytesleft); + + c = ((ls & 0x100 ? us | 0x80 : us) << 8) | (u_char)ls; + c = quirk_vendor2unix(c, pre_q_list, pre_q_size); + src[0] = (u_char)(c >> 8); + src[1] = (u_char)c; + + ret = my_iconv_char(cd, (const u_char **)&srcp, + &inbytesleft, &dstp, &outbytesleft); + if (ret == -1) { + table[us] = 0; + continue; + } + + ud = (u_char)dst[0]; + ld = (u_char)dst[1]; + + switch(outbytesleft) { + case 0: +#ifdef XLAT16_ACCEPT_3BYTE_CHR + table[us] = (ud << 8) | ld; + table[us] |= (u_char)dst[2] << 16; + table[us] |= XLAT16_IS_3BYTE_CHR; +#else + table[us] = 0; + continue; +#endif + break; + case 1: + table[us] = quirk_unix2vendor((ud << 8) | ld, + post_q_list, post_q_size); + if ((table[us] >> 8) == 0) + table[us] |= XLAT16_ACCEPT_NULL_OUT; + break; + case 2: + table[us] = ud; + if (lcase & KICONV_LOWER && ud != tolower(ud)) { + table[us] |= (u_char)tolower(ud) << 16; + table[us] |= XLAT16_HAS_LOWER_CASE; + } + if (lcase & KICONV_UPPER && ud != toupper(ud)) { + table[us] |= (u_char)toupper(ud) << 16; + table[us] |= XLAT16_HAS_UPPER_CASE; + } + break; + } + + switch(inbytesleft) { + case 0: + if ((ls & 0xff) == 0) + table[us] |= XLAT16_ACCEPT_NULL_IN; + break; + case 1: + c = ls > 0xff ? us | 0x80 : us; + if (lcase & KICONV_FROM_LOWER && c != tolower(c)) { + table[us] |= (u_char)tolower(c) << 16; + table[us] |= XLAT16_HAS_FROM_LOWER_CASE; + } + if (lcase & KICONV_FROM_UPPER && c != toupper(c)) { + table[us] |= (u_char)toupper(c) << 16; + table[us] |= XLAT16_HAS_FROM_UPPER_CASE; + } + break; + } + + if (table[us] == 0) + continue; + + /* + * store not NULL + */ + xt.idx[ls] = table; + } + if (xt.idx[ls]) { + memcpy(p, table, sizeof(table)); + p += sizeof(table); + } + } + my_iconv_close(cd); + + xt.size = p - xt.data; + xt.data = realloc(xt.data, xt.size); + return (xt); +} + +static int +my_iconv_init(void) +{ + void *iconv_lib; + + iconv_lib = dlopen("libiconv.so", RTLD_LAZY | RTLD_GLOBAL); + if (iconv_lib == NULL) { + warn("Unable to load iconv library: %s\n", dlerror()); + errno = ENOENT; + return (-1); + } + my_iconv_open = dlsym(iconv_lib, "iconv_open"); + my_iconv = dlsym(iconv_lib, "iconv"); + my_iconv_close = dlsym(iconv_lib, "iconv_close"); + + return (0); +} + +static size_t +my_iconv_char(iconv_t cd, const u_char **ibuf, size_t * ilen, u_char **obuf, + size_t * olen) +{ + const u_char *sp; + u_char *dp, ilocal[3], olocal[3]; + u_char c1, c2; + int ret; + size_t ir, or; + + sp = *ibuf; + dp = *obuf; + ir = *ilen; + + bzero(*obuf, *olen); + ret = my_iconv(cd, (const char **)&sp, ilen, (char **)&dp, olen); + c1 = (*obuf)[0]; + c2 = (*obuf)[1]; + + if (ret == -1) { + if (*ilen == ir - 1 && (*ibuf)[1] == '\0' && (c1 || c2)) + return (0); + else + return (-1); + } + + /* + * We must judge if inbuf is a single byte char or double byte char. + * Here, to judge, try first byte(*sp) conversion and compare. + */ + ir = 1; + or = 3; + + bzero(olocal, or); + memcpy(ilocal, *ibuf, sizeof(ilocal)); + sp = ilocal; + dp = olocal; + + if ((my_iconv(cd,(const char **)&sp, &ir, (char **)&dp, &or)) != -1) { + if (olocal[0] != c1) + return (ret); + + if (olocal[1] == c2 && (*ibuf)[1] == '\0') { + /* + * inbuf is a single byte char + */ + *ilen = 1; + *olen = or; + return (ret); + } + + switch(or) { + case 0: + case 1: + if (olocal[1] == c2) { + /* + * inbuf is a single byte char, + * so return false here. + */ + return (-1); + } else { + /* + * inbuf is a double byte char + */ + return (ret); + } + break; + case 2: + /* + * should compare second byte of inbuf + */ + break; + } + } else { + /* + * inbuf clould not be splitted, so inbuf is + * a double byte char. + */ + return (ret); + } + + /* + * try second byte(*(sp+1)) conversion, and compare + */ + ir = 1; + or = 3; + + bzero(olocal, or); + + sp = ilocal + 1; + dp = olocal; + + if ((my_iconv(cd,(const char **)&sp, &ir, (char **)&dp, &or)) != -1) { + if (olocal[0] == c2) + /* + * inbuf is a single byte char + */ + return (-1); + } + + return (ret); +} + +#else /* statically linked */ + +#include + +int +kiconv_add_xlat16_cspair(const char *tocode, const char *fromcode, int flag) +{ + errno = EINVAL; + return (-1); +} + +#endif /* PIC */ Index: lib/libkiconv/xlat16_sysctl.c =================================================================== RCS file: lib/libkiconv/xlat16_sysctl.c diff -N lib/libkiconv/xlat16_sysctl.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libkiconv/xlat16_sysctl.c 10 Sep 2003 17:02:02 -0000 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2000-2001, Boris Popov + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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$ + */ + +/* + * kiconv(3) requires shared linked, and reduce module size + * when statically linked. + */ + +#ifdef PIC + +#include +#include +#include + +#include +#include + +int +kiconv_add_xlat16_table(const char *to, const char *from, const void *data, int datalen) +{ + struct iconv_add_in din; + struct iconv_add_out dout; + size_t olen; + + if (strlen(from) > ICONV_CSNMAXLEN || strlen(to) > ICONV_CSNMAXLEN) + return (EINVAL); + din.ia_version = ICONV_ADD_VER; + strcpy(din.ia_converter, "xlat16"); + strcpy(din.ia_from, from); + strcpy(din.ia_to, to); + din.ia_data = data; + din.ia_datalen = datalen; + olen = sizeof(dout); + if (sysctlbyname("kern.iconv.add", &dout, &olen, &din, sizeof(din)) == -1) + return (errno); + return (0); +} + +#else /* statically linked */ + +#include + +int +kiconv_add_xlat16_table(const char *to, const char *from, const void *data, int datalen) +{ + return (EINVAL); +} + +#endif /* PIC */ Index: release/i386/fixit_crunch.conf =================================================================== RCS file: /home/ncvs/src/release/i386/fixit_crunch.conf,v retrieving revision 1.10 diff -u -r1.10 fixit_crunch.conf --- release/i386/fixit_crunch.conf 17 May 2003 19:16:28 -0000 1.10 +++ release/i386/fixit_crunch.conf 9 Sep 2003 15:47:38 -0000 @@ -22,4 +22,4 @@ progs chown chroot ln chown chgrp -libs -ledit -lgeom -lkvm -lm -lncurses -lutil +libs -ledit -lgeom -lkvm -lm -lncurses -lutil -lkiconv Index: release/ia64/boot_crunch.conf =================================================================== RCS file: /home/ncvs/src/release/ia64/boot_crunch.conf,v retrieving revision 1.4 diff -u -r1.4 boot_crunch.conf --- release/ia64/boot_crunch.conf 23 Jan 2003 08:30:47 -0000 1.4 +++ release/ia64/boot_crunch.conf 9 Sep 2003 15:47:41 -0000 @@ -26,4 +26,4 @@ progs sysinstall libs -ll -ledit -lutil -lkvm -lmd -lcrypt -lftpio -lz -lnetgraph -libs -ldialog -lncurses -ldisk -lufs +libs -ldialog -lncurses -ldisk -lufs -lkiconv Index: release/pc98/fixit-small_crunch.conf =================================================================== RCS file: /home/ncvs/src/release/pc98/fixit-small_crunch.conf,v retrieving revision 1.3 diff -u -r1.3 fixit-small_crunch.conf --- release/pc98/fixit-small_crunch.conf 17 May 2003 19:16:28 -0000 1.3 +++ release/pc98/fixit-small_crunch.conf 9 Sep 2003 15:47:45 -0000 @@ -23,4 +23,4 @@ progs chown chroot ln chown chgrp -libs -ledit -lgeom -lkvm -lm -lncurses -lutil +libs -ledit -lgeom -lkvm -lm -lncurses -lutil -lkiconv Index: release/pc98/fixit_crunch.conf =================================================================== RCS file: /home/ncvs/src/release/pc98/fixit_crunch.conf,v retrieving revision 1.10 diff -u -r1.10 fixit_crunch.conf --- release/pc98/fixit_crunch.conf 17 May 2003 19:16:28 -0000 1.10 +++ release/pc98/fixit_crunch.conf 9 Sep 2003 15:47:53 -0000 @@ -24,4 +24,4 @@ progs chown chroot ln chown chgrp -libs -ledit -lgeom -lkvm -lm -lncurses -lutil +libs -ledit -lgeom -lkvm -lm -lncurses -lutil -lkiconv Index: sbin/mount_cd9660/Makefile =================================================================== RCS file: /home/ncvs/src/sbin/mount_cd9660/Makefile,v retrieving revision 1.7 diff -u -r1.7 Makefile --- sbin/mount_cd9660/Makefile 4 Dec 2001 02:19:50 -0000 1.7 +++ sbin/mount_cd9660/Makefile 20 Jul 2003 18:36:06 -0000 @@ -4,10 +4,16 @@ PROG= mount_cd9660 SRCS= mount_cd9660.c getmntopts.c MAN= mount_cd9660.8 +DPADD= ${LIBKICONV} +LDADD= -lkiconv MOUNT= ${.CURDIR}/../mount CFLAGS+= -I${MOUNT} WARNS= 0 + +# Needs to be dynamically linked for optional dlopen() access to +# userland libiconv +NOSHARED?= NO .PATH: ${MOUNT} Index: sbin/mount_cd9660/mount_cd9660.8 =================================================================== RCS file: /home/ncvs/src/sbin/mount_cd9660/mount_cd9660.8,v retrieving revision 1.21 diff -u -r1.21 mount_cd9660.8 --- sbin/mount_cd9660/mount_cd9660.8 21 Aug 2002 18:10:55 -0000 1.21 +++ sbin/mount_cd9660/mount_cd9660.8 10 Sep 2003 17:02:02 -0000 @@ -47,6 +47,7 @@ .Op Fl begjrv .Op Fl o Ar options .Op Fl s Ar startsector +.Op Fl C Ar charset .Ar special | node .Sh DESCRIPTION The @@ -123,6 +124,10 @@ the correct .Ar startsector here. +.It Fl C Ar charset +Specify local +.Ar charset +to convert Unicode file names when using Joliet extensions. .It Fl v Be verbose about the starting sector decisions made. .El @@ -150,3 +155,7 @@ .Nm utility first appeared in .Bx 4.4 . +.Pp +The unicode conversion routine was added by +.An Ryuichiro Imura Aq imura@ryu16.org +at 2003. Index: sbin/mount_cd9660/mount_cd9660.c =================================================================== RCS file: /home/ncvs/src/sbin/mount_cd9660/mount_cd9660.c,v retrieving revision 1.21 diff -u -r1.21 mount_cd9660.c --- sbin/mount_cd9660/mount_cd9660.c 21 Aug 2002 18:10:55 -0000 1.21 +++ sbin/mount_cd9660/mount_cd9660.c 10 Sep 2003 17:02:02 -0000 @@ -57,6 +57,8 @@ #include #include #include +#include +#include #include @@ -82,6 +84,7 @@ }; int get_ssector(const char *dev); +int set_charset(struct iso_args *, const char *); void usage(void); int @@ -95,7 +98,9 @@ mntflags = opts = verbose = 0; memset(&args, 0, sizeof args); args.ssector = -1; - while ((ch = getopt(argc, argv, "begjo:rs:v")) != -1) + args.cs_disk = NULL; + args.cs_local = NULL; + while ((ch = getopt(argc, argv, "begjo:rs:vC:")) != -1) switch (ch) { case 'b': opts |= ISOFSMNT_BROKENJOLIET; @@ -121,6 +126,11 @@ case 'v': verbose++; break; + case 'C': + if (set_charset(&args, optarg) == -1) + err(EX_OSERR, "cd9660_iconv"); + opts |= ISOFSMNT_KICONV; + break; case '?': default: usage(); @@ -180,7 +190,7 @@ usage(void) { (void)fprintf(stderr, - "usage: mount_cd9660 [-egrv] [-o options] [-s startsector] special node\n"); + "usage: mount_cd9660 [-egrv] [-o options] [-s startsector] [-C charset ] special node\n"); exit(EX_USAGE); } @@ -224,4 +234,32 @@ return -1; return ntohl(toc_buffer[i].addr.lba); +} + +int +set_charset(struct iso_args *args, const char *localcs) +{ + int error; + + if (modfind("cd9660_iconv") < 0) + if (kldload("cd9660_iconv") < 0 || modfind("cd9660_iconv") < 0) { + warnx( "cannot find or load \"cd9660_iconv\" kernel module"); + return (-1); + } + + if ((args->cs_disk = malloc(ICONV_CSNMAXLEN)) == NULL) + return (-1); + if ((args->cs_local = malloc(ICONV_CSNMAXLEN)) == NULL) + return (-1); + strncpy(args->cs_disk, ENCODING_UNICODE, ICONV_CSNMAXLEN); + strncpy(args->cs_local, kiconv_quirkcs(localcs, KICONV_VENDOR_MICSFT), + ICONV_CSNMAXLEN); + error = kiconv_add_xlat16_cspair(args->cs_local, args->cs_disk, 0); + if (error) + return (-1); + error = kiconv_add_xlat16_cspair(args->cs_disk, args->cs_local, 0); + if (error) + return (-1); + + return (0); } Index: sbin/mount_msdosfs/Makefile =================================================================== RCS file: /home/ncvs/src/sbin/mount_msdosfs/Makefile,v retrieving revision 1.23 diff -u -r1.23 Makefile --- sbin/mount_msdosfs/Makefile 29 Jul 2002 09:40:11 -0000 1.23 +++ sbin/mount_msdosfs/Makefile 20 Jul 2003 18:36:46 -0000 @@ -5,21 +5,17 @@ PROG= mount_msdosfs SRCS= mount_msdosfs.c getmntopts.c MAN= mount_msdosfs.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +DPADD= ${LIBKICONV} +LDADD= -lkiconv MOUNT= ${.CURDIR}/../mount CFLAGS+= -I${MOUNT} WARNS= 0 -.PATH: ${MOUNT} - -TABDIR= ${DESTDIR}${LIBDATADIR}/msdosfs -TABLES= iso22dos iso72dos koi2dos koi8u2dos +# Needs to be dynamically linked for optional dlopen() access to +# userland libiconv +NOSHARED?= NO -afterinstall: - cd ${.CURDIR} && \ - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${SHAREMODE} \ - ${TABLES} ${TABDIR} +.PATH: ${MOUNT} .include Index: sbin/mount_msdosfs/iso22dos =================================================================== RCS file: sbin/mount_msdosfs/iso22dos diff -N sbin/mount_msdosfs/iso22dos --- sbin/mount_msdosfs/iso22dos 8 Jan 2000 17:17:32 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,58 +0,0 @@ -# $FreeBSD: src/sbin/mount_msdosfs/iso22dos,v 1.1 2000/01/08 17:17:32 ache Exp $ -# -# u2w: 16 rows of Latin2 -> Unicode conversion table (upper half) -# -0x0080 0x0081 0x0082 0x0083 0x0084 0x0085 0x0086 0x0087 -0x0088 0x0089 0x008a 0x008b 0x008c 0x008d 0x008e 0x008f -0x0090 0x0091 0x0092 0x0093 0x0094 0x0095 0x0096 0x0097 -0x0098 0x0099 0x009a 0x009b 0x009c 0x009d 0x009e 0x009f -0x00a0 0x0104 0x02d8 0x0141 0x00a4 0x013d 0x015a 0x00a7 -0x00a8 0x0160 0x015e 0x0164 0x0179 0x00ad 0x017d 0x017b -0x00b0 0x0105 0x02db 0x0142 0x00b4 0x013e 0x015b 0x02c7 -0x00b8 0x0161 0x015f 0x0165 0x017a 0x02dd 0x017e 0x017c -0x0154 0x00c1 0x00c2 0x0102 0x00c4 0x0139 0x0106 0x00c7 -0x010c 0x00c9 0x0118 0x00cb 0x011a 0x00cd 0x00ce 0x010e -0x0110 0x0143 0x0147 0x00d3 0x00d4 0x0150 0x00d6 0x00d7 -0x0158 0x016e 0x00da 0x0170 0x00dc 0x00dd 0x0162 0x00df -0x0155 0x00e1 0x00e2 0x0103 0x00e4 0x013a 0x0107 0x00e7 -0x010d 0x00e9 0x0119 0x00eb 0x011b 0x00ed 0x00ee 0x010f -0x0111 0x0144 0x0148 0x00f3 0x00f4 0x0151 0x00f6 0x00f7 -0x0159 0x016f 0x00fa 0x0171 0x00fc 0x00fd 0x0163 0x02d9 -# -# d2u: 16 rows of CP852 -> Latin2 conversion table (upper half) -# -0xc7 0xfc 0xe9 0xe2 0xe4 0xf9 0xe6 0xe7 -0xb3 0xeb 0xd5 0xf5 0xee 0xac 0xc4 0xc6 -0xc9 0xc5 0xe5 0xf4 0xf6 0xa5 0xb5 0xa6 -0xb6 0xd6 0xdc 0xab 0xbb 0xa3 0xd7 0xe8 -0xe1 0xed 0xf3 0xfa 0xa1 0xb1 0xae 0xbe -0xca 0xea 0x3f 0xbc 0xc8 0xba 0x3f 0x3f -0x3f 0x3f 0x3f 0x3f 0x3f 0xc1 0xc2 0xcc -0xaa 0x3f 0x3f 0x3f 0x3f 0xaf 0xbf 0x3f -0x3f 0x3f 0x3f 0x3f 0x3f 0x3f 0xc3 0xe3 -0x3f 0x3f 0x3f 0x3f 0x3f 0x3f 0x3f 0xa4 -0xf0 0xd0 0xcf 0xcb 0xef 0xd2 0xcd 0xce -0xec 0x3f 0x3f 0x3f 0x3f 0xde 0xd9 0x3f -0xd3 0xdf 0xd4 0xd1 0xf1 0xf2 0xa9 0xb9 -0xc0 0xda 0xe0 0xdb 0xfd 0xdd 0xfe 0xb4 -0xad 0xbd 0xb2 0xb7 0xa2 0xa7 0xf7 0xb8 -0xb0 0xa8 0xff 0xfb 0xd8 0xf8 0x3f 0xa0 -# -# u2d: 16 rows of Latin2 -> CP852 conversion table (upper half) -# -0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 -0xff 0xa4 0xf4 0x9d 0xcf 0x95 0x97 0xf5 -0xf9 0xe6 0xb8 0x9b 0x8d 0xf0 0xa6 0xbd -0xf8 0xa5 0xf2 0x88 0xef 0x96 0x98 0xf3 -0xf7 0xe7 0xad 0x9c 0xab 0xf1 0xa7 0xbe -0xe8 0xb5 0xb6 0xc6 0x8e 0x91 0x8f 0x80 -0xac 0x90 0xa8 0xd3 0xb7 0xd6 0xd7 0xd2 -0xd1 0xe3 0xd5 0xe0 0xe2 0x8a 0x99 0x9e -0xfc 0xde 0xe9 0xeb 0x9a 0xed 0xdd 0xe1 -0xea 0xa0 0x83 0xc7 0x84 0x92 0x86 0x87 -0x9f 0x82 0xa9 0x89 0xd8 0xa1 0x8c 0xd4 -0xd0 0xe4 0xe5 0xa2 0x93 0x8b 0x94 0xf6 -0xfd 0x85 0xa3 0xfb 0x81 0xec 0xee 0xfa Index: sbin/mount_msdosfs/iso72dos =================================================================== RCS file: sbin/mount_msdosfs/iso72dos diff -N sbin/mount_msdosfs/iso72dos --- sbin/mount_msdosfs/iso72dos 23 Nov 2001 22:27:03 -0000 1.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,60 +0,0 @@ -# $FreeBSD: src/sbin/mount_msdosfs/iso72dos,v 1.2 2001/11/23 22:27:03 ache Exp $ -# -# usr/libdata/msdosfs/iso72dos -# -# u2w: 16 rows of Latin7 -> Unicode conversion table (upper half) -# -0x0080 0x0081 0x0082 0x0083 0x0084 0x0085 0x0086 0x0087 -0x0088 0x0089 0x008a 0x008b 0x008c 0x008d 0x008e 0x008f -0x0090 0x0091 0x0092 0x0093 0x0094 0x0095 0x0096 0x0097 -0x0098 0x0099 0x009a 0x009b 0x009c 0x009d 0x009e 0x009f -0x00a0 0x201b 0x2019 0x00a3 0x003f 0x003f 0x00a6 0x00a7 -0x00a8 0x00a9 0x003f 0x00ab 0x00ac 0x00ad 0x003f 0x2015 -0x00b0 0x00b1 0x00b2 0x00b3 0x00b4 0x0385 0x0386 0x00b7 -0x0388 0x0389 0x038a 0x00bb 0x038c 0x00bd 0x038e 0x038f -0x0390 0x0391 0x0392 0x0393 0x0394 0x0395 0x0396 0x0397 -0x0398 0x0399 0x039a 0x039b 0x039c 0x039d 0x039e 0x039f -0x03a0 0x03a1 0x003f 0x03a3 0x03a4 0x03a5 0x03a6 0x03a7 -0x03a8 0x03a9 0x03aa 0x03ab 0x03ac 0x03ad 0x03ae 0x03af -0x03b0 0x03b1 0x03b2 0x03b3 0x03b4 0x03b5 0x03b6 0x03b7 -0x03b8 0x03b9 0x03ba 0x03bb 0x03bc 0x03bd 0x03be 0x03bf -0x03c0 0x03c1 0x03c2 0x03c3 0x03c4 0x03c5 0x03c6 0x03c7 -0x03c8 0x03c9 0x03ca 0x03cb 0x03cc 0x03cd 0x03ce 0x003f -# -# d2u: 16 rows of CP737 -> Latin7 conversion table (upper half) -# -0xc1 0xc2 0xc3 0xc4 0xc5 0xc6 0xc7 0xc8 -0xc9 0xca 0xcb 0xcc 0xcd 0xce 0xcf 0xd0 -0xd1 0xd3 0xd4 0xd5 0xd6 0xd7 0xd8 0xd9 -0xe1 0xe2 0xe3 0xe4 0xe5 0xe6 0xe7 0xe8 -0xe9 0xea 0xeb 0xec 0xed 0xee 0xef 0xf0 -0xf1 0xf3 0xf2 0xf4 0xf5 0xf6 0xf7 0xf8 -0x3f 0x3f 0x3f 0x3f 0x3f 0x3f 0x3f 0x3f -0x3f 0x3f 0x3f 0x3f 0x3f 0x3f 0x3f 0x3f -0x3f 0x3f 0x3f 0x3f 0x3f 0x3f 0x3f 0x3f -0x3f 0x3f 0x3f 0x3f 0x3f 0x3f 0x3f 0x3f -0x3f 0x3f 0x3f 0x3f 0x3f 0x3f 0x3f 0x3f -0x3f 0x3f 0x3f 0x3f 0x3f 0x3f 0x3f 0x3f -0xf9 0xdc 0xdd 0xde 0xfa 0xdf 0xfc 0xfd -0xfb 0xfe 0xb6 0xb8 0xb9 0xba 0xbc 0xbe -0xbf 0xb1 0x3f 0x3f 0xda 0xdb 0x3f 0x3f -0xb0 0x3f 0xb7 0x3f 0x3f 0xb2 0x3f 0xa0 -# -# u2d: 16 rows of Latin7 -> CP737 conversion table (upper half) -# -0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 -0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 -0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 -0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 -0xff 0x00 0x00 0x00 0x00 0x00 0x00 0x00 -0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 -0xf8 0xf1 0xfd 0x00 0x00 0x00 0xea 0xfa -0xeb 0xec 0xed 0x00 0xee 0x00 0xef 0xf0 -0x00 0x80 0x81 0x82 0x83 0x84 0x85 0x86 -0x87 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e -0x8f 0x90 0x00 0x91 0x92 0x93 0x94 0x95 -0x96 0x97 0xf4 0xf5 0xe1 0xe2 0xe3 0xe5 -0x00 0x98 0x99 0x9a 0x9b 0x9c 0x9d 0x9e -0x9f 0xa0 0xa1 0xa2 0xa3 0xa4 0xa5 0xa6 -0xa7 0xa8 0xaa 0xa9 0xab 0xac 0xad 0xae -0xaf 0xe0 0xe4 0xe8 0xe6 0xe7 0xe9 0x00 Index: sbin/mount_msdosfs/koi2dos =================================================================== RCS file: sbin/mount_msdosfs/koi2dos diff -N sbin/mount_msdosfs/koi2dos --- sbin/mount_msdosfs/koi2dos 8 Jan 2000 16:47:54 -0000 1.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,58 +0,0 @@ -# $FreeBSD: src/sbin/mount_msdosfs/koi2dos,v 1.2 2000/01/08 16:47:54 ache Exp $ -# -# u2w: 16 rows of KOI8-R -> Unicode conversion table (upper half) -# -0x2500 0x2502 0x250c 0x2510 0x2514 0x2518 0x251c 0x2524 -0x252c 0x2534 0x253c 0x2580 0x2584 0x2588 0x258c 0x2590 -0x2591 0x2592 0x2593 0x2320 0x25a0 0x2219 0x221a 0x2248 -0x2264 0x2265 0x00a0 0x2321 0x00b0 0x00b2 0x00b7 0x00f7 -0x2550 0x2551 0x2552 0x0451 0x2553 0x2554 0x2555 0x2556 -0x2557 0x2558 0x2559 0x255a 0x255b 0x255c 0x255d 0x255e -0x255f 0x2560 0x2561 0x0401 0x2562 0x2563 0x2564 0x2565 -0x2566 0x2567 0x2568 0x2569 0x256a 0x256b 0x256c 0x00a9 -0x044e 0x0430 0x0431 0x0446 0x0434 0x0435 0x0444 0x0433 -0x0445 0x0438 0x0439 0x043a 0x043b 0x043c 0x043d 0x043e -0x043f 0x044f 0x0440 0x0441 0x0442 0x0443 0x0436 0x0432 -0x044c 0x044b 0x0437 0x0448 0x044d 0x0449 0x0447 0x044a -0x042e 0x0410 0x0411 0x0426 0x0414 0x0415 0x0424 0x0413 -0x0425 0x0418 0x0419 0x041a 0x041b 0x041c 0x041d 0x041e -0x041f 0x042f 0x0420 0x0421 0x0422 0x0423 0x0416 0x0412 -0x042c 0x042b 0x0417 0x0428 0x042d 0x0429 0x0427 0x042a -# -# d2u: 16 rows of CP866 -> KOI8-R conversion table (upper half) -# -0xe1 0xe2 0xf7 0xe7 0xe4 0xe5 0xf6 0xfa -0xe9 0xea 0xeb 0xec 0xed 0xee 0xef 0xf0 -0xf2 0xf3 0xf4 0xf5 0xe6 0xe8 0xe3 0xfe -0xfb 0xfd 0xff 0xf9 0xf8 0xfc 0xe0 0xf1 -0xc1 0xc2 0xd7 0xc7 0xc4 0xc5 0xd6 0xda -0xc9 0xca 0xcb 0xcc 0xcd 0xce 0xcf 0xd0 -0x90 0x91 0x92 0x81 0x87 0xb2 0xb4 0xa7 -0xa6 0xb5 0xa1 0xa8 0xae 0xad 0xac 0x83 -0x84 0x89 0x88 0x86 0x80 0x8a 0xaf 0xb0 -0xab 0xa5 0xbb 0xb8 0xb1 0xa0 0xbe 0xb9 -0xba 0xb6 0xb7 0xaa 0xa9 0xa2 0xa4 0xbd -0xbc 0x85 0x82 0x8d 0x8c 0x8e 0x8f 0x8b -0xd2 0xd3 0xd4 0xd5 0xc6 0xc8 0xc3 0xde -0xdb 0xdd 0xdf 0xd9 0xd8 0xdc 0xc0 0xd1 -0xb3 0xa3 229 197 73 105 245 213 -0x9c 0x95 0x9e 0x96 78 210 0x94 0x9a -# -# u2d: 16 rows of KOI8-R -> CP866 conversion table (upper half) -# -0xc4 0xb3 0xda 0xbf 0xc0 0xd9 0xc3 0xb4 -0xc2 0xc1 0xc5 0xdf 0xdc 0xdb 0xdd 0xde -0xb0 0xb1 0xb2 179 0xfe 0xf9 0xfb 61 - 60 62 0xff 179 0xf8 50 0xfa 58 -0xcd 0xba 0xd5 0xf1 0xd6 0xc9 0xb8 0xb7 -0xbb 0xd4 0xd3 0xc8 0xbe 0xbd 0xbc 0xc6 -0xc7 0xcc 0xb5 0xf0 0xb6 0xb9 0xd1 0xd2 -0xcb 0xcf 0xd0 0xca 0xd8 0xd7 0xce 99 -0xee 0xa0 0xa1 0xe6 0xa4 0xa5 0xe4 0xa3 -0xe5 0xa8 0xa9 0xaa 0xab 0xac 0xad 0xae -0xaf 0xef 0xe0 0xe1 0xe2 0xe3 0xa6 0xa2 -0xec 0xeb 0xa7 0xe8 0xed 0xe9 0xe7 0xea -0x9e 0x80 0x81 0x96 0x84 0x85 0x94 0x83 -0x95 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e -0x8f 0x9f 0x90 0x91 0x92 0x93 0x86 0x82 -0x9c 0x9b 0x87 0x98 0x9d 0x99 0x97 0x9a Index: sbin/mount_msdosfs/koi8u2dos =================================================================== RCS file: sbin/mount_msdosfs/koi8u2dos diff -N sbin/mount_msdosfs/koi8u2dos --- sbin/mount_msdosfs/koi8u2dos 28 Jul 2001 20:50:21 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,60 +0,0 @@ -# $FreeBSD: src/sbin/mount_msdosfs/koi8u2dos,v 1.1 2001/07/28 20:50:21 ache Exp $ -# -# Translation table for ukrainian filenames support by -# -# u2w: 16 rows of KOI8-U -> Unicode conversion table (upper half) -# -0x2500 0x2502 0x250c 0x2510 0x2514 0x2518 0x251c 0x2524 -0x252c 0x2534 0x253c 0x2580 0x2584 0x2588 0x258c 0x2590 -0x2591 0x2592 0x2593 0x2320 0x25a0 0x2219 0x221a 0x2248 -0x2264 0x2265 0x00a0 0x2321 0x00b0 0x00b2 0x00b7 0x00f7 -0x2550 0x2551 0x2552 0x0451 0x0454 0x2554 0x0456 0x0457 -0x2557 0x2558 0x2559 0x255a 0x255b 0x0491 0x255d 0x255e -0x255f 0x2560 0x2561 0x0401 0x0404 0x2563 0x0406 0x0407 -0x2566 0x2567 0x2568 0x2569 0x256a 0x0490 0x256c 0x00a9 -0x044e 0x0430 0x0431 0x0446 0x0434 0x0435 0x0444 0x0433 -0x0445 0x0438 0x0439 0x043a 0x043b 0x043c 0x043d 0x043e -0x043f 0x044f 0x0440 0x0441 0x0442 0x0443 0x0436 0x0432 -0x044c 0x044b 0x0437 0x0448 0x044d 0x0449 0x0447 0x044a -0x042e 0x0410 0x0411 0x0426 0x0414 0x0415 0x0424 0x0413 -0x0425 0x0418 0x0419 0x041a 0x041b 0x041c 0x041d 0x041e -0x041f 0x042f 0x0420 0x0421 0x0422 0x0423 0x0416 0x0412 -0x042c 0x042b 0x0417 0x0428 0x042d 0x0429 0x0427 0x042a -# -# d2u: 16 rows of CP866 -> KOI8-U conversion table (upper half) -# -0xe1 0xe2 0xf7 0xe7 0xe4 0xe5 0xf6 0xfa -0xe9 0xea 0xeb 0xec 0xed 0xee 0xef 0xf0 -0xf2 0xf3 0xf4 0xf5 0xe6 0xe8 0xe3 0xfe -0xfb 0xfd 0xff 0xf9 0xf8 0xfc 0xe0 0xf1 -0xc1 0xc2 0xd7 0xc7 0xc4 0xc5 0xd6 0xda -0xc9 0xca 0xcb 0xcc 0xcd 0xce 0xcf 0xd0 -0x90 0x91 0x92 0x81 0x87 0xb2 0xb4 0xa7 -0xa6 0xb5 0xa1 0xa8 0xae 0xad 0xac 0x83 -0x84 0x89 0x88 0x86 0x80 0x8a 0xaf 0xb0 -0xab 0xa5 0xbb 0xb8 0xb1 0xa0 0xbe 0xb9 -0xba 0xb6 0xb7 0xaa 0xa9 0xa2 0xa4 0xbd -0xbc 0x85 0x82 0x8d 0x8c 0x8e 0x8f 0x8b -0xd2 0xd3 0xd4 0xd5 0xc6 0xc8 0xc3 0xde -0xdb 0xdd 0xdf 0xd9 0xd8 0xdc 0xc0 0xd1 -0xb3 0xa3 0xb4 0xa4 0xb7 0xa7 245 213 -0x9c 0x95 0x9e 0x96 78 210 0x94 0x9a -# -# u2d: 16 rows of KOI8-U -> CP866 conversion table (upper half) -# -0xc4 0xb3 0xda 0xbf 0xc0 0xd9 0xc3 0xb4 -0xc2 0xc1 0xc5 0xdf 0xdc 0xdb 0xdd 0xde -0xb0 0xb1 0xb2 179 0xfe 0xf9 0xfb 61 - 60 62 0xff 179 0xf8 50 0xfa 58 -0xcd 0xba 0xd5 0xf1 0xf3 0xc9 0x01 0xf5 -0xbb 0xd4 0xd3 0xc8 0xbe 0x01 0xbc 0xc6 -0xc7 0xcc 0xb5 0xf0 0xf2 0xb9 0x01 0xf4 -0xcb 0xcf 0xd0 0xca 0xd8 0x01 0xce 99 -0xee 0xa0 0xa1 0xe6 0xa4 0xa5 0xe4 0xa3 -0xe5 0xa8 0xa9 0xaa 0xab 0xac 0xad 0xae -0xaf 0xef 0xe0 0xe1 0xe2 0xe3 0xa6 0xa2 -0xec 0xeb 0xa7 0xe8 0xed 0xe9 0xe7 0xea -0x9e 0x80 0x81 0x96 0x84 0x85 0x94 0x83 -0x95 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e -0x8f 0x9f 0x90 0x91 0x92 0x93 0x86 0x82 -0x9c 0x9b 0x87 0x98 0x9d 0x99 0x97 0x9a Index: sbin/mount_msdosfs/mount_msdosfs.8 =================================================================== RCS file: /home/ncvs/src/sbin/mount_msdosfs/mount_msdosfs.8,v retrieving revision 1.24 diff -u -r1.24 mount_msdosfs.8 --- sbin/mount_msdosfs/mount_msdosfs.8 21 Aug 2002 18:11:00 -0000 1.24 +++ sbin/mount_msdosfs/mount_msdosfs.8 10 Sep 2003 17:02:02 -0000 @@ -47,6 +47,7 @@ .Op Fl 9 .\".Op Fl G .Op Fl L Ar locale +.Op Fl D Ar dos-codepage .Op Fl W Ar table .Pa special .Pa node @@ -143,50 +144,38 @@ .\"limited to the boot block. This option enforces .\".Fl s . .It Fl L Ar locale -Specify locale name used for internal uppercase and lowercase conversions +Specify locale name used for file name conversions for DOS and Win'95 names. By default ISO 8859-1 assumed as local character set. +.It Fl D Ar dos-codepage +Specify the MS-DOS code page (aka IBM/OEM code page) name used for +file name conversions for DOS names. .It Fl W Ar table -Specify text file with 3 conversion tables: -.Bl -enum -.It -Local character set to Unicode conversion table (upper half) for Win'95 long -names, 128 Unicode codes separated by 8 per row. -If some code not present in Unicode, use -0x003F code ('?') as replacement. -.It -DOS to local character set conversion table (upper half) for DOS names, -128 character codes separated by 8 per row. -Code 0x3F ('?') used for impossible translations. -.It -Local character set to DOS conversion table (upper half) for DOS names, -128 character codes separated by 8 per row. -Some codes have special meaning: -.Bl -hang -.It 0x00 -character disallowed in DOS file name; -.It 0x01 -character should be replaced by '_' in DOS file name; -.It 0x02 -character should be skipped in DOS file name; -.El -.El +This option is remained for backward compatibility purpose, and will be +removed in the future. Please do not use this option. .Pp -By default ISO 8859-1 assumed as local character set. -If file path isn't absolute, -.Pa /usr/libdata/msdosfs/ -prefix prepended. +Specify text file name with conversion table: iso22dos, iso72dos, koi2dos, +koi8u2dos. .El -.Sh FILES -.Bl -tag -width /usr/libdata/msdosfs -compact -.It Pa /usr/libdata/msdosfs -default place for character sets conversion tables +.Sh EXAMPLES +To mount a Russian msdos file system located in /dev/ad1s1: +.Bd -literal -offset indent +# mount_msdosfs -L ru_RU.KOI8-R -D CP866 /dev/ad1s1 /mnt +.Ed +.Pp +To mount a Japanese msdos file system located in /dev/ad1s1: +.Bd -literal -offset indent +# mount_msdosfs -L ja_JP.eucJP -D CP932 /dev/ad1s1 /mnt +.Ed .El .Sh SEE ALSO .Xr mount 2 , .Xr unmount 2 , .Xr fstab 5 , .Xr mount 8 +.Pp +List of Localized MS Operating Systems: +.Pa http://www.microsoft.com/globaldev/reference/oslocversion.mspx . .Sh CAVEATS The use of the .Fl 9 @@ -213,3 +202,7 @@ and was abandoned in favor of the more aptly-named .Nm . +.Pp +The character code conversion routine was added by +.An Ryuichiro Imura Aq imura@ryu16.org +at 2003. Index: sbin/mount_msdosfs/mount_msdosfs.c =================================================================== RCS file: /home/ncvs/src/sbin/mount_msdosfs/mount_msdosfs.c,v retrieving revision 1.24 diff -u -r1.24 mount_msdosfs.c --- sbin/mount_msdosfs/mount_msdosfs.c 3 Aug 2002 16:03:19 -0000 1.24 +++ sbin/mount_msdosfs/mount_msdosfs.c 10 Sep 2003 17:02:02 -0000 @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include @@ -56,9 +58,11 @@ #include "mntopts.h" +#define TRANSITION_PERIOD_HACK + /* * XXX - no way to specify "foo="-type options; that's what we'd - * want for "-u", "-g", "-m", "-L", and "-W". + * want for "-u", "-g", "-m", "-L", "-D", and "-W". */ static struct mntopt mopts[] = { MOPT_STDOPTS, @@ -78,8 +82,7 @@ static uid_t a_uid(char *); static mode_t a_mask(char *); static void usage(void) __dead2; -static void load_u2wtable(struct msdosfs_args *, char *); -static void load_ultable(struct msdosfs_args *, char *); +static int set_charset(struct msdosfs_args *); int main(argc, argv) @@ -89,13 +92,20 @@ struct msdosfs_args args; struct stat sb; int c, mntflags, set_gid, set_uid, set_mask; - char *dev, *dir, mntpath[MAXPATHLEN]; + char *dev, *dir, mntpath[MAXPATHLEN], *csp; mntflags = set_gid = set_uid = set_mask = 0; (void)memset(&args, '\0', sizeof(args)); args.magic = MSDOSFS_ARGSMAGIC; - while ((c = getopt(argc, argv, "sl9u:g:m:o:L:W:")) != -1) { + args.cs_win = NULL; + args.cs_dos = NULL; + args.cs_local = NULL; +#ifdef TRANSITION_PERIOD_HACK + while ((c = getopt(argc, argv, "sl9u:g:m:o:L:D:W:")) != -1) { +#else + while ((c = getopt(argc, argv, "sl9u:g:m:o:L:D:")) != -1) { +#endif switch (c) { #ifdef MSDOSFSMNT_GEMDOSFS case 'G': @@ -124,16 +134,52 @@ set_mask = 1; break; case 'L': - load_ultable(&args, optarg); - args.flags |= MSDOSFSMNT_ULTABLE; - break; - case 'W': - load_u2wtable(&args, optarg); - args.flags |= MSDOSFSMNT_U2WTABLE; + if (setlocale(LC_CTYPE, optarg) == NULL) + err(EX_CONFIG, "%s", optarg); + csp = strchr(optarg,'.'); + if (!csp) + err(EX_CONFIG, "%s", optarg); + args.cs_local = malloc(ICONV_CSNMAXLEN); + if (args.cs_local == NULL) + err(EX_OSERR, "malloc()"); + strncpy(args.cs_local, + kiconv_quirkcs(csp + 1, KICONV_VENDOR_MICSFT), + ICONV_CSNMAXLEN); + break; + case 'D': + args.cs_dos = malloc(ICONV_CSNMAXLEN); + if (args.cs_dos == NULL) + err(EX_OSERR, "malloc()"); + strncpy(args.cs_dos, optarg, ICONV_CSNMAXLEN); break; case 'o': getmntopts(optarg, mopts, &mntflags, &args.flags); break; +#ifdef TRANSITION_PERIOD_HACK + case 'W': + args.cs_local = malloc(ICONV_CSNMAXLEN); + if (args.cs_local == NULL) + err(EX_OSERR, "malloc()"); + args.cs_dos = malloc(ICONV_CSNMAXLEN); + if (args.cs_dos == NULL) + err(EX_OSERR, "malloc()"); + if (strcmp(optarg, "iso22dos") == 0) { + strcpy(args.cs_local, "ISO8859-2"); + strcpy(args.cs_dos, "CP852"); + } else if (strcmp(optarg, "iso72dos") == 0) { + strcpy(args.cs_local, "ISO8859-13"); + strcpy(args.cs_dos, "CP737"); + } else if (strcmp(optarg, "koi2dos") == 0) { + strcpy(args.cs_local, "KOI8-R"); + strcpy(args.cs_dos, "CP866"); + } else if (strcmp(optarg, "koi8u2dos") == 0) { + strcpy(args.cs_local, "KOI8-U"); + strcpy(args.cs_dos, "CP866"); + } else { + err(EX_NOINPUT, "%s", optarg); + } + break; +#endif /* TRANSITION_PERIOD_HACK */ case '?': default: usage(); @@ -147,6 +193,19 @@ dev = argv[optind]; dir = argv[optind + 1]; + if (args.cs_local) { + if (set_charset(&args) == -1) + err(EX_OSERR, "msdosfs_iconv"); + args.flags |= MSDOSFSMNT_KICONV; + } else if (args.cs_dos) { + if ((args.cs_local = malloc(ICONV_CSNMAXLEN)) == NULL) + err(EX_OSERR, "malloc()"); + strcpy(args.cs_local, "ISO8859-1"); + if (set_charset(&args) == -1) + err(EX_OSERR, "msdosfs_iconv"); + args.flags |= MSDOSFSMNT_KICONV; + } + /* * Resolve the mountpoint with realpath(3) and remove unnecessary * slashes from the devicename if there are any. @@ -241,88 +300,50 @@ { fprintf(stderr, "%s\n%s\n", "usage: mount_msdosfs [-o options] [-u user] [-g group] [-m mask]", - " [-s] [-l] [-9] [-L locale] [-W table] bdev dir"); +#ifdef TRANSITION_PERIOD_HACK + " [-s] [-l] [-9] [-L locale] [-D dos-codepage] [-W table] bdev dir"); +#else + " [-s] [-l] [-9] [-L locale] [-D dos-codepage] bdev dir"); +#endif exit(EX_USAGE); } -void -load_u2wtable (pargs, name) - struct msdosfs_args *pargs; - char *name; +int +set_charset(struct msdosfs_args *args) { - FILE *f; - int i, j, code[8]; - size_t line = 0; - char buf[128]; - char *fn, *s, *p; + int error; - if (*name == '/') - fn = name; - else { - snprintf(buf, sizeof(buf), "/usr/libdata/msdosfs/%s", name); - buf[127] = '\0'; - fn = buf; - } - if ((f = fopen(fn, "r")) == NULL) - err(EX_NOINPUT, "%s", fn); - p = NULL; - for (i = 0; i < 16; i++) { - do { - if (p != NULL) free(p); - if ((p = s = fparseln(f, NULL, &line, NULL, 0)) == NULL) - errx(EX_DATAERR, "can't read u2w table row %d near line %d", i, line); - while (isspace((unsigned char)*s)) - s++; - } while (*s == '\0'); - if (sscanf(s, "%i%i%i%i%i%i%i%i", -code, code + 1, code + 2, code + 3, code + 4, code + 5, code + 6, code + 7) != 8) - errx(EX_DATAERR, "u2w table: missing item(s) in row %d, line %d", i, line); - for (j = 0; j < 8; j++) - pargs->u2w[i * 8 + j] = code[j]; - } - for (i = 0; i < 16; i++) { - do { - free(p); - if ((p = s = fparseln(f, NULL, &line, NULL, 0)) == NULL) - errx(EX_DATAERR, "can't read d2u table row %d near line %d", i, line); - while (isspace((unsigned char)*s)) - s++; - } while (*s == '\0'); - if (sscanf(s, "%i%i%i%i%i%i%i%i", -code, code + 1, code + 2, code + 3, code + 4, code + 5, code + 6, code + 7) != 8) - errx(EX_DATAERR, "d2u table: missing item(s) in row %d, line %d", i, line); - for (j = 0; j < 8; j++) - pargs->d2u[i * 8 + j] = code[j]; - } - for (i = 0; i < 16; i++) { - do { - free(p); - if ((p = s = fparseln(f, NULL, &line, NULL, 0)) == NULL) - errx(EX_DATAERR, "can't read u2d table row %d near line %d", i, line); - while (isspace((unsigned char)*s)) - s++; - } while (*s == '\0'); - if (sscanf(s, "%i%i%i%i%i%i%i%i", -code, code + 1, code + 2, code + 3, code + 4, code + 5, code + 6, code + 7) != 8) - errx(EX_DATAERR, "u2d table: missing item(s) in row %d, line %d", i, line); - for (j = 0; j < 8; j++) - pargs->u2d[i * 8 + j] = code[j]; - } - free(p); - fclose(f); -} - -void -load_ultable (pargs, name) - struct msdosfs_args *pargs; - char *name; -{ - int i; + if (modfind("msdosfs_iconv") < 0) + if (kldload("msdosfs_iconv") < 0 || modfind("msdosfs_iconv") < 0) { + warnx( "cannot find or load \"msdosfs_iconv\" kernel module"); + return (-1); + } - if (setlocale(LC_CTYPE, name) == NULL) - err(EX_CONFIG, "%s", name); - for (i = 0; i < 128; i++) { - pargs->ul[i] = tolower(i | 0x80); - pargs->lu[i] = toupper(i | 0x80); + if ((args->cs_win = malloc(ICONV_CSNMAXLEN)) == NULL) + return (-1); + strncpy(args->cs_win, ENCODING_UNICODE, ICONV_CSNMAXLEN); + error = kiconv_add_xlat16_cspair(args->cs_win, args->cs_local, 0); + if (error) + return (-1); + error = kiconv_add_xlat16_cspair(args->cs_local, args->cs_win, 0); + if (error) + return (-1); + if (args->cs_dos) { + error = kiconv_add_xlat16_cspair(args->cs_dos, args->cs_local, KICONV_FROM_UPPER); + if (error) + return (-1); + error = kiconv_add_xlat16_cspair(args->cs_local, args->cs_dos, KICONV_LOWER); + if (error) + return (-1); + } else { + if ((args->cs_dos = malloc(ICONV_CSNMAXLEN)) == NULL) + return (-1); + strcpy(args->cs_dos, args->cs_local); + error = kiconv_add_xlat16_cspair(args->cs_local, args->cs_local, + KICONV_FROM_UPPER | KICONV_LOWER); + if (error) + return (-1); } + + return (0); } Index: sbin/mount_ntfs/Makefile =================================================================== RCS file: /home/ncvs/src/sbin/mount_ntfs/Makefile,v retrieving revision 1.7 diff -u -r1.7 Makefile --- sbin/mount_ntfs/Makefile 4 Dec 2001 02:19:51 -0000 1.7 +++ sbin/mount_ntfs/Makefile 20 Jul 2003 18:37:00 -0000 @@ -5,12 +5,16 @@ PROG= mount_ntfs SRCS= mount_ntfs.c getmntopts.c MAN= mount_ntfs.8 -DPADD= ${LIBUTIL} -LDADD= -lutil +DPADD= ${LIBKICONV} +LDADD= -lkiconv MOUNT= ${.CURDIR}/../mount CFLAGS+=-I${MOUNT} WARNS= 0 + +# Needs to be dynamically linked for optional dlopen() access to +# userland libiconv +NOSHARED?= NO .PATH: ${MOUNT} Index: sbin/mount_ntfs/mount_ntfs.8 =================================================================== RCS file: /home/ncvs/src/sbin/mount_ntfs/mount_ntfs.8,v retrieving revision 1.18 diff -u -r1.18 mount_ntfs.8 --- sbin/mount_ntfs/mount_ntfs.8 21 Aug 2002 18:11:03 -0000 1.18 +++ sbin/mount_ntfs/mount_ntfs.8 10 Sep 2003 17:02:02 -0000 @@ -43,6 +43,7 @@ .Op Fl u Ar uid .Op Fl g Ar gid .Op Fl m Ar mask +.Op Fl C Ar charset .Op Fl W Ar u2wtable .Pa special .Pa node @@ -81,6 +82,11 @@ .It Fl m Ar mask Specify the maximum file permissions for files in the file system. +.It Fl C Ar charset +Specify local +.Ar charset +to convert Unicode file names. +Currently only reading is supported. .It Fl W Ar u2wtable Specify .Ux @@ -90,6 +96,9 @@ See .Xr mount_msdosfs 8 for the description of this option. +This option is remained for backward compatibility purpose, so +please do not use this option. This option will be removed in +the future. .El .Sh FEATURES NTFS file attributes are accessed in following way: @@ -120,11 +129,19 @@ .Bd -literal -offset indent # cat /mnt/foodir:\\$INDEX_ROOT:\\$I30 .Ed +.Pp +To mount a +.Pa Japanese +ntfs volume located in /dev/ad0s1: +.Bd -literal -offset indent +# mount_ntfs -C eucJP /dev/ad0s1 /mnt +.Ed .Sh WRITING There is limited writing ability. Limitations: file must be nonresident and must not contain any sparces (uninitialized areas); compressed files are also not supported. +The file name must not contain multibyte characters. .Sh SEE ALSO .Xr mount 2 , .Xr unmount 2 , @@ -141,6 +158,10 @@ .Nm utility first appeared in .Fx 3.0 . +.Pp +The unicode conversion routine was added by +.An Ryuichiro Imura Aq imura@ryu16.org +at 2003. .Sh AUTHORS The NTFS kernel implementation, .Nm Index: sbin/mount_ntfs/mount_ntfs.c =================================================================== RCS file: /home/ncvs/src/sbin/mount_ntfs/mount_ntfs.c,v retrieving revision 1.8 diff -u -r1.8 mount_ntfs.c --- sbin/mount_ntfs/mount_ntfs.c 3 Aug 2002 16:03:20 -0000 1.8 +++ sbin/mount_ntfs/mount_ntfs.c 10 Sep 2003 17:02:02 -0000 @@ -37,6 +37,8 @@ #define NTFS #include #include +#include +#include #include #include #include @@ -51,6 +53,8 @@ #include "mntopts.h" +#define TRANSITION_PERIOD_HACK + static struct mntopt mopts[] = { MOPT_STDOPTS, { NULL } @@ -61,7 +65,7 @@ static mode_t a_mask(char *); static void usage(void) __dead2; -static void load_u2wtable(struct ntfs_args *, char *); +static int set_charset(struct ntfs_args *); int main(argc, argv) @@ -75,8 +79,14 @@ mntflags = set_gid = set_uid = set_mask = 0; (void)memset(&args, '\0', sizeof(args)); + args.cs_ntfs = NULL; + args.cs_local = NULL; - while ((c = getopt(argc, argv, "aiu:g:m:o:W:")) != -1) { +#ifdef TRANSITION_PERIOD_HACK + while ((c = getopt(argc, argv, "aiu:g:m:o:C:W:")) != -1) { +#else + while ((c = getopt(argc, argv, "aiu:g:m:o:C:")) != -1) { +#endif switch (c) { case 'u': args.uid = a_uid(optarg); @@ -99,10 +109,32 @@ case 'o': getmntopts(optarg, mopts, &mntflags, 0); break; + case 'C': + args.cs_local = malloc(ICONV_CSNMAXLEN); + if (args.cs_local == NULL) + err(EX_OSERR, "malloc()"); + strncpy(args.cs_local, + kiconv_quirkcs(optarg, KICONV_VENDOR_MICSFT), + ICONV_CSNMAXLEN); + break; +#ifdef TRANSITION_PERIOD_HACK case 'W': - load_u2wtable(&args, optarg); - args.flag |= NTFSMNT_U2WTABLE; + args.cs_local = malloc(ICONV_CSNMAXLEN); + if (args.cs_local == NULL) + err(EX_OSERR, "malloc()"); + if (strcmp(optarg, "iso22dos") == 0) { + strcpy(args.cs_local, "ISO8859-2"); + } else if (strcmp(optarg, "iso72dos") == 0) { + strcpy(args.cs_local, "ISO8859-13"); + } else if (strcmp(optarg, "koi2dos") == 0) { + strcpy(args.cs_local, "KOI8-R"); + } else if (strcmp(optarg, "koi8u2dos") == 0) { + strcpy(args.cs_local, "KOI8-U"); + } else { + err(EX_NOINPUT, "%s", optarg); + } break; +#endif /* TRANSITION_PERIOD_HACK */ case '?': default: usage(); @@ -116,6 +148,12 @@ dev = argv[optind]; dir = argv[optind + 1]; + if (args.cs_local) { + if (set_charset(&args) == -1) + err(EX_OSERR, "ntfs_iconv"); + args.flag |= NTFS_MFLAG_KICONV; + } + /* * Resolve the mountpoint with realpath(3) and remove unnecessary * slashes from the devicename if there are any. @@ -207,74 +245,36 @@ void usage() { - fprintf(stderr, "usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-m mask] [-W u2wtable] bdev dir\n"); +#ifdef TRANSITION_PERIOD_HACK + fprintf(stderr, "%s\n%s\n", + "usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-m mask]", + " [-C charset] [-W u2wtable] bdev dir"); +#else + fprintf(stderr, "usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-m mask] [-C charset] bdev dir\n"); +#endif exit(EX_USAGE); } -void -load_u2wtable (pargs, name) - struct ntfs_args *pargs; - char *name; -{ - FILE *f; - int i, j, code[8]; - size_t line = 0; - char buf[128]; - char *fn, *s, *p; +int +set_charset(struct ntfs_args *pargs) +{ + int error; - if (*name == '/') - fn = name; - else { - snprintf(buf, sizeof(buf), "/usr/libdata/msdosfs/%s", name); - buf[127] = '\0'; - fn = buf; - } - if ((f = fopen(fn, "r")) == NULL) - err(EX_NOINPUT, "%s", fn); - p = NULL; - for (i = 0; i < 16; i++) { - do { - if (p != NULL) free(p); - if ((p = s = fparseln(f, NULL, &line, NULL, 0)) == NULL) - errx(EX_DATAERR, "can't read u2w table row %d near line %d", i, line); - while (isspace((unsigned char)*s)) - s++; - } while (*s == '\0'); - if (sscanf(s, "%i%i%i%i%i%i%i%i", -code, code + 1, code + 2, code + 3, code + 4, code + 5, code + 6, code + 7) != 8) - errx(EX_DATAERR, "u2w table: missing item(s) in row %d, line %d", i, line); - for (j = 0; j < 8; j++) - pargs->u2w[i * 8 + j] = code[j]; - } - for (i = 0; i < 16; i++) { - do { - free(p); - if ((p = s = fparseln(f, NULL, &line, NULL, 0)) == NULL) - errx(EX_DATAERR, "can't read d2u table row %d near line %d", i, line); - while (isspace((unsigned char)*s)) - s++; - } while (*s == '\0'); - if (sscanf(s, "%i%i%i%i%i%i%i%i", -code, code + 1, code + 2, code + 3, code + 4, code + 5, code + 6, code + 7) != 8) - errx(EX_DATAERR, "d2u table: missing item(s) in row %d, line %d", i, line); - for (j = 0; j < 8; j++) - /* pargs->d2u[i * 8 + j] = code[j] */; - } - for (i = 0; i < 16; i++) { - do { - free(p); - if ((p = s = fparseln(f, NULL, &line, NULL, 0)) == NULL) - errx(EX_DATAERR, "can't read u2d table row %d near line %d", i, line); - while (isspace((unsigned char)*s)) - s++; - } while (*s == '\0'); - if (sscanf(s, "%i%i%i%i%i%i%i%i", -code, code + 1, code + 2, code + 3, code + 4, code + 5, code + 6, code + 7) != 8) - errx(EX_DATAERR, "u2d table: missing item(s) in row %d, line %d", i, line); - for (j = 0; j < 8; j++) - /* pargs->u2d[i * 8 + j] = code[j] */; - } - free(p); - fclose(f); -} + if (modfind("ntfs_iconv") < 0) + if (kldload("ntfs_iconv") < 0 || modfind("ntfs_iconv") < 0) { + warnx( "cannot find or load \"ntfs_iconv\" kernel module"); + return (-1); + } + + if ((pargs->cs_ntfs = malloc(ICONV_CSNMAXLEN)) == NULL) + return (-1); + strncpy(pargs->cs_ntfs, ENCODING_UNICODE, ICONV_CSNMAXLEN); + error = kiconv_add_xlat16_cspair(pargs->cs_local, pargs->cs_ntfs, 0); + if (error) + return (-1); + error = kiconv_add_xlat16_cspair(pargs->cs_ntfs, pargs->cs_local, 0); + if (error) + return (-1); + return (0); +} Index: share/mk/bsd.libnames.mk =================================================================== RCS file: /home/ncvs/src/share/mk/bsd.libnames.mk,v retrieving revision 1.65 diff -u -r1.65 bsd.libnames.mk --- share/mk/bsd.libnames.mk 5 May 2003 07:58:43 -0000 1.65 +++ share/mk/bsd.libnames.mk 20 Jul 2003 18:14:41 -0000 @@ -47,6 +47,7 @@ LIBISC?= ${DESTDIR}${LIBDIR}/libisc.a LIBKDB?= ${DESTDIR}${LIBDIR}/libkdb.a # XXX in secure dist, not base LIBKEYCAP?= ${DESTDIR}${LIBDIR}/libkeycap.a +LIBKICONV?= ${DESTDIR}${LIBDIR}/libkiconv.a LIBKRB?= ${DESTDIR}${LIBDIR}/libkrb.a # XXX in secure dist, not base LIBKRB5?= ${DESTDIR}${LIBDIR}/libkrb5.a # XXX in secure dist, not base LIBKVM?= ${DESTDIR}${LIBDIR}/libkvm.a Index: sys/conf/NOTES =================================================================== RCS file: /home/ncvs/src/sys/conf/NOTES,v retrieving revision 1.1149 diff -u -r1.1149 NOTES --- sys/conf/NOTES 15 May 2003 02:10:29 -0000 1.1149 +++ sys/conf/NOTES 10 Sep 2003 17:02:02 -0000 @@ -773,6 +773,12 @@ # Cryptographically secure random number generator; /dev/[u]random device random +# Optional character code conversion support with LIBICONV. +# Each option requires their base file system and LIBICONV. +options CD9660_ICONV +options MSDOSFS_ICONV +options NTFS_ICONV + ##################################################################### # POSIX P1003.1B Index: sys/conf/files =================================================================== RCS file: /home/ncvs/src/sys/conf/files,v retrieving revision 1.790 diff -u -r1.790 files --- sys/conf/files 11 May 2003 06:37:52 -0000 1.790 +++ sys/conf/files 10 Sep 2003 17:02:02 -0000 @@ -848,11 +848,13 @@ fs/msdosfs/msdosfs_lookup.c optional msdosfs fs/msdosfs/msdosfs_vfsops.c optional msdosfs fs/msdosfs/msdosfs_vnops.c optional msdosfs +fs/msdosfs/msdosfs_iconv.c optional msdosfs_iconv fs/ntfs/ntfs_compr.c optional ntfs fs/ntfs/ntfs_ihash.c optional ntfs fs/ntfs/ntfs_subr.c optional ntfs fs/ntfs/ntfs_vfsops.c optional ntfs fs/ntfs/ntfs_vnops.c optional ntfs +fs/ntfs/ntfs_iconv.c optional ntfs_iconv fs/nullfs/null_subr.c optional nullfs fs/nullfs/null_vfsops.c optional nullfs fs/nullfs/null_vnops.c optional nullfs @@ -1008,6 +1010,7 @@ isofs/cd9660/cd9660_util.c optional cd9660 isofs/cd9660/cd9660_vfsops.c optional cd9660 isofs/cd9660/cd9660_vnops.c optional cd9660 +isofs/cd9660/cd9660_iconv.c optional cd9660_iconv kern/imgact_elf.c standard kern/imgact_shell.c standard kern/inflate.c optional gzip @@ -1148,6 +1151,7 @@ libkern/iconv.c optional libiconv libkern/iconv_converter_if.m optional libiconv libkern/iconv_xlat.c optional libiconv +libkern/iconv_xlat16.c optional libiconv libkern/index.c standard libkern/inet_ntoa.c standard libkern/mcount.c optional profiling-routine Index: sys/conf/options =================================================================== RCS file: /home/ncvs/src/sys/conf/options,v retrieving revision 1.393 diff -u -r1.393 options --- sys/conf/options 18 May 2003 03:46:30 -0000 1.393 +++ sys/conf/options 10 Sep 2003 17:02:02 -0000 @@ -196,6 +196,11 @@ NFSCLIENT opt_nfs.h NFSSERVER opt_nfs.h +# filesystems and libiconv bridge +CD9660_ICONV opt_dontuse.h +MSDOSFS_ICONV opt_dontuse.h +NTFS_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 # and make the system safer from crashes at the same time. Index: sys/fs/msdosfs/direntry.h =================================================================== RCS file: /home/ncvs/src/sys/fs/msdosfs/direntry.h,v retrieving revision 1.16 diff -u -r1.16 direntry.h --- sys/fs/msdosfs/direntry.h 19 Mar 2002 22:20:10 -0000 1.16 +++ sys/fs/msdosfs/direntry.h 10 Sep 2003 17:02:02 -0000 @@ -98,6 +98,11 @@ #define WIN_CHARS 13 /* Number of chars per winentry */ /* + * Maximum number of winentries for a filename + */ +#define WIN_MAXSUBENTRIES 20 + +/* * Maximum filename length in Win95 * Note: Must be < sizeof(dirent.d_name) */ @@ -132,12 +137,15 @@ void unix2dostime(struct timespec *tsp, u_int16_t *ddp, u_int16_t *dtp, u_int8_t *dhp); void dos2unixtime(u_int dd, u_int dt, u_int dh, struct timespec *tsp); -int dos2unixfn(u_char dn[11], u_char *un, int lower, int d2u_loaded, u_int8_t *d2u, int ul_loaded, u_int8_t *ul); -int unix2dosfn(const u_char *un, u_char dn[12], int unlen, u_int gen, int u2d_loaded, u_int8_t *u2d, int lu_loaded, u_int8_t *lu); -int unix2winfn(const u_char *un, int unlen, struct winentry *wep, int cnt, int chksum, int table_loaded, u_int16_t *u2w); -int winChkName(const u_char *un, int unlen, struct winentry *wep, int chksum, int u2w_loaded, u_int16_t *u2w, int ul_loaded, u_int8_t *ul); -int win2unixfn(struct winentry *wep, struct dirent *dp, int chksum, int table_loaded, u_int16_t *u2w); +int dos2unixfn(u_char dn[11], u_char *un, int lower, struct msdosfsmount *pmp); +int unix2dosfn(const u_char *un, u_char dn[12], int unlen, u_int gen, struct msdosfsmount *pmp); +int unix2winfn(const u_char *un, int unlen, struct winentry *wep, int cnt, int chksum, struct msdosfsmount *pmp); +int winChkName(const u_char *un, int unlen, int chksum, struct msdosfsmount *pmp); +int win2unixfn(struct winentry *wep, int chksum, struct msdosfsmount *pmp); u_int8_t winChksum(u_int8_t *name); -int winSlotCnt(const u_char *un, int unlen); +int winSlotCnt(const u_char *un, int unlen, struct msdosfsmount *); int winLenFixup(const u_char *un, int unlen); +void mbnambuf_init(void); +void mbnambuf_write(char *name, int id); +char * mbnambuf_flush(struct dirent *dp); #endif /* _KERNEL */ Index: sys/fs/msdosfs/msdosfs_conv.c =================================================================== RCS file: /home/ncvs/src/sys/fs/msdosfs/msdosfs_conv.c,v retrieving revision 1.33 diff -u -r1.33 msdosfs_conv.c --- sys/fs/msdosfs/msdosfs_conv.c 3 Feb 2003 19:49:33 -0000 1.33 +++ sys/fs/msdosfs/msdosfs_conv.c 10 Sep 2003 17:02:02 -0000 @@ -57,10 +57,17 @@ #include #include #include +#include +#include +#include + +extern struct iconv_functions *msdosfs_iconv; /* * MSDOSFS include files. */ +#include +#include #include /* @@ -88,7 +95,17 @@ static u_short lastddate; static u_short lastdtime; -static __inline u_int8_t find_lcode(u_int16_t code, u_int16_t *u2w); +static int mbsadjpos(const char **, int, int, int, int, void *handle); +static u_int16_t dos2unixchr(const u_char **, size_t *, int, struct msdosfsmount *); +static u_int16_t unix2doschr(const u_char **, size_t *, struct msdosfsmount *); +static u_int16_t win2unixchr(u_int16_t, struct msdosfsmount *); +static u_int16_t unix2winchr(const u_char **, size_t *, int, struct msdosfsmount *); + +struct mbnambuf { + char * p; + size_t n; +}; +static struct mbnambuf subent[WIN_MAXSUBENTRIES]; /* * Convert the unix version of time to dos's idea of time to be used in @@ -239,6 +256,7 @@ */ static u_char unix2dos[256] = { +/* iso8859-1 -> cp850 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 00-07 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 08-0f */ 0, 0, 0, 0, 0, 0, 0, 0, /* 10-17 */ @@ -275,6 +293,7 @@ static u_char dos2unix[256] = { +/* cp850 -> iso8859-1 */ 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, /* 00-07 */ 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, /* 08-0f */ 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, /* 10-17 */ @@ -311,6 +330,7 @@ static u_char u2l[256] = { +/* tolower */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 00-07 */ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 08-0f */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 10-17 */ @@ -347,6 +367,7 @@ static u_char l2u[256] = { +/* toupper */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 00-07 */ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 08-0f */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 10-17 */ @@ -394,18 +415,15 @@ * null. */ int -dos2unixfn(dn, un, lower, d2u_loaded, d2u, ul_loaded, ul) +dos2unixfn(dn, un, lower, pmp) u_char dn[11]; u_char *un; int lower; - int d2u_loaded; - u_int8_t *d2u; - int ul_loaded; - u_int8_t *ul; + struct msdosfsmount *pmp; { int i; - int thislong = 1; - u_char c; + int thislong = 0; + u_int16_t c; /* * If first char of the filename is SLOT_E5 (0x05), then the real @@ -414,26 +432,21 @@ * directory slot. Another dos quirk. */ if (*dn == SLOT_E5) - c = d2u_loaded ? d2u[0xe5 & 0x7f] : dos2unix[0xe5]; - else - c = d2u_loaded && (*dn & 0x80) ? d2u[*dn & 0x7f] : - dos2unix[*dn]; - *un++ = (lower & LCASE_BASE) ? (ul_loaded && (c & 0x80) ? - ul[c & 0x7f] : u2l[c]) : c; - dn++; + *dn = 0xe5; /* * Copy the name portion into the unix filename string. */ - for (i = 1; i < 8 && *dn != ' '; i++) { - c = d2u_loaded && (*dn & 0x80) ? d2u[*dn & 0x7f] : - dos2unix[*dn]; - dn++; - *un++ = (lower & LCASE_BASE) ? (ul_loaded && (c & 0x80) ? - ul[c & 0x7f] : u2l[c]) : c; + for (i = 8; i > 0 && *dn != ' ';) { + c = dos2unixchr((const u_char **)&dn, (size_t *)&i, lower, pmp); + if (c & 0xff00) { + *un++ = c >> 8; + thislong++; + } + *un++ = c; thislong++; } - dn += 8 - i; + dn += i; /* * Now, if there is an extension then put in a period and copy in @@ -442,12 +455,13 @@ if (*dn != ' ') { *un++ = '.'; thislong++; - for (i = 0; i < 3 && *dn != ' '; i++) { - c = d2u_loaded && (*dn & 0x80) ? d2u[*dn & 0x7f] : - dos2unix[*dn]; - dn++; - *un++ = (lower & LCASE_EXT) ? (ul_loaded && (c & 0x80) ? - ul[c & 0x7f] : u2l[c]) : c; + for (i = 3; i > 0 && *dn != ' ';) { + c = dos2unixchr((const u_char **)&dn, (size_t *)&i, lower, pmp); + if (c & 0xff00) { + *un++ = c >> 8; + thislong++; + } + *un++ = c; thislong++; } } @@ -468,22 +482,18 @@ * 3 if conversion was successful and generation number was inserted */ int -unix2dosfn(un, dn, unlen, gen, u2d_loaded, u2d, lu_loaded, lu) +unix2dosfn(un, dn, unlen, gen, pmp) const u_char *un; u_char dn[12]; int unlen; u_int gen; - int u2d_loaded; - u_int8_t *u2d; - int lu_loaded; - u_int8_t *lu; + struct msdosfsmount *pmp; { int i, j, l; int conv = 1; const u_char *cp, *dp, *dp1; u_char gentext[6], *wcp; - u_int8_t c; -#define U2D(c) (u2d_loaded && ((c) & 0x80) ? u2d[(c) & 0x7f] : unix2dos[c]) + u_int16_t c; /* * Fill the dos filename string with blanks. These are DOS's pad @@ -520,14 +530,18 @@ /* * Filenames with some characters are not allowed! */ - for (cp = un, i = unlen; --i >= 0; cp++) - if (U2D(*cp) == 0) + for (cp = un, i = unlen; i > 0;) + if (unix2doschr(&cp, (size_t *)&i, pmp) == 0) return 0; /* * Now find the extension * Note: dot as first char doesn't start extension * and trailing dots and blanks are ignored + * Note(2003/7): It seems recent Windows has + * defferent rule than this code, that Windows + * ignores all dots before extension, and use all + * chars as filename except for dots. */ dp = dp1 = 0; for (cp = un + 1, i = unlen - 1; --i >= 0;) { @@ -547,20 +561,29 @@ } /* - * Now convert it + * Now convert it (this part is for extension) */ if (dp) { if (dp1) l = dp1 - dp; else l = unlen - (dp - un); - for (i = 0, j = 8; i < l && j < 11; i++, j++) { - c = dp[i]; - c = lu_loaded && (c & 0x80) ? - lu[c & 0x7f] : l2u[c]; - c = U2D(c); - if (dp[i] != (dn[j] = c) - && conv != 3) + for (cp = dp, i = l, j = 8; i > 0 && j < 11; j++) { + c = unix2doschr(&cp, (size_t *)&i, pmp); + if (c & 0xff00) { + dn[j] = c >> 8; + if (++j < 11) { + dn[j] = c; + continue; + } else { + conv = 3; + dn[j-1] = ' '; + break; + } + } else { + dn[j] = c; + } + if (*(cp - 1) != dn[j] && conv != 3) conv = 2; if (dn[j] == 1) { conv = 3; @@ -571,7 +594,7 @@ dn[j--] = ' '; } } - if (i < l) + if (i > 0) conv = 3; dp--; } else { @@ -582,12 +605,22 @@ /* * Now convert the rest of the name */ - for (i = j = 0; un < dp && j < 8; i++, j++, un++) { - c = lu_loaded && (*un & 0x80) ? - lu[*un & 0x7f] : l2u[*un]; - c = U2D(c); - if (*un != (dn[j] = c) - && conv != 3) + for (i = dp - un, j = 0; un < dp && j < 8; j++) { + c = unix2doschr(&un, (size_t *)&i, pmp); + if (c & 0xff00) { + dn[j] = c >> 8; + if (++j < 8) { + dn[j] = c; + continue; + } else { + conv = 3; + dn[j-1] = ' '; + break; + } + } else { + dn[j] = c; + } + if (*(un - 1) != dn[j] && conv != 3) conv = 2; if (dn[j] == 1) { conv = 3; @@ -608,40 +641,56 @@ dn[0] = '_'; /* - * The first character cannot be E5, - * because that means a deleted entry - */ - if (dn[0] == 0xe5) - dn[0] = SLOT_E5; - - /* * If there wasn't any char dropped, * there is no place for generation numbers */ if (conv != 3) { if (gen > 1) - return 0; - return conv; + conv = 0; + goto done; } /* * Now insert the generation number into the filename part */ if (gen == 0) - return conv; + goto done; for (wcp = gentext + sizeof(gentext); wcp > gentext && gen; gen /= 10) *--wcp = gen % 10 + '0'; - if (gen) - return 0; + if (gen) { + conv = 0; + goto done; + } for (i = 8; dn[--i] == ' ';); i++; if (gentext + sizeof(gentext) - wcp + 1 > 8 - i) i = 8 - (gentext + sizeof(gentext) - wcp + 1); + /* + * Correct posision to where insert the generation number + */ + cp = dn; + i -= mbsadjpos((const char**)&cp, i, unlen, 1, pmp->pm_flags, pmp->pm_d2u); + dn[i++] = '~'; while (wcp < gentext + sizeof(gentext)) dn[i++] = *wcp++; - return 3; -#undef U2D + + /* + * Tail of the filename should be space + */ + while (i < 8) + dn[i++] = ' '; + conv = 3; + +done: + /* + * The first character cannot be E5, + * because that means a deleted entry + */ + if (dn[0] == 0xe5) + dn[0] = SLOT_E5; + + return conv; } /* @@ -650,27 +699,28 @@ * i.e. doesn't consist solely of blanks and dots */ int -unix2winfn(un, unlen, wep, cnt, chksum, table_loaded, u2w) +unix2winfn(un, unlen, wep, cnt, chksum, pmp) const u_char *un; int unlen; struct winentry *wep; int cnt; int chksum; - int table_loaded; - u_int16_t *u2w; + struct msdosfsmount *pmp; { - const u_int8_t *cp; u_int8_t *wcp; - int i; + int i, end; u_int16_t code; /* * Drop trailing blanks and dots */ - for (cp = un + unlen; *--cp == ' ' || *cp == '.'; unlen--); + unlen = winLenFixup(un, unlen); - un += (cnt - 1) * WIN_CHARS; - unlen -= (cnt - 1) * WIN_CHARS; + /* + * Cut *un for this slot + */ + unlen = mbsadjpos((const char **)&un, unlen, (cnt - 1) * WIN_CHARS, 2, + pmp->pm_flags, pmp->pm_u2w); /* * Initialize winentry to some useful default @@ -685,64 +735,32 @@ /* * Now convert the filename parts */ - for (wcp = wep->wePart1, i = sizeof(wep->wePart1)/2; --i >= 0;) { - if (--unlen < 0) - goto done; - if (table_loaded && (*un & 0x80)) { - code = u2w[*un++ & 0x7f]; - *wcp++ = code; - *wcp++ = code >> 8; - } else { - *wcp++ = *un++; - *wcp++ = 0; - } + end = 0; + for (wcp = wep->wePart1, i = sizeof(wep->wePart1)/2; --i >= 0 && !end;) { + code = unix2winchr(&un, (size_t *)&unlen, 0, pmp); + *wcp++ = code; + *wcp++ = code >> 8; + if (!code) + end = WIN_LAST; } - for (wcp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) { - if (--unlen < 0) - goto done; - if (table_loaded && (*un & 0x80)) { - code = u2w[*un++ & 0x7f]; - *wcp++ = code; - *wcp++ = code >> 8; - } else { - *wcp++ = *un++; - *wcp++ = 0; - } + for (wcp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0 && !end;) { + code = unix2winchr(&un, (size_t *)&unlen, 0, pmp); + *wcp++ = code; + *wcp++ = code >> 8; + if (!code) + end = WIN_LAST; } - for (wcp = wep->wePart3, i = sizeof(wep->wePart3)/2; --i >= 0;) { - if (--unlen < 0) - goto done; - if (table_loaded && (*un & 0x80)) { - code = u2w[*un++ & 0x7f]; - *wcp++ = code; - *wcp++ = code >> 8; - } else { - *wcp++ = *un++; - *wcp++ = 0; - } + for (wcp = wep->wePart3, i = sizeof(wep->wePart3)/2; --i >= 0 && !end;) { + code = unix2winchr(&un, (size_t *)&unlen, 0, pmp); + *wcp++ = code; + *wcp++ = code >> 8; + if (!code) + end = WIN_LAST; } - if (!unlen) - wep->weCnt |= WIN_LAST; - return unlen; - -done: - *wcp++ = 0; - *wcp++ = 0; - wep->weCnt |= WIN_LAST; - return 0; -} - -static __inline u_int8_t -find_lcode(code, u2w) - u_int16_t code; - u_int16_t *u2w; -{ - int i; - - for (i = 0; i < 128; i++) - if (u2w[i] == code) - return (i | 0x80); - return '?'; + if (*un == '\0') + end = WIN_LAST; + wep->weCnt |= end; + return !end; } /* @@ -750,116 +768,44 @@ * Returns the checksum or -1 if no match */ int -winChkName(un, unlen, wep, chksum, u2w_loaded, u2w, ul_loaded, ul) +winChkName(un, unlen, chksum, pmp) const u_char *un; int unlen; - struct winentry *wep; int chksum; - int u2w_loaded; - u_int16_t *u2w; - int ul_loaded; - u_int8_t *ul; + struct msdosfsmount *pmp; { - u_int8_t *cp; - int i; - u_int16_t code; - u_int8_t c1, c2; + int len; + u_int16_t c1, c2; + u_char *np; + struct dirent dirbuf; /* - * First compare checksums + * We alread have winentry in mbnambuf */ - if (wep->weCnt&WIN_LAST) - chksum = wep->weChksum; - else if (chksum != wep->weChksum) - chksum = -1; - if (chksum == -1) + if (!mbnambuf_flush(&dirbuf) || !dirbuf.d_namlen) return -1; - /* - * Offset of this entry - */ - i = ((wep->weCnt&WIN_CNT) - 1) * WIN_CHARS; - un += i; - unlen -= i; - - /* - * unlen being zero must not be treated as length missmatch. It is - * possible if the entry is WIN_LAST and contains nothing but the - * terminating 0. - */ - if (unlen < 0) - return -1; - if ((wep->weCnt&WIN_LAST) && unlen > WIN_CHARS) - return -1; +#ifdef MSDOSFS_DEBUG + printf("winChkName(): un=%s:%d,d_name=%s:%d\n", un, unlen, + dirbuf.d_name, + dirbuf.d_namlen); +#endif /* * Compare the name parts */ - for (cp = wep->wePart1, i = sizeof(wep->wePart1)/2; --i >= 0;) { - if (--unlen < 0) { - if (!*cp++ && !*cp) - return chksum; - return -1; - } - code = (cp[1] << 8) | cp[0]; - if (code & 0xff80) { - if (u2w_loaded) - code = find_lcode(code, u2w); - else if (code & 0xff00) - code = '?'; - } - c1 = ul_loaded && (code & 0x80) ? - ul[code & 0x7f] : u2l[code]; - c2 = ul_loaded && (*un & 0x80) ? - ul[*un & 0x7f] : u2l[*un]; - if (c1 != c2) - return -1; - cp += 2; - un++; - } - for (cp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) { - if (--unlen < 0) { - if (!*cp++ && !*cp) - return chksum; - return -1; - } - code = (cp[1] << 8) | cp[0]; - if (code & 0xff80) { - if (u2w_loaded) - code = find_lcode(code, u2w); - else if (code & 0xff00) - code = '?'; - } - c1 = ul_loaded && (code & 0x80) ? - ul[code & 0x7f] : u2l[code]; - c2 = ul_loaded && (*un & 0x80) ? - ul[*un & 0x7f] : u2l[*un]; - if (c1 != c2) - return -1; - cp += 2; - un++; - } - for (cp = wep->wePart3, i = sizeof(wep->wePart3)/2; --i >= 0;) { - if (--unlen < 0) { - if (!*cp++ && !*cp) - return chksum; - return -1; - } - code = (cp[1] << 8) | cp[0]; - if (code & 0xff80) { - if (u2w_loaded) - code = find_lcode(code, u2w); - else if (code & 0xff00) - code = '?'; - } - c1 = ul_loaded && (code & 0x80) ? - ul[code & 0x7f] : u2l[code]; - c2 = ul_loaded && (*un & 0x80) ? - ul[*un & 0x7f] : u2l[*un]; + len = dirbuf.d_namlen; + if (unlen != len) + return -2; + + for (np = dirbuf.d_name; unlen > 0 && len > 0;) { + /* + * Should comparison be case insensitive? + */ + c1 = unix2winchr((const u_char **)&np, (size_t *)&len, 0, pmp); + c2 = unix2winchr(&un, (size_t *)&unlen, 0, pmp); if (c1 != c2) - return -1; - cp += 2; - un++; + return -2; } return chksum; } @@ -869,15 +815,13 @@ * Returns the checksum or -1 if impossible */ int -win2unixfn(wep, dp, chksum, table_loaded, u2w) +win2unixfn(wep, chksum, pmp) struct winentry *wep; - struct dirent *dp; int chksum; - int table_loaded; - u_int16_t *u2w; + struct msdosfsmount *pmp; { u_int8_t *cp; - u_int8_t *np, *ep = dp->d_name + WIN_MAXLEN; + u_int8_t *np, name[WIN_CHARS * 2 + 1]; u_int16_t code; int i; @@ -890,54 +834,32 @@ */ if (wep->weCnt&WIN_LAST) { chksum = wep->weChksum; - /* - * This works even though d_namlen is one byte! - */ - dp->d_namlen = (wep->weCnt&WIN_CNT) * WIN_CHARS; } else if (chksum != wep->weChksum) chksum = -1; if (chksum == -1) return -1; /* - * Offset of this entry - */ - i = ((wep->weCnt&WIN_CNT) - 1) * WIN_CHARS; - np = (u_int8_t *)dp->d_name + i; - - /* * Convert the name parts */ + np = name; for (cp = wep->wePart1, i = sizeof(wep->wePart1)/2; --i >= 0;) { code = (cp[1] << 8) | cp[0]; switch (code) { case 0: *np = '\0'; - dp->d_namlen -= sizeof(wep->wePart2)/2 - + sizeof(wep->wePart3)/2 + i + 1; + mbnambuf_write(name, (wep->weCnt & WIN_CNT) - 1); return chksum; case '/': *np = '\0'; return -1; default: - if (code & 0xff80) { - if (table_loaded) - code = find_lcode(code, u2w); - else if (code & 0xff00) - code = '?'; - } + code = win2unixchr(code, pmp); + if (code & 0xff00) + *np++ = code >> 8; *np++ = code; break; } - /* - * The size comparison should result in the compiler - * optimizing the whole if away - */ - if (WIN_MAXLEN % WIN_CHARS < sizeof(wep->wePart1) / 2 - && np > ep) { - np[-1] = 0; - return -1; - } cp += 2; } for (cp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) { @@ -945,30 +867,18 @@ switch (code) { case 0: *np = '\0'; - dp->d_namlen -= sizeof(wep->wePart3)/2 + i + 1; + mbnambuf_write(name, (wep->weCnt & WIN_CNT) - 1); return chksum; case '/': *np = '\0'; return -1; default: - if (code & 0xff80) { - if (table_loaded) - code = find_lcode(code, u2w); - else if (code & 0xff00) - code = '?'; - } + code = win2unixchr(code, pmp); + if (code & 0xff00) + *np++ = code >> 8; *np++ = code; break; } - /* - * The size comparisons should be optimized away - */ - if (WIN_MAXLEN % WIN_CHARS >= sizeof(wep->wePart1) / 2 - && WIN_MAXLEN % WIN_CHARS < (sizeof(wep->wePart1) + sizeof(wep->wePart2)) / 2 - && np > ep) { - np[-1] = 0; - return -1; - } cp += 2; } for (cp = wep->wePart3, i = sizeof(wep->wePart3)/2; --i >= 0;) { @@ -976,31 +886,22 @@ switch (code) { case 0: *np = '\0'; - dp->d_namlen -= i + 1; + mbnambuf_write(name, (wep->weCnt & WIN_CNT) - 1); return chksum; case '/': *np = '\0'; return -1; default: - if (code & 0xff80) { - if (table_loaded) - code = find_lcode(code, u2w); - else if (code & 0xff00) - code = '?'; - } + code = win2unixchr(code, pmp); + if (code & 0xff00) + *np++ = code >> 8; *np++ = code; break; } - /* - * See above - */ - if (WIN_MAXLEN % WIN_CHARS >= (sizeof(wep->wePart1) + sizeof(wep->wePart2)) / 2 - && np > ep) { - np[-1] = 0; - return -1; - } cp += 2; } + *np = '\0'; + mbnambuf_write(name, (wep->weCnt & WIN_CNT) - 1); return chksum; } @@ -1023,11 +924,25 @@ * Determine the number of slots necessary for Win95 names */ int -winSlotCnt(un, unlen) +winSlotCnt(un, unlen, pmp) const u_char *un; int unlen; + struct msdosfsmount *pmp; { + size_t wlen; + char wn[WIN_MAXLEN * 2 + 1], *wnp; + unlen = winLenFixup(un, unlen); + + if (pmp->pm_flags & MSDOSFSMNT_KICONV && msdosfs_iconv) { + wlen = WIN_MAXLEN * 2; + wnp = wn; + msdosfs_iconv->conv(pmp->pm_u2w, (const char **)&un, (size_t *)&unlen, &wnp, &wlen); + if (unlen > 0) + return 0; + return howmany(WIN_MAXLEN - wlen/2, WIN_CHARS); + } + if (unlen > WIN_MAXLEN) return 0; return howmany(unlen, WIN_CHARS); @@ -1045,4 +960,282 @@ if (*--un != ' ' && *un != '.') break; return unlen; +} + +/* + * Store an area with multi byte string instr, and reterns left + * byte of instr and moves pointer forward. The area's size is + * inlen or outlen. + */ +static int +mbsadjpos(const char **instr, int inlen, int outlen, int weight, int flag, void *handle) +{ + char *outp, outstr[outlen * weight + 1]; + + if (flag & MSDOSFSMNT_KICONV && msdosfs_iconv) { + outp = outstr; + outlen *= weight; + msdosfs_iconv->conv(handle, instr, (size_t *)&inlen, &outp, (size_t *)&outlen); + return (inlen); + } + + (*instr) += min(inlen, outlen); + return (inlen - min(inlen, outlen)); +} + +/* + * Convert DOS char to Local char + */ +static u_int16_t +dos2unixchr(const u_char **instr, size_t *ilen, int lower, struct msdosfsmount *pmp) +{ + u_char c; + char *outp, outbuf[3]; + u_int16_t wc; + size_t len, olen; + + if (pmp->pm_flags & MSDOSFSMNT_KICONV && msdosfs_iconv) { + olen = len = 2; + outp = outbuf; + + if (lower & (LCASE_BASE | LCASE_EXT)) + msdosfs_iconv->convchr_case(pmp->pm_d2u, (const char **)instr, + ilen, &outp, &olen, KICONV_LOWER); + else + msdosfs_iconv->convchr(pmp->pm_d2u, (const char **)instr, + ilen, &outp, &olen); + len -= olen; + + /* + * return '?' if failed to convert + */ + if (len == 0) { + (*ilen)--; + (*instr)++; + return ('?'); + } + + wc = 0; + while(len--) + wc |= (*(outp - len - 1) & 0xff) << (len << 3); + return (wc); + } + + (*ilen)--; + c = *(*instr)++; + c = dos2unix[c]; + if (lower & (LCASE_BASE | LCASE_EXT)) + c = u2l[c]; + return ((u_int16_t)c); +} + +/* + * Convert Local char to DOS char + */ +static u_int16_t +unix2doschr(const u_char **instr, size_t *ilen, struct msdosfsmount *pmp) +{ + u_char c; + char *up, *outp, unicode[3], outbuf[3]; + u_int16_t wc; + size_t len, ulen, olen; + + if (pmp->pm_flags & MSDOSFSMNT_KICONV && msdosfs_iconv) { + /* + * to hide an invisible character, using a unicode filter + */ + ulen = 2; + len = *ilen; + up = unicode; + msdosfs_iconv->convchr(pmp->pm_u2w, (const char **)instr, + ilen, &up, &ulen); + + /* + * cannot be converted + */ + if (ulen == 2) { + (*ilen)--; + (*instr)++; + return (0); + } + + /* + * return magic number for ascii char + */ + if ((len - *ilen) == 1) { + c = *(*instr -1); + if (! (c & 0x80)) { + c = unix2dos[c]; + if (c <= 2) + return (c); + } + } + + /* + * now convert using libiconv + */ + *instr -= len - *ilen; + *ilen = (int)len; + + olen = len = 2; + outp = outbuf; + msdosfs_iconv->convchr_case(pmp->pm_u2d, (const char **)instr, + ilen, &outp, &olen, KICONV_FROM_UPPER); + len -= olen; + wc = 0; + while(len--) + wc |= (*(outp - len - 1) & 0xff) << (len << 3); + return (wc); + } + + (*ilen)--; + c = *(*instr)++; + c = l2u[c]; + c = unix2dos[c]; + return ((u_int16_t)c); +} + +/* + * Convert Windows char to Local char + */ +static u_int16_t +win2unixchr(u_int16_t wc, struct msdosfsmount *pmp) +{ + u_char *inp, *outp, inbuf[3], outbuf[3]; + size_t ilen, olen, len; + + if (wc == 0) + return (0); + + if (pmp->pm_flags & MSDOSFSMNT_KICONV && msdosfs_iconv) { + inbuf[0] = (u_char)(wc>>8); + inbuf[1] = (u_char)wc; + inbuf[2] = '\0'; + + ilen = olen = len = 2; + inp = inbuf; + outp = outbuf; + msdosfs_iconv->convchr(pmp->pm_w2u, (const char **)&inp, &ilen, + (char **)&outp, &olen); + len -= olen; + + /* + * return '?' if failed to convert + */ + if (len == 0) { + wc = '?'; + return (wc); + } + + wc = 0; + while(len--) + wc |= (*(outp - len - 1) & 0xff) << (len << 3); + return (wc); + } + + if (wc & 0xff00) + wc = '?'; + + return (wc); +} + +/* + * Convert Local char to Windows char + */ +static u_int16_t +unix2winchr(const u_char **instr, size_t *ilen, int lower, struct msdosfsmount *pmp) +{ + u_char *outp, outbuf[3]; + u_int16_t wc; + size_t olen; + + if (*ilen == 0) + return (0); + + if (pmp->pm_flags & MSDOSFSMNT_KICONV && msdosfs_iconv) { + outp = outbuf; + olen = 2; + if (lower & (LCASE_BASE | LCASE_EXT)) + msdosfs_iconv->convchr_case(pmp->pm_u2w, (const char **)instr, + ilen, (char **)&outp, &olen, + KICONV_FROM_LOWER); + else + msdosfs_iconv->convchr(pmp->pm_u2w, (const char **)instr, + ilen, (char **)&outp, &olen); + + /* + * return '0' if end of filename + */ + if (olen == 2) + return (0); + + wc = (outbuf[0]<<8) | outbuf[1]; + + return (wc); + } + + (*ilen)--; + wc = (*instr)[0]; + if (lower & (LCASE_BASE | LCASE_EXT)) + wc = u2l[wc]; + (*instr)++; + return (wc); +} + +/* + * Make subent empty + */ +void +mbnambuf_init(void) +{ + int i; + + for (i = 0; i < WIN_MAXSUBENTRIES; i++) { + if (subent[i].p) { + free(subent[i].p, M_MSDOSFSMNT); + subent[i].p = NULL; + subent[i].n = 0; + } + } +} + +/* + * Write a subent entry from a slot + */ +void +mbnambuf_write(char *name, int id) +{ + if (subent[id].p) { + printf("mbnambuf_write(): %s -> %s\n", subent[id].p, name); + free(subent[id].p, M_MSDOSFSMNT); + } + subent[id].n = strlen(name); + subent[id].p = malloc(subent[id].n + 1, M_MSDOSFSMNT, M_WAITOK); + strcpy(subent[id].p, name); +} + +/* + * Combine each subents to the *dp and initialize subent + */ +char * +mbnambuf_flush(struct dirent *dp) +{ + int i; + char *name = dp->d_name; + + *name = '\0'; + dp->d_namlen = 0; + for (i = 0; i < WIN_MAXSUBENTRIES; i++) { + if (subent[i].p) { + if (dp->d_namlen + subent[i].n > sizeof(dp->d_name) - 1) { + mbnambuf_init(); + return (NULL); + } + strcpy(name, subent[i].p); + dp->d_namlen += subent[i].n; + name += subent[i].n; + } + } + mbnambuf_init(); + return (dp->d_name); } Index: sys/fs/msdosfs/msdosfs_iconv.c =================================================================== RCS file: sys/fs/msdosfs/msdosfs_iconv.c diff -N sys/fs/msdosfs/msdosfs_iconv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/fs/msdosfs/msdosfs_iconv.c 10 Sep 2003 17:02:02 -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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +VFS_DECLARE_ICONV(msdosfs); Index: sys/fs/msdosfs/msdosfs_lookup.c =================================================================== RCS file: /home/ncvs/src/sys/fs/msdosfs/msdosfs_lookup.c,v retrieving revision 1.38 diff -u -r1.38 msdosfs_lookup.c --- sys/fs/msdosfs/msdosfs_lookup.c 4 Aug 2002 10:29:26 -0000 1.38 +++ sys/fs/msdosfs/msdosfs_lookup.c 10 Sep 2003 17:02:02 -0000 @@ -57,9 +57,9 @@ #include #include +#include #include #include -#include #include /* @@ -150,21 +150,19 @@ } switch (unix2dosfn((const u_char *)cnp->cn_nameptr, dosfilename, - cnp->cn_namelen, 0, - pmp->pm_flags & MSDOSFSMNT_U2WTABLE, pmp->pm_u2d, - pmp->pm_flags & MSDOSFSMNT_ULTABLE, pmp->pm_lu)) { + cnp->cn_namelen, 0, pmp)) { case 0: return (EINVAL); case 1: break; case 2: wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, - cnp->cn_namelen) + 1; + cnp->cn_namelen, pmp) + 1; break; case 3: olddos = 0; wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr, - cnp->cn_namelen) + 1; + cnp->cn_namelen, pmp) + 1; break; } if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) { @@ -193,6 +191,7 @@ * by cnp->cn_nameptr. */ tdp = NULL; + mbnambuf_init(); /* * The outer loop ranges over the clusters that make up the * directory. Note that the root directory is different from all @@ -232,6 +231,7 @@ * Drop memory of previous long matches */ chksum = -1; + mbnambuf_init(); if (slotcount < wincnt) { slotcount++; @@ -256,14 +256,18 @@ if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) continue; - chksum = winChkName((const u_char *)cnp->cn_nameptr, - unlen, - (struct winentry *)dep, + chksum = win2unixfn((struct winentry *)dep, chksum, - pmp->pm_flags & MSDOSFSMNT_U2WTABLE, - pmp->pm_u2w, - pmp->pm_flags & MSDOSFSMNT_ULTABLE, - pmp->pm_ul); + pmp); + continue; + } + + chksum = winChkName((const u_char *)cnp->cn_nameptr, + unlen, + chksum, + pmp); + if (chksum == -2) { + chksum = -1; continue; } @@ -659,9 +663,7 @@ ddep->de_fndoffset -= sizeof(struct direntry); } if (!unix2winfn(un, unlen, (struct winentry *)ndep, - cnt++, chksum, - pmp->pm_flags & MSDOSFSMNT_U2WTABLE, - pmp->pm_u2w)) + cnt++, chksum, pmp)) break; } } @@ -992,19 +994,14 @@ if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) return (unix2dosfn((const u_char *)cnp->cn_nameptr, cp, - cnp->cn_namelen, 0, - pmp->pm_flags & MSDOSFSMNT_U2WTABLE, pmp->pm_u2d, - pmp->pm_flags & MSDOSFSMNT_ULTABLE, pmp->pm_lu) ? - 0 : EINVAL); + cnp->cn_namelen, 0, pmp) ? 0 : EINVAL); for (gen = 1;; gen++) { /* * Generate DOS name with generation number */ if (!unix2dosfn((const u_char *)cnp->cn_nameptr, cp, - cnp->cn_namelen, gen, - pmp->pm_flags & MSDOSFSMNT_U2WTABLE, pmp->pm_u2d, - pmp->pm_flags & MSDOSFSMNT_ULTABLE, pmp->pm_lu)) + cnp->cn_namelen, gen, pmp)) return gen == 1 ? EINVAL : EEXIST; /* Index: sys/fs/msdosfs/msdosfs_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/fs/msdosfs/msdosfs_vfsops.c,v retrieving revision 1.101 diff -u -r1.101 msdosfs_vfsops.c --- sys/fs/msdosfs/msdosfs_vfsops.c 24 Apr 2003 18:19:19 -0000 1.101 +++ sys/fs/msdosfs/msdosfs_vfsops.c 10 Sep 2003 17:02:02 -0000 @@ -61,13 +61,14 @@ #include #include #include /* defines ALLPERMS */ +#include #include #include #include +#include #include #include -#include #include #define MSDOSFS_DFLTBSIZE 4096 @@ -86,6 +87,8 @@ MALLOC_DEFINE(M_MSDOSFSMNT, "MSDOSFS mount", "MSDOSFS mount structure"); static MALLOC_DEFINE(M_MSDOSFSFAT, "MSDOSFS FAT", "MSDOSFS file allocation table"); +struct iconv_functions *msdosfs_iconv = NULL; + static int update_mp(struct mount *mp, struct msdosfs_args *argp); static int mountmsdosfs(struct vnode *devvp, struct mount *mp, struct thread *td, struct msdosfs_args *argp); @@ -109,14 +112,16 @@ pmp->pm_uid = argp->uid; pmp->pm_mask = argp->mask & ALLPERMS; pmp->pm_flags |= argp->flags & MSDOSFSMNT_MNTOPT; - if (pmp->pm_flags & MSDOSFSMNT_U2WTABLE) { - bcopy(argp->u2w, pmp->pm_u2w, sizeof(pmp->pm_u2w)); - bcopy(argp->d2u, pmp->pm_d2u, sizeof(pmp->pm_d2u)); - bcopy(argp->u2d, pmp->pm_u2d, sizeof(pmp->pm_u2d)); - } - if (pmp->pm_flags & MSDOSFSMNT_ULTABLE) { - bcopy(argp->ul, pmp->pm_ul, sizeof(pmp->pm_ul)); - bcopy(argp->lu, pmp->pm_lu, sizeof(pmp->pm_lu)); + if (pmp->pm_flags & MSDOSFSMNT_KICONV && msdosfs_iconv) { + msdosfs_iconv->open(argp->cs_win, argp->cs_local , &pmp->pm_u2w); + msdosfs_iconv->open(argp->cs_local, argp->cs_win , &pmp->pm_w2u); + msdosfs_iconv->open(argp->cs_dos, argp->cs_local , &pmp->pm_u2d); + msdosfs_iconv->open(argp->cs_local, argp->cs_dos , &pmp->pm_d2u); + } else { + pmp->pm_w2u = NULL; + pmp->pm_u2w = NULL; + pmp->pm_d2u = NULL; + pmp->pm_u2d = NULL; } if (pmp->pm_flags & MSDOSFSMNT_NOWIN95) @@ -636,6 +641,16 @@ if (error) return error; pmp = VFSTOMSDOSFS(mp); + if (pmp->pm_flags & MSDOSFSMNT_KICONV && msdosfs_iconv) { + if (pmp->pm_w2u) + msdosfs_iconv->close(pmp->pm_w2u); + if (pmp->pm_u2w) + msdosfs_iconv->close(pmp->pm_u2w); + if (pmp->pm_d2u) + msdosfs_iconv->close(pmp->pm_d2u); + if (pmp->pm_u2d) + msdosfs_iconv->close(pmp->pm_u2d); + } pmp->pm_devvp->v_rdev->si_mountpoint = NULL; #ifdef MSDOSFS_DEBUG { @@ -849,3 +864,4 @@ }; VFS_SET(msdosfs_vfsops, msdosfs, 0); +MODULE_VERSION(msdosfs, 1); Index: sys/fs/msdosfs/msdosfs_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/fs/msdosfs/msdosfs_vnops.c,v retrieving revision 1.136 diff -u -r1.136 msdosfs_vnops.c --- sys/fs/msdosfs/msdosfs_vnops.c 4 Mar 2003 00:04:42 -0000 1.136 +++ sys/fs/msdosfs/msdosfs_vnops.c 10 Sep 2003 17:02:02 -0000 @@ -71,9 +71,9 @@ #include #include +#include #include #include -#include #include #define DOS_FILESIZE_MAX 0xffffffff @@ -1559,6 +1559,7 @@ } } + mbnambuf_init(); off = offset; while (uio->uio_resid > 0) { lbn = de_cluster(pmp, offset - bias); @@ -1601,6 +1602,7 @@ */ if (dentp->deName[0] == SLOT_DELETED) { chksum = -1; + mbnambuf_init(); continue; } @@ -1611,9 +1613,7 @@ if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME) continue; chksum = win2unixfn((struct winentry *)dentp, - &dirbuf, chksum, - pmp->pm_flags & MSDOSFSMNT_U2WTABLE, - pmp->pm_u2w); + chksum, pmp); continue; } @@ -1622,6 +1622,7 @@ */ if (dentp->deAttributes & ATTR_VOLUME) { chksum = -1; + mbnambuf_init(); continue; } /* @@ -1649,18 +1650,16 @@ dirbuf.d_fileno = offset / sizeof(struct direntry); dirbuf.d_type = DT_REG; } - if (chksum != winChksum(dentp->deName)) + if (chksum != winChksum(dentp->deName)) { dirbuf.d_namlen = dos2unixfn(dentp->deName, (u_char *)dirbuf.d_name, dentp->deLowerCase | ((pmp->pm_flags & MSDOSFSMNT_SHORTNAME) ? (LCASE_BASE | LCASE_EXT) : 0), - pmp->pm_flags & MSDOSFSMNT_U2WTABLE, - pmp->pm_d2u, - pmp->pm_flags & MSDOSFSMNT_ULTABLE, - pmp->pm_ul); - else - dirbuf.d_name[dirbuf.d_namlen] = 0; + pmp); + mbnambuf_init(); + } else + mbnambuf_flush(&dirbuf); chksum = -1; dirbuf.d_reclen = GENERIC_DIRSIZ(&dirbuf); if (uio->uio_resid < dirbuf.d_reclen) { Index: sys/fs/msdosfs/msdosfsmount.h =================================================================== RCS file: /home/ncvs/src/sys/fs/msdosfs/msdosfsmount.h,v retrieving revision 1.27 diff -u -r1.27 msdosfsmount.h --- sys/fs/msdosfs/msdosfsmount.h 16 May 2002 21:25:37 -0000 1.27 +++ sys/fs/msdosfs/msdosfsmount.h 10 Sep 2003 17:02:02 -0000 @@ -92,11 +92,10 @@ u_int pm_curfat; /* current fat for FAT32 (0 otherwise) */ u_int *pm_inusemap; /* ptr to bitmap of in-use clusters */ u_int pm_flags; /* see below */ - u_int16_t pm_u2w[128]; /* Local->Unicode table */ - u_int8_t pm_ul[128]; /* Local upper->lower table */ - u_int8_t pm_lu[128]; /* Local lower->upper table */ - u_int8_t pm_d2u[128]; /* DOS->local table */ - u_int8_t pm_u2d[128]; /* Local->DOS table */ + void *pm_u2w; /* Local->Unicode iconv handle */ + void *pm_w2u; /* Unicode->Local iconv handle */ + void *pm_u2d; /* Unicode->DOS iconv handle */ + void *pm_d2u; /* DOS->Local iconv handle */ }; /* Byte offset in FAT on filesystem pmp, cluster cn */ #define FATOFS(pmp, cn) ((cn) * (pmp)->pm_fatmult / (pmp)->pm_fatdiv) @@ -214,10 +213,9 @@ int flags; /* see below */ int magic; /* version number */ u_int16_t u2w[128]; /* Local->Unicode table */ - u_int8_t ul[128]; /* Local upper->lower table */ - u_int8_t lu[128]; /* Local lower->upper table */ - u_int8_t d2u[128]; /* DOS->local table */ - u_int8_t u2d[128]; /* Local->DOS table */ + char *cs_win; /* Windows(Unicode) Charset */ + char *cs_dos; /* DOS Charset */ + char *cs_local; /* Local Charset */ }; /* @@ -226,13 +224,11 @@ #define MSDOSFSMNT_SHORTNAME 1 /* Force old DOS short names only */ #define MSDOSFSMNT_LONGNAME 2 /* Force Win'95 long names */ #define MSDOSFSMNT_NOWIN95 4 /* Completely ignore Win95 entries */ -#define MSDOSFSMNT_U2WTABLE 0x10 /* Local->Unicode and local<->DOS */ - /* tables loaded */ -#define MSDOSFSMNT_ULTABLE 0x20 /* Local upper<->lower table loaded */ +#define MSDOSFSMNT_KICONV 0x10 /* Use libiconv to convert chars */ /* All flags above: */ #define MSDOSFSMNT_MNTOPT \ (MSDOSFSMNT_SHORTNAME|MSDOSFSMNT_LONGNAME|MSDOSFSMNT_NOWIN95 \ - |MSDOSFSMNT_U2WTABLE|MSDOSFSMNT_ULTABLE) + |MSDOSFSMNT_KICONV) #define MSDOSFSMNT_RONLY 0x80000000 /* mounted read-only */ #define MSDOSFSMNT_WAITONFAT 0x40000000 /* mounted synchronous */ #define MSDOSFS_FATMIRROR 0x20000000 /* FAT is mirrored */ Index: sys/fs/ntfs/ntfs.h =================================================================== RCS file: /home/ncvs/src/sys/fs/ntfs/ntfs.h,v retrieving revision 1.14 diff -u -r1.14 ntfs.h --- sys/fs/ntfs/ntfs.h 27 Nov 2001 00:18:33 -0000 1.14 +++ sys/fs/ntfs/ntfs.h 10 Sep 2003 17:02:02 -0000 @@ -254,6 +254,8 @@ int ntm_adnum; 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 Index: sys/fs/ntfs/ntfs_iconv.c =================================================================== RCS file: sys/fs/ntfs/ntfs_iconv.c diff -N sys/fs/ntfs/ntfs_iconv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/fs/ntfs/ntfs_iconv.c 10 Sep 2003 17:02:02 -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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +VFS_DECLARE_ICONV(ntfs); Index: sys/fs/ntfs/ntfs_subr.c =================================================================== RCS file: /home/ncvs/src/sys/fs/ntfs/ntfs_subr.c,v retrieving revision 1.29 diff -u -r1.29 ntfs_subr.c --- sys/fs/ntfs/ntfs_subr.c 4 Mar 2003 00:04:42 -0000 1.29 +++ sys/fs/ntfs/ntfs_subr.c 10 Sep 2003 17:02:02 -0000 @@ -40,6 +40,7 @@ #include #include #include +#include /* #define NTFS_DEBUG 1 */ #include @@ -67,6 +68,8 @@ static struct lock ntfs_toupper_lock; static signed int ntfs_toupper_usecount; +struct iconv_functions *ntfs_iconv = NULL; + /* support macro for ntfs_ntvattrget() */ #define NTFS_AALPCMP(aalp,type,name,namelen) ( \ (aalp->al_type == type) && (aalp->al_namelen == namelen) && \ @@ -665,20 +668,40 @@ const char *astr; size_t astrlen; { - size_t i; - int res; + size_t i, j, len, 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); } /* @@ -692,15 +715,25 @@ 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); } /* @@ -1986,11 +2019,18 @@ int ntfs_u28_init( struct ntfsmount *ntmp, - wchar *u2w) + 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++) { @@ -2017,8 +2057,12 @@ char ** u28; int i; - if (ntmp->ntm_u28 == NULL) + if (ntmp->ntm_u28 == NULL) { + if (ntfs_iconv && ntmp->ntm_ic_u2l) { + ntfs_iconv->close(ntmp->ntm_ic_u2l); + } return (0); + } u28 = ntmp->ntm_u28; @@ -2034,22 +2078,21 @@ int ntfs_82u_init( struct ntfsmount *ntmp, - u_int16_t *u2w) + 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++) + for (i=0; i<256; i++) _82u[i] = i; - for (i=0; i<128; i++) - _82u[i+128] = u2w[i]; - } ntmp->ntm_82u = _82u; @@ -2059,6 +2102,14 @@ 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); } @@ -2069,16 +2120,68 @@ * 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])); + } else if (olen == 0) { + return ((wchar)((outbuf[0]<<8) | (outbuf[1]&0xFF))); + } + return ('?'); + } p = ntmp->ntm_u28[(wc>>8)&0xFF]; if (p == NULL) return ('_'); 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 ('?'); } Index: sys/fs/ntfs/ntfs_subr.h =================================================================== RCS file: /home/ncvs/src/sys/fs/ntfs/ntfs_subr.h,v retrieving revision 1.12 diff -u -r1.12 ntfs_subr.h --- sys/fs/ntfs/ntfs_subr.h 19 Mar 2002 22:20:11 -0000 1.12 +++ sys/fs/ntfs/ntfs_subr.h 10 Sep 2003 17:02:02 -0000 @@ -108,13 +108,14 @@ 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) \ Index: sys/fs/ntfs/ntfs_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/fs/ntfs/ntfs_vfsops.c,v retrieving revision 1.53 diff -u -r1.53 ntfs_vfsops.c --- sys/fs/ntfs/ntfs_vfsops.c 11 Mar 2003 22:15:08 -0000 1.53 +++ sys/fs/ntfs/ntfs_vfsops.c 10 Sep 2003 17:02:02 -0000 @@ -342,15 +342,15 @@ 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); + /* Initialize Unicode to 8-bit table from 8toU table */ + if (argsp->flag & NTFS_MFLAG_KICONV) { + ntfs_82u_init(ntmp, argsp->cs_local, argsp->cs_ntfs); + ntfs_u28_init(ntmp, NULL, argsp->cs_local, argsp->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", @@ -791,3 +791,4 @@ vfs_stdextattrctl, }; VFS_SET(ntfs_vfsops, ntfs, 0); +MODULE_VERSION(ntfs, 1); Index: sys/fs/ntfs/ntfs_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/fs/ntfs/ntfs_vnops.c,v retrieving revision 1.38 diff -u -r1.38 ntfs_vnops.c --- sys/fs/ntfs/ntfs_vnops.c 3 Mar 2003 19:15:38 -0000 1.38 +++ sys/fs/ntfs/ntfs_vnops.c 10 Sep 2003 17:02:02 -0000 @@ -493,7 +493,8 @@ register 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; int ncookies = 0; struct dirent cde; @@ -550,14 +551,17 @@ if(!ntfs_isnamepermitted(ntmp,iep)) continue; - for(i=0; iie_fnamelen; i++) { - cde.d_name[i] = NTFS_U28(iep->ie_fname[i]); + for(i=0, j=0; iie_fnamelen; i++, j++) { + c = NTFS_U28(iep->ie_fname[i]); + if (c&0xFF00) + cde.d_name[j++] = (char)(c>>8); + cde.d_name[j] = (char)c&0xFF; } - cde.d_name[i] = '\0'; + cde.d_name[j] = '\0'; dprintf(("ntfs_readdir: elem: %d, fname:[%s] type: %d, flag: %d, ", num, cde.d_name, iep->ie_fnametype, iep->ie_flag)); - cde.d_namlen = iep->ie_fnamelen; + cde.d_namlen = j; cde.d_fileno = iep->ie_number; cde.d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG; cde.d_reclen = sizeof(struct dirent); Index: sys/fs/ntfs/ntfsmount.h =================================================================== RCS file: /home/ncvs/src/sys/fs/ntfs/ntfsmount.h,v retrieving revision 1.7 diff -u -r1.7 ntfsmount.h --- sys/fs/ntfs/ntfsmount.h 8 Sep 2001 23:03:52 -0000 1.7 +++ sys/fs/ntfs/ntfsmount.h 10 Sep 2003 17:02:02 -0000 @@ -30,7 +30,7 @@ #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 */ @@ -39,5 +39,6 @@ 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 */ + char *cs_ntfs; /* NTFS Charset */ + char *cs_local; /* Local Charset */ }; Index: sys/isofs/cd9660/cd9660_iconv.c =================================================================== RCS file: sys/isofs/cd9660/cd9660_iconv.c diff -N sys/isofs/cd9660/cd9660_iconv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/isofs/cd9660/cd9660_iconv.c 10 Sep 2003 17:02:02 -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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +VFS_DECLARE_ICONV(cd9660); Index: sys/isofs/cd9660/cd9660_lookup.c =================================================================== RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_lookup.c,v retrieving revision 1.33 diff -u -r1.33 cd9660_lookup.c --- sys/isofs/cd9660/cd9660_lookup.c 16 May 2002 21:25:46 -0000 1.33 +++ sys/isofs/cd9660/cd9660_lookup.c 10 Sep 2003 17:02:02 -0000 @@ -239,7 +239,12 @@ 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 Index: sys/isofs/cd9660/cd9660_mount.h =================================================================== RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_mount.h,v retrieving revision 1.5 diff -u -r1.5 cd9660_mount.h --- sys/isofs/cd9660/cd9660_mount.h 11 Mar 2001 10:05:08 -0000 1.5 +++ sys/isofs/cd9660/cd9660_mount.h 10 Sep 2003 17:02:02 -0000 @@ -47,9 +47,12 @@ 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 */ Index: sys/isofs/cd9660/cd9660_rrip.c =================================================================== RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_rrip.c,v retrieving revision 1.23 diff -u -r1.23 cd9660_rrip.c --- sys/isofs/cd9660/cd9660_rrip.c 25 Aug 2002 13:17:18 -0000 1.23 +++ sys/isofs/cd9660/cd9660_rrip.c 10 Sep 2003 17:02:02 -0000 @@ -291,7 +291,8 @@ { 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; @@ -489,7 +490,7 @@ register ISO_SUSP_HEADER *pend; struct buf *bp = NULL; char *pwhead; - u_char c; + u_short c; int result; /* @@ -499,7 +500,8 @@ 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) @@ -625,7 +627,7 @@ { ISO_RRIP_ANALYZE analyze; RRIP_TABLE *tab; - u_char c; + u_short c; analyze.outbuf = outbuf; analyze.outlen = outlen; @@ -636,7 +638,7 @@ *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); Index: sys/isofs/cd9660/cd9660_util.c =================================================================== RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_util.c,v retrieving revision 1.19 diff -u -r1.19 cd9660_util.c --- sys/isofs/cd9660/cd9660_util.c 4 May 2002 02:37:00 -0000 1.19 +++ sys/isofs/cd9660/cd9660_util.c 10 Sep 2003 17:02:02 -0000 @@ -44,16 +44,12 @@ #include #include #include +#include #include +#include -/* - * 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,29 +57,47 @@ * 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; } @@ -94,53 +108,60 @@ * 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; } @@ -156,7 +177,7 @@ * 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; @@ -164,25 +185,61 @@ 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); } Index: sys/isofs/cd9660/cd9660_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_vfsops.c,v retrieving revision 1.109 diff -u -r1.109 cd9660_vfsops.c --- sys/isofs/cd9660/cd9660_vfsops.c 11 Mar 2003 22:15:09 -0000 1.109 +++ sys/isofs/cd9660/cd9660_vfsops.c 10 Sep 2003 17:02:02 -0000 @@ -54,6 +54,7 @@ #include #include #include +#include #include @@ -64,6 +65,8 @@ 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; @@ -474,7 +477,16 @@ 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 */ @@ -554,6 +566,12 @@ 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); Index: sys/isofs/cd9660/cd9660_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_vnops.c,v retrieving revision 1.89 diff -u -r1.89 cd9660_vnops.c --- sys/isofs/cd9660/cd9660_vnops.c 3 Mar 2003 19:15:39 -0000 1.89 +++ sys/isofs/cd9660/cd9660_vnops.c 10 Sep 2003 17:02:02 -0000 @@ -560,7 +560,9 @@ 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); Index: sys/isofs/cd9660/iso.h =================================================================== RCS file: /home/ncvs/src/sys/isofs/cd9660/iso.h,v retrieving revision 1.24 diff -u -r1.24 iso.h --- sys/isofs/cd9660/iso.h 24 Mar 2002 04:35:23 -0000 1.24 +++ sys/isofs/cd9660/iso.h 10 Sep 2003 17:02:02 -0000 @@ -245,6 +245,9 @@ 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_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 */ Index: sys/libkern/iconv.c =================================================================== RCS file: /home/ncvs/src/sys/libkern/iconv.c,v retrieving revision 1.5 diff -u -r1.5 iconv.c --- sys/libkern/iconv.c 19 Feb 2003 05:47:28 -0000 1.5 +++ sys/libkern/iconv.c 10 Sep 2003 17:02:02 -0000 @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include "iconv_converter_if.h" @@ -46,7 +48,7 @@ MALLOC_DEFINE(M_ICONV, "ICONV", "ICONV structures"); MALLOC_DEFINE(M_ICONVDATA, "ICONV data", "ICONV data"); -MODULE_VERSION(libiconv, 1); +MODULE_VERSION(libiconv, 2); #ifdef notnow /* @@ -270,7 +272,28 @@ iconv_conv(void *handle, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { - return ICONV_CONVERTER_CONV(handle, inbuf, inbytesleft, outbuf, outbytesleft); + return ICONV_CONVERTER_CONV(handle, inbuf, inbytesleft, outbuf, outbytesleft, 0, 0); +} + +int +iconv_conv_case(void *handle, const char **inbuf, + size_t *inbytesleft, char **outbuf, size_t *outbytesleft, int casetype) +{ + return ICONV_CONVERTER_CONV(handle, inbuf, inbytesleft, outbuf, outbytesleft, 0, casetype); +} + +int +iconv_convchr(void *handle, const char **inbuf, + size_t *inbytesleft, char **outbuf, size_t *outbytesleft) +{ + return ICONV_CONVERTER_CONV(handle, inbuf, inbytesleft, outbuf, outbytesleft, 1, 0); +} + +int +iconv_convchr_case(void *handle, const char **inbuf, + size_t *inbytesleft, char **outbuf, size_t *outbytesleft, int casetype) +{ + return ICONV_CONVERTER_CONV(handle, inbuf, inbytesleft, outbuf, outbytesleft, 1, casetype); } /* @@ -369,6 +392,7 @@ error = SYSCTL_OUT(req, &dout, sizeof(dout)); if (error) goto bad; + ICDEBUG("%s => %s, %d bytes\n",din.ia_from, din.ia_to, din.ia_datalen); return 0; bad: iconv_unregister_cspair(csp); @@ -419,7 +443,7 @@ } /* - * Common used functions + * Common used functions (don't use with unicode) */ char * iconv_convstr(void *handle, char *dst, const char *src) @@ -432,7 +456,8 @@ strcpy(dst, src); return dst; } - inlen = outlen = strlen(src); + inlen = strlen(src); + outlen = inlen * 3; error = iconv_conv(handle, NULL, NULL, &p, &outlen); if (error) return NULL; @@ -457,7 +482,8 @@ memcpy(dst, src, size); return dst; } - inlen = outlen = size; + inlen = size; + outlen = inlen * 3; error = iconv_conv(handle, NULL, NULL, &d, &outlen); if (error) return NULL; @@ -480,4 +506,23 @@ if (strcmp(*cpp, s) == 0) return 0; return ENOENT; +} + +/* + * Return if fsname is in use of not + */ +int +iconv_vfs_refcount(const char *fsname) +{ + struct vfsconf *vfsp; + + for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) { + if (!strcmp(vfsp->vfc_name, fsname)) { + if (vfsp->vfc_refcount > 0) + return (EBUSY); + else + return (0); + } + } + return (0); } Index: sys/libkern/iconv_converter_if.m =================================================================== RCS file: /home/ncvs/src/sys/libkern/iconv_converter_if.m,v retrieving revision 1.1 diff -u -r1.1 iconv_converter_if.m --- sys/libkern/iconv_converter_if.m 9 Apr 2001 09:39:29 -0000 1.1 +++ sys/libkern/iconv_converter_if.m 10 Sep 2003 17:02:02 -0000 @@ -53,6 +53,8 @@ size_t *inbytesleft; char **outbuf; size_t *outbytesleft; + int convchar; + int casetype; }; STATICMETHOD int init { Index: sys/libkern/iconv_xlat.c =================================================================== RCS file: /home/ncvs/src/sys/libkern/iconv_xlat.c,v retrieving revision 1.3 diff -u -r1.3 iconv_xlat.c --- sys/libkern/iconv_xlat.c 19 Feb 2003 05:47:28 -0000 1.3 +++ sys/libkern/iconv_xlat.c 10 Sep 2003 17:02:02 -0000 @@ -44,7 +44,7 @@ */ #ifdef MODULE_DEPEND -MODULE_DEPEND(iconv_xlat, libiconv, 1, 1, 1); +MODULE_DEPEND(iconv_xlat, libiconv, 2, 2, 2); #endif /* @@ -82,7 +82,8 @@ static int iconv_xlat_conv(void *d2p, const char **inbuf, - size_t *inbytesleft, char **outbuf, size_t *outbytesleft) + size_t *inbytesleft, char **outbuf, size_t *outbytesleft, + int convchar, int casetype) { struct iconv_xlat *dp = (struct iconv_xlat*)d2p; const char *src; @@ -91,14 +92,19 @@ if (inbuf == NULL || *inbuf == NULL || outbuf == NULL || *outbuf == NULL) return 0; - r = n = min(*inbytesleft, *outbytesleft); + if (casetype != 0) + return -1; + if (convchar == 1) + r = n = 1; + else + r = n = min(*inbytesleft, *outbytesleft); src = *inbuf; dst = *outbuf; while(r--) *dst++ = dp->d_table[(u_char)*src++]; *inbuf += n; *outbuf += n; - *inbytesleft += n; + *inbytesleft -= n; *outbytesleft -= n; return 0; } Index: sys/libkern/iconv_xlat16.c =================================================================== RCS file: sys/libkern/iconv_xlat16.c diff -N sys/libkern/iconv_xlat16.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/libkern/iconv_xlat16.c 10 Sep 2003 17:02:02 -0000 @@ -0,0 +1,242 @@ +/*- + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include "iconv_converter_if.h" + +/* + * "XLAT16" converter + */ + +#ifdef MODULE_DEPEND +MODULE_DEPEND(iconv_xlat16, libiconv, 2, 2, 2); +#endif + +/* + * XLAT16 converter instance + */ +struct iconv_xlat16 { + KOBJ_FIELDS; + uint32_t * d_table[0x200]; + struct iconv_cspair * d_csp; +}; + +static int +iconv_xlat16_open(struct iconv_converter_class *dcp, + struct iconv_cspair *csp, struct iconv_cspair *cspf, void **dpp) +{ + struct iconv_xlat16 *dp; + uint32_t *headp, *idxp, dist = 0; + int i; + + dp = (struct iconv_xlat16 *)kobj_create((struct kobj_class*)dcp, M_ICONV, M_WAITOK); + headp = idxp = (uint32_t *)csp->cp_data; + dist = 0x200; + for (i = 0 ; i < 0x200 ; i++) { + if (*idxp) { + dp->d_table[i] = headp + dist; + dist += 0x80; + } else { + dp->d_table[i] = NULL; + } + idxp++; + } + dp->d_csp = csp; + csp->cp_refcount++; + *dpp = (void*)dp; + return (0); +} + +static int +iconv_xlat16_close(void *data) +{ + struct iconv_xlat16 *dp = data; + + dp->d_csp->cp_refcount--; + kobj_delete((struct kobj*)data, M_ICONV); + return (0); +} + +static int +iconv_xlat16_conv(void *d2p, const char **inbuf, + size_t *inbytesleft, char **outbuf, size_t *outbytesleft, + int convchar, int casetype) +{ + struct iconv_xlat16 *dp = (struct iconv_xlat16*)d2p; + const char *src; + char *dst; + int ret = 0; + size_t in, on, ir, or, inlen; + uint32_t code; + u_char u, l; + u_int16_t c1, c2; + + if (inbuf == NULL || *inbuf == NULL || outbuf == NULL || *outbuf == NULL) + return (0); + ir = in = *inbytesleft; + or = on = *outbytesleft; + src = *inbuf; + dst = *outbuf; + + while(ir > 0 && or > 0) { + + inlen = 0; + code = '\0'; + + c1 = ir > 1 ? *(src+1) & 0xff : 0; + c2 = *src & 0xff; + + c1 = c2 & 0x80 ? c1 | 0x100 : c1; + c2 = c2 & 0x80 ? c2 & 0x7f : c2; + + if (ir > 1 && dp->d_table[c1]) { + /* + * inbuf char is a double byte char + */ + code = dp->d_table[c1][c2]; + if (code) + inlen = 2; + } + + if (inlen == 0) { + c1 &= 0xff00; + if (!dp->d_table[c1]) { + ret = -1; + break; + } + /* + * inbuf char is a single byte char + */ + inlen = 1; + code = dp->d_table[c1][c2]; + if (!code) { + ret = -1; + break; + } + } + + if ((inlen == 1) && (code & XLAT16_ACCEPT_NULL_IN)) { + /* + * XLAT16_ACCEPT_NULL_IN requires inbuf has 2byte + */ + ret = -1; + break; + } + + /* + * now start translation + */ + u = (u_char)(code >> 8); + l = (u_char)code; + +#ifdef XLAT16_ACCEPT_3BYTE_CHR + if (code & XLAT16_IS_3BYTE_CHR) { + if (or < 3) { + ret = -1; + break; + } + *dst++ = u; + *dst++ = l; + *dst++ = (u_char)(code >> 16); + or -= 3; + } else +#endif + if (u || code & XLAT16_ACCEPT_NULL_OUT) { + if (or < 2) { + ret = -1; + break; + } + *dst++ = u; + *dst++ = l; + or -= 2; + } else { + if ((casetype == KICONV_LOWER && code & XLAT16_HAS_LOWER_CASE) || + (casetype == KICONV_UPPER && code & XLAT16_HAS_UPPER_CASE)) + *dst++ = (u_char)(code >> 16); + else if ((casetype == KICONV_FROM_LOWER && code & XLAT16_HAS_FROM_LOWER_CASE) || + (casetype == KICONV_FROM_UPPER && code & XLAT16_HAS_FROM_UPPER_CASE)) + *dst++ = dp->d_table[0][(u_char)(code >> 16)]; + else + *dst++ = l; + or--; + } + + if (inlen == 2) { + /* + * there is a case that inbuf char is a single + * byte char while inlen == 2 + */ + if ((u_char)*(src+1) == 0 && + (code & XLAT16_ACCEPT_NULL_IN) == 0 ) { + src++; + ir--; + } else { + src += 2; + ir -= 2; + } + } else { + src++; + ir--; + } + + if (convchar == 1) + break; + } + + *inbuf += in - ir; + *outbuf += on - or; + *inbytesleft -= in - ir; + *outbytesleft -= on - or; + return (ret); +} + +static const char * +iconv_xlat16_name(struct iconv_converter_class *dcp) +{ + return ("xlat16"); +} + +static kobj_method_t iconv_xlat16_methods[] = { + KOBJMETHOD(iconv_converter_open, iconv_xlat16_open), + KOBJMETHOD(iconv_converter_close, iconv_xlat16_close), + KOBJMETHOD(iconv_converter_conv, iconv_xlat16_conv), +#if 0 + KOBJMETHOD(iconv_converter_init, iconv_xlat16_init), + KOBJMETHOD(iconv_converter_done, iconv_xlat16_done), +#endif + KOBJMETHOD(iconv_converter_name, iconv_xlat16_name), + {0, 0} +}; + +KICONV_CONVERTER(xlat16, sizeof(struct iconv_xlat16)); Index: sys/modules/Makefile =================================================================== RCS file: /home/ncvs/src/sys/modules/Makefile,v retrieving revision 1.323 diff -u -r1.323 Makefile --- sys/modules/Makefile 13 May 2003 11:26:08 -0000 1.323 +++ sys/modules/Makefile 20 Jul 2003 18:33:10 -0000 @@ -22,6 +22,7 @@ cam \ ccd \ cd9660 \ + cd9660_iconv \ coda \ ${_crypto} \ ${_cryptodev} \ @@ -75,12 +76,14 @@ mlx \ mpt \ msdosfs \ + msdosfs_iconv \ my \ nfsclient \ nfsserver \ nge \ nmdm \ ntfs \ + ntfs_iconv \ nullfs \ pcn \ plip \ Index: sys/modules/cd9660/Makefile =================================================================== RCS file: /home/ncvs/src/sys/modules/cd9660/Makefile,v retrieving revision 1.14 diff -u -r1.14 Makefile --- sys/modules/cd9660/Makefile 11 Jan 2002 15:48:37 -0000 1.14 +++ sys/modules/cd9660/Makefile 20 Jul 2003 18:51:32 -0000 @@ -6,6 +6,6 @@ SRCS= vnode_if.h \ cd9660_bmap.c cd9660_lookup.c cd9660_node.c cd9660_rrip.c \ cd9660_util.c cd9660_vfsops.c cd9660_vnops.c -EXPORT_SYMS= cd9660_wchar2char +EXPORT_SYMS= cd9660_iconv .include Index: sys/modules/cd9660_iconv/Makefile =================================================================== RCS file: sys/modules/cd9660_iconv/Makefile diff -N sys/modules/cd9660_iconv/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/modules/cd9660_iconv/Makefile 20 Jul 2003 18:33:40 -0000 @@ -0,0 +1,7 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../isofs/cd9660 +KMOD= cd9660_iconv +SRCS= cd9660_iconv.c + +.include Index: sys/modules/libiconv/Makefile =================================================================== RCS file: /home/ncvs/src/sys/modules/libiconv/Makefile,v retrieving revision 1.3 diff -u -r1.3 Makefile --- sys/modules/libiconv/Makefile 11 Jan 2002 15:48:49 -0000 1.3 +++ sys/modules/libiconv/Makefile 21 Jul 2003 11:03:51 -0000 @@ -3,7 +3,7 @@ .PATH: ${.CURDIR}/../../libkern ${.CURDIR}/../../sys KMOD= libiconv -SRCS= iconv.c iconv_xlat.c +SRCS= iconv.c iconv_xlat.c iconv_xlat16.c SRCS+= iconv.h SRCS+= iconv_converter_if.c iconv_converter_if.h MFILES= libkern/iconv_converter_if.m @@ -11,7 +11,11 @@ EXPORT_SYMS= iconv_open \ iconv_close \ iconv_conv \ + iconv_conv_case \ + iconv_convchr \ + iconv_convchr_case \ iconv_convstr \ - iconv_convmem + iconv_convmem \ + iconv_vfs_refcount .include Index: sys/modules/msdosfs/Makefile =================================================================== RCS file: /home/ncvs/src/sys/modules/msdosfs/Makefile,v retrieving revision 1.19 diff -u -r1.19 Makefile --- sys/modules/msdosfs/Makefile 6 Nov 2002 13:46:59 -0000 1.19 +++ sys/modules/msdosfs/Makefile 20 Jul 2003 18:33:45 -0000 @@ -6,5 +6,6 @@ SRCS= vnode_if.h \ msdosfs_conv.c msdosfs_denode.c msdosfs_fat.c msdosfs_lookup.c \ msdosfs_vfsops.c msdosfs_vnops.c +EXPORT_SYMS= msdosfs_iconv .include Index: sys/modules/msdosfs_iconv/Makefile =================================================================== RCS file: sys/modules/msdosfs_iconv/Makefile diff -N sys/modules/msdosfs_iconv/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/modules/msdosfs_iconv/Makefile 20 Jul 2003 18:33:47 -0000 @@ -0,0 +1,7 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../fs/msdosfs +KMOD= msdosfs_iconv +SRCS= msdosfs_iconv.c + +.include Index: sys/modules/ntfs/Makefile =================================================================== RCS file: /home/ncvs/src/sys/modules/ntfs/Makefile,v retrieving revision 1.10 diff -u -r1.10 Makefile --- sys/modules/ntfs/Makefile 11 Jan 2002 15:48:55 -0000 1.10 +++ sys/modules/ntfs/Makefile 20 Jul 2003 18:51:53 -0000 @@ -6,5 +6,6 @@ SRCS= vnode_if.h \ ntfs_vfsops.c ntfs_vnops.c ntfs_subr.c ntfs_ihash.c \ ntfs_compr.c +EXPORT_SYMS= ntfs_iconv .include Index: sys/modules/ntfs_iconv/Makefile =================================================================== RCS file: sys/modules/ntfs_iconv/Makefile diff -N sys/modules/ntfs_iconv/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/modules/ntfs_iconv/Makefile 20 Jul 2003 18:33:52 -0000 @@ -0,0 +1,7 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../fs/ntfs +KMOD= ntfs_iconv +SRCS= ntfs_iconv.c + +.include Index: sys/sys/iconv.h =================================================================== RCS file: /home/ncvs/src/sys/sys/iconv.h,v retrieving revision 1.5 diff -u -r1.5 iconv.h --- sys/sys/iconv.h 15 Jul 2002 13:34:50 -0000 1.5 +++ sys/sys/iconv.h 10 Sep 2003 17:02:02 -0000 @@ -36,7 +36,20 @@ #define ICONV_CSNMAXLEN 31 /* maximum length of charset name */ #define ICONV_CNVNMAXLEN 31 /* maximum length of converter name */ -#define ICONV_CSMAXDATALEN 1024 /* maximum size of data associated with cs pair */ +#define ICONV_CSMAXDATALEN (2048+262144) /* maximum size of data associated with cs pair */ + +#define XLAT16_ACCEPT_NULL_OUT 0x01000000 +#define XLAT16_ACCEPT_NULL_IN 0x02000000 +#define XLAT16_HAS_LOWER_CASE 0x04000000 +#define XLAT16_HAS_UPPER_CASE 0x08000000 +#define XLAT16_HAS_FROM_LOWER_CASE 0x10000000 +#define XLAT16_HAS_FROM_UPPER_CASE 0x20000000 +#define XLAT16_IS_3BYTE_CHR 0x40000000 + +#define KICONV_LOWER 1 /* tolower converted character */ +#define KICONV_UPPER 2 /* toupper converted character */ +#define KICONV_FROM_LOWER 4 /* tolower source character, then convert */ +#define KICONV_FROM_UPPER 8 /* toupper source character, then convert */ /* * Entry for cslist sysctl @@ -74,7 +87,13 @@ __BEGIN_DECLS +#define ENCODING_UNICODE "ISO-10646-UCS-2" +#define KICONV_VENDOR_MICSFT 1 /* Microsoft Vendor Code for quirk */ + int kiconv_add_xlat_table(const char *, const char *, const u_char *); +int kiconv_add_xlat16_cspair(const char *, const char *, int); +int kiconv_add_xlat16_table(const char *, const char *, const void *, int); +const char *kiconv_quirkcs(const char *, int); __END_DECLS @@ -133,8 +152,74 @@ int iconv_close(void *handle); int iconv_conv(void *handle, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); +int iconv_conv_case(void *handle, const char **inbuf, + size_t *inbytesleft, char **outbuf, size_t *outbytesleft, int casetype); +int iconv_convchr(void *handle, const char **inbuf, + size_t *inbytesleft, char **outbuf, size_t *outbytesleft); +int iconv_convchr_case(void *handle, const char **inbuf, + size_t *inbytesleft, char **outbuf, size_t *outbytesleft, int casetype); char* iconv_convstr(void *handle, char *dst, const char *src); void* iconv_convmem(void *handle, void *dst, const void *src, int size); +int iconv_vfs_refcount(const char *fsname); + +/* + * Bridge struct of iconv functions + */ +struct iconv_functions { + int (*open)(const char *to, const char *from, void **handle); + int (*close)(void *handle); + int (*conv)(void *handle, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); + int (*conv_case)(void *handle, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft, int casetype); + int (*convchr)(void *handle, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); + int (*convchr_case)(void *handle, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft, int casetype); +}; + +#define VFS_DECLARE_ICONV(fsname) \ + static struct iconv_functions fsname ## _iconv_core = { \ + iconv_open, \ + iconv_close, \ + iconv_conv, \ + iconv_conv_case, \ + iconv_convchr, \ + iconv_convchr_case \ + }; \ + extern struct iconv_functions *fsname ## _iconv; \ + static int fsname ## _iconv_mod_handler(module_t mod, \ + int type, void *d); \ + static int \ + fsname ## _iconv_mod_handler(module_t mod, int type, void *d) \ + { \ + int error = 0; \ + switch(type) { \ + case MOD_LOAD: \ + fsname ## _iconv = & fsname ## _iconv_core; \ + break; \ + case MOD_UNLOAD: \ + error = iconv_vfs_refcount(#fsname); \ + if (error) \ + return (EBUSY); \ + fsname ## _iconv = NULL; \ + break; \ + default: \ + error = EINVAL; \ + break; \ + } \ + return (error); \ + } \ + static moduledata_t fsname ## _iconv_mod = { \ + #fsname"_iconv", \ + fsname ## _iconv_mod_handler, \ + NULL \ + }; \ + DECLARE_MODULE(fsname ## _iconv, fsname ## _iconv_mod, \ + SI_SUB_DRIVERS, SI_ORDER_ANY); \ + MODULE_DEPEND(fsname ## _iconv, fsname, 1, 1, 1); \ + MODULE_DEPEND(fsname ## _iconv, libiconv, 2, 2, 2); \ + MODULE_VERSION(fsname ## _iconv, 1) /* * Internal functions