diff options
Diffstat (limited to 'fs/isofs/joliet.c')
-rw-r--r-- | fs/isofs/joliet.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c new file mode 100644 index 000000000..c34bfef76 --- /dev/null +++ b/fs/isofs/joliet.c @@ -0,0 +1,110 @@ +/* + * linux/fs/isofs/joliet.c + * + * (C) 1996 Gordon Chaffee + * + * Joliet: Microsoft's Unicode extensions to iso9660 + */ + +#include <linux/string.h> +#include <linux/nls.h> +#include <linux/malloc.h> +#include <linux/iso_fs.h> + +/* + * Convert Unicode 16 to UTF8 or ascii. + */ +static int +uni16_to_x8(unsigned char *ascii, unsigned char *uni, int len, + struct nls_table *nls) +{ + unsigned char *ip, *op; + unsigned char ch, cl; + unsigned char *uni_page; + + ip = uni; + op = ascii; + + while ((*ip || ip[1]) && len) { + ch = *ip++; + cl = *ip++; + + uni_page = nls->page_uni2charset[ch]; + if (uni_page && uni_page[cl]) { + *op++ = uni_page[cl]; + } else { + *op++ = '?'; + } + len--; + } + *op = 0; + return (op - ascii); +} + +/* Convert big endian wide character string to utf8 */ +static int +wcsntombs_be(__u8 *s, const __u8 *pwcs, int inlen, int maxlen) +{ + const __u8 *ip; + __u8 *op; + int size; + __u16 c; + + op = s; + ip = pwcs; + while ((*ip || ip[1]) && (maxlen > 0) && (inlen > 0)) { + c = (*ip << 8) | ip[1]; + if (c > 0x7f) { + size = utf8_wctomb(op, c, maxlen); + if (size == -1) { + /* Ignore character and move on */ + maxlen--; + } else { + op += size; + maxlen -= size; + } + } else { + *op++ = (__u8) c; + } + ip += 2; + inlen--; + } + return (op - s); +} + +int +get_joliet_filename(struct iso_directory_record * de, struct inode * inode, + unsigned char *outname) +{ + unsigned char utf8; + struct nls_table *nls; + unsigned char len = 0; + int i; + char c; + + utf8 = inode->i_sb->u.isofs_sb.s_utf8; + nls = inode->i_sb->u.isofs_sb.s_nls_iocharset; + + if (utf8) { + len = wcsntombs_be(outname, de->name, + de->name_len[0] >> 1, PAGE_SIZE); + } else { + len = uni16_to_x8(outname, de->name, + de->name_len[0] >> 1, nls); + } + if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1')) { + len -= 2; + } + + if (inode->i_sb->u.isofs_sb.s_name_check == 'r') { + for (i = 0; i < len; i++) { + c = outname[i]; + /* lower case */ + if (c >= 'A' && c <= 'Z') c |= 0x20; + if (c == ';') c = '.'; + outname[i] = c; + } + } + + return len; +} |