xref: /openbmc/linux/fs/isofs/joliet.c (revision 762f99f4f3cb41a775b5157dd761217beba65873)
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