1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * linux/fs/isofs/joliet.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * (C) 1996 Gordon Chaffee
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * Joliet: Microsoft's Unicode extensions to iso9660
81da177e4SLinus Torvalds */
91da177e4SLinus Torvalds
1094f2f715SAl Viro #include <linux/types.h>
111da177e4SLinus Torvalds #include <linux/nls.h>
1294f2f715SAl Viro #include "isofs.h"
131da177e4SLinus Torvalds
141da177e4SLinus Torvalds /*
154de151d8SAlexey Dobriyan * Convert Unicode 16 to UTF-8 or ASCII.
161da177e4SLinus Torvalds */
171da177e4SLinus Torvalds static int
uni16_to_x8(unsigned char * ascii,__be16 * uni,int len,struct nls_table * nls)18d02d48d8SAl Viro uni16_to_x8(unsigned char *ascii, __be16 *uni, int len, struct nls_table *nls)
191da177e4SLinus Torvalds {
20d02d48d8SAl Viro __be16 *ip, ch;
211da177e4SLinus Torvalds unsigned char *op;
221da177e4SLinus Torvalds
231da177e4SLinus Torvalds ip = uni;
241da177e4SLinus Torvalds op = ascii;
251da177e4SLinus Torvalds
261da177e4SLinus Torvalds while ((ch = get_unaligned(ip)) && len) {
271da177e4SLinus Torvalds int llen;
28d02d48d8SAl Viro llen = nls->uni2char(be16_to_cpu(ch), op, NLS_MAX_CHARSET_SIZE);
29d02d48d8SAl Viro if (llen > 0)
301da177e4SLinus Torvalds op += llen;
311da177e4SLinus Torvalds else
321da177e4SLinus Torvalds *op++ = '?';
331da177e4SLinus Torvalds ip++;
341da177e4SLinus Torvalds
351da177e4SLinus Torvalds len--;
361da177e4SLinus Torvalds }
371da177e4SLinus Torvalds *op = 0;
381da177e4SLinus Torvalds return (op - ascii);
391da177e4SLinus Torvalds }
401da177e4SLinus Torvalds
411da177e4SLinus Torvalds int
get_joliet_filename(struct iso_directory_record * de,unsigned char * outname,struct inode * inode)421da177e4SLinus Torvalds get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, struct inode * inode)
431da177e4SLinus Torvalds {
441da177e4SLinus Torvalds struct nls_table *nls;
451da177e4SLinus Torvalds unsigned char len = 0;
461da177e4SLinus Torvalds
471da177e4SLinus Torvalds nls = ISOFS_SB(inode->i_sb)->s_nls_iocharset;
481da177e4SLinus Torvalds
49*28ce50f8SPali Rohár if (!nls) {
5074675a58SAlan Stern len = utf16s_to_utf8s((const wchar_t *) de->name,
5174675a58SAlan Stern de->name_len[0] >> 1, UTF16_BIG_ENDIAN,
5274675a58SAlan Stern outname, PAGE_SIZE);
531da177e4SLinus Torvalds } else {
54d02d48d8SAl Viro len = uni16_to_x8(outname, (__be16 *) de->name,
551da177e4SLinus Torvalds de->name_len[0] >> 1, nls);
561da177e4SLinus Torvalds }
57c3ed85a3SDave Jones if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1'))
581da177e4SLinus Torvalds len -= 2;
591da177e4SLinus Torvalds
601da177e4SLinus Torvalds /*
611da177e4SLinus Torvalds * Windows doesn't like periods at the end of a name,
621da177e4SLinus Torvalds * so neither do we
631da177e4SLinus Torvalds */
64c3ed85a3SDave Jones while (len >= 2 && (outname[len-1] == '.'))
651da177e4SLinus Torvalds len--;
661da177e4SLinus Torvalds
671da177e4SLinus Torvalds return len;
681da177e4SLinus Torvalds }
69