xref: /openbmc/linux/fs/jfs/jfs_unicode.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*1a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *   Copyright (C) International Business Machines Corp., 2000-2004
41da177e4SLinus Torvalds  */
51da177e4SLinus Torvalds 
61da177e4SLinus Torvalds #include <linux/fs.h>
71da177e4SLinus Torvalds #include <linux/slab.h>
81da177e4SLinus Torvalds #include "jfs_incore.h"
91da177e4SLinus Torvalds #include "jfs_filsys.h"
101da177e4SLinus Torvalds #include "jfs_unicode.h"
111da177e4SLinus Torvalds #include "jfs_debug.h"
121da177e4SLinus Torvalds 
131da177e4SLinus Torvalds /*
141da177e4SLinus Torvalds  * NAME:	jfs_strfromUCS()
151da177e4SLinus Torvalds  *
161da177e4SLinus Torvalds  * FUNCTION:	Convert little-endian unicode string to character string
171da177e4SLinus Torvalds  *
181da177e4SLinus Torvalds  */
jfs_strfromUCS_le(char * to,const __le16 * from,int len,struct nls_table * codepage)191da177e4SLinus Torvalds int jfs_strfromUCS_le(char *to, const __le16 * from,
201da177e4SLinus Torvalds 		      int len, struct nls_table *codepage)
211da177e4SLinus Torvalds {
221da177e4SLinus Torvalds 	int i;
231da177e4SLinus Torvalds 	int outlen = 0;
241da177e4SLinus Torvalds 	static int warn_again = 5;	/* Only warn up to 5 times total */
251da177e4SLinus Torvalds 	int warn = !!warn_again;	/* once per string */
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds 	if (codepage) {
281da177e4SLinus Torvalds 		for (i = 0; (i < len) && from[i]; i++) {
291da177e4SLinus Torvalds 			int charlen;
301da177e4SLinus Torvalds 			charlen =
311da177e4SLinus Torvalds 			    codepage->uni2char(le16_to_cpu(from[i]),
321da177e4SLinus Torvalds 					       &to[outlen],
331da177e4SLinus Torvalds 					       NLS_MAX_CHARSET_SIZE);
341da177e4SLinus Torvalds 			if (charlen > 0)
351da177e4SLinus Torvalds 				outlen += charlen;
361da177e4SLinus Torvalds 			else
371da177e4SLinus Torvalds 				to[outlen++] = '?';
381da177e4SLinus Torvalds 		}
391da177e4SLinus Torvalds 	} else {
401da177e4SLinus Torvalds 		for (i = 0; (i < len) && from[i]; i++) {
41f5f28773SSonny Rao 			if (unlikely(le16_to_cpu(from[i]) & 0xff00)) {
42f5f28773SSonny Rao 				to[i] = '?';
43f5f28773SSonny Rao 				if (unlikely(warn)) {
441da177e4SLinus Torvalds 					warn--;
451da177e4SLinus Torvalds 					warn_again--;
461da177e4SLinus Torvalds 					printk(KERN_ERR
471da177e4SLinus Torvalds 			"non-latin1 character 0x%x found in JFS file name\n",
481da177e4SLinus Torvalds 					       le16_to_cpu(from[i]));
491da177e4SLinus Torvalds 					printk(KERN_ERR
501da177e4SLinus Torvalds 				"mount with iocharset=utf8 to access\n");
511da177e4SLinus Torvalds 				}
52f5f28773SSonny Rao 
531da177e4SLinus Torvalds 			}
541da177e4SLinus Torvalds 			else
551da177e4SLinus Torvalds 				to[i] = (char) (le16_to_cpu(from[i]));
561da177e4SLinus Torvalds 		}
571da177e4SLinus Torvalds 		outlen = i;
581da177e4SLinus Torvalds 	}
591da177e4SLinus Torvalds 	to[outlen] = 0;
601da177e4SLinus Torvalds 	return outlen;
611da177e4SLinus Torvalds }
621da177e4SLinus Torvalds 
631da177e4SLinus Torvalds /*
641da177e4SLinus Torvalds  * NAME:	jfs_strtoUCS()
651da177e4SLinus Torvalds  *
661da177e4SLinus Torvalds  * FUNCTION:	Convert character string to unicode string
671da177e4SLinus Torvalds  *
681da177e4SLinus Torvalds  */
jfs_strtoUCS(wchar_t * to,const unsigned char * from,int len,struct nls_table * codepage)691da177e4SLinus Torvalds static int jfs_strtoUCS(wchar_t * to, const unsigned char *from, int len,
701da177e4SLinus Torvalds 		struct nls_table *codepage)
711da177e4SLinus Torvalds {
721da177e4SLinus Torvalds 	int charlen;
731da177e4SLinus Torvalds 	int i;
741da177e4SLinus Torvalds 
751da177e4SLinus Torvalds 	if (codepage) {
761da177e4SLinus Torvalds 		for (i = 0; len && *from; i++, from += charlen, len -= charlen)
771da177e4SLinus Torvalds 		{
781da177e4SLinus Torvalds 			charlen = codepage->char2uni(from, len, &to[i]);
791da177e4SLinus Torvalds 			if (charlen < 1) {
801da177e4SLinus Torvalds 				jfs_err("jfs_strtoUCS: char2uni returned %d.",
811da177e4SLinus Torvalds 					charlen);
821da177e4SLinus Torvalds 				jfs_err("charset = %s, char = 0x%x",
831da177e4SLinus Torvalds 					codepage->charset, *from);
841da177e4SLinus Torvalds 				return charlen;
851da177e4SLinus Torvalds 			}
861da177e4SLinus Torvalds 		}
871da177e4SLinus Torvalds 	} else {
881da177e4SLinus Torvalds 		for (i = 0; (i < len) && from[i]; i++)
891da177e4SLinus Torvalds 			to[i] = (wchar_t) from[i];
901da177e4SLinus Torvalds 	}
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds 	to[i] = 0;
931da177e4SLinus Torvalds 	return i;
941da177e4SLinus Torvalds }
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds /*
971da177e4SLinus Torvalds  * NAME:	get_UCSname()
981da177e4SLinus Torvalds  *
991da177e4SLinus Torvalds  * FUNCTION:	Allocate and translate to unicode string
1001da177e4SLinus Torvalds  *
1011da177e4SLinus Torvalds  */
get_UCSname(struct component_name * uniName,struct dentry * dentry)1021da177e4SLinus Torvalds int get_UCSname(struct component_name * uniName, struct dentry *dentry)
1031da177e4SLinus Torvalds {
1041da177e4SLinus Torvalds 	struct nls_table *nls_tab = JFS_SBI(dentry->d_sb)->nls_tab;
1051da177e4SLinus Torvalds 	int length = dentry->d_name.len;
1061da177e4SLinus Torvalds 
1071da177e4SLinus Torvalds 	if (length > JFS_NAME_MAX)
1081da177e4SLinus Torvalds 		return -ENAMETOOLONG;
1091da177e4SLinus Torvalds 
1101da177e4SLinus Torvalds 	uniName->name =
1116da2ec56SKees Cook 	    kmalloc_array(length + 1, sizeof(wchar_t), GFP_NOFS);
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds 	if (uniName->name == NULL)
114087387f9SAkinobu Mita 		return -ENOMEM;
1151da177e4SLinus Torvalds 
1161da177e4SLinus Torvalds 	uniName->namlen = jfs_strtoUCS(uniName->name, dentry->d_name.name,
1171da177e4SLinus Torvalds 				       length, nls_tab);
1181da177e4SLinus Torvalds 
1191da177e4SLinus Torvalds 	if (uniName->namlen < 0) {
1201da177e4SLinus Torvalds 		kfree(uniName->name);
1211da177e4SLinus Torvalds 		return uniName->namlen;
1221da177e4SLinus Torvalds 	}
1231da177e4SLinus Torvalds 
1241da177e4SLinus Torvalds 	return 0;
1251da177e4SLinus Torvalds }
126