1 /* 2 * linux/fs/isofs/joliet.c 3 * 4 * (C) 1996 Gordon Chaffee 5 * 6 * Joliet: Microsoft's Unicode extensions to iso9660 7 */ 8 9 #include <linux/types.h> 10 #include <linux/nls.h> 11 #include "isofs.h" 12 13 /* 14 * Convert Unicode 16 to UTF-8 or ASCII. 15 */ 16 static int 17 uni16_to_x8(unsigned char *ascii, u16 *uni, int len, struct nls_table *nls) 18 { 19 wchar_t *ip, ch; 20 unsigned char *op; 21 22 ip = uni; 23 op = ascii; 24 25 while ((ch = get_unaligned(ip)) && len) { 26 int llen; 27 ch = be16_to_cpu(ch); 28 if ((llen = nls->uni2char(ch, op, NLS_MAX_CHARSET_SIZE)) > 0) 29 op += llen; 30 else 31 *op++ = '?'; 32 ip++; 33 34 len--; 35 } 36 *op = 0; 37 return (op - ascii); 38 } 39 40 /* Convert big endian wide character string to utf8 */ 41 static int 42 wcsntombs_be(__u8 *s, const __u8 *pwcs, int inlen, int maxlen) 43 { 44 const __u8 *ip; 45 __u8 *op; 46 int size; 47 __u16 c; 48 49 op = s; 50 ip = pwcs; 51 while ((*ip || ip[1]) && (maxlen > 0) && (inlen > 0)) { 52 c = (*ip << 8) | ip[1]; 53 if (c > 0x7f) { 54 size = utf8_wctomb(op, c, maxlen); 55 if (size == -1) { 56 /* Ignore character and move on */ 57 maxlen--; 58 } else { 59 op += size; 60 maxlen -= size; 61 } 62 } else { 63 *op++ = (__u8) c; 64 } 65 ip += 2; 66 inlen--; 67 } 68 return (op - s); 69 } 70 71 int 72 get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, struct inode * inode) 73 { 74 unsigned char utf8; 75 struct nls_table *nls; 76 unsigned char len = 0; 77 78 utf8 = ISOFS_SB(inode->i_sb)->s_utf8; 79 nls = ISOFS_SB(inode->i_sb)->s_nls_iocharset; 80 81 if (utf8) { 82 len = wcsntombs_be(outname, de->name, 83 de->name_len[0] >> 1, PAGE_SIZE); 84 } else { 85 len = uni16_to_x8(outname, (u16 *) de->name, 86 de->name_len[0] >> 1, nls); 87 } 88 if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1')) { 89 len -= 2; 90 } 91 92 /* 93 * Windows doesn't like periods at the end of a name, 94 * so neither do we 95 */ 96 while (len >= 2 && (outname[len-1] == '.')) { 97 len--; 98 } 99 100 return len; 101 } 102