summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libkiconv/Makefile1
-rw-r--r--lib/libkiconv/kiconv.317
-rw-r--r--lib/libkiconv/xlat16_iconv.c24
-rw-r--r--sbin/mount_cd9660/mount_cd9660.c5
-rw-r--r--sbin/mount_msdosfs/mount_msdosfs.c10
-rw-r--r--sbin/mount_ntfs/mount_ntfs.c5
-rw-r--r--sbin/mount_udf/mount_udf.c7
-rw-r--r--sys/fs/msdosfs/msdosfs_conv.c8
-rw-r--r--sys/libkern/iconv_xlat16.c21
-rw-r--r--sys/sys/iconv.h1
10 files changed, 66 insertions, 33 deletions
diff --git a/lib/libkiconv/Makefile b/lib/libkiconv/Makefile
index a68f246..763c5fd 100644
--- a/lib/libkiconv/Makefile
+++ b/lib/libkiconv/Makefile
@@ -10,6 +10,7 @@ SHLIB_MAJOR= 1
MAN= kiconv.3
MLINKS+= kiconv.3 kiconv_add_xlat16_cspair.3 \
+ kiconv.3 kiconv_add_xlat16_cspairs.3 \
kiconv.3 kiconv_add_xlat16_table.3
CFLAGS+= -I${.CURDIR}/../../sys
diff --git a/lib/libkiconv/kiconv.3 b/lib/libkiconv/kiconv.3
index c742c7f..632252e 100644
--- a/lib/libkiconv/kiconv.3
+++ b/lib/libkiconv/kiconv.3
@@ -30,6 +30,7 @@
.Os
.Sh NAME
.Nm kiconv_add_xlat16_cspair ,
+.Nm kiconv_add_xlat16_cspairs ,
.Nm kiconv_add_xlat16_table
.Nd Kernel side iconv library
.Sh LIBRARY
@@ -43,6 +44,11 @@
.Fa "int flag"
.Fc
.Ft int
+.Fo kiconv_add_xlat16_cspairs
+.Fa "const char *foreigncode"
+.Fa "const char *localcode"
+.Fc
+.Ft int
.Fo kiconv_add_xlat16_table
.Fa "const char *tocode"
.Fa "const char *fromcode"
@@ -92,6 +98,17 @@ or toupper
.Pp
A tolower/toupper conversion is limited to single-byte characters.
.Pp
+.Fn kiconv_add_xlat16_cspairs
+defines two conversion tables which are from
+.Ar localcode
+to
+.Ar foreigncode
+and from
+.Ar foreigncode
+to
+.Ar localcode .
+This conversion tables also contain both of tolower and toupper tables.
+.Pp
.Fn kiconv_add_xlat16_table
defines a conversion table directly pointed by
.Ar data
diff --git a/lib/libkiconv/xlat16_iconv.c b/lib/libkiconv/xlat16_iconv.c
index 2490107..c714961 100644
--- a/lib/libkiconv/xlat16_iconv.c
+++ b/lib/libkiconv/xlat16_iconv.c
@@ -113,6 +113,23 @@ kiconv_add_xlat16_cspair(const char *tocode, const char *fromcode, int flag)
return (-1);
}
+int
+kiconv_add_xlat16_cspairs(const char *foreigncode, const char *localcode)
+{
+ int error;
+
+ error = kiconv_add_xlat16_cspair(foreigncode, localcode,
+ KICONV_FROM_LOWER | KICONV_FROM_UPPER);
+ if (error)
+ return (error);
+ error = kiconv_add_xlat16_cspair(localcode, foreigncode,
+ KICONV_LOWER | KICONV_UPPER);
+ if (error)
+ return (error);
+
+ return (0);
+}
+
static struct xlat16_table
kiconv_xlat16_open(const char *tocode, const char *fromcode, int lcase)
{
@@ -371,4 +388,11 @@ kiconv_add_xlat16_cspair(const char *tocode, const char *fromcode, int flag)
return (-1);
}
+int
+kiconv_add_xlat16_cspairs(const char *tocode, const char *fromcode)
+{
+ errno = EINVAL;
+ return (-1);
+}
+
#endif /* PIC */
diff --git a/sbin/mount_cd9660/mount_cd9660.c b/sbin/mount_cd9660/mount_cd9660.c
index 5fe7279..4ac6586 100644
--- a/sbin/mount_cd9660/mount_cd9660.c
+++ b/sbin/mount_cd9660/mount_cd9660.c
@@ -255,10 +255,7 @@ set_charset(struct iso_args *args, const char *localcs)
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);
+ error = kiconv_add_xlat16_cspairs(args->cs_disk, args->cs_local);
if (error)
return (-1);
diff --git a/sbin/mount_msdosfs/mount_msdosfs.c b/sbin/mount_msdosfs/mount_msdosfs.c
index dcf0b29..29a1f11 100644
--- a/sbin/mount_msdosfs/mount_msdosfs.c
+++ b/sbin/mount_msdosfs/mount_msdosfs.c
@@ -339,17 +339,11 @@ set_charset(struct msdosfs_args *args)
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);
+ error = kiconv_add_xlat16_cspairs(args->cs_win, args->cs_local);
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);
+ error = kiconv_add_xlat16_cspairs(args->cs_dos, args->cs_local);
if (error)
return (-1);
} else {
diff --git a/sbin/mount_ntfs/mount_ntfs.c b/sbin/mount_ntfs/mount_ntfs.c
index bf5adf3..5cabb09 100644
--- a/sbin/mount_ntfs/mount_ntfs.c
+++ b/sbin/mount_ntfs/mount_ntfs.c
@@ -275,10 +275,7 @@ set_charset(struct ntfs_args *pargs)
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);
+ error = kiconv_add_xlat16_cspairs(pargs->cs_ntfs, pargs->cs_local);
if (error)
return (-1);
diff --git a/sbin/mount_udf/mount_udf.c b/sbin/mount_udf/mount_udf.c
index 8a4692d..264c24c 100644
--- a/sbin/mount_udf/mount_udf.c
+++ b/sbin/mount_udf/mount_udf.c
@@ -172,14 +172,9 @@ set_charset(char **cs_disk, char **cs_local, const char *localcs)
return (-1);
strncpy(*cs_disk, ENCODING_UNICODE, ICONV_CSNMAXLEN);
strncpy(*cs_local, localcs, ICONV_CSNMAXLEN);
- error = kiconv_add_xlat16_cspair(*cs_local, *cs_disk, 0);
+ error = kiconv_add_xlat16_cspairs(*cs_disk, *cs_local);
if (error)
return (-1);
-#if 0
- error = kiconv_add_xlat16_cspair(*cs_disk, *cs_local, 0);
- if (error)
- return (-1);
-#endif
return (0);
}
diff --git a/sys/fs/msdosfs/msdosfs_conv.c b/sys/fs/msdosfs/msdosfs_conv.c
index 5c663c8..728c983 100644
--- a/sys/fs/msdosfs/msdosfs_conv.c
+++ b/sys/fs/msdosfs/msdosfs_conv.c
@@ -800,10 +800,12 @@ winChkName(un, unlen, chksum, pmp)
for (np = dirbuf.d_name; unlen > 0 && len > 0;) {
/*
- * Should comparison be case insensitive?
+ * Comparison must be case insensitive, because FAT disallows
+ * to look up or create files in case sensitive even when
+ * it's a long file name.
*/
- c1 = unix2winchr((const u_char **)&np, (size_t *)&len, 0, pmp);
- c2 = unix2winchr(&un, (size_t *)&unlen, 0, pmp);
+ c1 = unix2winchr((const u_char **)&np, (size_t *)&len, LCASE_BASE, pmp);
+ c2 = unix2winchr(&un, (size_t *)&unlen, LCASE_BASE, pmp);
if (c1 != c2)
return -2;
}
diff --git a/sys/libkern/iconv_xlat16.c b/sys/libkern/iconv_xlat16.c
index 6793159..68d468a 100644
--- a/sys/libkern/iconv_xlat16.c
+++ b/sys/libkern/iconv_xlat16.c
@@ -96,11 +96,11 @@ iconv_xlat16_conv(void *d2p, const char **inbuf,
struct iconv_xlat16 *dp = (struct iconv_xlat16*)d2p;
const char *src;
char *dst;
- int ret = 0;
+ int nullin, ret = 0;
size_t in, on, ir, or, inlen;
uint32_t code;
u_char u, l;
- u_int16_t c1, c2;
+ uint16_t c1, c2;
if (inbuf == NULL || *inbuf == NULL || outbuf == NULL || *outbuf == NULL)
return (0);
@@ -146,7 +146,8 @@ iconv_xlat16_conv(void *d2p, const char **inbuf,
}
}
- if ((inlen == 1) && (code & XLAT16_ACCEPT_NULL_IN)) {
+ nullin = (code & XLAT16_ACCEPT_NULL_IN) ? 1 : 0;
+ if (inlen == 1 && nullin) {
/*
* XLAT16_ACCEPT_NULL_IN requires inbuf has 2byte
*/
@@ -157,6 +158,14 @@ iconv_xlat16_conv(void *d2p, const char **inbuf,
/*
* now start translation
*/
+ if ((casetype == KICONV_FROM_LOWER && code & XLAT16_HAS_FROM_LOWER_CASE) ||
+ (casetype == KICONV_FROM_UPPER && code & XLAT16_HAS_FROM_UPPER_CASE)) {
+ c2 = (u_char)(code >> 16);
+ c1 = c2 & 0x80 ? 0x100 : 0;
+ c2 = c2 & 0x80 ? c2 & 0x7f : c2;
+ code = dp->d_table[c1][c2];
+ }
+
u = (u_char)(code >> 8);
l = (u_char)code;
@@ -184,9 +193,6 @@ iconv_xlat16_conv(void *d2p, const char **inbuf,
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--;
@@ -197,8 +203,7 @@ iconv_xlat16_conv(void *d2p, const char **inbuf,
* 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 ) {
+ if ((u_char)*(src+1) == 0 && !nullin ) {
src++;
ir--;
} else {
diff --git a/sys/sys/iconv.h b/sys/sys/iconv.h
index 0ac765c..754bea7 100644
--- a/sys/sys/iconv.h
+++ b/sys/sys/iconv.h
@@ -92,6 +92,7 @@ __BEGIN_DECLS
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_cspairs(const char *, const char *);
int kiconv_add_xlat16_table(const char *, const char *, const void *, int);
const char *kiconv_quirkcs(const char *, int);
OpenPOWER on IntegriCloud