- Support for multibyte charsets in LIBICONV.

- CD9660_ICONV, NTFS_ICONV and MSDOSFS_ICONV kernel options
(with corresponding modules).
- kiconv(3) for loadable charset conversion tables support.

Submitted by:	Ryuichiro Imura <imura@ryu16.org>
This commit is contained in:
fjoe 2003-09-26 20:26:25 +00:00
parent 0c8bfb6d00
commit 571ef024e3
75 changed files with 2731 additions and 981 deletions

View File

@ -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)

View File

@ -26,7 +26,7 @@ SUBDIR= ${_csu} libcom_err libcrypt libkvm msun libmd \
${_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} \

17
lib/libkiconv/Makefile Normal file
View File

@ -0,0 +1,17 @@
# $FreeBSD$
LIB= kiconv
SHLIBDIR?= /lib
SRCS= xlat16_iconv.c xlat16_sysctl.c
SRCS+= quirks.c
SHLIB_MAJOR= 1
MAN= kiconv.3
MLINKS+= kiconv.3 kiconv_add_xlat16_cspair.3 \
kiconv.3 kiconv_add_xlat16_table.3
CFLAGS+= -I${.CURDIR}/../../sys
.include <bsd.lib.mk>

106
lib/libkiconv/kiconv.3 Normal file
View File

@ -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

192
lib/libkiconv/quirks.c Normal file
View File

@ -0,0 +1,192 @@
/*-
* 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 <sys/types.h>
#include <sys/iconv.h>
#include <stdio.h>
#include <string.h>
#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,
(struct quirk_replace_list (*)[])&quirk_jis_cp932,
NumOf(quirk_jis_cp932)
},
{
"SJIS-ms", "CP932", ENCODING_UNICODE,
/* XXX - quirk_replace_list should be NULL */
(struct quirk_replace_list (*)[])&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 */

45
lib/libkiconv/quirks.h Normal file
View File

@ -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_ */

View File

@ -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 <sys/types.h>
#include <sys/iconv.h>
#include <sys/sysctl.h>
#include <ctype.h>
#include <dlfcn.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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 <errno.h>
int
kiconv_add_xlat16_cspair(const char *tocode, const char *fromcode, int flag)
{
errno = EINVAL;
return (-1);
}
#endif /* PIC */

View File

@ -0,0 +1,81 @@
/*
* 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 <sys/types.h>
#include <sys/iconv.h>
#include <sys/sysctl.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
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 <errno.h>
int
kiconv_add_xlat16_table(const char *to, const char *from, const void *data, int datalen)
{
return (EINVAL);
}
#endif /* PIC */

View File

@ -22,4 +22,4 @@ srcdirs /usr/src/usr.sbin
progs chown chroot
ln chown chgrp
libs -ledit -lgeom -lkvm -lm -lncurses -lutil
libs -ledit -lgeom -lkiconv -lkvm -lm -lncurses -lutil

View File

@ -26,4 +26,4 @@ progs arp ppp
progs sysinstall
libs -ll -ledit -lutil -lkvm -lmd -lcrypt -lftpio -lz -lnetgraph
libs -ldialog -lncurses -ldisk -lufs
libs -ldialog -lncurses -ldisk -lufs -lkiconv

View File

@ -23,4 +23,4 @@ srcdirs /usr/src/usr.sbin
progs chown chroot
ln chown chgrp
libs -ledit -lgeom -lkvm -lm -lncurses -lutil
libs -ledit -lgeom -lkiconv -lkvm -lm -lncurses -lutil

View File

@ -24,4 +24,4 @@ srcdirs /usr/src/usr.sbin
progs chown chroot
ln chown chgrp
libs -ledit -lgeom -lkvm -lm -lncurses -lutil
libs -ledit -lgeom -lkiconv -lkvm -lm -lncurses -lutil

View File

@ -135,7 +135,7 @@ CRUNCH_PROGS_sbin+= ipf ipfs ipfstat ipmon ipnat
# CRUNCH_PROGS+= devd
CRUNCH_LIBS+= -lalias -lbsdxml -lcam -lcurses -ldevstat -lipsec -lipx \
-lgeom -lmd -lreadline -lsbuf -lufs -lz
-lgeom -lkiconv -lmd -lreadline -lsbuf -lufs -lz
.if ${MACHINE_ARCH} == "i386"
CRUNCH_PROGS_sbin+= cxconfig fdisk

View File

@ -4,11 +4,17 @@
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}
.include <bsd.prog.mk>

View File

@ -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 @@ It is possible to mount an arbitrary session of a multi-session CD by specifying
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 @@ The
.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.

View File

@ -57,6 +57,8 @@ static const char rcsid[] =
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/../isofs/cd9660/cd9660_mount.h>
#include <sys/module.h>
#include <sys/iconv.h>
#include <arpa/inet.h>
@ -82,6 +84,7 @@ struct mntopt mopts[] = {
};
int get_ssector(const char *dev);
int set_charset(struct iso_args *, const char *);
void usage(void);
int
@ -95,7 +98,9 @@ main(int argc, char **argv)
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 @@ main(int argc, char **argv)
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 @@ void
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);
}
@ -225,3 +235,31 @@ get_ssector(const char *dev)
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);
}

View File

