1 /* 2 * Copyright (C) International Business Machines Corp., 2000-2004 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12 * the GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 */ 18 19 #include <linux/fs.h> 20 #include <linux/slab.h> 21 #include "jfs_incore.h" 22 #include "jfs_filsys.h" 23 #include "jfs_unicode.h" 24 #include "jfs_debug.h" 25 26 /* 27 * NAME: jfs_strfromUCS() 28 * 29 * FUNCTION: Convert little-endian unicode string to character string 30 * 31 */ 32 int jfs_strfromUCS_le(char *to, const __le16 * from, 33 int len, struct nls_table *codepage) 34 { 35 int i; 36 int outlen = 0; 37 static int warn_again = 5; /* Only warn up to 5 times total */ 38 int warn = !!warn_again; /* once per string */ 39 40 if (codepage) { 41 for (i = 0; (i < len) && from[i]; i++) { 42 int charlen; 43 charlen = 44 codepage->uni2char(le16_to_cpu(from[i]), 45 &to[outlen], 46 NLS_MAX_CHARSET_SIZE); 47 if (charlen > 0) 48 outlen += charlen; 49 else 50 to[outlen++] = '?'; 51 } 52 } else { 53 for (i = 0; (i < len) && from[i]; i++) { 54 if (unlikely(le16_to_cpu(from[i]) & 0xff00)) { 55 to[i] = '?'; 56 if (unlikely(warn)) { 57 warn--; 58 warn_again--; 59 printk(KERN_ERR 60 "non-latin1 character 0x%x found in JFS file name\n", 61 le16_to_cpu(from[i])); 62 printk(KERN_ERR 63 "mount with iocharset=utf8 to access\n"); 64 } 65 66 } 67 else 68 to[i] = (char) (le16_to_cpu(from[i])); 69 } 70 outlen = i; 71 } 72 to[outlen] = 0; 73 return outlen; 74 } 75 76 /* 77 * NAME: jfs_strtoUCS() 78 * 79 * FUNCTION: Convert character string to unicode string 80 * 81 */ 82 static int jfs_strtoUCS(wchar_t * to, const unsigned char *from, int len, 83 struct nls_table *codepage) 84 { 85 int charlen; 86 int i; 87 88 if (codepage) { 89 for (i = 0; len && *from; i++, from += charlen, len -= charlen) 90 { 91 charlen = codepage->char2uni(from, len, &to[i]); 92 if (charlen < 1) { 93 jfs_err("jfs_strtoUCS: char2uni returned %d.", 94 charlen); 95 jfs_err("charset = %s, char = 0x%x", 96 codepage->charset, *from); 97 return charlen; 98 } 99 } 100 } else { 101 for (i = 0; (i < len) && from[i]; i++) 102 to[i] = (wchar_t) from[i]; 103 } 104 105 to[i] = 0; 106 return i; 107 } 108 109 /* 110 * NAME: get_UCSname() 111 * 112 * FUNCTION: Allocate and translate to unicode string 113 * 114 */ 115 int get_UCSname(struct component_name * uniName, struct dentry *dentry) 116 { 117 struct nls_table *nls_tab = JFS_SBI(dentry->d_sb)->nls_tab; 118 int length = dentry->d_name.len; 119 120 if (length > JFS_NAME_MAX) 121 return -ENAMETOOLONG; 122 123 uniName->name = 124 kmalloc_array(length + 1, sizeof(wchar_t), GFP_NOFS); 125 126 if (uniName->name == NULL) 127 return -ENOMEM; 128 129 uniName->namlen = jfs_strtoUCS(uniName->name, dentry->d_name.name, 130 length, nls_tab); 131 132 if (uniName->namlen < 0) { 133 kfree(uniName->name); 134 return uniName->namlen; 135 } 136 137 return 0; 138 } 139