diff options
Diffstat (limited to 'fs/jfs/jfs_unicode.c')
-rw-r--r-- | fs/jfs/jfs_unicode.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/fs/jfs/jfs_unicode.c b/fs/jfs/jfs_unicode.c new file mode 100644 index 000000000..0148e2e4d --- /dev/null +++ b/fs/jfs/jfs_unicode.c @@ -0,0 +1,138 @@ +/* + * Copyright (C) International Business Machines Corp., 2000-2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/fs.h> +#include <linux/slab.h> +#include "jfs_incore.h" +#include "jfs_filsys.h" +#include "jfs_unicode.h" +#include "jfs_debug.h" + +/* + * NAME: jfs_strfromUCS() + * + * FUNCTION: Convert little-endian unicode string to character string + * + */ +int jfs_strfromUCS_le(char *to, const __le16 * from, + int len, struct nls_table *codepage) +{ + int i; + int outlen = 0; + static int warn_again = 5; /* Only warn up to 5 times total */ + int warn = !!warn_again; /* once per string */ + + if (codepage) { + for (i = 0; (i < len) && from[i]; i++) { + int charlen; + charlen = + codepage->uni2char(le16_to_cpu(from[i]), + &to[outlen], + NLS_MAX_CHARSET_SIZE); + if (charlen > 0) + outlen += charlen; + else + to[outlen++] = '?'; + } + } else { + for (i = 0; (i < len) && from[i]; i++) { + if (unlikely(le16_to_cpu(from[i]) & 0xff00)) { + to[i] = '?'; + if (unlikely(warn)) { + warn--; + warn_again--; + printk(KERN_ERR + "non-latin1 character 0x%x found in JFS file name\n", + le16_to_cpu(from[i])); + printk(KERN_ERR + "mount with iocharset=utf8 to access\n"); + } + + } + else + to[i] = (char) (le16_to_cpu(from[i])); + } + outlen = i; + } + to[outlen] = 0; + return outlen; +} + +/* + * NAME: jfs_strtoUCS() + * + * FUNCTION: Convert character string to unicode string + * + */ +static int jfs_strtoUCS(wchar_t * to, const unsigned char *from, int len, + struct nls_table *codepage) +{ + int charlen; + int i; + + if (codepage) { + for (i = 0; len && *from; i++, from += charlen, len -= charlen) + { + charlen = codepage->char2uni(from, len, &to[i]); + if (charlen < 1) { + jfs_err("jfs_strtoUCS: char2uni returned %d.", + charlen); + jfs_err("charset = %s, char = 0x%x", + codepage->charset, *from); + return charlen; + } + } + } else { + for (i = 0; (i < len) && from[i]; i++) + to[i] = (wchar_t) from[i]; + } + + to[i] = 0; + return i; +} + +/* + * NAME: get_UCSname() + * + * FUNCTION: Allocate and translate to unicode string + * + */ +int get_UCSname(struct component_name * uniName, struct dentry *dentry) +{ + struct nls_table *nls_tab = JFS_SBI(dentry->d_sb)->nls_tab; + int length = dentry->d_name.len; + + if (length > JFS_NAME_MAX) + return -ENAMETOOLONG; + + uniName->name = + kmalloc_array(length + 1, sizeof(wchar_t), GFP_NOFS); + + if (uniName->name == NULL) + return -ENOMEM; + + uniName->namlen = jfs_strtoUCS(uniName->name, dentry->d_name.name, + length, nls_tab); + + if (uniName->namlen < 0) { + kfree(uniName->name); + return uniName->namlen; + } + + return 0; +} |