@ -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
# Needs to be dynamically linked for optional dlopen() access to
# userland libiconv
NOSHARED?= NO
.PATH: ${MOUNT}
TABDIR= ${DESTDIR}${LIBDATADIR}/msdosfs
TABLES= iso22dos iso72dos koi2dos koi8u2dos
afterinstall:
cd ${.CURDIR} && \
${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${SHAREMODE} \
${TABLES} ${TABDIR}
.include <bsd.prog.mk>

View File

@ -1,58 +0,0 @@
# $FreeBSD$
#
# 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

View File

@ -1,60 +0,0 @@
# $FreeBSD$
#
# 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

View File

@ -1,58 +0,0 @@
# $FreeBSD$
#
# 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

View File

@ -1,60 +0,0 @@
# $FreeBSD$
#
# Translation table for ukrainian filenames support by <kunia@istc.kiev.ua>
#
# 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

View File

@ -48,6 +48,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
@ -160,50 +161,38 @@ This forces
.\"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
@ -230,3 +219,7 @@ utility appeared in
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.

View File

@ -38,6 +38,8 @@ static const char rcsid[] =
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/module.h>
#include <sys/iconv.h>
#include <fs/msdosfs/msdosfsmount.h>
@ -56,9 +58,11 @@ static const char rcsid[] =
#include "mntopts.h"
#define TRANSITION_PERIOD_HACK
/*
* XXX - no way to specify "foo=<bar>"-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 gid_t a_gid(char *);
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 @@ main(argc, argv)
struct msdosfs_args args;
struct stat sb;
int c, mntflags, set_gid, set_uid, set_mask, set_dirmask;
char *dev, *dir, mntpath[MAXPATHLEN];
char *dev, *dir, mntpath[MAXPATHLEN], *csp;
mntflags = set_gid = set_uid = set_mask = set_dirmask = 0;
(void)memset(&args, '\0', sizeof(args));
args.magic = MSDOSFS_ARGSMAGIC;
while ((c = getopt(argc, argv, "sl9u:g:m: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:M:o:L:D:W:")) != -1) {
#else
while ((c = getopt(argc, argv, "sl9u:g:m:M:o:L:D:")) != -1) {
#endif
switch (c) {
#ifdef MSDOSFSMNT_GEMDOSFS
case 'G':
@ -128,16 +138,52 @@ main(argc, argv)
set_dirmask = 1;
break;
case 'L':
load_ultable(&args, optarg);
args.flags |= MSDOSFSMNT_ULTABLE;
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 'W':
load_u2wtable(&args, optarg);
args.flags |= MSDOSFSMNT_U2WTABLE;
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-7");
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();
@ -160,6 +206,19 @@ main(argc, argv)
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.
@ -254,89 +313,52 @@ void
usage()
{
fprintf(stderr, "%s\n%s\n",
#ifdef TRANSITION_PERIOD_HACK
"usage: mount_msdosfs [-o options] [-u user] [-g group] [-m mask] [-s] [-l]",
" [-9] [-L locale] [-D dos-codepage] [-W table] bdev dir");
#else
"usage: mount_msdosfs [-o options] [-u user] [-g group] [-m mask]",
" [-s] [-l] [-9] [-L locale] [-W table] bdev dir");
" [-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 (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 (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 ((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);
}

View File

@ -5,13 +5,17 @@
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}
.include <bsd.prog.mk>

View File

@ -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,12 @@ on which the file system is being mounted.
.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, thus the file system is to be
mounted read-only.
.It Fl W Ar u2wtable
Specify
.Ux
@ -90,6 +97,9 @@ translation table.
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 +130,19 @@ To read directory raw data:
.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 +159,10 @@ The
.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

View File

@ -37,6 +37,8 @@
#define NTFS
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/module.h>
#include <sys/iconv.h>
#include <fs/ntfs/ntfsmount.h>
#include <ctype.h>
#include <err.h>
@ -51,6 +53,8 @@
#include "mntopts.h"
#define TRANSITION_PERIOD_HACK
static struct mntopt mopts[] = {
MOPT_STDOPTS,
{ NULL }
@ -61,7 +65,7 @@ static uid_t a_uid(char *);
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 @@ main(argc, argv)
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 @@ main(argc, argv)
case 'o':
getmntopts(optarg, mopts, &mntflags, 0);
break;
case 'W':
load_u2wtable(&args, optarg);
args.flag |= NTFSMNT_U2WTABLE;
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':
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-7");
} 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,18 @@ main(argc, argv)
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;
/*
* XXX
* Force to be MNT_RDONLY,
* since only reading is supported right now,
*/
mntflags |= MNT_RDONLY;
}
/*
* Resolve the mountpoint with realpath(3) and remove unnecessary
* slashes from the devicename if there are any.
@ -207,74 +251,36 @@ a_mask(s)
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;
int
set_charset(struct ntfs_args *pargs)
{
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);
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);
}

View File

@ -49,6 +49,7 @@ LIBISC?= ${DESTDIR}${LIBDIR}/libisc.a
LIBKADM5CLNT?= ${DESTDIR}${LIBDIR}/libkadm5clnt.a # XXX in secure dist, not base
LIBKADM5SRV?= ${DESTDIR}${LIBDIR}/libkadm5srv.a # XXX in secure dist, not base
LIBKEYCAP?= ${DESTDIR}${LIBDIR}/libkeycap.a
LIBKICONV?= ${DESTDIR}${LIBDIR}/libkiconv.a
LIBKRB5?= ${DESTDIR}${LIBDIR}/libkrb5.a # XXX in secure dist, not base
LIBKVM?= ${DESTDIR}${LIBDIR}/libkvm.a
LIBL?= ${DESTDIR}${LIBDIR}/libl.a

View File

@ -788,6 +788,12 @@ options VFS_AIO
# 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

View File

@ -893,11 +893,13 @@ fs/msdosfs/msdosfs_fat.c optional msdosfs
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
@ -1056,6 +1058,7 @@ isofs/cd9660/cd9660_rrip.c optional cd9660
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
@ -1198,6 +1201,7 @@ libkern/crc32.c standard
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

View File

@ -198,6 +198,11 @@ FFS opt_ffs_broken_fixme.h
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.

View File

@ -0,0 +1,36 @@
/*-
* Copyright (c) 2003 Ryuichiro Imura
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/mount.h>
#include <sys/iconv.h>
VFS_DECLARE_ICONV(cd9660);

View File

@ -238,7 +238,12 @@ cd9660_lookup(ap)
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

View File

@ -47,9 +47,12 @@ struct iso_args {
struct export_args export; /* network export info */
int flags; /* mounting flags, see below */
int ssector; /* starting sector, 0 for 1st session */
char *cs_disk; /* disk charset for Joliet cs conversion */
char *cs_local; /* local charset for Joliet cs conversion */
};
#define ISOFSMNT_NORRIP 0x00000001 /* disable Rock Ridge Ext.*/
#define ISOFSMNT_GENS 0x00000002 /* enable generation numbers */
#define ISOFSMNT_EXTATT 0x00000004 /* enable extended attributes */
#define ISOFSMNT_NOJOLIET 0x00000008 /* disable Joliet Ext.*/
#define ISOFSMNT_BROKENJOLIET 0x00000010/* allow broken Joliet disks */
#define ISOFSMNT_KICONV 0x00000020 /* Use libiconv to convert chars */

View File

