GNU Linux-libre 5.19-rc6-gnu
[releases.git] / fs / jfs / jfs_unicode.c
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  */
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  */
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  */
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 }