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