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 */
19int 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 */
69static 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 */
102int 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