162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) International Business Machines Corp., 2000-2004 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/fs.h> 762306a36Sopenharmony_ci#include <linux/slab.h> 862306a36Sopenharmony_ci#include "jfs_incore.h" 962306a36Sopenharmony_ci#include "jfs_filsys.h" 1062306a36Sopenharmony_ci#include "jfs_unicode.h" 1162306a36Sopenharmony_ci#include "jfs_debug.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* 1462306a36Sopenharmony_ci * NAME: jfs_strfromUCS() 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * FUNCTION: Convert little-endian unicode string to character string 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci */ 1962306a36Sopenharmony_ciint jfs_strfromUCS_le(char *to, const __le16 * from, 2062306a36Sopenharmony_ci int len, struct nls_table *codepage) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci int i; 2362306a36Sopenharmony_ci int outlen = 0; 2462306a36Sopenharmony_ci static int warn_again = 5; /* Only warn up to 5 times total */ 2562306a36Sopenharmony_ci int warn = !!warn_again; /* once per string */ 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci if (codepage) { 2862306a36Sopenharmony_ci for (i = 0; (i < len) && from[i]; i++) { 2962306a36Sopenharmony_ci int charlen; 3062306a36Sopenharmony_ci charlen = 3162306a36Sopenharmony_ci codepage->uni2char(le16_to_cpu(from[i]), 3262306a36Sopenharmony_ci &to[outlen], 3362306a36Sopenharmony_ci NLS_MAX_CHARSET_SIZE); 3462306a36Sopenharmony_ci if (charlen > 0) 3562306a36Sopenharmony_ci outlen += charlen; 3662306a36Sopenharmony_ci else 3762306a36Sopenharmony_ci to[outlen++] = '?'; 3862306a36Sopenharmony_ci } 3962306a36Sopenharmony_ci } else { 4062306a36Sopenharmony_ci for (i = 0; (i < len) && from[i]; i++) { 4162306a36Sopenharmony_ci if (unlikely(le16_to_cpu(from[i]) & 0xff00)) { 4262306a36Sopenharmony_ci to[i] = '?'; 4362306a36Sopenharmony_ci if (unlikely(warn)) { 4462306a36Sopenharmony_ci warn--; 4562306a36Sopenharmony_ci warn_again--; 4662306a36Sopenharmony_ci printk(KERN_ERR 4762306a36Sopenharmony_ci "non-latin1 character 0x%x found in JFS file name\n", 4862306a36Sopenharmony_ci le16_to_cpu(from[i])); 4962306a36Sopenharmony_ci printk(KERN_ERR 5062306a36Sopenharmony_ci "mount with iocharset=utf8 to access\n"); 5162306a36Sopenharmony_ci } 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci else 5562306a36Sopenharmony_ci to[i] = (char) (le16_to_cpu(from[i])); 5662306a36Sopenharmony_ci } 5762306a36Sopenharmony_ci outlen = i; 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci to[outlen] = 0; 6062306a36Sopenharmony_ci return outlen; 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/* 6462306a36Sopenharmony_ci * NAME: jfs_strtoUCS() 6562306a36Sopenharmony_ci * 6662306a36Sopenharmony_ci * FUNCTION: Convert character string to unicode string 6762306a36Sopenharmony_ci * 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_cistatic int jfs_strtoUCS(wchar_t * to, const unsigned char *from, int len, 7062306a36Sopenharmony_ci struct nls_table *codepage) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci int charlen; 7362306a36Sopenharmony_ci int i; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci if (codepage) { 7662306a36Sopenharmony_ci for (i = 0; len && *from; i++, from += charlen, len -= charlen) 7762306a36Sopenharmony_ci { 7862306a36Sopenharmony_ci charlen = codepage->char2uni(from, len, &to[i]); 7962306a36Sopenharmony_ci if (charlen < 1) { 8062306a36Sopenharmony_ci jfs_err("jfs_strtoUCS: char2uni returned %d.", 8162306a36Sopenharmony_ci charlen); 8262306a36Sopenharmony_ci jfs_err("charset = %s, char = 0x%x", 8362306a36Sopenharmony_ci codepage->charset, *from); 8462306a36Sopenharmony_ci return charlen; 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci } 8762306a36Sopenharmony_ci } else { 8862306a36Sopenharmony_ci for (i = 0; (i < len) && from[i]; i++) 8962306a36Sopenharmony_ci to[i] = (wchar_t) from[i]; 9062306a36Sopenharmony_ci } 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci to[i] = 0; 9362306a36Sopenharmony_ci return i; 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci/* 9762306a36Sopenharmony_ci * NAME: get_UCSname() 9862306a36Sopenharmony_ci * 9962306a36Sopenharmony_ci * FUNCTION: Allocate and translate to unicode string 10062306a36Sopenharmony_ci * 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_ciint get_UCSname(struct component_name * uniName, struct dentry *dentry) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci struct nls_table *nls_tab = JFS_SBI(dentry->d_sb)->nls_tab; 10562306a36Sopenharmony_ci int length = dentry->d_name.len; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci if (length > JFS_NAME_MAX) 10862306a36Sopenharmony_ci return -ENAMETOOLONG; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci uniName->name = 11162306a36Sopenharmony_ci kmalloc_array(length + 1, sizeof(wchar_t), GFP_NOFS); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci if (uniName->name == NULL) 11462306a36Sopenharmony_ci return -ENOMEM; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci uniName->namlen = jfs_strtoUCS(uniName->name, dentry->d_name.name, 11762306a36Sopenharmony_ci length, nls_tab); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci if (uniName->namlen < 0) { 12062306a36Sopenharmony_ci kfree(uniName->name); 12162306a36Sopenharmony_ci return uniName->namlen; 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci return 0; 12562306a36Sopenharmony_ci} 126