1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *   Copyright (C) International Business Machines Corp., 2000-2004
4  */
5 
6 #include <linux/fs.h>
7 #include <linux/slab.h>
8 #include "jfs_incore.h"
9 #include "jfs_filsys.h"
10 #include "jfs_unicode.h"
11 #include "jfs_debug.h"
12 
13 /*
14  * NAME:	jfs_strfromUCS()
15  *
16  * FUNCTION:	Convert little-endian unicode string to character string
17  *
18  */
jfs_strfromUCS_le(char * to,const __le16 * from,int len,struct nls_table * codepage)19 int jfs_strfromUCS_le(char *to, const __le16 * from,
20 		      int len, struct nls_table *codepage)
21 {
22 	int i;
23 	int outlen = 0;
24 	static int warn_again = 5;	/* Only warn up to 5 times total */
25 	int warn = !!warn_again;	/* once per string */
26 
27 	if (codepage) {
28 		for (i = 0; (i < len) && from[i]; i++) {
29 			int charlen;
30 			charlen =
31 			    codepage->uni2char(le16_to_cpu(from[i]),
32 					       &to[outlen],
33 					       NLS_MAX_CHARSET_SIZE);
34 			if (charlen > 0)
35 				outlen += charlen;
36 			else
37 				to[outlen++] = '?';
38 		}
39 	} else {
40 		for (i = 0; (i < len) && from[i]; i++) {
41 			if (unlikely(le16_to_cpu(from[i]) & 0xff00)) {
42 				to[i] = '?';
43 				if (unlikely(warn)) {
44 					warn--;
45 					warn_again--;
46 					printk(KERN_ERR
47 			"non-latin1 character 0x%x found in JFS file name\n",
48 					       le16_to_cpu(from[i]));
49 					printk(KERN_ERR
50 				"mount with iocharset=utf8 to access\n");
51 				}
52 
53 			}
54 			else
55 				to[i] = (char) (le16_to_cpu(from[i]));
56 		}
57 		outlen = i;
58 	}
59 	to[outlen] = 0;
60 	return outlen;
61 }
62 
63 /*
64  * NAME:	jfs_strtoUCS()
65  *
66  * FUNCTION:	Convert character string to unicode string
67  *
68  */
jfs_strtoUCS(wchar_t * to,const unsigned char * from,int len,struct nls_table * codepage)69 static int jfs_strtoUCS(wchar_t * to, const unsigned char *from, int len,
70 		struct nls_table *codepage)
71 {
72 	int charlen;
73 	int i;
74 
75 	if (codepage) {
76 		for (i = 0; len && *from; i++, from += charlen, len -= charlen)
77 		{
78 			charlen = codepage->char2uni(from, len, &to[i]);
79 			if (charlen < 1) {
80 				jfs_err("jfs_strtoUCS: char2uni returned %d.",
81 					charlen);
82 				jfs_err("charset = %s, char = 0x%x",
83 					codepage->charset, *from);
84 				return charlen;
85 			}
86 		}
87 	} else {
88 		for (i = 0; (i < len) && from[i]; i++)
89 			to[i] = (wchar_t) from[i];
90 	}
91 
92 	to[i] = 0;
93 	return i;
94 }
95 
96 /*
97  * NAME:	get_UCSname()
98  *
99  * FUNCTION:	Allocate and translate to unicode string
100  *
101  */
get_UCSname(struct component_name * uniName,struct dentry * dentry)102 int get_UCSname(struct component_name * uniName, struct dentry *dentry)
103 {
104 	struct nls_table *nls_tab = JFS_SBI(dentry->d_sb)->nls_tab;
105 	int length = dentry->d_name.len;
106 
107 	if (length > JFS_NAME_MAX)
108 		return -ENAMETOOLONG;
109 
110 	uniName->name =
111 	    kmalloc_array(length + 1, sizeof(wchar_t), GFP_NOFS);
112 
113 	if (uniName->name == NULL)
114 		return -ENOMEM;
115 
116 	uniName->namlen = jfs_strtoUCS(uniName->name, dentry->d_name.name,
117 				       length, nls_tab);
118 
119 	if (uniName->namlen < 0) {
120 		kfree(uniName->name);
121 		return uniName->namlen;
122 	}
123 
124 	return 0;
125 }
126