@ -293,7 +293,8 @@ cd9660_rrip_defname(isodir,ana)
{
isofntrans(isodir->name,isonum_711(isodir->name_len),
ana->outbuf,ana->outlen,
1,isonum_711(isodir->flags)&4, ana->imp->joliet_level);
1,isonum_711(isodir->flags)&4, ana->imp->joliet_level,
ana->imp->im_flags, ana->imp->im_d2l);
switch (*ana->outbuf) {
default:
break;
@ -491,7 +492,7 @@ cd9660_rrip_loop(isodir,ana,table)
register ISO_SUSP_HEADER *pend;
struct buf *bp = NULL;
char *pwhead;
u_char c;
u_short c;
int result;
/*
@ -501,7 +502,8 @@ cd9660_rrip_loop(isodir,ana,table)
pwhead = isodir->name + isonum_711(isodir->name_len);
if (!(isonum_711(isodir->name_len)&1))
pwhead++;
isochar(isodir->name, pwhead, ana->imp->joliet_level, &c);
isochar(isodir->name, pwhead, ana->imp->joliet_level, &c, NULL,
ana->imp->im_flags, ana->imp->im_d2l);
/* If it's not the '.' entry of the root dir obey SP field */
if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent)
@ -627,7 +629,7 @@ cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)
{
ISO_RRIP_ANALYZE analyze;
RRIP_TABLE *tab;
u_char c;
u_short c;
analyze.outbuf = outbuf;
analyze.outlen = outlen;
@ -638,7 +640,7 @@ cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)
*outlen = 0;
isochar(isodir->name, isodir->name + isonum_711(isodir->name_len),
imp->joliet_level, &c);
imp->joliet_level, &c, NULL, imp->im_flags, imp->im_d2l);
tab = rrip_table_getname;
if (c == 0 || c == 1) {
cd9660_rrip_defname(isodir,&analyze);

View File

@ -46,16 +46,12 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <sys/iconv.h>
#include <isofs/cd9660/iso.h>
#include <isofs/cd9660/cd9660_mount.h>
/*
* XXX: limited support for loading of Unicode
* conversion routine as a kld at a run-time.
* Should be removed when native Unicode kernel
* interfaces have been introduced.
*/
u_char (*cd9660_wchar2char)(u_int32_t wchar) = NULL;
extern struct iconv_functions *cd9660_iconv;
/*
* Get one character out of an iso filename
@ -63,29 +59,47 @@ u_char (*cd9660_wchar2char)(u_int32_t wchar) = NULL;
* Return number of bytes consumed
*/
int
isochar(isofn, isoend, joliet_level, c)
isochar(isofn, isoend, joliet_level, c, clen, flags, handle)
u_char *isofn;
u_char *isoend;
int joliet_level;
u_char *c;
u_short *c;
int *clen;
int flags;
void *handle;
{
size_t i, j, len;
char inbuf[3], outbuf[3], *inp, *outp;
*c = *isofn++;
if (clen) *clen = 1;
if (joliet_level == 0 || isofn == isoend)
/* (00) and (01) are one byte in Joliet, too */
return 1;
/* No Unicode support yet :-( */
switch (*c) {
default:
*c = '?';
break;
case '\0':
*c = *isofn;
break;
if (flags & ISOFSMNT_KICONV && cd9660_iconv) {
i = j = len = 2;
inbuf[0]=(char)*(isofn - 1);
inbuf[1]=(char)*isofn;
inbuf[2]='\0';
inp = inbuf;
outp = outbuf;
cd9660_iconv->convchr(handle, (const char **)&inp, &i, &outp, &j);
len -= j;
if (clen) *clen = len;
*c = '\0';
while(len--)
*c |= (*(outp - len - 1) & 0xff) << (len << 3);
} else {
switch (*c) {
default:
*c = '?';
break;
case '\0':
*c = *isofn;
break;
}
}
/* XXX: if Unicode conversion routine is loaded then use it */
if (cd9660_wchar2char != NULL)
*c = cd9660_wchar2char((*(isofn - 1) << 8) | *isofn);
return 2;
}
@ -96,53 +110,60 @@ isochar(isofn, isoend, joliet_level, c)
* Note: Version number plus ';' may be omitted.
*/
int
isofncmp(fn, fnlen, isofn, isolen, joliet_level)
isofncmp(fn, fnlen, isofn, isolen, joliet_level, flags, handle, lhandle)
u_char *fn;
int fnlen;
u_char *isofn;
int isolen;
int joliet_level;
int flags;
void *handle;
void *lhandle;
{
int i, j;
u_char c, *fnend = fn + fnlen, *isoend = isofn + isolen;
u_short c, d;
u_char *fnend = fn + fnlen, *isoend = isofn + isolen;
for (; fn != fnend; fn++) {
for (; fn < fnend; ) {
d = sgetrune(fn, fnend - fn, (char const **)&fn, flags, lhandle);
if (isofn == isoend)
return *fn;
isofn += isochar(isofn, isoend, joliet_level, &c);
return d;
isofn += isochar(isofn, isoend, joliet_level, &c, NULL, flags, handle);
if (c == ';') {
if (*fn++ != ';')
return fn[-1];
for (i = 0; fn != fnend; i = i * 10 + *fn++ - '0') {
if (d != ';')
return d;
for (i = 0; fn < fnend; i = i * 10 + *fn++ - '0') {
if (*fn < '0' || *fn > '9') {
return -1;
}
}
for (j = 0; isofn != isoend; j = j * 10 + c - '0')
isofn += isochar(isofn, isoend,
joliet_level, &c);
joliet_level, &c,
NULL, flags, handle);
return i - j;
}
if (c != *fn) {
if (c != d) {
if (c >= 'A' && c <= 'Z') {
if (c + ('a' - 'A') != *fn) {
if (*fn >= 'a' && *fn <= 'z')
return *fn - ('a' - 'A') - c;
if (c + ('a' - 'A') != d) {
if (d >= 'a' && d <= 'z')
return d - ('a' - 'A') - c;
else
return *fn - c;
return d - c;
}
} else
return *fn - c;
return d - c;
}
}
if (isofn != isoend) {
isofn += isochar(isofn, isoend, joliet_level, &c);
isofn += isochar(isofn, isoend, joliet_level, &c, NULL, flags, handle);
switch (c) {
default:
return -c;
case '.':
if (isofn != isoend) {
isochar(isofn, isoend, joliet_level, &c);
isochar(isofn, isoend, joliet_level, &c,
NULL, flags, handle);
if (c == ';')
return 0;
}
@ -158,7 +179,7 @@ isofncmp(fn, fnlen, isofn, isolen, joliet_level)
* translate a filename of length > 0
*/
void
isofntrans(infn, infnlen, outfn, outfnlen, original, assoc, joliet_level)
isofntrans(infn, infnlen, outfn, outfnlen, original, assoc, joliet_level, flags, handle)
u_char *infn;
int infnlen;
u_char *outfn;
@ -166,25 +187,61 @@ isofntrans(infn, infnlen, outfn, outfnlen, original, assoc, joliet_level)
int original;
int assoc;
int joliet_level;
int flags;
void *handle;
{
int fnidx = 0;
u_char c, d = '\0', *infnend = infn + infnlen;
u_short c, d = '\0';
u_char *outp = outfn, *infnend = infn + infnlen;
int clen;
if (assoc) {
*outfn++ = ASSOCCHAR;
fnidx++;
*outp++ = ASSOCCHAR;
}
for (; infn != infnend; fnidx++) {
infn += isochar(infn, infnend, joliet_level, &c);
for (; infn != infnend; ) {
infn += isochar(infn, infnend, joliet_level, &c, &clen, flags, handle);
if (!original && !joliet_level && c >= 'A' && c <= 'Z')
*outfn++ = c + ('a' - 'A');
c += ('a' - 'A');
else if (!original && c == ';') {
fnidx -= (d == '.');
outp -= (d == '.');
break;
} else
*outfn++ = c;
}
d = c;
while(clen--)
*outp++ = c >> (clen << 3);
}
*outfnlen = fnidx;
*outfnlen = outp - outfn;
}
/*
* same as sgetrune(3)
*/
u_short
sgetrune(string, n, result, flags, handle)
const char *string;
size_t n;
char const **result;
int flags;
void *handle;
{
size_t i, j, len;
char outbuf[3], *outp;
u_short c = '\0';
len = i = (n < 2) ? n : 2;
j = 2;
outp = outbuf;
if (flags & ISOFSMNT_KICONV && cd9660_iconv) {
cd9660_iconv->convchr(handle, (const char **)&string,
&i, &outp, &j);
len -= i;
} else {
len = 1;
string++;
}
if (result) *result = string;
while(len--) c |= (*(string - len - 1) & 0xff) << (len << 3);
return (c);
}

View File

@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/stat.h>
#include <sys/syslog.h>
#include <sys/iconv.h>
#include <isofs/cd9660/iso.h>
@ -66,6 +67,8 @@ __FBSDID("$FreeBSD$");
MALLOC_DEFINE(M_ISOFSMNT, "ISOFS mount", "ISOFS mount structure");
MALLOC_DEFINE(M_ISOFSNODE, "ISOFS node", "ISOFS vnode private part");
struct iconv_functions *cd9660_iconv = NULL;
static vfs_mount_t cd9660_mount;
static vfs_unmount_t cd9660_unmount;
static vfs_root_t cd9660_root;
@ -471,7 +474,16 @@ iso_mountfs(devvp, mp, td, argp)
bp = NULL;
}
isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET);
ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET |
ISOFSMNT_KICONV);
if (isomp->im_flags & ISOFSMNT_KICONV && cd9660_iconv) {
cd9660_iconv->open(argp->cs_local, argp->cs_disk, &isomp->im_d2l);
cd9660_iconv->open(argp->cs_disk, argp->cs_local, &isomp->im_l2d);
} else {
isomp->im_d2l = NULL;
isomp->im_l2d = NULL;
}
if (high_sierra) {
/* this effectively ignores all the mount flags */
@ -551,6 +563,12 @@ cd9660_unmount(mp, mntflags, td)
isomp = VFSTOISOFS(mp);
if (isomp->im_flags & ISOFSMNT_KICONV && cd9660_iconv) {
if (isomp->im_d2l)
cd9660_iconv->close(isomp->im_d2l);
if (isomp->im_l2d)
cd9660_iconv->close(isomp->im_l2d);
}
isomp->im_devvp->v_rdev->si_mountpoint = NULL;
error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, td);
vrele(isomp->im_devvp);

View File

@ -562,7 +562,9 @@ cd9660_readdir(ap)
idp->current.d_name, &namelen,
imp->iso_ftype == ISO_FTYPE_9660,
isonum_711(ep->flags)&4,
imp->joliet_level);
imp->joliet_level,
imp->im_flags,
imp->im_d2l);
idp->current.d_namlen = (u_char)namelen;
if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
error = iso_shipdir(idp);

View File

@ -245,6 +245,9 @@ struct iso_mnt {
int rr_skip0;
int joliet_level;
void *im_d2l;
void *im_l2d;
};
#define VFSTOISOFS(mp) ((struct iso_mnt *)((mp)->mnt_data))
@ -265,10 +268,11 @@ extern vop_t **cd9660_vnodeop_p;
extern vop_t **cd9660_specop_p;
extern vop_t **cd9660_fifoop_p;
int isochar(u_char *, u_char *, int, u_char *);
int isofncmp(u_char *, int, u_char *, int, int);
void isofntrans(u_char *, int, u_char *, u_short *, int, int, int);
int isochar(u_char *, u_char *, int, u_short *, int *, int, void *);
int isofncmp(u_char *, int, u_char *, int, int, int, void *, void *);
void isofntrans(u_char *, int, u_char *, u_short *, int, int, int, int, void *);
ino_t isodirino(struct iso_directory_record *, struct iso_mnt *);
u_short sgetrune(const char *, size_t, char const **, int, void *);
#endif /* _KERNEL */

View File

@ -97,6 +97,11 @@ struct winentry {
};
#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 @@ struct dirent;
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 */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
/*-
* Copyright (c) 2003 Ryuichiro Imura
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/mount.h>
#include <sys/iconv.h>
VFS_DECLARE_ICONV(msdosfs);

View File

@ -57,9 +57,9 @@
#include <sys/mount.h>
#include <fs/msdosfs/bpb.h>
#include <fs/msdosfs/msdosfsmount.h>
#include <fs/msdosfs/direntry.h>
#include <fs/msdosfs/denode.h>
#include <fs/msdosfs/msdosfsmount.h>
#include <fs/msdosfs/fat.h>
/*
@ -150,21 +150,19 @@ msdosfs_lookup(ap)
}
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 @@ msdosfs_lookup(ap)
* 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 @@ msdosfs_lookup(ap)
* Drop memory of previous long matches
*/
chksum = -1;
mbnambuf_init();
if (slotcount < wincnt) {
slotcount++;
@ -256,14 +256,18 @@ msdosfs_lookup(ap)
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 @@ createde(dep, ddep, depp, cnp)
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 @@ uniqdosname(dep, cnp, cp)
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;
/*

View File

@ -61,13 +61,14 @@
#include <sys/fcntl.h>
#include <sys/malloc.h>
#include <sys/stat.h> /* defines ALLPERMS */
#include <sys/iconv.h>
#include <sys/mutex.h>
#include <fs/msdosfs/bpb.h>
#include <fs/msdosfs/bootsect.h>
#include <fs/msdosfs/msdosfsmount.h>
#include <fs/msdosfs/direntry.h>
#include <fs/msdosfs/denode.h>
#include <fs/msdosfs/msdosfsmount.h>
#include <fs/msdosfs/fat.h>
#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);
@ -110,14 +113,16 @@ update_mp(mp, argp)
pmp->pm_mask = argp->mask & ALLPERMS;
pmp->pm_dirmask = argp->dirmask & 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)
@ -651,6 +656,16 @@ msdosfs_unmount(mp, mntflags, td)
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
{
@ -864,3 +879,4 @@ static struct vfsops msdosfs_vfsops = {
};
VFS_SET(msdosfs_vfsops, msdosfs, 0);
MODULE_VERSION(msdosfs, 1);

View File

@ -71,9 +71,9 @@
#include <machine/mutex.h>
#include <fs/msdosfs/bpb.h>
#include <fs/msdosfs/msdosfsmount.h>
#include <fs/msdosfs/direntry.h>
#include <fs/msdosfs/denode.h>
#include <fs/msdosfs/msdosfsmount.h>
#include <fs/msdosfs/fat.h>
#define DOS_FILESIZE_MAX 0xffffffff
@ -1554,6 +1554,7 @@ msdosfs_readdir(ap)
}
}
mbnambuf_init();
off = offset;
while (uio->uio_resid > 0) {
lbn = de_cluster(pmp, offset - bias);
@ -1600,6 +1601,7 @@ msdosfs_readdir(ap)
*/
if (dentp->deName[0] == SLOT_DELETED) {
chksum = -1;
mbnambuf_init();
continue;
}
@ -1610,9 +1612,7 @@ msdosfs_readdir(ap)
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;
}
@ -1621,6 +1621,7 @@ msdosfs_readdir(ap)
*/
if (dentp->deAttributes & ATTR_VOLUME) {
chksum = -1;
mbnambuf_init();
continue;
}
/*
@ -1648,18 +1649,16 @@ msdosfs_readdir(ap)
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) {

View File

@ -95,11 +95,10 @@ struct msdosfsmount {
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)
@ -218,10 +217,9 @@ struct msdosfs_args {
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 */
};
/*
@ -230,13 +228,11 @@ struct msdosfs_args {
#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 */

View File

@ -254,6 +254,8 @@ struct ntfsmount {
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

36
sys/fs/ntfs/ntfs_iconv.c Normal file
View File

@ -0,0 +1,36 @@
/*-
* Copyright (c) 2003 Ryuichiro Imura
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/mount.h>
#include <sys/iconv.h>
VFS_DECLARE_ICONV(ntfs);

View File

@ -40,6 +40,7 @@
#include <sys/file.h>
#include <sys/malloc.h>
#include <sys/lock.h>
#include <sys/iconv.h>
/* #define NTFS_DEBUG 1 */
#include <fs/ntfs/ntfs.h>
@ -67,6 +68,8 @@ static wchar *ntfs_toupper_tab;
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,41 @@ ntfs_uastricmp(ntmp, ustr, ustrlen, astr, astrlen)
const char *astr;
size_t astrlen;
{
size_t i;
int res;
int len;
size_t i, j, mbstrlen = astrlen;
int res;
wchar wc;
/*
* 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 (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;
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 +716,25 @@ ntfs_uastrcmp(ntmp, ustr, ustrlen, astr, astrlen)
const char *astr;
size_t astrlen;
{
size_t i;
int res;
char u, l;
size_t i, j, mbstrlen = astrlen;
int res;
wchar wc;
for (i = 0; (i < ustrlen) && (i < astrlen); i++) {
res = (int) (((char)NTFS_U28(ustr[i])) - astr[i]);
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);
}
/*
@ -2003,11 +2037,18 @@ ntfs_toupper_unuse()
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++) {
@ -2034,8 +2075,12 @@ ntfs_u28_uninit(struct ntfsmount *ntmp)
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;
@ -2051,22 +2096,21 @@ ntfs_u28_uninit(struct ntfsmount *ntmp)
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++)
for (i=0; i<256; i++)
_82u[i] = i;
} else {
for (i=0; i<128; i++)
_82u[i] = i;
for (i=0; i<128; i++)
_82u[i+128] = u2w[i];
}
ntmp->ntm_82u = _82u;
@ -2076,6 +2120,14 @@ ntfs_82u_init(
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);
}
@ -2086,12 +2138,31 @@ ntfs_82u_uninit(struct ntfsmount *ntmp)
* and substitutes a '_' for it if the result would be '\0';
* something better has to be definitely though out
*/
char
wchar
ntfs_u28(
struct ntfsmount *ntmp,
wchar wc)
{
char * p;
char *p, *outp, inbuf[3], outbuf[3];
size_t ilen, olen;
if (ntfs_iconv && ntmp->ntm_ic_u2l) {
ilen = olen = 2;
inbuf[0] = (char)(wc>>8);
inbuf[1] = (char)wc;
inbuf[2] = '\0';
p = inbuf;
outp = outbuf;
ntfs_iconv->convchr(ntmp->ntm_ic_u2l, (const char **)&p, &ilen,
&outp, &olen);
if (olen == 1) {
return ((wchar)(outbuf[0]));
} else if (olen == 0) {
return ((wchar)((outbuf[0]<<8) | (outbuf[1]&0xFF)));
}
return ('?');
}
p = ntmp->ntm_u28[(wc>>8)&0xFF];
if (p == NULL)
@ -2099,3 +2170,36 @@ ntfs_u28(
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 ('?');
}

View File

@ -108,13 +108,14 @@ void ntfs_toupper_unuse(void);
int ntfs_fget(struct ntfsmount *, struct ntnode *, int, char *, struct fnode **);
void ntfs_frele(struct fnode *);
int ntfs_u28_init(struct ntfsmount *ntmp, wchar *u2w);
int ntfs_u28_init(struct ntfsmount *ntmp, wchar *u2w, char *cs_local, char *cs_ntfs);
int ntfs_u28_uninit(struct ntfsmount *ntmp);
int ntfs_82u_init(struct ntfsmount *ntmp, u_int16_t *u2w);
int ntfs_82u_init(struct ntfsmount *ntmp, char *cs_local, char *cs_ntfs);
int ntfs_82u_uninit(struct ntfsmount *ntmp);
char ntfs_u28(struct ntfsmount *ntmp, wchar wc);
wchar ntfs_u28(struct ntfsmount *ntmp, wchar wc);
wchar ntfs_82u(struct ntfsmount *ntmp, wchar wc, int *len);
#define NTFS_U28(ch) ntfs_u28(ntmp, (ch))
#define NTFS_82U(ch) (ntmp->ntm_82u[(ch)&0xFF])
#define NTFS_82U(ch, len) ntfs_82u(ntmp, (ch), len)
#define NTFS_UASTRCMP(ustr, ustrlen, astr, astrlen) \
ntfs_uastrcmp(ntmp, (ustr), (ustrlen), (astr), (astrlen))
#define NTFS_UASTRICMP(ustr, ustrlen, astr, astrlen) \

View File

@ -350,14 +350,14 @@ ntfs_mountfs(devvp, mp, argsp, td)
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);
} else {
ntfs_82u_init(ntmp, NULL);
}
/* Initialize Unicode to 8-bit table from 8toU table */
ntfs_u28_init(ntmp, ntmp->ntm_82u);
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, NULL);
ntfs_u28_init(ntmp, ntmp->ntm_82u, NULL, NULL);
}
mp->mnt_data = (qaddr_t)ntmp;
@ -794,3 +794,4 @@ static struct vfsops ntfs_vfsops = {
.vfs_vptofh = ntfs_vptofh,
};
VFS_SET(ntfs_vfsops, ntfs, 0);
MODULE_VERSION(ntfs, 1);

