Subject: kern/36370: support for cyrilic charsets is needed in msdosfs
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <cheusov@tut.by>
List: netbsd-bugs
Date: 05/21/2007 19:25:01
>Number: 36370
>Category: kern
>Synopsis: support for cyrilic charsets is needed in msdosfs
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Mon May 21 19:25:00 +0000 2007
>Originator: cheusov@tut.by
>Release: NetBSD 4.0_BETA2
>Organization:
Best regards, Aleksey Cheusov.
>Environment:
System: NetBSD chen.chizhovka.net 4.0_BETA2 NetBSD 4.0_BETA2 (GENERIC) #16: Mon May 21 00:01:33 EEST 2007 cheusov@chen.chizhovka.net:/srv/src/sys/arch/i386/compile/GENERIC i386
Architecture: i386
Machine: i386
>Description:
MSDOS' fat file system is still alife. Many people use flashes
where FAT file system is ordinary choise.
Unforunately cyrillic character sets are not supported in NetBSD's
msdosfs implementation.
>Fix:
I'm not kernel developer, it's hard for me to hack a kernel
but months ago I created a patch for NetBSD. Now it corresponds
to netbsd-4 branch and works fine for me.
A few notes about it:
- there are some printf() for debugging purposes
- mount_msdos -L and -D options are added
The default is msdos_msdosfs -L iso-8859-1 -D cp850 is the default
For cyrillic support -L cp-1251 -D cp866 works for me.
- sys/fs/msdosfs/msdosfs_kiconv.c is kernel space tiny library
with iconv(3) like API
- Original dos2unix and unix2dos tables from NetBSD code is not the same
as tr__cp850_to_iso88591 and tr__iso88591_to_cp850. I don't know why.
I didn't read specs.
- -L and -D options comes from FreeBSD
People around the world use NetBSD and I hope you'll consider
internationalizing msdosfs useful task.
P.S.
FreeBSD has workable code for cyrillic charset for more than 5 years or so.
I took some ideas from it.
Patch:
Index: distrib/sets/lists/comp/mi
===================================================================
RCS file: /cvsroot/src/distrib/sets/lists/comp/mi,v
retrieving revision 1.981.2.2
diff -u -r1.981.2.2 mi
--- distrib/sets/lists/comp/mi 8 May 2007 10:45:13 -0000 1.981.2.2
+++ distrib/sets/lists/comp/mi 21 May 2007 18:04:27 -0000
@@ -1273,7 +1273,8 @@
./usr/include/msdosfs/denode.h comp-c-include
./usr/include/msdosfs/direntry.h comp-c-include
./usr/include/msdosfs/fat.h comp-c-include
+./usr/include/msdosfs/msdosfs_kiconv.h comp-c-include
./usr/include/msdosfs/msdosfsmount.h comp-c-include
./usr/include/ndbm.h comp-c-include
./usr/include/net/bpf.h comp-c-include
Index: sbin/mount_msdos/mount_msdos.c
===================================================================
RCS file: /cvsroot/src/sbin/mount_msdos/mount_msdos.c,v
retrieving revision 1.39
diff -u -r1.39 mount_msdos.c
--- sbin/mount_msdos/mount_msdos.c 16 Oct 2006 03:37:42 -0000 1.39
+++ sbin/mount_msdos/mount_msdos.c 21 May 2007 18:05:15 -0000
@@ -92,7 +92,7 @@
mntflags = set_gid = set_uid = set_mask = set_dirmask = set_gmtoff = 0;
(void)memset(&args, '\0', sizeof(args));
- while ((c = getopt(argc, argv, "Gsl9u:g:m:M:o:t:")) != -1) {
+ while ((c = getopt(argc, argv, "Gsl9u:g:m:M:o:t:D:L:")) != -1) {
switch (c) {
case 'G':
args.flags |= MSDOSFSMNT_GEMDOSFS;
@@ -132,7 +132,13 @@
args.gmtoff = atoi(optarg);
set_gmtoff = 1;
break;
+ case 'D':
+ strlcpy(args.cs_dos, optarg, sizeof (args.cs_dos));
+ break;
+ case 'L':
+ strlcpy(args.cs_unix, optarg, sizeof (args.cs_unix));
+ break;
case '?':
default:
usage();
Index: sys/fs/msdosfs/Makefile
===================================================================
RCS file: /cvsroot/src/sys/fs/msdosfs/Makefile,v
retrieving revision 1.1
diff -u -r1.1 Makefile
--- sys/fs/msdosfs/Makefile 26 Dec 2002 12:31:32 -0000 1.1
+++ sys/fs/msdosfs/Makefile 21 May 2007 18:05:42 -0000
@@ -2,6 +2,6 @@
INCSDIR= /usr/include/msdosfs
-INCS= bootsect.h bpb.h denode.h direntry.h fat.h msdosfsmount.h
+INCS= bootsect.h bpb.h denode.h direntry.h fat.h msdosfsmount.h msdosfs_kiconv.h
.include <bsd.kinc.mk>
Index: sys/fs/msdosfs/files.msdosfs
===================================================================
RCS file: /cvsroot/src/sys/fs/msdosfs/files.msdosfs,v
retrieving revision 1.1
diff -u -r1.1 files.msdosfs
--- sys/fs/msdosfs/files.msdosfs 26 Dec 2002 12:31:33 -0000 1.1
+++ sys/fs/msdosfs/files.msdosfs 21 May 2007 18:05:42 -0000
@@ -8,3 +8,4 @@
file fs/msdosfs/msdosfs_lookup.c msdosfs
file fs/msdosfs/msdosfs_vfsops.c msdosfs
file fs/msdosfs/msdosfs_vnops.c msdosfs
+file fs/msdosfs/msdosfs_kiconv.c msdosfs
Index: sys/fs/msdosfs/msdosfs_conv.c
===================================================================
RCS file: /cvsroot/src/sys/fs/msdosfs/msdosfs_conv.c,v
retrieving revision 1.5
diff -u -r1.5 msdosfs_conv.c
--- sys/fs/msdosfs/msdosfs_conv.c 11 Dec 2005 12:24:25 -0000 1.5
+++ sys/fs/msdosfs/msdosfs_conv.c 21 May 2007 18:05:42 -0000
@@ -60,6 +60,8 @@
#include <sys/dirent.h>
#include <sys/vnode.h>
+#include <fs/msdosfs/msdosfs_kiconv.h>
+
/*
* MSDOSFS include files.
*/
@@ -92,6 +94,14 @@
u_short lastdtime;
/*
+ * Character class convertors
+ */
+extern void *cs_u2d;
+extern void *cs_d2u;
+extern void *cs_d2uc;
+extern void *cs_u2lc;
+
+/*
* Convert the unix version of time to dos's idea of time to be used in
* file timestamps. The passed in unix time is assumed to be in GMT.
*/
@@ -233,114 +243,6 @@
tsp->tv_nsec = (dh % 100) * 10000000;
}
-static const u_char
-unix2dos[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, /* 00-07 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* 08-0f */
- 0, 0, 0, 0, 0, 0, 0, 0, /* 10-17 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* 18-1f */
- 0, '!', 0, '#', '$', '%', '&', '\'', /* 20-27 */
- '(', ')', 0, '+', 0, '-', 0, 0, /* 28-2f */
- '0', '1', '2', '3', '4', '5', '6', '7', /* 30-37 */
- '8', '9', 0, 0, 0, 0, 0, 0, /* 38-3f */
- '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40-47 */
- 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 48-4f */
- 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 50-57 */
- 'X', 'Y', 'Z', 0, 0, 0, '^', '_', /* 58-5f */
- '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 60-67 */
- 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 68-6f */
- 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 70-77 */
- 'X', 'Y', 'Z', '{', 0, '}', '~', 0, /* 78-7f */
- 0, 0, 0, 0, 0, 0, 0, 0, /* 80-87 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* 88-8f */
- 0, 0, 0, 0, 0, 0, 0, 0, /* 90-97 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* 98-9f */
- 0, 0xad, 0xbd, 0x9c, 0xcf, 0xbe, 0xdd, 0xf5, /* a0-a7 */
- 0xf9, 0xb8, 0xa6, 0xae, 0xaa, 0xf0, 0xa9, 0xee, /* a8-af */
- 0xf8, 0xf1, 0xfd, 0xfc, 0xef, 0xe6, 0xf4, 0xfa, /* b0-b7 */
- 0xf7, 0xfb, 0xa7, 0xaf, 0xac, 0xab, 0xf3, 0xa8, /* b8-bf */
- 0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80, /* c0-c7 */
- 0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8, /* c8-cf */
- 0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0x9e, /* d0-d7 */
- 0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0xe1, /* d8-df */
- 0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80, /* e0-e7 */
- 0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8, /* e8-ef */
- 0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0xf6, /* f0-f7 */
- 0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0x98, /* f8-ff */
-};
-
-static const u_char
-dos2unix[256] = {
- '?', '?', '?', '?', '?', '?', '?', '?', /* 00-07 */
- '?', '?', '?', '?', '?', '?', '?', '?', /* 08-0f */
- '?', '?', '?', '?', '?', '?', '?', '?', /* 10-17 */
- '?', '?', '?', '?', '?', '?', '?', '?', /* 18-1f */
- ' ', '!', '"', '#', '$', '%', '&', '\'', /* 20-27 */
- '(', ')', '*', '+', ',', '-', '.', '/', /* 28-2f */
- '0', '1', '2', '3', '4', '5', '6', '7', /* 30-37 */
- '8', '9', ':', ';', '<', '=', '>', '?', /* 38-3f */
- '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40-47 */
- 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 48-4f */
- 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 50-57 */
- 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', /* 58-5f */
- '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 60-67 */
- 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 68-6f */
- 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 70-77 */
- 'x', 'y', 'z', '{', '|', '}', '~', 0x7f, /* 78-7f */
- 0xc7, 0xfc, 0xe9, 0xe2, 0xe4, 0xe0, 0xe5, 0xe7, /* 80-87 */
- 0xea, 0xeb, 0xe8, 0xef, 0xee, 0xec, 0xc4, 0xc5, /* 88-8f */
- 0xc9, 0xe6, 0xc6, 0xf4, 0xf6, 0xf2, 0xfb, 0xf9, /* 90-97 */
- 0xff, 0xd6, 0xdc, 0xf8, 0xa3, 0xd8, 0xd7, '?', /* 98-9f */
- 0xe1, 0xed, 0xf3, 0xfa, 0xf1, 0xd1, 0xaa, 0xba, /* a0-a7 */
- 0xbf, 0xae, 0xac, 0xbd, 0xbc, 0xa1, 0xab, 0xbb, /* a8-af */
- '?', '?', '?', '?', '?', 0xc1, 0xc2, 0xc0, /* b0-b7 */
- 0xa9, '?', '?', '?', '?', 0xa2, 0xa5, '?', /* b8-bf */
- '?', '?', '?', '?', '?', '?', 0xe3, 0xc3, /* c0-c7 */
- '?', '?', '?', '?', '?', '?', '?', 0xa4, /* c8-cf */
- 0xf0, 0xd0, 0xca, 0xcb, 0xc8, '?', 0xcd, 0xce, /* d0-d7 */
- 0xcf, '?', '?', '?', '?', 0xa6, 0xcc, '?', /* d8-df */
- 0xd3, 0xdf, 0xd4, 0xd2, 0xf5, 0xd5, 0xb5, 0xfe, /* e0-e7 */
- 0xde, 0xda, 0xdb, 0xd9, 0xfd, 0xdd, 0xaf, 0x3f, /* e8-ef */
- 0xad, 0xb1, '?', 0xbe, 0xb6, 0xa7, 0xf7, 0xb8, /* f0-f7 */
- 0xb0, 0xa8, 0xb7, 0xb9, 0xb3, 0xb2, '?', '?', /* f8-ff */
-};
-
-static const u_char
-u2l[256] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 00-07 */
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 08-0f */
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 10-17 */
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 18-1f */
- ' ', '!', '"', '#', '$', '%', '&', '\'', /* 20-27 */
- '(', ')', '*', '+', ',', '-', '.', '/', /* 28-2f */
- '0', '1', '2', '3', '4', '5', '6', '7', /* 30-37 */
- '8', '9', ':', ';', '<', '=', '>', '?', /* 38-3f */
- '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 40-47 */
- 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 48-4f */
- 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 50-57 */
- 'x', 'y', 'z', '[', '\\', ']', '^', '_', /* 58-5f */
- '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 60-67 */
- 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 68-6f */
- 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 70-77 */
- 'x', 'y', 'z', '{', '|', '}', '~', 0x7f, /* 78-7f */
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 80-87 */
- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 88-8f */
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 90-97 */
- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 98-9f */
- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* a0-a7 */
- 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* a8-af */
- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* b0-b7 */
- 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* b8-bf */
- 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* c0-c7 */
- 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* c8-cf */
- 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* d0-d7 */
- 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* d8-df */
- 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* e0-e7 */
- 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* e8-ef */
- 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* f0-f7 */
- 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* f8-ff */
-};
-
/*
* DOS filenames are made of 2 parts, the name part and the extension part.
* The name part is 8 characters long and the extension part is 3
@@ -369,11 +271,16 @@
* just have a 0xe5 mean 0xe5 because that is used to mean a freed
* directory slot. Another dos quirk.
*/
+ /* Does the comment above consern cp866 or cp850 only? */
if (*dn == SLOT_E5)
- c = dos2unix[0xe5];
+ c = kiconv_char (cs_d2u, '\xe5', '?');
else
- c = dos2unix[*dn];
- *un++ = lower ? u2l[c] : c;
+ c = kiconv_char (cs_d2u, *dn, '?');
+
+ if (lower)
+ c = kiconv_char (cs_u2lc, c, 0);
+
+ *un++ = c;
/*
* Copy the rest into the unix filename string, ignoring
@@ -384,8 +291,10 @@
;
for (i = 1; i <= j; i++) {
- c = dos2unix[dn[i]];
- *un++ = lower ? u2l[c] : c;
+ c = kiconv_char (cs_d2u, dn [i], '?');
+ if (lower)
+ c = kiconv_char (cs_u2lc, c, 0);
+ *un++ = c;
thislong++;
}
dn += 8;
@@ -398,8 +307,11 @@
*un++ = '.';
thislong++;
for (i = 0; i < 3 && *dn != ' '; i++) {
- c = dos2unix[*dn++];
- *un++ = lower ? u2l[c] : c;
+ c = kiconv_char (cs_d2u, *dn, '?');
+ ++dn;
+ if (lower)
+ c = kiconv_char (cs_u2lc, c, 0);
+ *un++ = c;
thislong++;
}
}
@@ -431,6 +343,7 @@
const u_char *cp, *dp, *dp1;
u_char gentext[6], *wcp;
int shortlen;
+ int c;
/*
* Fill the dos filename string with blanks. These are DOS's pad
@@ -494,7 +407,9 @@
else
l = unlen - (dp - un);
for (i = 0, j = 8; i < l && j < 11; i++, j++) {
- if (dp[i] != (dn[j] = unix2dos[dp[i]])
+ c = kiconv_char (cs_u2d, dp[i], 0);
+ c = dn[j] = kiconv_char (cs_d2uc, c, 0);
+ if (dp[i] != c
&& conv != 3)
conv = 2;
if (!dn[j]) {
@@ -519,7 +434,7 @@
if ((*un == ' ') && shortlen)
dn[j] = ' ';
else
- dn[j] = unix2dos[*un];
+ dn[j] = kiconv_char (cs_d2uc, kiconv_char (cs_u2d, *un, 0), 0);
if ((*un != dn[j])
&& conv != 3)
conv = 2;
@@ -694,8 +609,11 @@
return chksum;
return -1;
}
- if (u2l[*cp++] != u2l[*un++] || *cp++)
+ if (kiconv_char (cs_u2lc, *cp++, 0) != kiconv_char (cs_u2lc, *un++, 0)
+ || *cp++)
+ {
return -1;
+ }
}
for (cp = wep->wePart2, i = sizeof(wep->wePart2)/2; --i >= 0;) {
if (--unlen < 0) {
@@ -703,8 +621,11 @@
return chksum;
return -1;
}
- if (u2l[*cp++] != u2l[*un++] || *cp++)
+ if (kiconv_char (cs_u2lc, *cp++, 0) != kiconv_char (cs_u2lc, *un++, 0)
+ || *cp++)
+ {
return -1;
+ }
}
for (cp = wep->wePart3, i = sizeof(wep->wePart3)/2; --i >= 0;) {
if (--unlen < 0) {
@@ -712,8 +633,11 @@
return chksum;
return -1;
}
- if (u2l[*cp++] != u2l[*un++] || *cp++)
+ if (kiconv_char (cs_u2lc, *cp++, 0) != kiconv_char (cs_u2lc, *un++, 0)
+ || *cp++)
+ {
return -1;
+ }
}
return chksum;
}
Index: sys/fs/msdosfs/msdosfs_kiconv.c
===================================================================
RCS file: sys/fs/msdosfs/msdosfs_kiconv.c
diff -N sys/fs/msdosfs/msdosfs_kiconv.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/fs/msdosfs/msdosfs_kiconv.c 21 May 2007 18:05:42 -0000
@@ -0,0 +1,456 @@
+#ifdef _KERNEL
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/null.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <fs/msdosfs/msdosfs_kiconv.h>
+//#include <lib/libkern/libkern.h>
+#include <sys/malloc.h>
+#define KICONV_MALLOC(size, type, flags) malloc (size, type, flags)
+#define KICONV_FREE(size, type) free (size, type)
+#else
+#define KICONV_MALLOC(size, type, flags) malloc (size)
+#define KICONV_FREE(ptr, type) free (ptr)
+#endif
+
+typedef struct kiconv_data_ {
+ const int *table;
+} kiconv_data;
+
+static const int
+tr__cp850_to_iso88591 [256] = {
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ ' ', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '[', 0x5C, ']', '^', '_',
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', '{', '|', '}', '~', 0x7F,
+ 0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7,
+ 0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5,
+ 0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9,
+ 0xFF, 0xD6, 0xDC, 0xF8, 0xA3, 0xD8, 0xD7, -1,
+ 0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA,
+ 0xBF, 0xAE, 0xAC, 0xBD, 0xBC, 0xA1, 0xAB, 0xBB,
+ -1, -1, -1, -1, -1, 0xC1, 0xC2, 0xC0,
+ 0xA9, -1, -1, -1, -1, 0xA2, 0xA5, -1,
+ -1, -1, -1, -1, -1, -1, 0xE3, 0xC3,
+ -1, -1, -1, -1, -1, -1, -1, 0xA4,
+ 0xF0, 0xD0, 0xCA, 0xCB, 0xC8, -1, 0xCD, 0xCE,
+ 0xCF, -1, -1, -1, -1, 0xA6, 0xCC, -1,
+ 0xD3, 0xDF, 0xD4, 0xD2, 0xF5, 0xD5, 0xB5, 0xFE,
+ 0xDE, 0xDA, 0xDB, 0xD9, 0xFD, 0xDD, 0xAF, 0xB4,
+ 0xAD, 0xB1, -1, 0xBE, 0xB6, 0xA7, 0xF7, 0xB8,
+ 0xB0, 0xA8, 0xB7, 0xB9, 0xB3, 0xB2, -1, 0xA0,
+};
+
+static const int
+tr__iso88591_to_cp850 [256] = {
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ ' ', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '[', 0x5C, ']', '^', '_',
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', '{', '|', '}', '~', 0x7F,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 0xFF, 0xAD, 0xBD, 0x9C, 0xCF, 0xBE, 0xDD, 0xF5,
+ 0xF9, 0xB8, 0xA6, 0xAE, 0xAA, 0xF0, 0xA9, 0xEE,
+ 0xF8, 0xF1, 0xFD, 0xFC, 0xEF, 0xE6, 0xF4, 0xFA,
+ 0xF7, 0xFB, 0xA7, 0xAF, 0xAC, 0xAB, 0xF3, 0xA8,
+ 0xB7, 0xB5, 0xB6, 0xC7, 0x8E, 0x8F, 0x92, 0x80,
+ 0xD4, 0x90, 0xD2, 0xD3, 0xDE, 0xD6, 0xD7, 0xD8,
+ 0xD1, 0xA5, 0xE3, 0xE0, 0xE2, 0xE5, 0x99, 0x9E,
+ 0x9D, 0xEB, 0xE9, 0xEA, 0x9A, 0xED, 0xE8, 0xE1,
+ 0x85, 0xA0, 0x83, 0xC6, 0x84, 0x86, 0x91, 0x87,
+ 0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B,
+ 0xD0, 0xA4, 0x95, 0xA2, 0x93, 0xE4, 0x94, 0xF6,
+ 0x9B, 0x97, 0xA3, 0x96, 0x81, 0xEC, 0xE7, 0x98,
+};
+
+static const int
+tr__cp850_to_upper [256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ ' ', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '[', 0x5C, ']', '^', '_',
+ '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '{', '|', '}', '~', 0x7F,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+ 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
+ 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
+ 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
+ 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
+ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
+ 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
+ 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+};
+
+static const int
+tr__iso88591_to_lower [256] = {
+ 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ ' ', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', '[', 0x5C, ']', '^', '_',
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', '{', '|', '}', '~', 0x7F,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+ 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
+ 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
+ 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
+ 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
+ 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xD7,
+ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xDF,
+ 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+};
+
+static const int
+tr__cp866_to_cp1251 [256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ ' ', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', '{', '|', '}', '~', 0x7F,
+ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
+ 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
+ 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+ 0xA8, 0xB8, 0xAA, 0xBA, 0xAF, 0xBF, 0xA1, 0xA2,
+ 0xB0, -1, 0xB7, -1, 0xB9, 0xA4, -1, 0xA0,
+};
+
+static const int
+tr__cp1251_to_cp866 [256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ ' ', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', '{', '|', '}', '~', 0x7F,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 0xFF, 0xF6, 0xF7, -1, 0xFD, -1, -1, -1,
+ 0xF0, -1, 0xF2, -1, -1, -1, -1, 0xF4,
+ 0xF8, -1, -1, -1, -1, -1, -1, 0xFA,
+ 0xF1, 0xFC, 0xF3, -1, -1, -1, -1, 0xF5,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+ 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
+ 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
+ 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
+};
+
+static const int
+tr__cp866_to_upper [256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ ' ', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
+ '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '{', '|', '}', '~', 0x7F,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+ 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
+ 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
+ 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
+ 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
+ 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+ 0xF0, 0xF0, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+};
+
+static const int
+tr__cp1251_to_lower [256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ ' ', '!', '"', '#', '$', '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', '[', '\\', ']', '^', '_',
+ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', '{', '|', '}', '~', 0x7F,
+ 0x90, 0x83, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x9A, 0x8B, 0x9C, 0x9D, 0x9E, 0x9F,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+ 0xA0, 0xA2, 0xA2, 0xBC, 0xA4, 0xB4, 0xA6, 0xA7,
+ 0xB8, 0xA9, 0xBA, 0xAB, 0xAC, 0xAD, 0xAE, 0xBF,
+ 0xB0, 0xB1, 0xB3, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
+ 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBE, 0xBE, 0xBF,
+ 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+ 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+ 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+};
+
+void * kiconv_open (const char *dstname, const char *srcname)
+{
+ static const char s_CP1251 [] = "cp1251";
+ static const char s_CP866 [] = "cp866";
+ static const char s_ISO88591 [] = "iso-8859-1";
+ static const char s_CP850 [] = "cp850";
+
+ static struct {
+ const char *s;
+ const char *d;
+ const int *t;
+ } conv_table [] = {
+ {s_CP1251, KICONV_TOLOWER, tr__cp1251_to_lower},
+ {s_CP866, KICONV_TOUPPER, tr__cp866_to_upper},
+
+ {s_CP1251, s_CP866, tr__cp1251_to_cp866},
+ {s_CP866, s_CP1251, tr__cp866_to_cp1251},
+
+ {s_ISO88591, KICONV_TOLOWER, tr__iso88591_to_lower},
+ {s_CP850, KICONV_TOUPPER, tr__cp850_to_upper},
+
+ {s_CP850, s_ISO88591, tr__cp850_to_iso88591},
+ {s_ISO88591, s_CP850, tr__iso88591_to_cp850},
+ };
+
+ int i;
+
+ printf ("kiconv_open: before malloc\n");
+
+ kiconv_data *ret = KICONV_MALLOC (sizeof (kiconv_data), M_TEMP, M_WAITOK);
+
+ printf ("kiconv_open: after malloc %p\n", ret);
+
+ if (!ret)
+ return NULL;
+
+ printf ("kiconv_open: before strcmp\n");
+ printf ("kiconv_open: before strcmp dst=%s\n", dstname);
+ printf ("kiconv_open: before strcmp src=%s\n", srcname);
+
+ for (i=0; i < sizeof (conv_table)/sizeof (conv_table [0]); ++i){
+ if (!strcmp (conv_table [i].s, srcname) &&
+ !strcmp (conv_table [i].d, dstname))
+ {
+ ret -> table = conv_table [i].t;
+ return ret;
+ }
+ }
+
+ printf ("kiconv_open: NULL!!!\n");
+/* Uncomment the following line!
+ KICONV_FREE (ret -> table, M_TEMP);
+*/
+ return NULL;
+}
+
+int kiconv_close (void * descr)
+{
+ if (!descr){
+ /* NULL must be allowed */
+ return 0;
+ }
+
+ /* actual code here */
+ return 0;
+}
+
+size_t kiconv (void * descr, const char ** src, size_t * srcleft,
+ char ** dst, size_t * dstleft)
+{
+ size_t srcl, dstl;
+ const char *srcp;
+ char *dstp;
+ int s, d;
+ size_t ret;
+
+ srcp = *src;
+ dstp = *dst;
+ srcl = *srcleft;
+ dstl = *dstleft;
+
+ ret = 0;
+
+ while (srcl && dstl){
+ s = (unsigned char) *srcp;
+ d = ((const kiconv_data *) descr) -> table [s];
+
+ if (d == 0 && s != 0){
+ ret = (size_t) -1;
+ break;
+ }
+
+ *dstp = d;
+
+ ++srcp;
+ --srcl;
+ ++dstp;
+ --dstl;
+ }
+
+ *src = srcp;
+ *dst = dstp;
+ *srcleft = srcl;
+ *dstleft = dstl;
+ return ret;
+}
+
+void kiconv_string (
+ void * descr,
+ const char *src, size_t src_len,
+ char *dst, size_t dst_max_len,
+ char error_char)
+{
+ /* assert (max_dst_len > 0); */
+
+ if (src_len == (size_t) -1)
+ src_len = strlen (src) + 1;
+
+ while (0 != kiconv (descr, &src, &src_len, &dst, &dst_max_len)){
+ *dst++ = error_char;
+ --dst_max_len;
+
+ ++src;
+ --src_len;
+ }
+}
+
+char
+kiconv_char (void * descr, char c, char error_char)
+{
+ size_t sl;
+ size_t dl;
+ const char *s;
+ char *d;
+ size_t err_cnt;
+
+ sl = dl = 1;
+ s = &c;
+ d = &c;
+
+ err_cnt = kiconv (descr, &s, &sl, &d, &dl);
+
+ if (err_cnt)
+ return error_char;
+ else
+ return c;
+}
Index: sys/fs/msdosfs/msdosfs_kiconv.h
===================================================================
RCS file: sys/fs/msdosfs/msdosfs_kiconv.h
diff -N sys/fs/msdosfs/msdosfs_kiconv.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/fs/msdosfs/msdosfs_kiconv.h 21 May 2007 18:05:42 -0000
@@ -0,0 +1,29 @@
+#ifndef _KICONV_H_
+#define _KICONV_H_
+
+#define KICONV_TOUPPER ("toupper")
+#define KICONV_TOLOWER ("tolower")
+
+/* iconv(3) like API */
+void *
+kiconv_open (const char *dstname, const char *srcname);
+
+int
+kiconv_close (void * descr);
+
+size_t
+kiconv (void * descr, const char ** src, size_t * srcleft,
+ char ** dst, size_t * dstleft);
+
+/* extrac funcs */
+void
+kiconv_string (
+ void * descr,
+ const char *src, size_t src_len,
+ char *dst, size_t dst_max_len,
+ char error_char);
+
+char
+kiconv_char (void * descr, char c, char error_char);
+
+#endif // _KICONV_H_
Index: sys/fs/msdosfs/msdosfs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/msdosfs/msdosfs_vfsops.c,v
retrieving revision 1.40.2.1
diff -u -r1.40.2.1 msdosfs_vfsops.c
--- sys/fs/msdosfs/msdosfs_vfsops.c 27 Feb 2007 23:11:36 -0000 1.40.2.1
+++ sys/fs/msdosfs/msdosfs_vfsops.c 21 May 2007 18:05:47 -0000
@@ -76,6 +76,7 @@
#include <sys/conf.h>
#include <sys/kauth.h>
+#include <fs/msdosfs/msdosfs_kiconv.h>
#include <fs/msdosfs/bpb.h>
#include <fs/msdosfs/bootsect.h>
#include <fs/msdosfs/direntry.h>
@@ -107,6 +108,11 @@
MALLOC_DEFINE(M_MSDOSFSMNT, "MSDOSFS mount", "MSDOS FS mount structure");
MALLOC_DEFINE(M_MSDOSFSFAT, "MSDOSFS fat", "MSDOS FS fat table");
+void *cs_u2d;
+void *cs_d2u;
+void *cs_d2uc;
+void *cs_u2lc;
+
#define ROOTNAME "root_device"
extern const struct vnodeopv_desc msdosfs_vnodeop_opv_desc;
@@ -140,6 +146,54 @@
};
VFS_ATTACH(msdosfs_vfsops);
+static
+int update_mp_kiconv (
+ struct msdosfs_args *argp,
+ struct msdosfsmount *pmp)
+{
+ int error;
+
+ if (!argp->cs_unix [0]){
+ strlcpy (argp->cs_unix, MSDOSFSMNT_CS_UNIX, sizeof (argp->cs_unix));
+ }
+ if (!argp->cs_dos [0]){
+ strlcpy (argp->cs_dos, MSDOSFSMNT_CS_DOS, sizeof (argp->cs_dos));
+ }
+
+ printf ("msdosfs_mount: cs_unix=%p\n", argp->cs_unix);
+ printf ("msdosfs_mount: cs_unix=%s\n", argp->cs_unix);
+
+ printf ("msdosfs_mount: cs_dos=%p\n", argp->cs_dos);
+ printf ("msdosfs_mount: cs_dos=%s\n", argp->cs_dos);
+
+
+ error = 0;
+ printf ("msdosfs_mount: I'm before kiconv_open\n");
+
+ cs_u2d = pmp->pm_cs_u2d = kiconv_open (argp->cs_dos, argp->cs_unix);
+ cs_d2u = pmp->pm_cs_d2u = kiconv_open (argp->cs_unix, argp->cs_dos);
+ cs_u2lc = pmp->pm_cs_u2lc = kiconv_open (KICONV_TOLOWER, argp->cs_unix);
+ cs_d2uc = pmp->pm_cs_d2uc = kiconv_open (KICONV_TOUPPER, argp->cs_dos);
+
+ printf ("msdosfs_mount: I'm after kiconv_open\n");
+
+ if (!cs_u2d || !cs_d2u || !cs_u2lc || !cs_d2uc){
+ kiconv_close (cs_u2d);
+ kiconv_close (cs_d2u);
+ kiconv_close (cs_u2lc);
+ kiconv_close (cs_d2uc);
+
+ error = EFAULT;
+ goto ex;
+ }
+
+ printf ("msdosfs_mount: kiconv_open succeded\n");
+
+ ex:
+ printf ("msdosfs_mount: error code=%d\n", error);
+ return error;
+}
+
static int
update_mp(mp, argp)
struct mount *mp;
@@ -148,6 +202,11 @@
struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
int error;
+ printf ("msdosfs_mount: I'm inside update_mp\n");
+ error = update_mp_kiconv (argp, pmp);
+ if (error)
+ return error;
+
pmp->pm_gid = argp->gid;
pmp->pm_uid = argp->uid;
pmp->pm_mask = argp->mask & ALLPERMS;
@@ -844,6 +903,11 @@
((u_int *)vp->v_data)[1]);
}
#endif
+ kiconv_close (pmp->pm_cs_d2u);
+ kiconv_close (pmp->pm_cs_u2d);
+ kiconv_close (pmp->pm_cs_d2uc);
+ kiconv_close (pmp->pm_cs_u2lc);
+
vn_lock(pmp->pm_devvp, LK_EXCLUSIVE | LK_RETRY);
error = VOP_CLOSE(pmp->pm_devvp,
pmp->pm_flags & MSDOSFSMNT_RONLY ? FREAD : FREAD|FWRITE, NOCRED, l);
Index: sys/fs/msdosfs/msdosfsmount.h
===================================================================
RCS file: /cvsroot/src/sys/fs/msdosfs/msdosfsmount.h,v
retrieving revision 1.12
diff -u -r1.12 msdosfsmount.h
--- sys/fs/msdosfs/msdosfsmount.h 25 Nov 2006 12:17:30 -0000 1.12
+++ sys/fs/msdosfs/msdosfsmount.h 21 May 2007 18:05:47 -0000
@@ -50,9 +50,15 @@
#ifndef _MSDOSFS_MSDOSFSMOUNT_H_
#define _MSDOSFS_MSDOSFSMOUNT_H_
+/* default charsets */
+#define MSDOSFSMNT_CS_DOS "cp850"
+#define MSDOSFSMNT_CS_UNIX "iso-8859-1" /* "utf-8" */
+
/*
* Arguments to mount MSDOS filesystems.
*/
+#define MSDOSFSMNT_MAXCSLEN 32
+
struct msdosfs_args {
char *fspec; /* blocks special holding the fs to mount */
struct export_args30 _pad1; /* compat with old userland tools */
@@ -66,6 +72,9 @@
#define MSDOSFSMNT_VERSION 3
mode_t dirmask; /* v2: mask to be applied for msdosfs perms */
int gmtoff; /* v3: offset from UTC in seconds */
+ /* Character sets */
+ char cs_dos [MSDOSFSMNT_MAXCSLEN];
+ char cs_unix [MSDOSFSMNT_MAXCSLEN];
};
/*
@@ -133,6 +142,11 @@
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 */
+ /* Character sets convertors */
+ void *pm_cs_d2u; /* DOS to Unix */
+ void *pm_cs_u2d; /* Unix to DOS */
+ void *pm_cs_u2lc; /* UNIX to lower case */
+ void *pm_cs_d2uc; /* DOS to upper case */
};
/* Byte offset in FAT on filesystem pmp, cluster cn */
#define FATOFS(pmp, cn) ((cn) * (pmp)->pm_fatmult / (pmp)->pm_fatdiv)
Index: sys/lkm/vfs/msdosfs/Makefile
===================================================================
RCS file: /cvsroot/src/sys/lkm/vfs/msdosfs/Makefile,v
retrieving revision 1.10
diff -u -r1.10 Makefile
--- sys/lkm/vfs/msdosfs/Makefile 26 Dec 2002 12:31:25 -0000 1.10
+++ sys/lkm/vfs/msdosfs/Makefile 21 May 2007 18:05:47 -0000
@@ -8,6 +8,6 @@
SRCS= lkminit_vfs.c
SRCS+= msdosfs_conv.c msdosfs_denode.c msdosfs_fat.c msdosfs_lookup.c
-SRCS+= msdosfs_vfsops.c msdosfs_vnops.c
+SRCS+= msdosfs_vfsops.c msdosfs_vnops.c msdosfs_kiconv.c
.include <bsd.kmod.mk>