File: joliet.c

package info (click to toggle)
kernel-source-2.2.20 2.2.20-5woody3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 93,308 kB
  • ctags: 278,986
  • sloc: ansic: 1,724,452; asm: 59,550; makefile: 10,263; sh: 2,401; perl: 907; tcl: 570; lisp: 218; cpp: 186; awk: 133; sed: 72
file content (99 lines) | stat: -rw-r--r-- 1,840 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
 *  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;

	ip = uni;
	op = ascii;

	while ((*ip || ip[1]) && len) {
		int llen;
		nls->uni2char(ip[0], ip[1], op, 20, &llen);
		op += llen;
		ip += 2;
		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, unsigned char *outname,
		    struct inode * inode)
{
	unsigned char utf8;
	struct nls_table *nls;
	unsigned char len = 0;

	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;
	}

	/*
	 * Windows doesn't like periods at the end of a name,
	 * so neither do we
	 */
	while (len >= 2 && (outname[len-1] == '.')) {
		len--;
	}

	return len;
}