View File

@ -495,7 +495,8 @@ ntfs_readdir(ap)
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;
@ -552,14 +553,17 @@ ntfs_readdir(ap)
if(!ntfs_isnamepermitted(ntmp,iep))
continue;
for(i=0; i<iep->ie_fnamelen; i++) {
cde.d_name[i] = NTFS_U28(iep->ie_fname[i]);
for(i=0, j=0; i<iep->ie_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);

View File

@ -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 @@ struct ntfs_args {
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 */
};

View File

@ -101,7 +101,7 @@ static struct vfsops smbfs_vfsops = {
VFS_SET(smbfs_vfsops, smbfs, VFCF_NETWORK);
MODULE_DEPEND(smbfs, netsmb, NSMB_VERSION, NSMB_VERSION, NSMB_VERSION);
MODULE_DEPEND(smbfs, libiconv, 1, 1, 1);
MODULE_DEPEND(smbfs, libiconv, 1, 1, 2);
MODULE_DEPEND(smbfs, libmchain, 1, 1, 1);
int smbfs_pbuf_freecnt = -1; /* start out unlimited */

View File

@ -0,0 +1,36 @@
/*-
* Copyright (c) 2003 Ryuichiro Imura
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/mount.h>
#include <sys/iconv.h>
VFS_DECLARE_ICONV(cd9660);

View File

@ -238,7 +238,12 @@ cd9660_lookup(ap)
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

View File

@ -47,9 +47,12 @@ struct iso_args {
struct export_args export; /* network export info */
int flags; /* mounting flags, see below */
int ssector; /* starting sector, 0 for 1st session */
char *cs_disk; /* disk charset for Joliet cs conversion */
char *cs_local; /* local charset for Joliet cs conversion */
};
#define ISOFSMNT_NORRIP 0x00000001 /* disable Rock Ridge Ext.*/
#define ISOFSMNT_GENS 0x00000002 /* enable generation numbers */
#define ISOFSMNT_EXTATT 0x00000004 /* enable extended attributes */
#define ISOFSMNT_NOJOLIET 0x00000008 /* disable Joliet Ext.*/
#define ISOFSMNT_BROKENJOLIET 0x00000010/* allow broken Joliet disks */
#define ISOFSMNT_KICONV 0x00000020 /* Use libiconv to convert chars */

View File

@ -293,7 +293,8 @@ cd9660_rrip_defname(isodir,ana)
{
isofntrans(isodir->name,isonum_711(isodir->name_len),
ana->outbuf,ana->outlen,
1,isonum_711(isodir->flags)&4, ana->imp->joliet_level);
1,isonum_711(isodir->flags)&4, ana->imp->joliet_level,
ana->imp->im_flags, ana->imp->im_d2l);
switch (*ana->outbuf) {
default:
break;
@ -491,7 +492,7 @@ cd9660_rrip_loop(isodir,ana,table)
register ISO_SUSP_HEADER *pend;
struct buf *bp = NULL;
char *pwhead;
u_char c;
u_short c;
int result;
/*
@ -501,7 +502,8 @@ cd9660_rrip_loop(isodir,ana,table)
pwhead = isodir->name + isonum_711(isodir->name_len);
if (!(isonum_711(isodir->name_len)&1))
pwhead++;
isochar(isodir->name, pwhead, ana->imp->joliet_level, &c);
isochar(isodir->name, pwhead, ana->imp->joliet_level, &c, NULL,
ana->imp->im_flags, ana->imp->im_d2l);
/* If it's not the '.' entry of the root dir obey SP field */
if (c != 0 || isonum_733(isodir->extent) != ana->imp->root_extent)
@ -627,7 +629,7 @@ cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)
{
ISO_RRIP_ANALYZE analyze;
RRIP_TABLE *tab;
u_char c;
u_short c;
analyze.outbuf = outbuf;
analyze.outlen = outlen;
@ -638,7 +640,7 @@ cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)
*outlen = 0;
isochar(isodir->name, isodir->name + isonum_711(isodir->name_len),
imp->joliet_level, &c);
imp->joliet_level, &c, NULL, imp->im_flags, imp->im_d2l);
tab = rrip_table_getname;
if (c == 0 || c == 1) {
cd9660_rrip_defname(isodir,&analyze);

View File

@ -46,16 +46,12 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <sys/iconv.h>
#include <isofs/cd9660/iso.h>
#include <isofs/cd9660/cd9660_mount.h>
/*
* XXX: limited support for loading of Unicode
* conversion routine as a kld at a run-time.
* Should be removed when native Unicode kernel
* interfaces have been introduced.
*/
u_char (*cd9660_wchar2char)(u_int32_t wchar) = NULL;
extern struct iconv_functions *cd9660_iconv;
/*
* Get one character out of an iso filename
@ -63,29 +59,47 @@ u_char (*cd9660_wchar2char)(u_int32_t wchar) = NULL;
* Return number of bytes consumed
*/
int
isochar(isofn, isoend, joliet_level, c)
isochar(isofn, isoend, joliet_level, c, clen, flags, handle)
u_char *isofn;
u_char *isoend;
int joliet_level;
u_char *c;
u_short *c;
int *clen;
int flags;
void *handle;
{
size_t i, j, len;
char inbuf[3], outbuf[3], *inp, *outp;
*c = *isofn++;
if (clen) *clen = 1;
if (joliet_level == 0 || isofn == isoend)
/* (00) and (01) are one byte in Joliet, too */
return 1;
/* No Unicode support yet :-( */
switch (*c) {
default:
*c = '?';
break;
case '\0':
*c = *isofn;
break;
if (flags & ISOFSMNT_KICONV && cd9660_iconv) {
i = j = len = 2;
inbuf[0]=(char)*(isofn - 1);
inbuf[1]=(char)*isofn;
inbuf[2]='\0';
inp = inbuf;
outp = outbuf;
cd9660_iconv->convchr(handle, (const char **)&inp, &i, &outp, &j);
len -= j;
if (clen) *clen = len;
*c = '\0';
while(len--)
*c |= (*(outp - len - 1) & 0xff) << (len << 3);
} else {
switch (*c) {
default:
*c = '?';
break;
case '\0':
*c = *isofn;
break;
}
}
/* XXX: if Unicode conversion routine is loaded then use it */
if (cd9660_wchar2char != NULL)
*c = cd9660_wchar2char((*(isofn - 1) << 8) | *isofn);
return 2;
}
@ -96,53 +110,60 @@ isochar(isofn, isoend, joliet_level, c)
* Note: Version number plus ';' may be omitted.
*/
int
isofncmp(fn, fnlen, isofn, isolen, joliet_level)
isofncmp(fn, fnlen, isofn, isolen, joliet_level, flags, handle, lhandle)
u_char *fn;
int fnlen;
u_char *isofn;
int isolen;
int joliet_level;
int flags;
void *handle;
void *lhandle;
{
int i, j;
u_char c, *fnend = fn + fnlen, *isoend = isofn + isolen;
u_short c, d;
u_char *fnend = fn + fnlen, *isoend = isofn + isolen;
for (; fn != fnend; fn++) {
for (; fn < fnend; ) {
d = sgetrune(fn, fnend - fn, (char const **)&fn, flags, lhandle);
if (isofn == isoend)
return *fn;
isofn += isochar(isofn, isoend, joliet_level, &c);
return d;
isofn += isochar(isofn, isoend, joliet_level, &c, NULL, flags, handle);
if (c == ';') {
if (*fn++ != ';')
return fn[-1];
for (i = 0; fn != fnend; i = i * 10 + *fn++ - '0') {
if (d != ';')
return d;
for (i = 0; fn < fnend; i = i * 10 + *fn++ - '0') {
if (*fn < '0' || *fn > '9') {
return -1;
}
}
for (j = 0; isofn != isoend; j = j * 10 + c - '0')
isofn += isochar(isofn, isoend,
joliet_level, &c);
joliet_level, &c,
NULL, flags, handle);
return i - j;
}
if (c != *fn) {
if (c != d) {
if (c >= 'A' && c <= 'Z') {
if (c + ('a' - 'A') != *fn) {
if (*fn >= 'a' && *fn <= 'z')
return *fn - ('a' - 'A') - c;
if (c + ('a' - 'A') != d) {
if (d >= 'a' && d <= 'z')
return d - ('a' - 'A') - c;
else
return *fn - c;
return d - c;
}
} else
return *fn - c;
return d - c;
}
}
if (isofn != isoend) {
isofn += isochar(isofn, isoend, joliet_level, &c);
isofn += isochar(isofn, isoend, joliet_level, &c, NULL, flags, handle);
switch (c) {
default:
return -c;
case '.':
if (isofn != isoend) {
isochar(isofn, isoend, joliet_level, &c);
isochar(isofn, isoend, joliet_level, &c,
NULL, flags, handle);
if (c == ';')
return 0;
}
@ -158,7 +179,7 @@ isofncmp(fn, fnlen, isofn, isolen, joliet_level)
* translate a filename of length > 0
*/
void
isofntrans(infn, infnlen, outfn, outfnlen, original, assoc, joliet_level)
isofntrans(infn, infnlen, outfn, outfnlen, original, assoc, joliet_level, flags, handle)
u_char *infn;
int infnlen;
u_char *outfn;
@ -166,25 +187,61 @@ isofntrans(infn, infnlen, outfn, outfnlen, original, assoc, joliet_level)
int original;
int assoc;
int joliet_level;
int flags;
void *handle;
{
int fnidx = 0;
u_char c, d = '\0', *infnend = infn + infnlen;
u_short c, d = '\0';
u_char *outp = outfn, *infnend = infn + infnlen;
int clen;
if (assoc) {
*outfn++ = ASSOCCHAR;
fnidx++;
*outp++ = ASSOCCHAR;
}
for (; infn != infnend; fnidx++) {
infn += isochar(infn, infnend, joliet_level, &c);
for (; infn != infnend; ) {
infn += isochar(infn, infnend, joliet_level, &c, &clen, flags, handle);
if (!original && !joliet_level && c >= 'A' && c <= 'Z')
*outfn++ = c + ('a' - 'A');
c += ('a' - 'A');
else if (!original && c == ';') {
fnidx -= (d == '.');
outp -= (d == '.');
break;
} else
*outfn++ = c;
}
d = c;
while(clen--)
*outp++ = c >> (clen << 3);
}
*outfnlen = fnidx;
*outfnlen = outp - outfn;
}
/*
* same as sgetrune(3)
*/
u_short
sgetrune(string, n, result, flags, handle)
const char *string;
size_t n;
char const **result;
int flags;
void *handle;
{
size_t i, j, len;
char outbuf[3], *outp;
u_short c = '\0';
len = i = (n < 2) ? n : 2;
j = 2;
outp = outbuf;
if (flags & ISOFSMNT_KICONV && cd9660_iconv) {
cd9660_iconv->convchr(handle, (const char **)&string,
&i, &outp, &j);
len -= i;
} else {
len = 1;
string++;
}
if (result) *result = string;
while(len--) c |= (*(string - len - 1) & 0xff) << (len << 3);
return (c);
}

View File

@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/stat.h>
#include <sys/syslog.h>
#include <sys/iconv.h>
#include <isofs/cd9660/iso.h>
@ -66,6 +67,8 @@ __FBSDID("$FreeBSD$");
MALLOC_DEFINE(M_ISOFSMNT, "ISOFS mount", "ISOFS mount structure");
MALLOC_DEFINE(M_ISOFSNODE, "ISOFS node", "ISOFS vnode private part");
struct iconv_functions *cd9660_iconv = NULL;
static vfs_mount_t cd9660_mount;
static vfs_unmount_t cd9660_unmount;
static vfs_root_t cd9660_root;
@ -471,7 +474,16 @@ iso_mountfs(devvp, mp, td, argp)
bp = NULL;
}
isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET);
ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET |
ISOFSMNT_KICONV);
if (isomp->im_flags & ISOFSMNT_KICONV && cd9660_iconv) {
cd9660_iconv->open(argp->cs_local, argp->cs_disk, &isomp->im_d2l);
cd9660_iconv->open(argp->cs_disk, argp->cs_local, &isomp->im_l2d);
} else {
isomp->im_d2l = NULL;
isomp->im_l2d = NULL;
}
if (high_sierra) {
/* this effectively ignores all the mount flags */
@ -551,6 +563,12 @@ cd9660_unmount(mp, mntflags, td)
isomp = VFSTOISOFS(mp);
if (isomp->im_flags & ISOFSMNT_KICONV && cd9660_iconv) {
if (isomp->im_d2l)
cd9660_iconv->close(isomp->im_d2l);
if (isomp->im_l2d)
cd9660_iconv->close(isomp->im_l2d);
}
isomp->im_devvp->v_rdev->si_mountpoint = NULL;
error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, td);
vrele(isomp->im_devvp);

View File

@ -562,7 +562,9 @@ cd9660_readdir(ap)
idp->current.d_name, &namelen,
imp->iso_ftype == ISO_FTYPE_9660,
isonum_711(ep->flags)&4,
imp->joliet_level);
imp->joliet_level,
imp->im_flags,
imp->im_d2l);
idp->current.d_namlen = (u_char)namelen;
if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
error = iso_shipdir(idp);

View File

@ -245,6 +245,9 @@ struct iso_mnt {
int rr_skip0;
int joliet_level;
void *im_d2l;
void *im_l2d;
};
#define VFSTOISOFS(mp) ((struct iso_mnt *)((mp)->mnt_data))
@ -265,10 +268,11 @@ extern vop_t **cd9660_vnodeop_p;
extern vop_t **cd9660_specop_p;
extern vop_t **cd9660_fifoop_p;
int isochar(u_char *, u_char *, int, u_char *);
int isofncmp(u_char *, int, u_char *, int, int);
void isofntrans(u_char *, int, u_char *, u_short *, int, int, int);
int isochar(u_char *, u_char *, int, u_short *, int *, int, void *);
int isofncmp(u_char *, int, u_char *, int, int, int, void *, void *);
void isofntrans(u_char *, int, u_char *, u_short *, int, int, int, int, void *);
ino_t isodirino(struct iso_directory_record *, struct iso_mnt *);
u_short sgetrune(const char *, size_t, char const **, int, void *);
#endif /* _KERNEL */

View File

@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/iconv.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/syslog.h>
#include "iconv_converter_if.h"
@ -48,7 +50,7 @@ SYSCTL_NODE(_kern, OID_AUTO, iconv, CTLFLAG_RW, NULL, "kernel iconv interface");
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
/*
@ -272,7 +274,28 @@ int
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);
}
/*
@ -371,6 +394,7 @@ iconv_sysctl_add(SYSCTL_HANDLER_ARGS)
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);
@ -421,7 +445,7 @@ iconv_converter_handler(module_t mod, int type, void *data)
}
/*
* Common used functions
* Common used functions (don't use with unicode)
*/
char *
iconv_convstr(void *handle, char *dst, const char *src)
@ -434,7 +458,8 @@ iconv_convstr(void *handle, char *dst, const char *src)
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;
@ -459,7 +484,8 @@ iconv_convmem(void *handle, void *dst, const void *src, int size)
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;
@ -483,3 +509,22 @@ iconv_lookupcp(char **cpp, const char *s)
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);
}

View File

@ -53,6 +53,8 @@ METHOD int conv {
size_t *inbytesleft;
char **outbuf;
size_t *outbytesleft;
int convchar;
int casetype;
};
STATICMETHOD int init {

View File

@ -46,7 +46,7 @@ __FBSDID("$FreeBSD$");
*/
#ifdef MODULE_DEPEND
MODULE_DEPEND(iconv_xlat, libiconv, 1, 1, 1);
MODULE_DEPEND(iconv_xlat, libiconv, 2, 2, 2);
#endif
/*
@ -84,7 +84,8 @@ iconv_xlat_close(void *data)
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;
@ -93,14 +94,19 @@ iconv_xlat_conv(void *d2p, const char **inbuf,
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;
}

242
sys/libkern/iconv_xlat16.c Normal file
View File

@ -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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/iconv.h>
#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));

View File

@ -25,6 +25,7 @@ SUBDIR= accf_data \
bridge \
cam \
cd9660 \
cd9660_iconv \
coda \
coda5 \
${_crypto} \
@ -85,12 +86,14 @@ SUBDIR= accf_data \
mlx \
mpt \
msdosfs \
msdosfs_iconv \
my \
nfsclient \
nfsserver \
nge \
nmdm \
ntfs \
ntfs_iconv \
nullfs \
patm \
pcn \

View File

@ -6,6 +6,6 @@ KMOD= cd9660
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 <bsd.kmod.mk>

View File

@ -0,0 +1,7 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../isofs/cd9660
KMOD= cd9660_iconv
SRCS= cd9660_iconv.c
.include <bsd.kmod.mk>

View File

@ -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 @@ MFILES= libkern/iconv_converter_if.m
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 <bsd.kmod.mk>

View File

@ -6,5 +6,6 @@ KMOD= msdosfs
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 <bsd.kmod.mk>

View File

@ -0,0 +1,7 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../fs/msdosfs
KMOD= msdosfs_iconv
SRCS= msdosfs_iconv.c
.include <bsd.kmod.mk>

View File

@ -6,5 +6,6 @@ KMOD= ntfs
SRCS= vnode_if.h \
ntfs_vfsops.c ntfs_vnops.c ntfs_subr.c ntfs_ihash.c \
ntfs_compr.c
EXPORT_SYMS= ntfs_iconv
.include <bsd.kmod.mk>

View File

@ -0,0 +1,7 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../fs/ntfs
KMOD= ntfs_iconv
SRCS= ntfs_iconv.c
.include <bsd.kmod.mk>

View File

@ -70,7 +70,7 @@ static d_open_t nsmb_dev_open;
static d_close_t nsmb_dev_close;
static d_ioctl_t nsmb_dev_ioctl;
MODULE_DEPEND(netsmb, libiconv, 1, 1, 1);
MODULE_DEPEND(netsmb, libiconv, 1, 1, 2);
MODULE_VERSION(netsmb, NSMB_VERSION);
static int smb_version = NSMB_VERSION;

View File

@ -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 @@ struct iconv_add_out {
__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_open(const char *to, const char *from, void **handle);
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