diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /fs/hfsplus |
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'fs/hfsplus')
-rw-r--r-- | fs/hfsplus/Makefile | 9 | ||||
-rw-r--r-- | fs/hfsplus/bfind.c | 210 | ||||
-rw-r--r-- | fs/hfsplus/bitmap.c | 221 | ||||
-rw-r--r-- | fs/hfsplus/bnode.c | 662 | ||||
-rw-r--r-- | fs/hfsplus/brec.c | 491 | ||||
-rw-r--r-- | fs/hfsplus/btree.c | 319 | ||||
-rw-r--r-- | fs/hfsplus/catalog.c | 358 | ||||
-rw-r--r-- | fs/hfsplus/dir.c | 484 | ||||
-rw-r--r-- | fs/hfsplus/extents.c | 505 | ||||
-rw-r--r-- | fs/hfsplus/hfsplus_fs.h | 414 | ||||
-rw-r--r-- | fs/hfsplus/hfsplus_raw.h | 326 | ||||
-rw-r--r-- | fs/hfsplus/inode.c | 555 | ||||
-rw-r--r-- | fs/hfsplus/ioctl.c | 188 | ||||
-rw-r--r-- | fs/hfsplus/options.c | 162 | ||||
-rw-r--r-- | fs/hfsplus/part_tbl.c | 133 | ||||
-rw-r--r-- | fs/hfsplus/super.c | 502 | ||||
-rw-r--r-- | fs/hfsplus/tables.c | 3245 | ||||
-rw-r--r-- | fs/hfsplus/unicode.c | 271 | ||||
-rw-r--r-- | fs/hfsplus/wrapper.c | 171 |
19 files changed, 9226 insertions, 0 deletions
diff --git a/fs/hfsplus/Makefile b/fs/hfsplus/Makefile new file mode 100644 index 000000000000..3cc0df730156 --- /dev/null +++ b/fs/hfsplus/Makefile | |||
@@ -0,0 +1,9 @@ | |||
1 | # | ||
2 | ## Makefile for the linux hfsplus filesystem routines. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_HFSPLUS_FS) += hfsplus.o | ||
6 | |||
7 | hfsplus-objs := super.o options.o inode.o ioctl.o extents.o catalog.o dir.o btree.o \ | ||
8 | bnode.o brec.o bfind.o tables.o unicode.o wrapper.o bitmap.o part_tbl.o | ||
9 | |||
diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c new file mode 100644 index 000000000000..257cdde0514b --- /dev/null +++ b/fs/hfsplus/bfind.c | |||
@@ -0,0 +1,210 @@ | |||
1 | /* | ||
2 | * linux/fs/hfsplus/bfind.c | ||
3 | * | ||
4 | * Copyright (C) 2001 | ||
5 | * Brad Boyer (flar@allandria.com) | ||
6 | * (C) 2003 Ardis Technologies <roman@ardistech.com> | ||
7 | * | ||
8 | * Search routines for btrees | ||
9 | */ | ||
10 | |||
11 | #include <linux/slab.h> | ||
12 | #include "hfsplus_fs.h" | ||
13 | |||
14 | int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd) | ||
15 | { | ||
16 | void *ptr; | ||
17 | |||
18 | fd->tree = tree; | ||
19 | fd->bnode = NULL; | ||
20 | ptr = kmalloc(tree->max_key_len * 2 + 4, GFP_KERNEL); | ||
21 | if (!ptr) | ||
22 | return -ENOMEM; | ||
23 | fd->search_key = ptr; | ||
24 | fd->key = ptr + tree->max_key_len + 2; | ||
25 | dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n", tree->cnid, __builtin_return_address(0)); | ||
26 | down(&tree->tree_lock); | ||
27 | return 0; | ||
28 | } | ||
29 | |||
30 | void hfs_find_exit(struct hfs_find_data *fd) | ||
31 | { | ||
32 | hfs_bnode_put(fd->bnode); | ||
33 | kfree(fd->search_key); | ||
34 | dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n", fd->tree->cnid, __builtin_return_address(0)); | ||
35 | up(&fd->tree->tree_lock); | ||
36 | fd->tree = NULL; | ||
37 | } | ||
38 | |||
39 | /* Find the record in bnode that best matches key (not greater than...)*/ | ||
40 | int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd) | ||
41 | { | ||
42 | int cmpval; | ||
43 | u16 off, len, keylen; | ||
44 | int rec; | ||
45 | int b, e; | ||
46 | int res; | ||
47 | |||
48 | b = 0; | ||
49 | e = bnode->num_recs - 1; | ||
50 | res = -ENOENT; | ||
51 | do { | ||
52 | rec = (e + b) / 2; | ||
53 | len = hfs_brec_lenoff(bnode, rec, &off); | ||
54 | keylen = hfs_brec_keylen(bnode, rec); | ||
55 | hfs_bnode_read(bnode, fd->key, off, keylen); | ||
56 | cmpval = bnode->tree->keycmp(fd->key, fd->search_key); | ||
57 | if (!cmpval) { | ||
58 | e = rec; | ||
59 | res = 0; | ||
60 | goto done; | ||
61 | } | ||
62 | if (cmpval < 0) | ||
63 | b = rec + 1; | ||
64 | else | ||
65 | e = rec - 1; | ||
66 | } while (b <= e); | ||
67 | //printk("%d: %d,%d,%d\n", bnode->this, b, e, rec); | ||
68 | if (rec != e && e >= 0) { | ||
69 | len = hfs_brec_lenoff(bnode, e, &off); | ||
70 | keylen = hfs_brec_keylen(bnode, e); | ||
71 | hfs_bnode_read(bnode, fd->key, off, keylen); | ||
72 | } | ||
73 | done: | ||
74 | fd->record = e; | ||
75 | fd->keyoffset = off; | ||
76 | fd->keylength = keylen; | ||
77 | fd->entryoffset = off + keylen; | ||
78 | fd->entrylength = len - keylen; | ||
79 | return res; | ||
80 | } | ||
81 | |||
82 | /* Traverse a B*Tree from the root to a leaf finding best fit to key */ | ||
83 | /* Return allocated copy of node found, set recnum to best record */ | ||
84 | int hfs_brec_find(struct hfs_find_data *fd) | ||
85 | { | ||
86 | struct hfs_btree *tree; | ||
87 | struct hfs_bnode *bnode; | ||
88 | u32 nidx, parent; | ||
89 | __be32 data; | ||
90 | int height, res; | ||
91 | |||
92 | tree = fd->tree; | ||
93 | if (fd->bnode) | ||
94 | hfs_bnode_put(fd->bnode); | ||
95 | fd->bnode = NULL; | ||
96 | nidx = tree->root; | ||
97 | if (!nidx) | ||
98 | return -ENOENT; | ||
99 | height = tree->depth; | ||
100 | res = 0; | ||
101 | parent = 0; | ||
102 | for (;;) { | ||
103 | bnode = hfs_bnode_find(tree, nidx); | ||
104 | if (IS_ERR(bnode)) { | ||
105 | res = PTR_ERR(bnode); | ||
106 | bnode = NULL; | ||
107 | break; | ||
108 | } | ||
109 | if (bnode->height != height) | ||
110 | goto invalid; | ||
111 | if (bnode->type != (--height ? HFS_NODE_INDEX : HFS_NODE_LEAF)) | ||
112 | goto invalid; | ||
113 | bnode->parent = parent; | ||
114 | |||
115 | res = __hfs_brec_find(bnode, fd); | ||
116 | if (!height) | ||
117 | break; | ||
118 | if (fd->record < 0) | ||
119 | goto release; | ||
120 | |||
121 | parent = nidx; | ||
122 | hfs_bnode_read(bnode, &data, fd->entryoffset, 4); | ||
123 | nidx = be32_to_cpu(data); | ||
124 | hfs_bnode_put(bnode); | ||
125 | } | ||
126 | fd->bnode = bnode; | ||
127 | return res; | ||
128 | |||
129 | invalid: | ||
130 | printk("HFS+-fs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n", | ||
131 | height, bnode->height, bnode->type, nidx, parent); | ||
132 | res = -EIO; | ||
133 | release: | ||
134 | hfs_bnode_put(bnode); | ||
135 | return res; | ||
136 | } | ||
137 | |||
138 | int hfs_brec_read(struct hfs_find_data *fd, void *rec, int rec_len) | ||
139 | { | ||
140 | int res; | ||
141 | |||
142 | res = hfs_brec_find(fd); | ||
143 | if (res) | ||
144 | return res; | ||
145 | if (fd->entrylength > rec_len) | ||
146 | return -EINVAL; | ||
147 | hfs_bnode_read(fd->bnode, rec, fd->entryoffset, fd->entrylength); | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | int hfs_brec_goto(struct hfs_find_data *fd, int cnt) | ||
152 | { | ||
153 | struct hfs_btree *tree; | ||
154 | struct hfs_bnode *bnode; | ||
155 | int idx, res = 0; | ||
156 | u16 off, len, keylen; | ||
157 | |||
158 | bnode = fd->bnode; | ||
159 | tree = bnode->tree; | ||
160 | |||
161 | if (cnt < 0) { | ||
162 | cnt = -cnt; | ||
163 | while (cnt > fd->record) { | ||
164 | cnt -= fd->record + 1; | ||
165 | fd->record = bnode->num_recs - 1; | ||
166 | idx = bnode->prev; | ||
167 | if (!idx) { | ||
168 | res = -ENOENT; | ||
169 | goto out; | ||
170 | } | ||
171 | hfs_bnode_put(bnode); | ||
172 | bnode = hfs_bnode_find(tree, idx); | ||
173 | if (IS_ERR(bnode)) { | ||
174 | res = PTR_ERR(bnode); | ||
175 | bnode = NULL; | ||
176 | goto out; | ||
177 | } | ||
178 | } | ||
179 | fd->record -= cnt; | ||
180 | } else { | ||
181 | while (cnt >= bnode->num_recs - fd->record) { | ||
182 | cnt -= bnode->num_recs - fd->record; | ||
183 | fd->record = 0; | ||
184 | idx = bnode->next; | ||
185 | if (!idx) { | ||
186 | res = -ENOENT; | ||
187 | goto out; | ||
188 | } | ||
189 | hfs_bnode_put(bnode); | ||
190 | bnode = hfs_bnode_find(tree, idx); | ||
191 | if (IS_ERR(bnode)) { | ||
192 | res = PTR_ERR(bnode); | ||
193 | bnode = NULL; | ||
194 | goto out; | ||
195 | } | ||
196 | } | ||
197 | fd->record += cnt; | ||
198 | } | ||
199 | |||
200 | len = hfs_brec_lenoff(bnode, fd->record, &off); | ||
201 | keylen = hfs_brec_keylen(bnode, fd->record); | ||
202 | fd->keyoffset = off; | ||
203 | fd->keylength = keylen; | ||
204 | fd->entryoffset = off + keylen; | ||
205 | fd->entrylength = len - keylen; | ||
206 | hfs_bnode_read(bnode, fd->key, off, keylen); | ||
207 | out: | ||
208 | fd->bnode = bnode; | ||
209 | return res; | ||
210 | } | ||
diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c new file mode 100644 index 000000000000..c7d316455fa0 --- /dev/null +++ b/fs/hfsplus/bitmap.c | |||
@@ -0,0 +1,221 @@ | |||
1 | /* | ||
2 | * linux/fs/hfsplus/bitmap.c | ||
3 | * | ||
4 | * Copyright (C) 2001 | ||
5 | * Brad Boyer (flar@allandria.com) | ||
6 | * (C) 2003 Ardis Technologies <roman@ardistech.com> | ||
7 | * | ||
8 | * Handling of allocation file | ||
9 | */ | ||
10 | |||
11 | #include <linux/pagemap.h> | ||
12 | |||
13 | #include "hfsplus_fs.h" | ||
14 | #include "hfsplus_raw.h" | ||
15 | |||
16 | #define PAGE_CACHE_BITS (PAGE_CACHE_SIZE * 8) | ||
17 | |||
18 | int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *max) | ||
19 | { | ||
20 | struct page *page; | ||
21 | struct address_space *mapping; | ||
22 | __be32 *pptr, *curr, *end; | ||
23 | u32 mask, start, len, n; | ||
24 | __be32 val; | ||
25 | int i; | ||
26 | |||
27 | len = *max; | ||
28 | if (!len) | ||
29 | return size; | ||
30 | |||
31 | dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len); | ||
32 | down(&HFSPLUS_SB(sb).alloc_file->i_sem); | ||
33 | mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; | ||
34 | page = read_cache_page(mapping, offset / PAGE_CACHE_BITS, | ||
35 | (filler_t *)mapping->a_ops->readpage, NULL); | ||
36 | pptr = kmap(page); | ||
37 | curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32; | ||
38 | i = offset % 32; | ||
39 | offset &= ~(PAGE_CACHE_BITS - 1); | ||
40 | if ((size ^ offset) / PAGE_CACHE_BITS) | ||
41 | end = pptr + PAGE_CACHE_BITS / 32; | ||
42 | else | ||
43 | end = pptr + ((size + 31) & (PAGE_CACHE_BITS - 1)) / 32; | ||
44 | |||
45 | /* scan the first partial u32 for zero bits */ | ||
46 | val = *curr; | ||
47 | if (~val) { | ||
48 | n = be32_to_cpu(val); | ||
49 | mask = (1U << 31) >> i; | ||
50 | for (; i < 32; mask >>= 1, i++) { | ||
51 | if (!(n & mask)) | ||
52 | goto found; | ||
53 | } | ||
54 | } | ||
55 | curr++; | ||
56 | |||
57 | /* scan complete u32s for the first zero bit */ | ||
58 | while (1) { | ||
59 | while (curr < end) { | ||
60 | val = *curr; | ||
61 | if (~val) { | ||
62 | n = be32_to_cpu(val); | ||
63 | mask = 1 << 31; | ||
64 | for (i = 0; i < 32; mask >>= 1, i++) { | ||
65 | if (!(n & mask)) | ||
66 | goto found; | ||
67 | } | ||
68 | } | ||
69 | curr++; | ||
70 | } | ||
71 | kunmap(page); | ||
72 | offset += PAGE_CACHE_BITS; | ||
73 | if (offset >= size) | ||
74 | break; | ||
75 | page = read_cache_page(mapping, offset / PAGE_CACHE_BITS, | ||
76 | (filler_t *)mapping->a_ops->readpage, NULL); | ||
77 | curr = pptr = kmap(page); | ||
78 | if ((size ^ offset) / PAGE_CACHE_BITS) | ||
79 | end = pptr + PAGE_CACHE_BITS / 32; | ||
80 | else | ||
81 | end = pptr + ((size + 31) & (PAGE_CACHE_BITS - 1)) / 32; | ||
82 | } | ||
83 | dprint(DBG_BITMAP, "bitmap full\n"); | ||
84 | start = size; | ||
85 | goto out; | ||
86 | |||
87 | found: | ||
88 | start = offset + (curr - pptr) * 32 + i; | ||
89 | if (start >= size) { | ||
90 | dprint(DBG_BITMAP, "bitmap full\n"); | ||
91 | goto out; | ||
92 | } | ||
93 | /* do any partial u32 at the start */ | ||
94 | len = min(size - start, len); | ||
95 | while (1) { | ||
96 | n |= mask; | ||
97 | if (++i >= 32) | ||
98 | break; | ||
99 | mask >>= 1; | ||
100 | if (!--len || n & mask) | ||
101 | goto done; | ||
102 | } | ||
103 | if (!--len) | ||
104 | goto done; | ||
105 | *curr++ = cpu_to_be32(n); | ||
106 | /* do full u32s */ | ||
107 | while (1) { | ||
108 | while (curr < end) { | ||
109 | n = be32_to_cpu(*curr); | ||
110 | if (len < 32) | ||
111 | goto last; | ||
112 | if (n) { | ||
113 | len = 32; | ||
114 | goto last; | ||
115 | } | ||
116 | *curr++ = cpu_to_be32(0xffffffff); | ||
117 | len -= 32; | ||
118 | } | ||
119 | set_page_dirty(page); | ||
120 | kunmap(page); | ||
121 | offset += PAGE_CACHE_BITS; | ||
122 | page = read_cache_page(mapping, offset / PAGE_CACHE_BITS, | ||
123 | (filler_t *)mapping->a_ops->readpage, NULL); | ||
124 | pptr = kmap(page); | ||
125 | curr = pptr; | ||
126 | end = pptr + PAGE_CACHE_BITS / 32; | ||
127 | } | ||
128 | last: | ||
129 | /* do any partial u32 at end */ | ||
130 | mask = 1U << 31; | ||
131 | for (i = 0; i < len; i++) { | ||
132 | if (n & mask) | ||
133 | break; | ||
134 | n |= mask; | ||
135 | mask >>= 1; | ||
136 | } | ||
137 | done: | ||
138 | *curr = cpu_to_be32(n); | ||
139 | set_page_dirty(page); | ||
140 | kunmap(page); | ||
141 | *max = offset + (curr - pptr) * 32 + i - start; | ||
142 | HFSPLUS_SB(sb).free_blocks -= *max; | ||
143 | sb->s_dirt = 1; | ||
144 | dprint(DBG_BITMAP, "-> %u,%u\n", start, *max); | ||
145 | out: | ||
146 | up(&HFSPLUS_SB(sb).alloc_file->i_sem); | ||
147 | return start; | ||
148 | } | ||
149 | |||
150 | int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count) | ||
151 | { | ||
152 | struct page *page; | ||
153 | struct address_space *mapping; | ||
154 | __be32 *pptr, *curr, *end; | ||
155 | u32 mask, len, pnr; | ||
156 | int i; | ||
157 | |||
158 | /* is there any actual work to be done? */ | ||
159 | if (!count) | ||
160 | return 0; | ||
161 | |||
162 | dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count); | ||
163 | /* are all of the bits in range? */ | ||
164 | if ((offset + count) > HFSPLUS_SB(sb).total_blocks) | ||
165 | return -2; | ||
166 | |||
167 | down(&HFSPLUS_SB(sb).alloc_file->i_sem); | ||
168 | mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; | ||
169 | pnr = offset / PAGE_CACHE_BITS; | ||
170 | page = read_cache_page(mapping, pnr, (filler_t *)mapping->a_ops->readpage, NULL); | ||
171 | pptr = kmap(page); | ||
172 | curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32; | ||
173 | end = pptr + PAGE_CACHE_BITS / 32; | ||
174 | len = count; | ||
175 | |||
176 | /* do any partial u32 at the start */ | ||
177 | i = offset % 32; | ||
178 | if (i) { | ||
179 | int j = 32 - i; | ||
180 | mask = 0xffffffffU << j; | ||
181 | if (j > count) { | ||
182 | mask |= 0xffffffffU >> (i + count); | ||
183 | *curr++ &= cpu_to_be32(mask); | ||
184 | goto out; | ||
185 | } | ||
186 | *curr++ &= cpu_to_be32(mask); | ||
187 | count -= j; | ||
188 | } | ||
189 | |||
190 | /* do full u32s */ | ||
191 | while (1) { | ||
192 | while (curr < end) { | ||
193 | if (count < 32) | ||
194 | goto done; | ||
195 | *curr++ = 0; | ||
196 | count -= 32; | ||
197 | } | ||
198 | if (!count) | ||
199 | break; | ||
200 | set_page_dirty(page); | ||
201 | kunmap(page); | ||
202 | page = read_cache_page(mapping, ++pnr, (filler_t *)mapping->a_ops->readpage, NULL); | ||
203 | pptr = kmap(page); | ||
204 | curr = pptr; | ||
205 | end = pptr + PAGE_CACHE_BITS / 32; | ||
206 | } | ||
207 | done: | ||
208 | /* do any partial u32 at end */ | ||
209 | if (count) { | ||
210 | mask = 0xffffffffU >> count; | ||
211 | *curr &= cpu_to_be32(mask); | ||
212 | } | ||
213 | out: | ||
214 | set_page_dirty(page); | ||
215 | kunmap(page); | ||
216 | HFSPLUS_SB(sb).free_blocks += len; | ||
217 | sb->s_dirt = 1; | ||
218 | up(&HFSPLUS_SB(sb).alloc_file->i_sem); | ||
219 | |||
220 | return 0; | ||
221 | } | ||
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c new file mode 100644 index 000000000000..267872e84d71 --- /dev/null +++ b/fs/hfsplus/bnode.c | |||
@@ -0,0 +1,662 @@ | |||
1 | /* | ||
2 | * linux/fs/hfsplus/bnode.c | ||
3 | * | ||
4 | * Copyright (C) 2001 | ||
5 | * Brad Boyer (flar@allandria.com) | ||
6 | * (C) 2003 Ardis Technologies <roman@ardistech.com> | ||
7 | * | ||
8 | * Handle basic btree node operations | ||
9 | */ | ||
10 | |||
11 | #include <linux/string.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/pagemap.h> | ||
14 | #include <linux/fs.h> | ||
15 | #include <linux/swap.h> | ||
16 | #include <linux/version.h> | ||
17 | |||
18 | #include "hfsplus_fs.h" | ||
19 | #include "hfsplus_raw.h" | ||
20 | |||
21 | #define REF_PAGES 0 | ||
22 | |||
23 | /* Copy a specified range of bytes from the raw data of a node */ | ||
24 | void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len) | ||
25 | { | ||
26 | struct page **pagep; | ||
27 | int l; | ||
28 | |||
29 | off += node->page_offset; | ||
30 | pagep = node->page + (off >> PAGE_CACHE_SHIFT); | ||
31 | off &= ~PAGE_CACHE_MASK; | ||
32 | |||
33 | l = min(len, (int)PAGE_CACHE_SIZE - off); | ||
34 | memcpy(buf, kmap(*pagep) + off, l); | ||
35 | kunmap(*pagep); | ||
36 | |||
37 | while ((len -= l) != 0) { | ||
38 | buf += l; | ||
39 | l = min(len, (int)PAGE_CACHE_SIZE); | ||
40 | memcpy(buf, kmap(*++pagep), l); | ||
41 | kunmap(*pagep); | ||
42 | } | ||
43 | } | ||
44 | |||
45 | u16 hfs_bnode_read_u16(struct hfs_bnode *node, int off) | ||
46 | { | ||
47 | __be16 data; | ||
48 | // optimize later... | ||
49 | hfs_bnode_read(node, &data, off, 2); | ||
50 | return be16_to_cpu(data); | ||
51 | } | ||
52 | |||
53 | u8 hfs_bnode_read_u8(struct hfs_bnode *node, int off) | ||
54 | { | ||
55 | u8 data; | ||
56 | // optimize later... | ||
57 | hfs_bnode_read(node, &data, off, 1); | ||
58 | return data; | ||
59 | } | ||
60 | |||
61 | void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off) | ||
62 | { | ||
63 | struct hfs_btree *tree; | ||
64 | int key_len; | ||
65 | |||
66 | tree = node->tree; | ||
67 | if (node->type == HFS_NODE_LEAF || | ||
68 | tree->attributes & HFS_TREE_VARIDXKEYS) | ||
69 | key_len = hfs_bnode_read_u16(node, off) + 2; | ||
70 | else | ||
71 | key_len = tree->max_key_len + 2; | ||
72 | |||
73 | hfs_bnode_read(node, key, off, key_len); | ||
74 | } | ||
75 | |||
76 | void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len) | ||
77 | { | ||
78 | struct page **pagep; | ||
79 | int l; | ||
80 | |||
81 | off += node->page_offset; | ||
82 | pagep = node->page + (off >> PAGE_CACHE_SHIFT); | ||
83 | off &= ~PAGE_CACHE_MASK; | ||
84 | |||
85 | l = min(len, (int)PAGE_CACHE_SIZE - off); | ||
86 | memcpy(kmap(*pagep) + off, buf, l); | ||
87 | set_page_dirty(*pagep); | ||
88 | kunmap(*pagep); | ||
89 | |||
90 | while ((len -= l) != 0) { | ||
91 | buf += l; | ||
92 | l = min(len, (int)PAGE_CACHE_SIZE); | ||
93 | memcpy(kmap(*++pagep), buf, l); | ||
94 | set_page_dirty(*pagep); | ||
95 | kunmap(*pagep); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | void hfs_bnode_write_u16(struct hfs_bnode *node, int off, u16 data) | ||
100 | { | ||
101 | __be16 v = cpu_to_be16(data); | ||
102 | // optimize later... | ||
103 | hfs_bnode_write(node, &v, off, 2); | ||
104 | } | ||
105 | |||
106 | void hfs_bnode_clear(struct hfs_bnode *node, int off, int len) | ||
107 | { | ||
108 | struct page **pagep; | ||
109 | int l; | ||
110 | |||
111 | off += node->page_offset; | ||
112 | pagep = node->page + (off >> PAGE_CACHE_SHIFT); | ||
113 | off &= ~PAGE_CACHE_MASK; | ||
114 | |||
115 | l = min(len, (int)PAGE_CACHE_SIZE - off); | ||
116 | memset(kmap(*pagep) + off, 0, l); | ||
117 | set_page_dirty(*pagep); | ||
118 | kunmap(*pagep); | ||
119 | |||
120 | while ((len -= l) != 0) { | ||
121 | l = min(len, (int)PAGE_CACHE_SIZE); | ||
122 | memset(kmap(*++pagep), 0, l); | ||
123 | set_page_dirty(*pagep); | ||
124 | kunmap(*pagep); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | void hfs_bnode_copy(struct hfs_bnode *dst_node, int dst, | ||
129 | struct hfs_bnode *src_node, int src, int len) | ||
130 | { | ||
131 | struct hfs_btree *tree; | ||
132 | struct page **src_page, **dst_page; | ||
133 | int l; | ||
134 | |||
135 | dprint(DBG_BNODE_MOD, "copybytes: %u,%u,%u\n", dst, src, len); | ||
136 | if (!len) | ||
137 | return; | ||
138 | tree = src_node->tree; | ||
139 | src += src_node->page_offset; | ||
140 | dst += dst_node->page_offset; | ||
141 | src_page = src_node->page + (src >> PAGE_CACHE_SHIFT); | ||
142 | src &= ~PAGE_CACHE_MASK; | ||
143 | dst_page = dst_node->page + (dst >> PAGE_CACHE_SHIFT); | ||
144 | dst &= ~PAGE_CACHE_MASK; | ||
145 | |||
146 | if (src == dst) { | ||
147 | l = min(len, (int)PAGE_CACHE_SIZE - src); | ||
148 | memcpy(kmap(*dst_page) + src, kmap(*src_page) + src, l); | ||
149 | kunmap(*src_page); | ||
150 | set_page_dirty(*dst_page); | ||
151 | kunmap(*dst_page); | ||
152 | |||
153 | while ((len -= l) != 0) { | ||
154 | l = min(len, (int)PAGE_CACHE_SIZE); | ||
155 | memcpy(kmap(*++dst_page), kmap(*++src_page), l); | ||
156 | kunmap(*src_page); | ||
157 | set_page_dirty(*dst_page); | ||
158 | kunmap(*dst_page); | ||
159 | } | ||
160 | } else { | ||
161 | void *src_ptr, *dst_ptr; | ||
162 | |||
163 | do { | ||
164 | src_ptr = kmap(*src_page) + src; | ||
165 | dst_ptr = kmap(*dst_page) + dst; | ||
166 | if (PAGE_CACHE_SIZE - src < PAGE_CACHE_SIZE - dst) { | ||
167 | l = PAGE_CACHE_SIZE - src; | ||
168 | src = 0; | ||
169 | dst += l; | ||
170 | } else { | ||
171 | l = PAGE_CACHE_SIZE - dst; | ||
172 | src += l; | ||
173 | dst = 0; | ||
174 | } | ||
175 | l = min(len, l); | ||
176 | memcpy(dst_ptr, src_ptr, l); | ||
177 | kunmap(*src_page); | ||
178 | set_page_dirty(*dst_page); | ||
179 | kunmap(*dst_page); | ||
180 | if (!dst) | ||
181 | dst_page++; | ||
182 | else | ||
183 | src_page++; | ||
184 | } while ((len -= l)); | ||
185 | } | ||
186 | } | ||
187 | |||
188 | void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len) | ||
189 | { | ||
190 | struct page **src_page, **dst_page; | ||
191 | int l; | ||
192 | |||
193 | dprint(DBG_BNODE_MOD, "movebytes: %u,%u,%u\n", dst, src, len); | ||
194 | if (!len) | ||
195 | return; | ||
196 | src += node->page_offset; | ||
197 | dst += node->page_offset; | ||
198 | if (dst > src) { | ||
199 | src += len - 1; | ||
200 | src_page = node->page + (src >> PAGE_CACHE_SHIFT); | ||
201 | src = (src & ~PAGE_CACHE_MASK) + 1; | ||
202 | dst += len - 1; | ||
203 | dst_page = node->page + (dst >> PAGE_CACHE_SHIFT); | ||
204 | dst = (dst & ~PAGE_CACHE_MASK) + 1; | ||
205 | |||
206 | if (src == dst) { | ||
207 | while (src < len) { | ||
208 | memmove(kmap(*dst_page), kmap(*src_page), src); | ||
209 | kunmap(*src_page); | ||
210 | set_page_dirty(*dst_page); | ||
211 | kunmap(*dst_page); | ||
212 | len -= src; | ||
213 | src = PAGE_CACHE_SIZE; | ||
214 | src_page--; | ||
215 | dst_page--; | ||
216 | } | ||
217 | src -= len; | ||
218 | memmove(kmap(*dst_page) + src, kmap(*src_page) + src, len); | ||
219 | kunmap(*src_page); | ||
220 | set_page_dirty(*dst_page); | ||
221 | kunmap(*dst_page); | ||
222 | } else { | ||
223 | void *src_ptr, *dst_ptr; | ||
224 | |||
225 | do { | ||
226 | src_ptr = kmap(*src_page) + src; | ||
227 | dst_ptr = kmap(*dst_page) + dst; | ||
228 | if (src < dst) { | ||
229 | l = src; | ||
230 | src = PAGE_CACHE_SIZE; | ||
231 | dst -= l; | ||
232 | } else { | ||
233 | l = dst; | ||
234 | src -= l; | ||
235 | dst = PAGE_CACHE_SIZE; | ||
236 | } | ||
237 | l = min(len, l); | ||
238 | memmove(dst_ptr - l, src_ptr - l, l); | ||
239 | kunmap(*src_page); | ||
240 | set_page_dirty(*dst_page); | ||
241 | kunmap(*dst_page); | ||
242 | if (dst == PAGE_CACHE_SIZE) | ||
243 | dst_page--; | ||
244 | else | ||
245 | src_page--; | ||
246 | } while ((len -= l)); | ||
247 | } | ||
248 | } else { | ||
249 | src_page = node->page + (src >> PAGE_CACHE_SHIFT); | ||
250 | src &= ~PAGE_CACHE_MASK; | ||
251 | dst_page = node->page + (dst >> PAGE_CACHE_SHIFT); | ||
252 | dst &= ~PAGE_CACHE_MASK; | ||
253 | |||
254 | if (src == dst) { | ||
255 | l = min(len, (int)PAGE_CACHE_SIZE - src); | ||
256 | memmove(kmap(*dst_page) + src, kmap(*src_page) + src, l); | ||
257 | kunmap(*src_page); | ||
258 | set_page_dirty(*dst_page); | ||
259 | kunmap(*dst_page); | ||
260 | |||
261 | while ((len -= l) != 0) { | ||
262 | l = min(len, (int)PAGE_CACHE_SIZE); | ||
263 | memmove(kmap(*++dst_page), kmap(*++src_page), l); | ||
264 | kunmap(*src_page); | ||
265 | set_page_dirty(*dst_page); | ||
266 | kunmap(*dst_page); | ||
267 | } | ||
268 | } else { | ||
269 | void *src_ptr, *dst_ptr; | ||
270 | |||
271 | do { | ||
272 | src_ptr = kmap(*src_page) + src; | ||
273 | dst_ptr = kmap(*dst_page) + dst; | ||
274 | if (PAGE_CACHE_SIZE - src < PAGE_CACHE_SIZE - dst) { | ||
275 | l = PAGE_CACHE_SIZE - src; | ||
276 | src = 0; | ||
277 | dst += l; | ||
278 | } else { | ||
279 | l = PAGE_CACHE_SIZE - dst; | ||
280 | src += l; | ||
281 | dst = 0; | ||
282 | } | ||
283 | l = min(len, l); | ||
284 | memmove(dst_ptr, src_ptr, l); | ||
285 | kunmap(*src_page); | ||
286 | set_page_dirty(*dst_page); | ||
287 | kunmap(*dst_page); | ||
288 | if (!dst) | ||
289 | dst_page++; | ||
290 | else | ||
291 | src_page++; | ||
292 | } while ((len -= l)); | ||
293 | } | ||
294 | } | ||
295 | } | ||
296 | |||
297 | void hfs_bnode_dump(struct hfs_bnode *node) | ||
298 | { | ||
299 | struct hfs_bnode_desc desc; | ||
300 | __be32 cnid; | ||
301 | int i, off, key_off; | ||
302 | |||
303 | dprint(DBG_BNODE_MOD, "bnode: %d\n", node->this); | ||
304 | hfs_bnode_read(node, &desc, 0, sizeof(desc)); | ||
305 | dprint(DBG_BNODE_MOD, "%d, %d, %d, %d, %d\n", | ||
306 | be32_to_cpu(desc.next), be32_to_cpu(desc.prev), | ||
307 | desc.type, desc.height, be16_to_cpu(desc.num_recs)); | ||
308 | |||
309 | off = node->tree->node_size - 2; | ||
310 | for (i = be16_to_cpu(desc.num_recs); i >= 0; off -= 2, i--) { | ||
311 | key_off = hfs_bnode_read_u16(node, off); | ||
312 | dprint(DBG_BNODE_MOD, " %d", key_off); | ||
313 | if (i && node->type == HFS_NODE_INDEX) { | ||
314 | int tmp; | ||
315 | |||
316 | if (node->tree->attributes & HFS_TREE_VARIDXKEYS) | ||
317 | tmp = hfs_bnode_read_u16(node, key_off) + 2; | ||
318 | else | ||
319 | tmp = node->tree->max_key_len + 2; | ||
320 | dprint(DBG_BNODE_MOD, " (%d", tmp); | ||
321 | hfs_bnode_read(node, &cnid, key_off + tmp, 4); | ||
322 | dprint(DBG_BNODE_MOD, ",%d)", be32_to_cpu(cnid)); | ||
323 | } else if (i && node->type == HFS_NODE_LEAF) { | ||
324 | int tmp; | ||
325 | |||
326 | tmp = hfs_bnode_read_u16(node, key_off); | ||
327 | dprint(DBG_BNODE_MOD, " (%d)", tmp); | ||
328 | } | ||
329 | } | ||
330 | dprint(DBG_BNODE_MOD, "\n"); | ||
331 | } | ||
332 | |||
333 | void hfs_bnode_unlink(struct hfs_bnode *node) | ||
334 | { | ||
335 | struct hfs_btree *tree; | ||
336 | struct hfs_bnode *tmp; | ||
337 | __be32 cnid; | ||
338 | |||
339 | tree = node->tree; | ||
340 | if (node->prev) { | ||
341 | tmp = hfs_bnode_find(tree, node->prev); | ||
342 | if (IS_ERR(tmp)) | ||
343 | return; | ||
344 | tmp->next = node->next; | ||
345 | cnid = cpu_to_be32(tmp->next); | ||
346 | hfs_bnode_write(tmp, &cnid, offsetof(struct hfs_bnode_desc, next), 4); | ||
347 | hfs_bnode_put(tmp); | ||
348 | } else if (node->type == HFS_NODE_LEAF) | ||
349 | tree->leaf_head = node->next; | ||
350 | |||
351 | if (node->next) { | ||
352 | tmp = hfs_bnode_find(tree, node->next); | ||
353 | if (IS_ERR(tmp)) | ||
354 | return; | ||
355 | tmp->prev = node->prev; | ||
356 | cnid = cpu_to_be32(tmp->prev); | ||
357 | hfs_bnode_write(tmp, &cnid, offsetof(struct hfs_bnode_desc, prev), 4); | ||
358 | hfs_bnode_put(tmp); | ||
359 | } else if (node->type == HFS_NODE_LEAF) | ||
360 | tree->leaf_tail = node->prev; | ||
361 | |||
362 | // move down? | ||
363 | if (!node->prev && !node->next) { | ||
364 | printk("hfs_btree_del_level\n"); | ||
365 | } | ||
366 | if (!node->parent) { | ||
367 | tree->root = 0; | ||
368 | tree->depth = 0; | ||
369 | } | ||
370 | set_bit(HFS_BNODE_DELETED, &node->flags); | ||
371 | } | ||
372 | |||
373 | static inline int hfs_bnode_hash(u32 num) | ||
374 | { | ||
375 | num = (num >> 16) + num; | ||
376 | num += num >> 8; | ||
377 | return num & (NODE_HASH_SIZE - 1); | ||
378 | } | ||
379 | |||
380 | struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *tree, u32 cnid) | ||
381 | { | ||
382 | struct hfs_bnode *node; | ||
383 | |||
384 | if (cnid >= tree->node_count) { | ||
385 | printk("HFS+-fs: request for non-existent node %d in B*Tree\n", cnid); | ||
386 | return NULL; | ||
387 | } | ||
388 | |||
389 | for (node = tree->node_hash[hfs_bnode_hash(cnid)]; | ||
390 | node; node = node->next_hash) { | ||
391 | if (node->this == cnid) { | ||
392 | return node; | ||
393 | } | ||
394 | } | ||
395 | return NULL; | ||
396 | } | ||
397 | |||
398 | static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid) | ||
399 | { | ||
400 | struct super_block *sb; | ||
401 | struct hfs_bnode *node, *node2; | ||
402 | struct address_space *mapping; | ||
403 | struct page *page; | ||
404 | int size, block, i, hash; | ||
405 | loff_t off; | ||
406 | |||
407 | if (cnid >= tree->node_count) { | ||
408 | printk("HFS+-fs: request for non-existent node %d in B*Tree\n", cnid); | ||
409 | return NULL; | ||
410 | } | ||
411 | |||
412 | sb = tree->inode->i_sb; | ||
413 | size = sizeof(struct hfs_bnode) + tree->pages_per_bnode * | ||
414 | sizeof(struct page *); | ||
415 | node = kmalloc(size, GFP_KERNEL); | ||
416 | if (!node) | ||
417 | return NULL; | ||
418 | memset(node, 0, size); | ||
419 | node->tree = tree; | ||
420 | node->this = cnid; | ||
421 | set_bit(HFS_BNODE_NEW, &node->flags); | ||
422 | atomic_set(&node->refcnt, 1); | ||
423 | dprint(DBG_BNODE_REFS, "new_node(%d:%d): 1\n", | ||
424 | node->tree->cnid, node->this); | ||
425 | init_waitqueue_head(&node->lock_wq); | ||
426 | spin_lock(&tree->hash_lock); | ||
427 | node2 = hfs_bnode_findhash(tree, cnid); | ||
428 | if (!node2) { | ||
429 | hash = hfs_bnode_hash(cnid); | ||
430 | node->next_hash = tree->node_hash[hash]; | ||
431 | tree->node_hash[hash] = node; | ||
432 | tree->node_hash_cnt++; | ||
433 | } else { | ||
434 | spin_unlock(&tree->hash_lock); | ||
435 | kfree(node); | ||
436 | wait_event(node2->lock_wq, !test_bit(HFS_BNODE_NEW, &node2->flags)); | ||
437 | return node2; | ||
438 | } | ||
439 | spin_unlock(&tree->hash_lock); | ||
440 | |||
441 | mapping = tree->inode->i_mapping; | ||
442 | off = (loff_t)cnid << tree->node_size_shift; | ||
443 | block = off >> PAGE_CACHE_SHIFT; | ||
444 | node->page_offset = off & ~PAGE_CACHE_MASK; | ||
445 | for (i = 0; i < tree->pages_per_bnode; block++, i++) { | ||
446 | page = read_cache_page(mapping, block, (filler_t *)mapping->a_ops->readpage, NULL); | ||
447 | if (IS_ERR(page)) | ||
448 | goto fail; | ||
449 | if (PageError(page)) { | ||
450 | page_cache_release(page); | ||
451 | goto fail; | ||
452 | } | ||
453 | #if !REF_PAGES | ||
454 | page_cache_release(page); | ||
455 | #endif | ||
456 | node->page[i] = page; | ||
457 | } | ||
458 | |||
459 | return node; | ||
460 | fail: | ||
461 | set_bit(HFS_BNODE_ERROR, &node->flags); | ||
462 | return node; | ||
463 | } | ||
464 | |||
465 | void hfs_bnode_unhash(struct hfs_bnode *node) | ||
466 | { | ||
467 | struct hfs_bnode **p; | ||
468 | |||
469 | dprint(DBG_BNODE_REFS, "remove_node(%d:%d): %d\n", | ||
470 | node->tree->cnid, node->this, atomic_read(&node->refcnt)); | ||
471 | for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)]; | ||
472 | *p && *p != node; p = &(*p)->next_hash) | ||
473 | ; | ||
474 | if (!*p) | ||
475 | BUG(); | ||
476 | *p = node->next_hash; | ||
477 | node->tree->node_hash_cnt--; | ||
478 | } | ||
479 | |||
480 | /* Load a particular node out of a tree */ | ||
481 | struct hfs_bnode *hfs_bnode_find(struct hfs_btree *tree, u32 num) | ||
482 | { | ||
483 | struct hfs_bnode *node; | ||
484 | struct hfs_bnode_desc *desc; | ||
485 | int i, rec_off, off, next_off; | ||
486 | int entry_size, key_size; | ||
487 | |||
488 | spin_lock(&tree->hash_lock); | ||
489 | node = hfs_bnode_findhash(tree, num); | ||
490 | if (node) { | ||
491 | hfs_bnode_get(node); | ||
492 | spin_unlock(&tree->hash_lock); | ||
493 | wait_event(node->lock_wq, !test_bit(HFS_BNODE_NEW, &node->flags)); | ||
494 | if (test_bit(HFS_BNODE_ERROR, &node->flags)) | ||
495 | goto node_error; | ||
496 | return node; | ||
497 | } | ||
498 | spin_unlock(&tree->hash_lock); | ||
499 | node = __hfs_bnode_create(tree, num); | ||
500 | if (!node) | ||
501 | return ERR_PTR(-ENOMEM); | ||
502 | if (test_bit(HFS_BNODE_ERROR, &node->flags)) | ||
503 | goto node_error; | ||
504 | if (!test_bit(HFS_BNODE_NEW, &node->flags)) | ||
505 | return node; | ||
506 | |||
507 | desc = (struct hfs_bnode_desc *)(kmap(node->page[0]) + node->page_offset); | ||
508 | node->prev = be32_to_cpu(desc->prev); | ||
509 | node->next = be32_to_cpu(desc->next); | ||
510 | node->num_recs = be16_to_cpu(desc->num_recs); | ||
511 | node->type = desc->type; | ||
512 | node->height = desc->height; | ||
513 | kunmap(node->page[0]); | ||
514 | |||
515 | switch (node->type) { | ||
516 | case HFS_NODE_HEADER: | ||
517 | case HFS_NODE_MAP: | ||
518 | if (node->height != 0) | ||
519 | goto node_error; | ||
520 | break; | ||
521 | case HFS_NODE_LEAF: | ||
522 | if (node->height != 1) | ||
523 | goto node_error; | ||
524 | break; | ||
525 | case HFS_NODE_INDEX: | ||
526 | if (node->height <= 1 || node->height > tree->depth) | ||
527 | goto node_error; | ||
528 | break; | ||
529 | default: | ||
530 | goto node_error; | ||
531 | } | ||
532 | |||
533 | rec_off = tree->node_size - 2; | ||
534 | off = hfs_bnode_read_u16(node, rec_off); | ||
535 | if (off != sizeof(struct hfs_bnode_desc)) | ||
536 | goto node_error; | ||
537 | for (i = 1; i <= node->num_recs; off = next_off, i++) { | ||
538 | rec_off -= 2; | ||
539 | next_off = hfs_bnode_read_u16(node, rec_off); | ||
540 | if (next_off <= off || | ||
541 | next_off > tree->node_size || | ||
542 | next_off & 1) | ||
543 | goto node_error; | ||
544 | entry_size = next_off - off; | ||
545 | if (node->type != HFS_NODE_INDEX && | ||
546 | node->type != HFS_NODE_LEAF) | ||
547 | continue; | ||
548 | key_size = hfs_bnode_read_u16(node, off) + 2; | ||
549 | if (key_size >= entry_size || key_size & 1) | ||
550 | goto node_error; | ||
551 | } | ||
552 | clear_bit(HFS_BNODE_NEW, &node->flags); | ||
553 | wake_up(&node->lock_wq); | ||
554 | return node; | ||
555 | |||
556 | node_error: | ||
557 | set_bit(HFS_BNODE_ERROR, &node->flags); | ||
558 | clear_bit(HFS_BNODE_NEW, &node->flags); | ||
559 | wake_up(&node->lock_wq); | ||
560 | hfs_bnode_put(node); | ||
561 | return ERR_PTR(-EIO); | ||
562 | } | ||
563 | |||
564 | void hfs_bnode_free(struct hfs_bnode *node) | ||
565 | { | ||
566 | //int i; | ||
567 | |||
568 | //for (i = 0; i < node->tree->pages_per_bnode; i++) | ||
569 | // if (node->page[i]) | ||
570 | // page_cache_release(node->page[i]); | ||
571 | kfree(node); | ||
572 | } | ||
573 | |||
574 | struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num) | ||
575 | { | ||
576 | struct hfs_bnode *node; | ||
577 | struct page **pagep; | ||
578 | int i; | ||
579 | |||
580 | spin_lock(&tree->hash_lock); | ||
581 | node = hfs_bnode_findhash(tree, num); | ||
582 | spin_unlock(&tree->hash_lock); | ||
583 | if (node) { | ||
584 | printk("new node %u already hashed?\n", num); | ||
585 | BUG(); | ||
586 | } | ||
587 | node = __hfs_bnode_create(tree, num); | ||
588 | if (!node) | ||
589 | return ERR_PTR(-ENOMEM); | ||
590 | if (test_bit(HFS_BNODE_ERROR, &node->flags)) { | ||
591 | hfs_bnode_put(node); | ||
592 | return ERR_PTR(-EIO); | ||
593 | } | ||
594 | |||
595 | pagep = node->page; | ||
596 | memset(kmap(*pagep) + node->page_offset, 0, | ||
597 | min((int)PAGE_CACHE_SIZE, (int)tree->node_size)); | ||
598 | set_page_dirty(*pagep); | ||
599 | kunmap(*pagep); | ||
600 | for (i = 1; i < tree->pages_per_bnode; i++) { | ||
601 | memset(kmap(*++pagep), 0, PAGE_CACHE_SIZE); | ||
602 | set_page_dirty(*pagep); | ||
603 | kunmap(*pagep); | ||
604 | } | ||
605 | clear_bit(HFS_BNODE_NEW, &node->flags); | ||
606 | wake_up(&node->lock_wq); | ||
607 | |||
608 | return node; | ||
609 | } | ||
610 | |||
611 | void hfs_bnode_get(struct hfs_bnode *node) | ||
612 | { | ||
613 | if (node) { | ||
614 | atomic_inc(&node->refcnt); | ||
615 | #if REF_PAGES | ||
616 | { | ||
617 | int i; | ||
618 | for (i = 0; i < node->tree->pages_per_bnode; i++) | ||
619 | get_page(node->page[i]); | ||
620 | } | ||
621 | #endif | ||
622 | dprint(DBG_BNODE_REFS, "get_node(%d:%d): %d\n", | ||
623 | node->tree->cnid, node->this, atomic_read(&node->refcnt)); | ||
624 | } | ||
625 | } | ||
626 | |||
627 | /* Dispose of resources used by a node */ | ||
628 | void hfs_bnode_put(struct hfs_bnode *node) | ||
629 | { | ||
630 | if (node) { | ||
631 | struct hfs_btree *tree = node->tree; | ||
632 | int i; | ||
633 | |||
634 | dprint(DBG_BNODE_REFS, "put_node(%d:%d): %d\n", | ||
635 | node->tree->cnid, node->this, atomic_read(&node->refcnt)); | ||
636 | if (!atomic_read(&node->refcnt)) | ||
637 | BUG(); | ||
638 | if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock)) { | ||
639 | #if REF_PAGES | ||
640 | for (i = 0; i < tree->pages_per_bnode; i++) | ||
641 | put_page(node->page[i]); | ||
642 | #endif | ||
643 | return; | ||
644 | } | ||
645 | for (i = 0; i < tree->pages_per_bnode; i++) { | ||
646 | mark_page_accessed(node->page[i]); | ||
647 | #if REF_PAGES | ||
648 | put_page(node->page[i]); | ||
649 | #endif | ||
650 | } | ||
651 | |||
652 | if (test_bit(HFS_BNODE_DELETED, &node->flags)) { | ||
653 | hfs_bnode_unhash(node); | ||
654 | spin_unlock(&tree->hash_lock); | ||
655 | hfs_bmap_free(node); | ||
656 | hfs_bnode_free(node); | ||
657 | return; | ||
658 | } | ||
659 | spin_unlock(&tree->hash_lock); | ||
660 | } | ||
661 | } | ||
662 | |||
diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c new file mode 100644 index 000000000000..0ccef2ab790c --- /dev/null +++ b/fs/hfsplus/brec.c | |||
@@ -0,0 +1,491 @@ | |||
1 | /* | ||
2 | * linux/fs/hfsplus/brec.c | ||
3 | * | ||
4 | * Copyright (C) 2001 | ||
5 | * Brad Boyer (flar@allandria.com) | ||
6 | * (C) 2003 Ardis Technologies <roman@ardistech.com> | ||
7 | * | ||
8 | * Handle individual btree records | ||
9 | */ | ||
10 | |||
11 | #include "hfsplus_fs.h" | ||
12 | #include "hfsplus_raw.h" | ||
13 | |||
14 | static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd); | ||
15 | static int hfs_brec_update_parent(struct hfs_find_data *fd); | ||
16 | static int hfs_btree_inc_height(struct hfs_btree *); | ||
17 | |||
18 | /* Get the length and offset of the given record in the given node */ | ||
19 | u16 hfs_brec_lenoff(struct hfs_bnode *node, u16 rec, u16 *off) | ||
20 | { | ||
21 | __be16 retval[2]; | ||
22 | u16 dataoff; | ||
23 | |||
24 | dataoff = node->tree->node_size - (rec + 2) * 2; | ||
25 | hfs_bnode_read(node, retval, dataoff, 4); | ||
26 | *off = be16_to_cpu(retval[1]); | ||
27 | return be16_to_cpu(retval[0]) - *off; | ||
28 | } | ||
29 | |||
30 | /* Get the length of the key from a keyed record */ | ||
31 | u16 hfs_brec_keylen(struct hfs_bnode *node, u16 rec) | ||
32 | { | ||
33 | u16 retval, recoff; | ||
34 | |||
35 | if (node->type != HFS_NODE_INDEX && node->type != HFS_NODE_LEAF) | ||
36 | return 0; | ||
37 | |||
38 | if ((node->type == HFS_NODE_INDEX) && | ||
39 | !(node->tree->attributes & HFS_TREE_VARIDXKEYS)) { | ||
40 | retval = node->tree->max_key_len + 2; | ||
41 | } else { | ||
42 | recoff = hfs_bnode_read_u16(node, node->tree->node_size - (rec + 1) * 2); | ||
43 | if (!recoff) | ||
44 | return 0; | ||
45 | if (node->tree->attributes & HFS_TREE_BIGKEYS) | ||
46 | retval = hfs_bnode_read_u16(node, recoff) + 2; | ||
47 | else | ||
48 | retval = (hfs_bnode_read_u8(node, recoff) | 1) + 1; | ||
49 | } | ||
50 | return retval; | ||
51 | } | ||
52 | |||
53 | int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len) | ||
54 | { | ||
55 | struct hfs_btree *tree; | ||
56 | struct hfs_bnode *node, *new_node; | ||
57 | int size, key_len, rec; | ||
58 | int data_off, end_off; | ||
59 | int idx_rec_off, data_rec_off, end_rec_off; | ||
60 | __be32 cnid; | ||
61 | |||
62 | tree = fd->tree; | ||
63 | if (!fd->bnode) { | ||
64 | if (!tree->root) | ||
65 | hfs_btree_inc_height(tree); | ||
66 | fd->bnode = hfs_bnode_find(tree, tree->leaf_head); | ||
67 | if (IS_ERR(fd->bnode)) | ||
68 | return PTR_ERR(fd->bnode); | ||
69 | fd->record = -1; | ||
70 | } | ||
71 | new_node = NULL; | ||
72 | key_len = be16_to_cpu(fd->search_key->key_len) + 2; | ||
73 | again: | ||
74 | /* new record idx and complete record size */ | ||
75 | rec = fd->record + 1; | ||
76 | size = key_len + entry_len; | ||
77 | |||
78 | node = fd->bnode; | ||
79 | hfs_bnode_dump(node); | ||
80 | /* get last offset */ | ||
81 | end_rec_off = tree->node_size - (node->num_recs + 1) * 2; | ||
82 | end_off = hfs_bnode_read_u16(node, end_rec_off); | ||
83 | end_rec_off -= 2; | ||
84 | dprint(DBG_BNODE_MOD, "insert_rec: %d, %d, %d, %d\n", rec, size, end_off, end_rec_off); | ||
85 | if (size > end_rec_off - end_off) { | ||
86 | if (new_node) | ||
87 | panic("not enough room!\n"); | ||
88 | new_node = hfs_bnode_split(fd); | ||
89 | if (IS_ERR(new_node)) | ||
90 | return PTR_ERR(new_node); | ||
91 | goto again; | ||
92 | } | ||
93 | if (node->type == HFS_NODE_LEAF) { | ||
94 | tree->leaf_count++; | ||
95 | mark_inode_dirty(tree->inode); | ||
96 | } | ||
97 | node->num_recs++; | ||
98 | /* write new last offset */ | ||
99 | hfs_bnode_write_u16(node, offsetof(struct hfs_bnode_desc, num_recs), node->num_recs); | ||
100 | hfs_bnode_write_u16(node, end_rec_off, end_off + size); | ||
101 | data_off = end_off; | ||
102 | data_rec_off = end_rec_off + 2; | ||
103 | idx_rec_off = tree->node_size - (rec + 1) * 2; | ||
104 | if (idx_rec_off == data_rec_off) | ||
105 | goto skip; | ||
106 | /* move all following entries */ | ||
107 | do { | ||
108 | data_off = hfs_bnode_read_u16(node, data_rec_off + 2); | ||
109 | hfs_bnode_write_u16(node, data_rec_off, data_off + size); | ||
110 | data_rec_off += 2; | ||
111 | } while (data_rec_off < idx_rec_off); | ||
112 | |||
113 | /* move data away */ | ||
114 | hfs_bnode_move(node, data_off + size, data_off, | ||
115 | end_off - data_off); | ||
116 | |||
117 | skip: | ||
118 | hfs_bnode_write(node, fd->search_key, data_off, key_len); | ||
119 | hfs_bnode_write(node, entry, data_off + key_len, entry_len); | ||
120 | hfs_bnode_dump(node); | ||
121 | |||
122 | if (new_node) { | ||
123 | /* update parent key if we inserted a key | ||
124 | * at the start of the first node | ||
125 | */ | ||
126 | if (!rec && new_node != node) | ||
127 | hfs_brec_update_parent(fd); | ||
128 | |||
129 | hfs_bnode_put(fd->bnode); | ||
130 | if (!new_node->parent) { | ||
131 | hfs_btree_inc_height(tree); | ||
132 | new_node->parent = tree->root; | ||
133 | } | ||
134 | fd->bnode = hfs_bnode_find(tree, new_node->parent); | ||
135 | |||
136 | /* create index data entry */ | ||
137 | cnid = cpu_to_be32(new_node->this); | ||
138 | entry = &cnid; | ||
139 | entry_len = sizeof(cnid); | ||
140 | |||
141 | /* get index key */ | ||
142 | hfs_bnode_read_key(new_node, fd->search_key, 14); | ||
143 | __hfs_brec_find(fd->bnode, fd); | ||
144 | |||
145 | hfs_bnode_put(new_node); | ||
146 | new_node = NULL; | ||
147 | |||
148 | if (tree->attributes & HFS_TREE_VARIDXKEYS) | ||
149 | key_len = be16_to_cpu(fd->search_key->key_len) + 2; | ||
150 | else { | ||
151 | fd->search_key->key_len = cpu_to_be16(tree->max_key_len); | ||
152 | key_len = tree->max_key_len + 2; | ||
153 | } | ||
154 | goto again; | ||
155 | } | ||
156 | |||
157 | if (!rec) | ||
158 | hfs_brec_update_parent(fd); | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | int hfs_brec_remove(struct hfs_find_data *fd) | ||
164 | { | ||
165 | struct hfs_btree *tree; | ||
166 | struct hfs_bnode *node, *parent; | ||
167 | int end_off, rec_off, data_off, size; | ||
168 | |||
169 | tree = fd->tree; | ||
170 | node = fd->bnode; | ||
171 | again: | ||
172 | rec_off = tree->node_size - (fd->record + 2) * 2; | ||
173 | end_off = tree->node_size - (node->num_recs + 1) * 2; | ||
174 | |||
175 | if (node->type == HFS_NODE_LEAF) { | ||
176 | tree->leaf_count--; | ||
177 | mark_inode_dirty(tree->inode); | ||
178 | } | ||
179 | hfs_bnode_dump(node); | ||
180 | dprint(DBG_BNODE_MOD, "remove_rec: %d, %d\n", fd->record, fd->keylength + fd->entrylength); | ||
181 | if (!--node->num_recs) { | ||
182 | hfs_bnode_unlink(node); | ||
183 | if (!node->parent) | ||
184 | return 0; | ||
185 | parent = hfs_bnode_find(tree, node->parent); | ||
186 | if (IS_ERR(parent)) | ||
187 | return PTR_ERR(parent); | ||
188 | hfs_bnode_put(node); | ||
189 | node = fd->bnode = parent; | ||
190 | |||
191 | __hfs_brec_find(node, fd); | ||
192 | goto again; | ||
193 | } | ||
194 | hfs_bnode_write_u16(node, offsetof(struct hfs_bnode_desc, num_recs), node->num_recs); | ||
195 | |||
196 | if (rec_off == end_off) | ||
197 | goto skip; | ||
198 | size = fd->keylength + fd->entrylength; | ||
199 | |||
200 | do { | ||
201 | data_off = hfs_bnode_read_u16(node, rec_off); | ||
202 | hfs_bnode_write_u16(node, rec_off + 2, data_off - size); | ||
203 | rec_off -= 2; | ||
204 | } while (rec_off >= end_off); | ||
205 | |||
206 | /* fill hole */ | ||
207 | hfs_bnode_move(node, fd->keyoffset, fd->keyoffset + size, | ||
208 | data_off - fd->keyoffset - size); | ||
209 | skip: | ||
210 | hfs_bnode_dump(node); | ||
211 | if (!fd->record) | ||
212 | hfs_brec_update_parent(fd); | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) | ||
217 | { | ||
218 | struct hfs_btree *tree; | ||
219 | struct hfs_bnode *node, *new_node; | ||
220 | struct hfs_bnode_desc node_desc; | ||
221 | int num_recs, new_rec_off, new_off, old_rec_off; | ||
222 | int data_start, data_end, size; | ||
223 | |||
224 | tree = fd->tree; | ||
225 | node = fd->bnode; | ||
226 | new_node = hfs_bmap_alloc(tree); | ||
227 | if (IS_ERR(new_node)) | ||
228 | return new_node; | ||
229 | hfs_bnode_get(node); | ||
230 | dprint(DBG_BNODE_MOD, "split_nodes: %d - %d - %d\n", | ||
231 | node->this, new_node->this, node->next); | ||
232 | new_node->next = node->next; | ||
233 | new_node->prev = node->this; | ||
234 | new_node->parent = node->parent; | ||
235 | new_node->type = node->type; | ||
236 | new_node->height = node->height; | ||
237 | |||
238 | size = tree->node_size / 2 - node->num_recs * 2 - 14; | ||
239 | old_rec_off = tree->node_size - 4; | ||
240 | num_recs = 1; | ||
241 | for (;;) { | ||
242 | data_start = hfs_bnode_read_u16(node, old_rec_off); | ||
243 | if (data_start > size) | ||
244 | break; | ||
245 | old_rec_off -= 2; | ||
246 | if (++num_recs < node->num_recs) | ||
247 | continue; | ||
248 | /* panic? */ | ||
249 | hfs_bnode_put(node); | ||
250 | hfs_bnode_put(new_node); | ||
251 | return ERR_PTR(-ENOSPC); | ||
252 | } | ||
253 | |||
254 | if (fd->record + 1 < num_recs) { | ||
255 | /* new record is in the lower half, | ||
256 | * so leave some more space there | ||
257 | */ | ||
258 | old_rec_off += 2; | ||
259 | num_recs--; | ||
260 | data_start = hfs_bnode_read_u16(node, old_rec_off); | ||
261 | } else { | ||
262 | hfs_bnode_put(node); | ||
263 | hfs_bnode_get(new_node); | ||
264 | fd->bnode = new_node; | ||
265 | fd->record -= num_recs; | ||
266 | fd->keyoffset -= data_start - 14; | ||
267 | fd->entryoffset -= data_start - 14; | ||
268 | } | ||
269 | new_node->num_recs = node->num_recs - num_recs; | ||
270 | node->num_recs = num_recs; | ||
271 | |||
272 | new_rec_off = tree->node_size - 2; | ||
273 | new_off = 14; | ||
274 | size = data_start - new_off; | ||
275 | num_recs = new_node->num_recs; | ||
276 | data_end = data_start; | ||
277 | while (num_recs) { | ||
278 | hfs_bnode_write_u16(new_node, new_rec_off, new_off); | ||
279 | old_rec_off -= 2; | ||
280 | new_rec_off -= 2; | ||
281 | data_end = hfs_bnode_read_u16(node, old_rec_off); | ||
282 | new_off = data_end - size; | ||
283 | num_recs--; | ||
284 | } | ||
285 | hfs_bnode_write_u16(new_node, new_rec_off, new_off); | ||
286 | hfs_bnode_copy(new_node, 14, node, data_start, data_end - data_start); | ||
287 | |||
288 | /* update new bnode header */ | ||
289 | node_desc.next = cpu_to_be32(new_node->next); | ||
290 | node_desc.prev = cpu_to_be32(new_node->prev); | ||
291 | node_desc.type = new_node->type; | ||
292 | node_desc.height = new_node->height; | ||
293 | node_desc.num_recs = cpu_to_be16(new_node->num_recs); | ||
294 | node_desc.reserved = 0; | ||
295 | hfs_bnode_write(new_node, &node_desc, 0, sizeof(node_desc)); | ||
296 | |||
297 | /* update previous bnode header */ | ||
298 | node->next = new_node->this; | ||
299 | hfs_bnode_read(node, &node_desc, 0, sizeof(node_desc)); | ||
300 | node_desc.next = cpu_to_be32(node->next); | ||
301 | node_desc.num_recs = cpu_to_be16(node->num_recs); | ||
302 | hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc)); | ||
303 | |||
304 | /* update next bnode header */ | ||
305 | if (new_node->next) { | ||
306 | struct hfs_bnode *next_node = hfs_bnode_find(tree, new_node->next); | ||
307 | next_node->prev = new_node->this; | ||
308 | hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc)); | ||
309 | node_desc.prev = cpu_to_be32(next_node->prev); | ||
310 | hfs_bnode_write(next_node, &node_desc, 0, sizeof(node_desc)); | ||
311 | hfs_bnode_put(next_node); | ||
312 | } else if (node->this == tree->leaf_tail) { | ||
313 | /* if there is no next node, this might be the new tail */ | ||
314 | tree->leaf_tail = new_node->this; | ||
315 | mark_inode_dirty(tree->inode); | ||
316 | } | ||
317 | |||
318 | hfs_bnode_dump(node); | ||
319 | hfs_bnode_dump(new_node); | ||
320 | hfs_bnode_put(node); | ||
321 | |||
322 | return new_node; | ||
323 | } | ||
324 | |||
325 | static int hfs_brec_update_parent(struct hfs_find_data *fd) | ||
326 | { | ||
327 | struct hfs_btree *tree; | ||
328 | struct hfs_bnode *node, *new_node, *parent; | ||
329 | int newkeylen, diff; | ||
330 | int rec, rec_off, end_rec_off; | ||
331 | int start_off, end_off; | ||
332 | |||
333 | tree = fd->tree; | ||
334 | node = fd->bnode; | ||
335 | new_node = NULL; | ||
336 | if (!node->parent) | ||
337 | return 0; | ||
338 | |||
339 | again: | ||
340 | parent = hfs_bnode_find(tree, node->parent); | ||
341 | if (IS_ERR(parent)) | ||
342 | return PTR_ERR(parent); | ||
343 | __hfs_brec_find(parent, fd); | ||
344 | hfs_bnode_dump(parent); | ||
345 | rec = fd->record; | ||
346 | |||
347 | /* size difference between old and new key */ | ||
348 | if (tree->attributes & HFS_TREE_VARIDXKEYS) | ||
349 | newkeylen = hfs_bnode_read_u16(node, 14) + 2; | ||
350 | else | ||
351 | fd->keylength = newkeylen = tree->max_key_len + 2; | ||
352 | dprint(DBG_BNODE_MOD, "update_rec: %d, %d, %d\n", rec, fd->keylength, newkeylen); | ||
353 | |||
354 | rec_off = tree->node_size - (rec + 2) * 2; | ||
355 | end_rec_off = tree->node_size - (parent->num_recs + 1) * 2; | ||
356 | diff = newkeylen - fd->keylength; | ||
357 | if (!diff) | ||
358 | goto skip; | ||
359 | if (diff > 0) { | ||
360 | end_off = hfs_bnode_read_u16(parent, end_rec_off); | ||
361 | if (end_rec_off - end_off < diff) { | ||
362 | |||
363 | printk("splitting index node...\n"); | ||
364 | fd->bnode = parent; | ||
365 | new_node = hfs_bnode_split(fd); | ||
366 | if (IS_ERR(new_node)) | ||
367 | return PTR_ERR(new_node); | ||
368 | parent = fd->bnode; | ||
369 | rec = fd->record; | ||
370 | rec_off = tree->node_size - (rec + 2) * 2; | ||
371 | end_rec_off = tree->node_size - (parent->num_recs + 1) * 2; | ||
372 | } | ||
373 | } | ||
374 | |||
375 | end_off = start_off = hfs_bnode_read_u16(parent, rec_off); | ||
376 | hfs_bnode_write_u16(parent, rec_off, start_off + diff); | ||
377 | start_off -= 4; /* move previous cnid too */ | ||
378 | |||
379 | while (rec_off > end_rec_off) { | ||
380 | rec_off -= 2; | ||
381 | end_off = hfs_bnode_read_u16(parent, rec_off); | ||
382 | hfs_bnode_write_u16(parent, rec_off, end_off + diff); | ||
383 | } | ||
384 | hfs_bnode_move(parent, start_off + diff, start_off, | ||
385 | end_off - start_off); | ||
386 | skip: | ||
387 | hfs_bnode_copy(parent, fd->keyoffset, node, 14, newkeylen); | ||
388 | hfs_bnode_dump(parent); | ||
389 | |||
390 | hfs_bnode_put(node); | ||
391 | node = parent; | ||
392 | |||
393 | if (new_node) { | ||
394 | __be32 cnid; | ||
395 | |||
396 | fd->bnode = hfs_bnode_find(tree, new_node->parent); | ||
397 | /* create index key and entry */ | ||
398 | hfs_bnode_read_key(new_node, fd->search_key, 14); | ||
399 | cnid = cpu_to_be32(new_node->this); | ||
400 | |||
401 | __hfs_brec_find(fd->bnode, fd); | ||
402 | hfs_brec_insert(fd, &cnid, sizeof(cnid)); | ||
403 | hfs_bnode_put(fd->bnode); | ||
404 | hfs_bnode_put(new_node); | ||
405 | |||
406 | if (!rec) { | ||
407 | if (new_node == node) | ||
408 | goto out; | ||
409 | /* restore search_key */ | ||
410 | hfs_bnode_read_key(node, fd->search_key, 14); | ||
411 | } | ||
412 | } | ||
413 | |||
414 | if (!rec && node->parent) | ||
415 | goto again; | ||
416 | out: | ||
417 | fd->bnode = node; | ||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | static int hfs_btree_inc_height(struct hfs_btree *tree) | ||
422 | { | ||
423 | struct hfs_bnode *node, *new_node; | ||
424 | struct hfs_bnode_desc node_desc; | ||
425 | int key_size, rec; | ||
426 | __be32 cnid; | ||
427 | |||
428 | node = NULL; | ||
429 | if (tree->root) { | ||
430 | node = hfs_bnode_find(tree, tree->root); | ||
431 | if (IS_ERR(node)) | ||
432 | return PTR_ERR(node); | ||
433 | } | ||
434 | new_node = hfs_bmap_alloc(tree); | ||
435 | if (IS_ERR(new_node)) { | ||
436 | hfs_bnode_put(node); | ||
437 | return PTR_ERR(new_node); | ||
438 | } | ||
439 | |||
440 | tree->root = new_node->this; | ||
441 | if (!tree->depth) { | ||
442 | tree->leaf_head = tree->leaf_tail = new_node->this; | ||
443 | new_node->type = HFS_NODE_LEAF; | ||
444 | new_node->num_recs = 0; | ||
445 | } else { | ||
446 | new_node->type = HFS_NODE_INDEX; | ||
447 | new_node->num_recs = 1; | ||
448 | } | ||
449 | new_node->parent = 0; | ||
450 | new_node->next = 0; | ||
451 | new_node->prev = 0; | ||
452 | new_node->height = ++tree->depth; | ||
453 | |||
454 | node_desc.next = cpu_to_be32(new_node->next); | ||
455 | node_desc.prev = cpu_to_be32(new_node->prev); | ||
456 | node_desc.type = new_node->type; | ||
457 | node_desc.height = new_node->height; | ||
458 | node_desc.num_recs = cpu_to_be16(new_node->num_recs); | ||
459 | node_desc.reserved = 0; | ||
460 | hfs_bnode_write(new_node, &node_desc, 0, sizeof(node_desc)); | ||
461 | |||
462 | rec = tree->node_size - 2; | ||
463 | hfs_bnode_write_u16(new_node, rec, 14); | ||
464 | |||
465 | if (node) { | ||
466 | /* insert old root idx into new root */ | ||
467 | node->parent = tree->root; | ||
468 | if (node->type == HFS_NODE_LEAF || | ||
469 | tree->attributes & HFS_TREE_VARIDXKEYS) | ||
470 | key_size = hfs_bnode_read_u16(node, 14) + 2; | ||
471 | else | ||
472 | key_size = tree->max_key_len + 2; | ||
473 | hfs_bnode_copy(new_node, 14, node, 14, key_size); | ||
474 | |||
475 | if (!(tree->attributes & HFS_TREE_VARIDXKEYS)) { | ||
476 | key_size = tree->max_key_len + 2; | ||
477 | hfs_bnode_write_u16(new_node, 14, tree->max_key_len); | ||
478 | } | ||
479 | cnid = cpu_to_be32(node->this); | ||
480 | hfs_bnode_write(new_node, &cnid, 14 + key_size, 4); | ||
481 | |||
482 | rec -= 2; | ||
483 | hfs_bnode_write_u16(new_node, rec, 14 + key_size + 4); | ||
484 | |||
485 | hfs_bnode_put(node); | ||
486 | } | ||
487 | hfs_bnode_put(new_node); | ||
488 | mark_inode_dirty(tree->inode); | ||
489 | |||
490 | return 0; | ||
491 | } | ||
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c new file mode 100644 index 000000000000..44326aa2bd34 --- /dev/null +++ b/fs/hfsplus/btree.c | |||
@@ -0,0 +1,319 @@ | |||
1 | /* | ||
2 | * linux/fs/hfsplus/btree.c | ||
3 | * | ||
4 | * Copyright (C) 2001 | ||
5 | * Brad Boyer (flar@allandria.com) | ||
6 | * (C) 2003 Ardis Technologies <roman@ardistech.com> | ||
7 | * | ||
8 | * Handle opening/closing btree | ||
9 | */ | ||
10 | |||
11 | #include <linux/slab.h> | ||
12 | #include <linux/pagemap.h> | ||
13 | |||
14 | #include "hfsplus_fs.h" | ||
15 | #include "hfsplus_raw.h" | ||
16 | |||
17 | |||
18 | /* Get a reference to a B*Tree and do some initial checks */ | ||
19 | struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) | ||
20 | { | ||
21 | struct hfs_btree *tree; | ||
22 | struct hfs_btree_header_rec *head; | ||
23 | struct address_space *mapping; | ||
24 | struct page *page; | ||
25 | unsigned int size; | ||
26 | |||
27 | tree = kmalloc(sizeof(*tree), GFP_KERNEL); | ||
28 | if (!tree) | ||
29 | return NULL; | ||
30 | memset(tree, 0, sizeof(*tree)); | ||
31 | |||
32 | init_MUTEX(&tree->tree_lock); | ||
33 | spin_lock_init(&tree->hash_lock); | ||
34 | /* Set the correct compare function */ | ||
35 | tree->sb = sb; | ||
36 | tree->cnid = id; | ||
37 | if (id == HFSPLUS_EXT_CNID) { | ||
38 | tree->keycmp = hfsplus_ext_cmp_key; | ||
39 | } else if (id == HFSPLUS_CAT_CNID) { | ||
40 | tree->keycmp = hfsplus_cat_cmp_key; | ||
41 | } else { | ||
42 | printk("HFS+-fs: unknown B*Tree requested\n"); | ||
43 | goto free_tree; | ||
44 | } | ||
45 | tree->inode = iget(sb, id); | ||
46 | if (!tree->inode) | ||
47 | goto free_tree; | ||
48 | |||
49 | mapping = tree->inode->i_mapping; | ||
50 | page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage, NULL); | ||
51 | if (IS_ERR(page)) | ||
52 | goto free_tree; | ||
53 | |||
54 | /* Load the header */ | ||
55 | head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc)); | ||
56 | tree->root = be32_to_cpu(head->root); | ||
57 | tree->leaf_count = be32_to_cpu(head->leaf_count); | ||
58 | tree->leaf_head = be32_to_cpu(head->leaf_head); | ||
59 | tree->leaf_tail = be32_to_cpu(head->leaf_tail); | ||
60 | tree->node_count = be32_to_cpu(head->node_count); | ||
61 | tree->free_nodes = be32_to_cpu(head->free_nodes); | ||
62 | tree->attributes = be32_to_cpu(head->attributes); | ||
63 | tree->node_size = be16_to_cpu(head->node_size); | ||
64 | tree->max_key_len = be16_to_cpu(head->max_key_len); | ||
65 | tree->depth = be16_to_cpu(head->depth); | ||
66 | |||
67 | size = tree->node_size; | ||
68 | if (!size || size & (size - 1)) | ||
69 | goto fail_page; | ||
70 | if (!tree->node_count) | ||
71 | goto fail_page; | ||
72 | tree->node_size_shift = ffs(size) - 1; | ||
73 | |||
74 | tree->pages_per_bnode = (tree->node_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | ||
75 | |||
76 | kunmap(page); | ||
77 | page_cache_release(page); | ||
78 | return tree; | ||
79 | |||
80 | fail_page: | ||
81 | tree->inode->i_mapping->a_ops = &hfsplus_aops; | ||
82 | page_cache_release(page); | ||
83 | free_tree: | ||
84 | iput(tree->inode); | ||
85 | kfree(tree); | ||
86 | return NULL; | ||
87 | } | ||
88 | |||
89 | /* Release resources used by a btree */ | ||
90 | void hfs_btree_close(struct hfs_btree *tree) | ||
91 | { | ||
92 | struct hfs_bnode *node; | ||
93 | int i; | ||
94 | |||
95 | if (!tree) | ||
96 | return; | ||
97 | |||
98 | for (i = 0; i < NODE_HASH_SIZE; i++) { | ||
99 | while ((node = tree->node_hash[i])) { | ||
100 | tree->node_hash[i] = node->next_hash; | ||
101 | if (atomic_read(&node->refcnt)) | ||
102 | printk("HFS+: node %d:%d still has %d user(s)!\n", | ||
103 | node->tree->cnid, node->this, atomic_read(&node->refcnt)); | ||
104 | hfs_bnode_free(node); | ||
105 | tree->node_hash_cnt--; | ||
106 | } | ||
107 | } | ||
108 | iput(tree->inode); | ||
109 | kfree(tree); | ||
110 | } | ||
111 | |||
112 | void hfs_btree_write(struct hfs_btree *tree) | ||
113 | { | ||
114 | struct hfs_btree_header_rec *head; | ||
115 | struct hfs_bnode *node; | ||
116 | struct page *page; | ||
117 | |||
118 | node = hfs_bnode_find(tree, 0); | ||
119 | if (IS_ERR(node)) | ||
120 | /* panic? */ | ||
121 | return; | ||
122 | /* Load the header */ | ||
123 | page = node->page[0]; | ||
124 | head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc)); | ||
125 | |||
126 | head->root = cpu_to_be32(tree->root); | ||
127 | head->leaf_count = cpu_to_be32(tree->leaf_count); | ||
128 | head->leaf_head = cpu_to_be32(tree->leaf_head); | ||
129 | head->leaf_tail = cpu_to_be32(tree->leaf_tail); | ||
130 | head->node_count = cpu_to_be32(tree->node_count); | ||
131 | head->free_nodes = cpu_to_be32(tree->free_nodes); | ||
132 | head->attributes = cpu_to_be32(tree->attributes); | ||
133 | head->depth = cpu_to_be16(tree->depth); | ||
134 | |||
135 | kunmap(page); | ||
136 | set_page_dirty(page); | ||
137 | hfs_bnode_put(node); | ||
138 | } | ||
139 | |||
140 | static struct hfs_bnode *hfs_bmap_new_bmap(struct hfs_bnode *prev, u32 idx) | ||
141 | { | ||
142 | struct hfs_btree *tree = prev->tree; | ||
143 | struct hfs_bnode *node; | ||
144 | struct hfs_bnode_desc desc; | ||
145 | __be32 cnid; | ||
146 | |||
147 | node = hfs_bnode_create(tree, idx); | ||
148 | if (IS_ERR(node)) | ||
149 | return node; | ||
150 | |||
151 | tree->free_nodes--; | ||
152 | prev->next = idx; | ||
153 | cnid = cpu_to_be32(idx); | ||
154 | hfs_bnode_write(prev, &cnid, offsetof(struct hfs_bnode_desc, next), 4); | ||
155 | |||
156 | node->type = HFS_NODE_MAP; | ||
157 | node->num_recs = 1; | ||
158 | hfs_bnode_clear(node, 0, tree->node_size); | ||
159 | desc.next = 0; | ||
160 | desc.prev = 0; | ||
161 | desc.type = HFS_NODE_MAP; | ||
162 | desc.height = 0; | ||
163 | desc.num_recs = cpu_to_be16(1); | ||
164 | desc.reserved = 0; | ||
165 | hfs_bnode_write(node, &desc, 0, sizeof(desc)); | ||
166 | hfs_bnode_write_u16(node, 14, 0x8000); | ||
167 | hfs_bnode_write_u16(node, tree->node_size - 2, 14); | ||
168 | hfs_bnode_write_u16(node, tree->node_size - 4, tree->node_size - 6); | ||
169 | |||
170 | return node; | ||
171 | } | ||
172 | |||
173 | struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) | ||
174 | { | ||
175 | struct hfs_bnode *node, *next_node; | ||
176 | struct page **pagep; | ||
177 | u32 nidx, idx; | ||
178 | u16 off, len; | ||
179 | u8 *data, byte, m; | ||
180 | int i; | ||
181 | |||
182 | while (!tree->free_nodes) { | ||
183 | struct inode *inode = tree->inode; | ||
184 | u32 count; | ||
185 | int res; | ||
186 | |||
187 | res = hfsplus_file_extend(inode); | ||
188 | if (res) | ||
189 | return ERR_PTR(res); | ||
190 | HFSPLUS_I(inode).phys_size = inode->i_size = | ||
191 | (loff_t)HFSPLUS_I(inode).alloc_blocks << | ||
192 | HFSPLUS_SB(tree->sb).alloc_blksz_shift; | ||
193 | HFSPLUS_I(inode).fs_blocks = HFSPLUS_I(inode).alloc_blocks << | ||
194 | HFSPLUS_SB(tree->sb).fs_shift; | ||
195 | inode_set_bytes(inode, inode->i_size); | ||
196 | count = inode->i_size >> tree->node_size_shift; | ||
197 | tree->free_nodes = count - tree->node_count; | ||
198 | tree->node_count = count; | ||
199 | } | ||
200 | |||
201 | nidx = 0; | ||
202 | node = hfs_bnode_find(tree, nidx); | ||
203 | if (IS_ERR(node)) | ||
204 | return node; | ||
205 | len = hfs_brec_lenoff(node, 2, &off); | ||
206 | |||
207 | off += node->page_offset; | ||
208 | pagep = node->page + (off >> PAGE_CACHE_SHIFT); | ||
209 | data = kmap(*pagep); | ||
210 | off &= ~PAGE_CACHE_MASK; | ||
211 | idx = 0; | ||
212 | |||
213 | for (;;) { | ||
214 | while (len) { | ||
215 | byte = data[off]; | ||
216 | if (byte != 0xff) { | ||
217 | for (m = 0x80, i = 0; i < 8; m >>= 1, i++) { | ||
218 | if (!(byte & m)) { | ||
219 | idx += i; | ||
220 | data[off] |= m; | ||
221 | set_page_dirty(*pagep); | ||
222 | kunmap(*pagep); | ||
223 | tree->free_nodes--; | ||
224 | mark_inode_dirty(tree->inode); | ||
225 | hfs_bnode_put(node); | ||
226 | if (!idx) { | ||
227 | printk("unexpected idx %u (%u)\n", idx, node->this); | ||
228 | BUG(); | ||
229 | } | ||
230 | return hfs_bnode_create(tree, idx); | ||
231 | } | ||
232 | } | ||
233 | } | ||
234 | if (++off >= PAGE_CACHE_SIZE) { | ||
235 | kunmap(*pagep); | ||
236 | data = kmap(*++pagep); | ||
237 | off = 0; | ||
238 | } | ||
239 | idx += 8; | ||
240 | len--; | ||
241 | } | ||
242 | kunmap(*pagep); | ||
243 | nidx = node->next; | ||
244 | if (!nidx) { | ||
245 | printk("create new bmap node...\n"); | ||
246 | next_node = hfs_bmap_new_bmap(node, idx); | ||
247 | } else | ||
248 | next_node = hfs_bnode_find(tree, nidx); | ||
249 | hfs_bnode_put(node); | ||
250 | if (IS_ERR(next_node)) | ||
251 | return next_node; | ||
252 | node = next_node; | ||
253 | |||
254 | len = hfs_brec_lenoff(node, 0, &off); | ||
255 | off += node->page_offset; | ||
256 | pagep = node->page + (off >> PAGE_CACHE_SHIFT); | ||
257 | data = kmap(*pagep); | ||
258 | off &= ~PAGE_CACHE_MASK; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | void hfs_bmap_free(struct hfs_bnode *node) | ||
263 | { | ||
264 | struct hfs_btree *tree; | ||
265 | struct page *page; | ||
266 | u16 off, len; | ||
267 | u32 nidx; | ||
268 | u8 *data, byte, m; | ||
269 | |||
270 | dprint(DBG_BNODE_MOD, "btree_free_node: %u\n", node->this); | ||
271 | if (!node->this) | ||
272 | BUG(); | ||
273 | tree = node->tree; | ||
274 | nidx = node->this; | ||
275 | node = hfs_bnode_find(tree, 0); | ||
276 | if (IS_ERR(node)) | ||
277 | return; | ||
278 | len = hfs_brec_lenoff(node, 2, &off); | ||
279 | while (nidx >= len * 8) { | ||
280 | u32 i; | ||
281 | |||
282 | nidx -= len * 8; | ||
283 | i = node->next; | ||
284 | hfs_bnode_put(node); | ||
285 | if (!i) { | ||
286 | /* panic */; | ||
287 | printk("HFS: unable to free bnode %u. bmap not found!\n", node->this); | ||
288 | return; | ||
289 | } | ||
290 | node = hfs_bnode_find(tree, i); | ||
291 | if (IS_ERR(node)) | ||
292 | return; | ||
293 | if (node->type != HFS_NODE_MAP) { | ||
294 | /* panic */; | ||
295 | printk("HFS: invalid bmap found! (%u,%d)\n", node->this, node->type); | ||
296 | hfs_bnode_put(node); | ||
297 | return; | ||
298 | } | ||
299 | len = hfs_brec_lenoff(node, 0, &off); | ||
300 | } | ||
301 | off += node->page_offset + nidx / 8; | ||
302 | page = node->page[off >> PAGE_CACHE_SHIFT]; | ||
303 | data = kmap(page); | ||
304 | off &= ~PAGE_CACHE_MASK; | ||
305 | m = 1 << (~nidx & 7); | ||
306 | byte = data[off]; | ||
307 | if (!(byte & m)) { | ||
308 | printk("HFS: trying to free free bnode %u(%d)\n", node->this, node->type); | ||
309 | kunmap(page); | ||
310 | hfs_bnode_put(node); | ||
311 | return; | ||
312 | } | ||
313 | data[off] = byte & ~m; | ||
314 | set_page_dirty(page); | ||
315 | kunmap(page); | ||
316 | hfs_bnode_put(node); | ||
317 | tree->free_nodes++; | ||
318 | mark_inode_dirty(tree->inode); | ||
319 | } | ||
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c new file mode 100644 index 000000000000..94712790c8b3 --- /dev/null +++ b/fs/hfsplus/catalog.c | |||
@@ -0,0 +1,358 @@ | |||
1 | /* | ||
2 | * linux/fs/hfsplus/catalog.c | ||
3 | * | ||
4 | * Copyright (C) 2001 | ||
5 | * Brad Boyer (flar@allandria.com) | ||
6 | * (C) 2003 Ardis Technologies <roman@ardistech.com> | ||
7 | * | ||
8 | * Handling of catalog records | ||
9 | */ | ||
10 | |||
11 | #include <linux/sched.h> | ||
12 | |||
13 | #include "hfsplus_fs.h" | ||
14 | #include "hfsplus_raw.h" | ||
15 | |||
16 | int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2) | ||
17 | { | ||
18 | __be32 k1p, k2p; | ||
19 | |||
20 | k1p = k1->cat.parent; | ||
21 | k2p = k2->cat.parent; | ||
22 | if (k1p != k2p) | ||
23 | return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1; | ||
24 | |||
25 | return hfsplus_unistrcmp(&k1->cat.name, &k2->cat.name); | ||
26 | } | ||
27 | |||
28 | void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *key, | ||
29 | u32 parent, struct qstr *str) | ||
30 | { | ||
31 | int len; | ||
32 | |||
33 | key->cat.parent = cpu_to_be32(parent); | ||
34 | if (str) { | ||
35 | hfsplus_asc2uni(sb, &key->cat.name, str->name, str->len); | ||
36 | len = be16_to_cpu(key->cat.name.length); | ||
37 | } else { | ||
38 | key->cat.name.length = 0; | ||
39 | len = 0; | ||
40 | } | ||
41 | key->key_len = cpu_to_be16(6 + 2 * len); | ||
42 | } | ||
43 | |||
44 | static void hfsplus_cat_build_key_uni(hfsplus_btree_key *key, u32 parent, | ||
45 | struct hfsplus_unistr *name) | ||
46 | { | ||
47 | int ustrlen; | ||
48 | |||
49 | ustrlen = be16_to_cpu(name->length); | ||
50 | key->cat.parent = cpu_to_be32(parent); | ||
51 | key->cat.name.length = cpu_to_be16(ustrlen); | ||
52 | ustrlen *= 2; | ||
53 | memcpy(key->cat.name.unicode, name->unicode, ustrlen); | ||
54 | key->key_len = cpu_to_be16(6 + ustrlen); | ||
55 | } | ||
56 | |||
57 | static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms) | ||
58 | { | ||
59 | if (inode->i_flags & S_IMMUTABLE) | ||
60 | perms->rootflags |= HFSPLUS_FLG_IMMUTABLE; | ||
61 | else | ||
62 | perms->rootflags &= ~HFSPLUS_FLG_IMMUTABLE; | ||
63 | if (inode->i_flags & S_APPEND) | ||
64 | perms->rootflags |= HFSPLUS_FLG_APPEND; | ||
65 | else | ||
66 | perms->rootflags &= ~HFSPLUS_FLG_APPEND; | ||
67 | HFSPLUS_I(inode).rootflags = perms->rootflags; | ||
68 | HFSPLUS_I(inode).userflags = perms->userflags; | ||
69 | perms->mode = cpu_to_be16(inode->i_mode); | ||
70 | perms->owner = cpu_to_be32(inode->i_uid); | ||
71 | perms->group = cpu_to_be32(inode->i_gid); | ||
72 | } | ||
73 | |||
74 | static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct inode *inode) | ||
75 | { | ||
76 | if (S_ISDIR(inode->i_mode)) { | ||
77 | struct hfsplus_cat_folder *folder; | ||
78 | |||
79 | folder = &entry->folder; | ||
80 | memset(folder, 0, sizeof(*folder)); | ||
81 | folder->type = cpu_to_be16(HFSPLUS_FOLDER); | ||
82 | folder->id = cpu_to_be32(inode->i_ino); | ||
83 | folder->create_date = folder->content_mod_date = | ||
84 | folder->attribute_mod_date = folder->access_date = hfsp_now2mt(); | ||
85 | hfsplus_set_perms(inode, &folder->permissions); | ||
86 | if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir) | ||
87 | /* invisible and namelocked */ | ||
88 | folder->user_info.frFlags = cpu_to_be16(0x5000); | ||
89 | return sizeof(*folder); | ||
90 | } else { | ||
91 | struct hfsplus_cat_file *file; | ||
92 | |||
93 | file = &entry->file; | ||
94 | memset(file, 0, sizeof(*file)); | ||
95 | file->type = cpu_to_be16(HFSPLUS_FILE); | ||
96 | file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS); | ||
97 | file->id = cpu_to_be32(cnid); | ||
98 | file->create_date = file->content_mod_date = | ||
99 | file->attribute_mod_date = file->access_date = hfsp_now2mt(); | ||
100 | if (cnid == inode->i_ino) { | ||
101 | hfsplus_set_perms(inode, &file->permissions); | ||
102 | file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type); | ||
103 | file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator); | ||
104 | if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) | ||
105 | file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); | ||
106 | } else { | ||
107 | file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE); | ||
108 | file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR); | ||
109 | file->user_info.fdFlags = cpu_to_be16(0x100); | ||
110 | file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev); | ||
111 | } | ||
112 | return sizeof(*file); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | static int hfsplus_fill_cat_thread(struct super_block *sb, | ||
117 | hfsplus_cat_entry *entry, int type, | ||
118 | u32 parentid, struct qstr *str) | ||
119 | { | ||
120 | entry->type = cpu_to_be16(type); | ||
121 | entry->thread.reserved = 0; | ||
122 | entry->thread.parentID = cpu_to_be32(parentid); | ||
123 | hfsplus_asc2uni(sb, &entry->thread.nodeName, str->name, str->len); | ||
124 | return 10 + be16_to_cpu(entry->thread.nodeName.length) * 2; | ||
125 | } | ||
126 | |||
127 | /* Try to get a catalog entry for given catalog id */ | ||
128 | int hfsplus_find_cat(struct super_block *sb, u32 cnid, | ||
129 | struct hfs_find_data *fd) | ||
130 | { | ||
131 | hfsplus_cat_entry tmp; | ||
132 | int err; | ||
133 | u16 type; | ||
134 | |||
135 | hfsplus_cat_build_key(sb, fd->search_key, cnid, NULL); | ||
136 | err = hfs_brec_read(fd, &tmp, sizeof(hfsplus_cat_entry)); | ||
137 | if (err) | ||
138 | return err; | ||
139 | |||
140 | type = be16_to_cpu(tmp.type); | ||
141 | if (type != HFSPLUS_FOLDER_THREAD && type != HFSPLUS_FILE_THREAD) { | ||
142 | printk("HFS+-fs: Found bad thread record in catalog\n"); | ||
143 | return -EIO; | ||
144 | } | ||
145 | |||
146 | hfsplus_cat_build_key_uni(fd->search_key, be32_to_cpu(tmp.thread.parentID), | ||
147 | &tmp.thread.nodeName); | ||
148 | return hfs_brec_find(fd); | ||
149 | } | ||
150 | |||
151 | int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct inode *inode) | ||
152 | { | ||
153 | struct hfs_find_data fd; | ||
154 | struct super_block *sb; | ||
155 | hfsplus_cat_entry entry; | ||
156 | int entry_size; | ||
157 | int err; | ||
158 | |||
159 | dprint(DBG_CAT_MOD, "create_cat: %s,%u(%d)\n", str->name, cnid, inode->i_nlink); | ||
160 | sb = dir->i_sb; | ||
161 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | ||
162 | |||
163 | hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL); | ||
164 | entry_size = hfsplus_fill_cat_thread(sb, &entry, S_ISDIR(inode->i_mode) ? | ||
165 | HFSPLUS_FOLDER_THREAD : HFSPLUS_FILE_THREAD, | ||
166 | dir->i_ino, str); | ||
167 | err = hfs_brec_find(&fd); | ||
168 | if (err != -ENOENT) { | ||
169 | if (!err) | ||
170 | err = -EEXIST; | ||
171 | goto err2; | ||
172 | } | ||
173 | err = hfs_brec_insert(&fd, &entry, entry_size); | ||
174 | if (err) | ||
175 | goto err2; | ||
176 | |||
177 | hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, str); | ||
178 | entry_size = hfsplus_cat_build_record(&entry, cnid, inode); | ||
179 | err = hfs_brec_find(&fd); | ||
180 | if (err != -ENOENT) { | ||
181 | /* panic? */ | ||
182 | if (!err) | ||
183 | err = -EEXIST; | ||
184 | goto err1; | ||
185 | } | ||
186 | err = hfs_brec_insert(&fd, &entry, entry_size); | ||
187 | if (err) | ||
188 | goto err1; | ||
189 | |||
190 | dir->i_size++; | ||
191 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | ||
192 | mark_inode_dirty(dir); | ||
193 | hfs_find_exit(&fd); | ||
194 | return 0; | ||
195 | |||
196 | err1: | ||
197 | hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL); | ||
198 | if (!hfs_brec_find(&fd)) | ||
199 | hfs_brec_remove(&fd); | ||
200 | err2: | ||
201 | hfs_find_exit(&fd); | ||
202 | return err; | ||
203 | } | ||
204 | |||
205 | int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) | ||
206 | { | ||
207 | struct super_block *sb; | ||
208 | struct hfs_find_data fd; | ||
209 | struct hfsplus_fork_raw fork; | ||
210 | struct list_head *pos; | ||
211 | int err, off; | ||
212 | u16 type; | ||
213 | |||
214 | dprint(DBG_CAT_MOD, "delete_cat: %s,%u\n", str ? str->name : NULL, cnid); | ||
215 | sb = dir->i_sb; | ||
216 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | ||
217 | |||
218 | if (!str) { | ||
219 | int len; | ||
220 | |||
221 | hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL); | ||
222 | err = hfs_brec_find(&fd); | ||
223 | if (err) | ||
224 | goto out; | ||
225 | |||
226 | off = fd.entryoffset + offsetof(struct hfsplus_cat_thread, nodeName); | ||
227 | fd.search_key->cat.parent = cpu_to_be32(dir->i_ino); | ||
228 | hfs_bnode_read(fd.bnode, &fd.search_key->cat.name.length, off, 2); | ||
229 | len = be16_to_cpu(fd.search_key->cat.name.length) * 2; | ||
230 | hfs_bnode_read(fd.bnode, &fd.search_key->cat.name.unicode, off + 2, len); | ||
231 | fd.search_key->key_len = cpu_to_be16(6 + len); | ||
232 | } else | ||
233 | hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, str); | ||
234 | |||
235 | err = hfs_brec_find(&fd); | ||
236 | if (err) | ||
237 | goto out; | ||
238 | |||
239 | type = hfs_bnode_read_u16(fd.bnode, fd.entryoffset); | ||
240 | if (type == HFSPLUS_FILE) { | ||
241 | #if 0 | ||
242 | off = fd.entryoffset + offsetof(hfsplus_cat_file, data_fork); | ||
243 | hfs_bnode_read(fd.bnode, &fork, off, sizeof(fork)); | ||
244 | hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_DATA); | ||
245 | #endif | ||
246 | |||
247 | off = fd.entryoffset + offsetof(struct hfsplus_cat_file, rsrc_fork); | ||
248 | hfs_bnode_read(fd.bnode, &fork, off, sizeof(fork)); | ||
249 | hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_RSRC); | ||
250 | } | ||
251 | |||
252 | list_for_each(pos, &HFSPLUS_I(dir).open_dir_list) { | ||
253 | struct hfsplus_readdir_data *rd = | ||
254 | list_entry(pos, struct hfsplus_readdir_data, list); | ||
255 | if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0) | ||
256 | rd->file->f_pos--; | ||
257 | } | ||
258 | |||
259 | err = hfs_brec_remove(&fd); | ||
260 | if (err) | ||
261 | goto out; | ||
262 | |||
263 | hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL); | ||
264 | err = hfs_brec_find(&fd); | ||
265 | if (err) | ||
266 | goto out; | ||
267 | |||
268 | err = hfs_brec_remove(&fd); | ||
269 | if (err) | ||
270 | goto out; | ||
271 | |||
272 | dir->i_size--; | ||
273 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | ||
274 | mark_inode_dirty(dir); | ||
275 | out: | ||
276 | hfs_find_exit(&fd); | ||
277 | |||
278 | return err; | ||
279 | } | ||
280 | |||
281 | int hfsplus_rename_cat(u32 cnid, | ||
282 | struct inode *src_dir, struct qstr *src_name, | ||
283 | struct inode *dst_dir, struct qstr *dst_name) | ||
284 | { | ||
285 | struct super_block *sb; | ||
286 | struct hfs_find_data src_fd, dst_fd; | ||
287 | hfsplus_cat_entry entry; | ||
288 | int entry_size, type; | ||
289 | int err = 0; | ||
290 | |||
291 | dprint(DBG_CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n", cnid, src_dir->i_ino, src_name->name, | ||
292 | dst_dir->i_ino, dst_name->name); | ||
293 | sb = src_dir->i_sb; | ||
294 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &src_fd); | ||
295 | dst_fd = src_fd; | ||
296 | |||
297 | /* find the old dir entry and read the data */ | ||
298 | hfsplus_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name); | ||
299 | err = hfs_brec_find(&src_fd); | ||
300 | if (err) | ||
301 | goto out; | ||
302 | |||
303 | hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset, | ||
304 | src_fd.entrylength); | ||
305 | |||
306 | /* create new dir entry with the data from the old entry */ | ||
307 | hfsplus_cat_build_key(sb, dst_fd.search_key, dst_dir->i_ino, dst_name); | ||
308 | err = hfs_brec_find(&dst_fd); | ||
309 | if (err != -ENOENT) { | ||
310 | if (!err) | ||
311 | err = -EEXIST; | ||
312 | goto out; | ||
313 | } | ||
314 | |||
315 | err = hfs_brec_insert(&dst_fd, &entry, src_fd.entrylength); | ||
316 | if (err) | ||
317 | goto out; | ||
318 | dst_dir->i_size++; | ||
319 | dst_dir->i_mtime = dst_dir->i_ctime = CURRENT_TIME_SEC; | ||
320 | mark_inode_dirty(dst_dir); | ||
321 | |||
322 | /* finally remove the old entry */ | ||
323 | hfsplus_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name); | ||
324 | err = hfs_brec_find(&src_fd); | ||
325 | if (err) | ||
326 | goto out; | ||
327 | err = hfs_brec_remove(&src_fd); | ||
328 | if (err) | ||
329 | goto out; | ||
330 | src_dir->i_size--; | ||
331 | src_dir->i_mtime = src_dir->i_ctime = CURRENT_TIME_SEC; | ||
332 | mark_inode_dirty(src_dir); | ||
333 | |||
334 | /* remove old thread entry */ | ||
335 | hfsplus_cat_build_key(sb, src_fd.search_key, cnid, NULL); | ||
336 | err = hfs_brec_find(&src_fd); | ||
337 | if (err) | ||
338 | goto out; | ||
339 | type = hfs_bnode_read_u16(src_fd.bnode, src_fd.entryoffset); | ||
340 | err = hfs_brec_remove(&src_fd); | ||
341 | if (err) | ||
342 | goto out; | ||
343 | |||
344 | /* create new thread entry */ | ||
345 | hfsplus_cat_build_key(sb, dst_fd.search_key, cnid, NULL); | ||
346 | entry_size = hfsplus_fill_cat_thread(sb, &entry, type, dst_dir->i_ino, dst_name); | ||
347 | err = hfs_brec_find(&dst_fd); | ||
348 | if (err != -ENOENT) { | ||
349 | if (!err) | ||
350 | err = -EEXIST; | ||
351 | goto out; | ||
352 | } | ||
353 | err = hfs_brec_insert(&dst_fd, &entry, entry_size); | ||
354 | out: | ||
355 | hfs_bnode_put(dst_fd.bnode); | ||
356 | hfs_find_exit(&src_fd); | ||
357 | return err; | ||
358 | } | ||
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c new file mode 100644 index 000000000000..7bda76667a4a --- /dev/null +++ b/fs/hfsplus/dir.c | |||
@@ -0,0 +1,484 @@ | |||
1 | /* | ||
2 | * linux/fs/hfsplus/dir.c | ||
3 | * | ||
4 | * Copyright (C) 2001 | ||
5 | * Brad Boyer (flar@allandria.com) | ||
6 | * (C) 2003 Ardis Technologies <roman@ardistech.com> | ||
7 | * | ||
8 | * Handling of directories | ||
9 | */ | ||
10 | |||
11 | #include <linux/errno.h> | ||
12 | #include <linux/fs.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/random.h> | ||
16 | #include <linux/version.h> | ||
17 | |||
18 | #include "hfsplus_fs.h" | ||
19 | #include "hfsplus_raw.h" | ||
20 | |||
21 | static inline void hfsplus_instantiate(struct dentry *dentry, | ||
22 | struct inode *inode, u32 cnid) | ||
23 | { | ||
24 | dentry->d_fsdata = (void *)(unsigned long)cnid; | ||
25 | d_instantiate(dentry, inode); | ||
26 | } | ||
27 | |||
28 | /* Find the entry inside dir named dentry->d_name */ | ||
29 | static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry, | ||
30 | struct nameidata *nd) | ||
31 | { | ||
32 | struct inode *inode = NULL; | ||
33 | struct hfs_find_data fd; | ||
34 | struct super_block *sb; | ||
35 | hfsplus_cat_entry entry; | ||
36 | int err; | ||
37 | u32 cnid, linkid = 0; | ||
38 | u16 type; | ||
39 | |||
40 | sb = dir->i_sb; | ||
41 | dentry->d_fsdata = NULL; | ||
42 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | ||
43 | hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name); | ||
44 | again: | ||
45 | err = hfs_brec_read(&fd, &entry, sizeof(entry)); | ||
46 | if (err) { | ||
47 | if (err == -ENOENT) { | ||
48 | hfs_find_exit(&fd); | ||
49 | /* No such entry */ | ||
50 | inode = NULL; | ||
51 | goto out; | ||
52 | } | ||
53 | goto fail; | ||
54 | } | ||
55 | type = be16_to_cpu(entry.type); | ||
56 | if (type == HFSPLUS_FOLDER) { | ||
57 | if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) { | ||
58 | err = -EIO; | ||
59 | goto fail; | ||
60 | } | ||
61 | cnid = be32_to_cpu(entry.folder.id); | ||
62 | dentry->d_fsdata = (void *)(unsigned long)cnid; | ||
63 | } else if (type == HFSPLUS_FILE) { | ||
64 | if (fd.entrylength < sizeof(struct hfsplus_cat_file)) { | ||
65 | err = -EIO; | ||
66 | goto fail; | ||
67 | } | ||
68 | cnid = be32_to_cpu(entry.file.id); | ||
69 | if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) && | ||
70 | entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR)) { | ||
71 | struct qstr str; | ||
72 | char name[32]; | ||
73 | |||
74 | if (dentry->d_fsdata) { | ||
75 | err = -ENOENT; | ||
76 | inode = NULL; | ||
77 | goto out; | ||
78 | } | ||
79 | dentry->d_fsdata = (void *)(unsigned long)cnid; | ||
80 | linkid = be32_to_cpu(entry.file.permissions.dev); | ||
81 | str.len = sprintf(name, "iNode%d", linkid); | ||
82 | str.name = name; | ||
83 | hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str); | ||
84 | goto again; | ||
85 | } else if (!dentry->d_fsdata) | ||
86 | dentry->d_fsdata = (void *)(unsigned long)cnid; | ||
87 | } else { | ||
88 | printk("HFS+-fs: Illegal catalog entry type in lookup\n"); | ||
89 | err = -EIO; | ||
90 | goto fail; | ||
91 | } | ||
92 | hfs_find_exit(&fd); | ||
93 | inode = iget(dir->i_sb, cnid); | ||
94 | if (!inode) | ||
95 | return ERR_PTR(-EACCES); | ||
96 | if (S_ISREG(inode->i_mode)) | ||
97 | HFSPLUS_I(inode).dev = linkid; | ||
98 | out: | ||
99 | d_add(dentry, inode); | ||
100 | return NULL; | ||
101 | fail: | ||
102 | hfs_find_exit(&fd); | ||
103 | return ERR_PTR(err); | ||
104 | } | ||
105 | |||
106 | static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | ||
107 | { | ||
108 | struct inode *inode = filp->f_dentry->d_inode; | ||
109 | struct super_block *sb = inode->i_sb; | ||
110 | int len, err; | ||
111 | char strbuf[HFSPLUS_MAX_STRLEN + 1]; | ||
112 | hfsplus_cat_entry entry; | ||
113 | struct hfs_find_data fd; | ||
114 | struct hfsplus_readdir_data *rd; | ||
115 | u16 type; | ||
116 | |||
117 | if (filp->f_pos >= inode->i_size) | ||
118 | return 0; | ||
119 | |||
120 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | ||
121 | hfsplus_cat_build_key(sb, fd.search_key, inode->i_ino, NULL); | ||
122 | err = hfs_brec_find(&fd); | ||
123 | if (err) | ||
124 | goto out; | ||
125 | |||
126 | switch ((u32)filp->f_pos) { | ||
127 | case 0: | ||
128 | /* This is completely artificial... */ | ||
129 | if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR)) | ||
130 | goto out; | ||
131 | filp->f_pos++; | ||
132 | /* fall through */ | ||
133 | case 1: | ||
134 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); | ||
135 | if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) { | ||
136 | printk("HFS+-fs: bad catalog folder thread\n"); | ||
137 | err = -EIO; | ||
138 | goto out; | ||
139 | } | ||
140 | if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) { | ||
141 | printk("HFS+-fs: truncated catalog thread\n"); | ||
142 | err = -EIO; | ||
143 | goto out; | ||
144 | } | ||
145 | if (filldir(dirent, "..", 2, 1, | ||
146 | be32_to_cpu(entry.thread.parentID), DT_DIR)) | ||
147 | goto out; | ||
148 | filp->f_pos++; | ||
149 | /* fall through */ | ||
150 | default: | ||
151 | if (filp->f_pos >= inode->i_size) | ||
152 | goto out; | ||
153 | err = hfs_brec_goto(&fd, filp->f_pos - 1); | ||
154 | if (err) | ||
155 | goto out; | ||
156 | } | ||
157 | |||
158 | for (;;) { | ||
159 | if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) { | ||
160 | printk("HFS+-fs: walked past end of dir\n"); | ||
161 | err = -EIO; | ||
162 | goto out; | ||
163 | } | ||
164 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); | ||
165 | type = be16_to_cpu(entry.type); | ||
166 | len = HFSPLUS_MAX_STRLEN; | ||
167 | err = hfsplus_uni2asc(sb, &fd.key->cat.name, strbuf, &len); | ||
168 | if (err) | ||
169 | goto out; | ||
170 | if (type == HFSPLUS_FOLDER) { | ||
171 | if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) { | ||
172 | printk("HFS+-fs: small dir entry\n"); | ||
173 | err = -EIO; | ||
174 | goto out; | ||
175 | } | ||
176 | if (HFSPLUS_SB(sb).hidden_dir && | ||
177 | HFSPLUS_SB(sb).hidden_dir->i_ino == be32_to_cpu(entry.folder.id)) | ||
178 | goto next; | ||
179 | if (filldir(dirent, strbuf, len, filp->f_pos, | ||
180 | be32_to_cpu(entry.folder.id), DT_DIR)) | ||
181 | break; | ||
182 | } else if (type == HFSPLUS_FILE) { | ||
183 | if (fd.entrylength < sizeof(struct hfsplus_cat_file)) { | ||
184 | printk("HFS+-fs: small file entry\n"); | ||
185 | err = -EIO; | ||
186 | goto out; | ||
187 | } | ||
188 | if (filldir(dirent, strbuf, len, filp->f_pos, | ||
189 | be32_to_cpu(entry.file.id), DT_REG)) | ||
190 | break; | ||
191 | } else { | ||
192 | printk("HFS+-fs: bad catalog entry type\n"); | ||
193 | err = -EIO; | ||
194 | goto out; | ||
195 | } | ||
196 | next: | ||
197 | filp->f_pos++; | ||
198 | if (filp->f_pos >= inode->i_size) | ||
199 | goto out; | ||
200 | err = hfs_brec_goto(&fd, 1); | ||
201 | if (err) | ||
202 | goto out; | ||
203 | } | ||
204 | rd = filp->private_data; | ||
205 | if (!rd) { | ||
206 | rd = kmalloc(sizeof(struct hfsplus_readdir_data), GFP_KERNEL); | ||
207 | if (!rd) { | ||
208 | err = -ENOMEM; | ||
209 | goto out; | ||
210 | } | ||
211 | filp->private_data = rd; | ||
212 | rd->file = filp; | ||
213 | list_add(&rd->list, &HFSPLUS_I(inode).open_dir_list); | ||
214 | } | ||
215 | memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key)); | ||
216 | out: | ||
217 | hfs_find_exit(&fd); | ||
218 | return err; | ||
219 | } | ||
220 | |||
221 | static int hfsplus_dir_release(struct inode *inode, struct file *file) | ||
222 | { | ||
223 | struct hfsplus_readdir_data *rd = file->private_data; | ||
224 | if (rd) { | ||
225 | list_del(&rd->list); | ||
226 | kfree(rd); | ||
227 | } | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode, | ||
232 | struct nameidata *nd) | ||
233 | { | ||
234 | struct inode *inode; | ||
235 | int res; | ||
236 | |||
237 | inode = hfsplus_new_inode(dir->i_sb, mode); | ||
238 | if (!inode) | ||
239 | return -ENOSPC; | ||
240 | |||
241 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); | ||
242 | if (res) { | ||
243 | inode->i_nlink = 0; | ||
244 | hfsplus_delete_inode(inode); | ||
245 | iput(inode); | ||
246 | return res; | ||
247 | } | ||
248 | hfsplus_instantiate(dentry, inode, inode->i_ino); | ||
249 | mark_inode_dirty(inode); | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, | ||
254 | struct dentry *dst_dentry) | ||
255 | { | ||
256 | struct super_block *sb = dst_dir->i_sb; | ||
257 | struct inode *inode = src_dentry->d_inode; | ||
258 | struct inode *src_dir = src_dentry->d_parent->d_inode; | ||
259 | struct qstr str; | ||
260 | char name[32]; | ||
261 | u32 cnid, id; | ||
262 | int res; | ||
263 | |||
264 | if (HFSPLUS_IS_RSRC(inode)) | ||
265 | return -EPERM; | ||
266 | |||
267 | if (inode->i_ino == (u32)(unsigned long)src_dentry->d_fsdata) { | ||
268 | for (;;) { | ||
269 | get_random_bytes(&id, sizeof(cnid)); | ||
270 | id &= 0x3fffffff; | ||
271 | str.name = name; | ||
272 | str.len = sprintf(name, "iNode%d", id); | ||
273 | res = hfsplus_rename_cat(inode->i_ino, | ||
274 | src_dir, &src_dentry->d_name, | ||
275 | HFSPLUS_SB(sb).hidden_dir, &str); | ||
276 | if (!res) | ||
277 | break; | ||
278 | if (res != -EEXIST) | ||
279 | return res; | ||
280 | } | ||
281 | HFSPLUS_I(inode).dev = id; | ||
282 | cnid = HFSPLUS_SB(sb).next_cnid++; | ||
283 | src_dentry->d_fsdata = (void *)(unsigned long)cnid; | ||
284 | res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode); | ||
285 | if (res) | ||
286 | /* panic? */ | ||
287 | return res; | ||
288 | HFSPLUS_SB(sb).file_count++; | ||
289 | } | ||
290 | cnid = HFSPLUS_SB(sb).next_cnid++; | ||
291 | res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode); | ||
292 | if (res) | ||
293 | return res; | ||
294 | |||
295 | inode->i_nlink++; | ||
296 | hfsplus_instantiate(dst_dentry, inode, cnid); | ||
297 | atomic_inc(&inode->i_count); | ||
298 | inode->i_ctime = CURRENT_TIME_SEC; | ||
299 | mark_inode_dirty(inode); | ||
300 | HFSPLUS_SB(sb).file_count++; | ||
301 | sb->s_dirt = 1; | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | ||
307 | { | ||
308 | struct super_block *sb = dir->i_sb; | ||
309 | struct inode *inode = dentry->d_inode; | ||
310 | struct qstr str; | ||
311 | char name[32]; | ||
312 | u32 cnid; | ||
313 | int res; | ||
314 | |||
315 | if (HFSPLUS_IS_RSRC(inode)) | ||
316 | return -EPERM; | ||
317 | |||
318 | cnid = (u32)(unsigned long)dentry->d_fsdata; | ||
319 | if (inode->i_ino == cnid && | ||
320 | atomic_read(&HFSPLUS_I(inode).opencnt)) { | ||
321 | str.name = name; | ||
322 | str.len = sprintf(name, "temp%lu", inode->i_ino); | ||
323 | res = hfsplus_rename_cat(inode->i_ino, | ||
324 | dir, &dentry->d_name, | ||
325 | HFSPLUS_SB(sb).hidden_dir, &str); | ||
326 | if (!res) | ||
327 | inode->i_flags |= S_DEAD; | ||
328 | return res; | ||
329 | } | ||
330 | res = hfsplus_delete_cat(cnid, dir, &dentry->d_name); | ||
331 | if (res) | ||
332 | return res; | ||
333 | |||
334 | inode->i_nlink--; | ||
335 | hfsplus_delete_inode(inode); | ||
336 | if (inode->i_ino != cnid && !inode->i_nlink) { | ||
337 | if (!atomic_read(&HFSPLUS_I(inode).opencnt)) { | ||
338 | res = hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL); | ||
339 | if (!res) | ||
340 | hfsplus_delete_inode(inode); | ||
341 | } else | ||
342 | inode->i_flags |= S_DEAD; | ||
343 | } | ||
344 | inode->i_ctime = CURRENT_TIME_SEC; | ||
345 | mark_inode_dirty(inode); | ||
346 | |||
347 | return res; | ||
348 | } | ||
349 | |||
350 | static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode) | ||
351 | { | ||
352 | struct inode *inode; | ||
353 | int res; | ||
354 | |||
355 | inode = hfsplus_new_inode(dir->i_sb, S_IFDIR | mode); | ||
356 | if (!inode) | ||
357 | return -ENOSPC; | ||
358 | |||
359 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); | ||
360 | if (res) { | ||
361 | inode->i_nlink = 0; | ||
362 | hfsplus_delete_inode(inode); | ||
363 | iput(inode); | ||
364 | return res; | ||
365 | } | ||
366 | hfsplus_instantiate(dentry, inode, inode->i_ino); | ||
367 | mark_inode_dirty(inode); | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry) | ||
372 | { | ||
373 | struct inode *inode; | ||
374 | int res; | ||
375 | |||
376 | inode = dentry->d_inode; | ||
377 | if (inode->i_size != 2) | ||
378 | return -ENOTEMPTY; | ||
379 | res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name); | ||
380 | if (res) | ||
381 | return res; | ||
382 | inode->i_nlink = 0; | ||
383 | inode->i_ctime = CURRENT_TIME_SEC; | ||
384 | hfsplus_delete_inode(inode); | ||
385 | mark_inode_dirty(inode); | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | static int hfsplus_symlink(struct inode *dir, struct dentry *dentry, | ||
390 | const char *symname) | ||
391 | { | ||
392 | struct super_block *sb; | ||
393 | struct inode *inode; | ||
394 | int res; | ||
395 | |||
396 | sb = dir->i_sb; | ||
397 | inode = hfsplus_new_inode(sb, S_IFLNK | S_IRWXUGO); | ||
398 | if (!inode) | ||
399 | return -ENOSPC; | ||
400 | |||
401 | res = page_symlink(inode, symname, strlen(symname) + 1); | ||
402 | if (res) { | ||
403 | inode->i_nlink = 0; | ||
404 | hfsplus_delete_inode(inode); | ||
405 | iput(inode); | ||
406 | return res; | ||
407 | } | ||
408 | |||
409 | mark_inode_dirty(inode); | ||
410 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); | ||
411 | |||
412 | if (!res) { | ||
413 | hfsplus_instantiate(dentry, inode, inode->i_ino); | ||
414 | mark_inode_dirty(inode); | ||
415 | } | ||
416 | |||
417 | return res; | ||
418 | } | ||
419 | |||
420 | static int hfsplus_mknod(struct inode *dir, struct dentry *dentry, | ||
421 | int mode, dev_t rdev) | ||
422 | { | ||
423 | struct super_block *sb; | ||
424 | struct inode *inode; | ||
425 | int res; | ||
426 | |||
427 | sb = dir->i_sb; | ||
428 | inode = hfsplus_new_inode(sb, mode); | ||
429 | if (!inode) | ||
430 | return -ENOSPC; | ||
431 | |||
432 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); | ||
433 | if (res) { | ||
434 | inode->i_nlink = 0; | ||
435 | hfsplus_delete_inode(inode); | ||
436 | iput(inode); | ||
437 | return res; | ||
438 | } | ||
439 | init_special_inode(inode, mode, rdev); | ||
440 | hfsplus_instantiate(dentry, inode, inode->i_ino); | ||
441 | mark_inode_dirty(inode); | ||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, | ||
447 | struct inode *new_dir, struct dentry *new_dentry) | ||
448 | { | ||
449 | int res; | ||
450 | |||
451 | /* Unlink destination if it already exists */ | ||
452 | if (new_dentry->d_inode) { | ||
453 | res = hfsplus_unlink(new_dir, new_dentry); | ||
454 | if (res) | ||
455 | return res; | ||
456 | } | ||
457 | |||
458 | res = hfsplus_rename_cat((u32)(unsigned long)old_dentry->d_fsdata, | ||
459 | old_dir, &old_dentry->d_name, | ||
460 | new_dir, &new_dentry->d_name); | ||
461 | if (!res) | ||
462 | new_dentry->d_fsdata = old_dentry->d_fsdata; | ||
463 | return res; | ||
464 | } | ||
465 | |||
466 | struct inode_operations hfsplus_dir_inode_operations = { | ||
467 | .lookup = hfsplus_lookup, | ||
468 | .create = hfsplus_create, | ||
469 | .link = hfsplus_link, | ||
470 | .unlink = hfsplus_unlink, | ||
471 | .mkdir = hfsplus_mkdir, | ||
472 | .rmdir = hfsplus_rmdir, | ||
473 | .symlink = hfsplus_symlink, | ||
474 | .mknod = hfsplus_mknod, | ||
475 | .rename = hfsplus_rename, | ||
476 | }; | ||
477 | |||
478 | struct file_operations hfsplus_dir_operations = { | ||
479 | .read = generic_read_dir, | ||
480 | .readdir = hfsplus_readdir, | ||
481 | .ioctl = hfsplus_ioctl, | ||
482 | .llseek = generic_file_llseek, | ||
483 | .release = hfsplus_dir_release, | ||
484 | }; | ||
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c new file mode 100644 index 000000000000..376498cc64fd --- /dev/null +++ b/fs/hfsplus/extents.c | |||
@@ -0,0 +1,505 @@ | |||
1 | /* | ||
2 | * linux/fs/hfsplus/extents.c | ||
3 | * | ||
4 | * Copyright (C) 2001 | ||
5 | * Brad Boyer (flar@allandria.com) | ||
6 | * (C) 2003 Ardis Technologies <roman@ardistech.com> | ||
7 | * | ||
8 | * Handling of Extents both in catalog and extents overflow trees | ||
9 | */ | ||
10 | |||
11 | #include <linux/errno.h> | ||
12 | #include <linux/fs.h> | ||
13 | #include <linux/pagemap.h> | ||
14 | #include <linux/version.h> | ||
15 | |||
16 | #include "hfsplus_fs.h" | ||
17 | #include "hfsplus_raw.h" | ||
18 | |||
19 | /* Compare two extents keys, returns 0 on same, pos/neg for difference */ | ||
20 | int hfsplus_ext_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2) | ||
21 | { | ||
22 | __be32 k1id, k2id; | ||
23 | __be32 k1s, k2s; | ||
24 | |||
25 | k1id = k1->ext.cnid; | ||
26 | k2id = k2->ext.cnid; | ||
27 | if (k1id != k2id) | ||
28 | return be32_to_cpu(k1id) < be32_to_cpu(k2id) ? -1 : 1; | ||
29 | |||
30 | if (k1->ext.fork_type != k2->ext.fork_type) | ||
31 | return k1->ext.fork_type < k2->ext.fork_type ? -1 : 1; | ||
32 | |||
33 | k1s = k1->ext.start_block; | ||
34 | k2s = k2->ext.start_block; | ||
35 | if (k1s == k2s) | ||
36 | return 0; | ||
37 | return be32_to_cpu(k1s) < be32_to_cpu(k2s) ? -1 : 1; | ||
38 | } | ||
39 | |||
40 | static void hfsplus_ext_build_key(hfsplus_btree_key *key, u32 cnid, | ||
41 | u32 block, u8 type) | ||
42 | { | ||
43 | key->key_len = cpu_to_be16(HFSPLUS_EXT_KEYLEN - 2); | ||
44 | key->ext.cnid = cpu_to_be32(cnid); | ||
45 | key->ext.start_block = cpu_to_be32(block); | ||
46 | key->ext.fork_type = type; | ||
47 | key->ext.pad = 0; | ||
48 | } | ||
49 | |||
50 | static u32 hfsplus_ext_find_block(struct hfsplus_extent *ext, u32 off) | ||
51 | { | ||
52 | int i; | ||
53 | u32 count; | ||
54 | |||
55 | for (i = 0; i < 8; ext++, i++) { | ||
56 | count = be32_to_cpu(ext->block_count); | ||
57 | if (off < count) | ||
58 | return be32_to_cpu(ext->start_block) + off; | ||
59 | off -= count; | ||
60 | } | ||
61 | /* panic? */ | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int hfsplus_ext_block_count(struct hfsplus_extent *ext) | ||
66 | { | ||
67 | int i; | ||
68 | u32 count = 0; | ||
69 | |||
70 | for (i = 0; i < 8; ext++, i++) | ||
71 | count += be32_to_cpu(ext->block_count); | ||
72 | return count; | ||
73 | } | ||
74 | |||
75 | static u32 hfsplus_ext_lastblock(struct hfsplus_extent *ext) | ||
76 | { | ||
77 | int i; | ||
78 | |||
79 | ext += 7; | ||
80 | for (i = 0; i < 7; ext--, i++) | ||
81 | if (ext->block_count) | ||
82 | break; | ||
83 | return be32_to_cpu(ext->start_block) + be32_to_cpu(ext->block_count); | ||
84 | } | ||
85 | |||
86 | static void __hfsplus_ext_write_extent(struct inode *inode, struct hfs_find_data *fd) | ||
87 | { | ||
88 | int res; | ||
89 | |||
90 | hfsplus_ext_build_key(fd->search_key, inode->i_ino, HFSPLUS_I(inode).cached_start, | ||
91 | HFSPLUS_IS_RSRC(inode) ? HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA); | ||
92 | res = hfs_brec_find(fd); | ||
93 | if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_NEW) { | ||
94 | if (res != -ENOENT) | ||
95 | return; | ||
96 | hfs_brec_insert(fd, HFSPLUS_I(inode).cached_extents, sizeof(hfsplus_extent_rec)); | ||
97 | HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); | ||
98 | } else { | ||
99 | if (res) | ||
100 | return; | ||
101 | hfs_bnode_write(fd->bnode, HFSPLUS_I(inode).cached_extents, fd->entryoffset, fd->entrylength); | ||
102 | HFSPLUS_I(inode).flags &= ~HFSPLUS_FLG_EXT_DIRTY; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | void hfsplus_ext_write_extent(struct inode *inode) | ||
107 | { | ||
108 | if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_DIRTY) { | ||
109 | struct hfs_find_data fd; | ||
110 | |||
111 | hfs_find_init(HFSPLUS_SB(inode->i_sb).ext_tree, &fd); | ||
112 | __hfsplus_ext_write_extent(inode, &fd); | ||
113 | hfs_find_exit(&fd); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd, | ||
118 | struct hfsplus_extent *extent, | ||
119 | u32 cnid, u32 block, u8 type) | ||
120 | { | ||
121 | int res; | ||
122 | |||
123 | hfsplus_ext_build_key(fd->search_key, cnid, block, type); | ||
124 | fd->key->ext.cnid = 0; | ||
125 | res = hfs_brec_find(fd); | ||
126 | if (res && res != -ENOENT) | ||
127 | return res; | ||
128 | if (fd->key->ext.cnid != fd->search_key->ext.cnid || | ||
129 | fd->key->ext.fork_type != fd->search_key->ext.fork_type) | ||
130 | return -ENOENT; | ||
131 | if (fd->entrylength != sizeof(hfsplus_extent_rec)) | ||
132 | return -EIO; | ||
133 | hfs_bnode_read(fd->bnode, extent, fd->entryoffset, sizeof(hfsplus_extent_rec)); | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static inline int __hfsplus_ext_cache_extent(struct hfs_find_data *fd, struct inode *inode, u32 block) | ||
138 | { | ||
139 | int res; | ||
140 | |||
141 | if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_DIRTY) | ||
142 | __hfsplus_ext_write_extent(inode, fd); | ||
143 | |||
144 | res = __hfsplus_ext_read_extent(fd, HFSPLUS_I(inode).cached_extents, inode->i_ino, | ||
145 | block, HFSPLUS_IS_RSRC(inode) ? HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA); | ||
146 | if (!res) { | ||
147 | HFSPLUS_I(inode).cached_start = be32_to_cpu(fd->key->ext.start_block); | ||
148 | HFSPLUS_I(inode).cached_blocks = hfsplus_ext_block_count(HFSPLUS_I(inode).cached_extents); | ||
149 | } else { | ||
150 | HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).cached_blocks = 0; | ||
151 | HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); | ||
152 | } | ||
153 | return res; | ||
154 | } | ||
155 | |||
156 | static int hfsplus_ext_read_extent(struct inode *inode, u32 block) | ||
157 | { | ||
158 | struct hfs_find_data fd; | ||
159 | int res; | ||
160 | |||
161 | if (block >= HFSPLUS_I(inode).cached_start && | ||
162 | block < HFSPLUS_I(inode).cached_start + HFSPLUS_I(inode).cached_blocks) | ||
163 | return 0; | ||
164 | |||
165 | hfs_find_init(HFSPLUS_SB(inode->i_sb).ext_tree, &fd); | ||
166 | res = __hfsplus_ext_cache_extent(&fd, inode, block); | ||
167 | hfs_find_exit(&fd); | ||
168 | return res; | ||
169 | } | ||
170 | |||
171 | /* Get a block at iblock for inode, possibly allocating if create */ | ||
172 | int hfsplus_get_block(struct inode *inode, sector_t iblock, | ||
173 | struct buffer_head *bh_result, int create) | ||
174 | { | ||
175 | struct super_block *sb; | ||
176 | int res = -EIO; | ||
177 | u32 ablock, dblock, mask; | ||
178 | int shift; | ||
179 | |||
180 | sb = inode->i_sb; | ||
181 | |||
182 | /* Convert inode block to disk allocation block */ | ||
183 | shift = HFSPLUS_SB(sb).alloc_blksz_shift - sb->s_blocksize_bits; | ||
184 | ablock = iblock >> HFSPLUS_SB(sb).fs_shift; | ||
185 | |||
186 | if (iblock >= HFSPLUS_I(inode).fs_blocks) { | ||
187 | if (iblock > HFSPLUS_I(inode).fs_blocks || !create) | ||
188 | return -EIO; | ||
189 | if (ablock >= HFSPLUS_I(inode).alloc_blocks) { | ||
190 | res = hfsplus_file_extend(inode); | ||
191 | if (res) | ||
192 | return res; | ||
193 | } | ||
194 | } else | ||
195 | create = 0; | ||
196 | |||
197 | if (ablock < HFSPLUS_I(inode).first_blocks) { | ||
198 | dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).first_extents, ablock); | ||
199 | goto done; | ||
200 | } | ||
201 | |||
202 | down(&HFSPLUS_I(inode).extents_lock); | ||
203 | res = hfsplus_ext_read_extent(inode, ablock); | ||
204 | if (!res) { | ||
205 | dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).cached_extents, ablock - | ||
206 | HFSPLUS_I(inode).cached_start); | ||
207 | } else { | ||
208 | up(&HFSPLUS_I(inode).extents_lock); | ||
209 | return -EIO; | ||
210 | } | ||
211 | up(&HFSPLUS_I(inode).extents_lock); | ||
212 | |||
213 | done: | ||
214 | dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock); | ||
215 | mask = (1 << HFSPLUS_SB(sb).fs_shift) - 1; | ||
216 | map_bh(bh_result, sb, (dblock << HFSPLUS_SB(sb).fs_shift) + HFSPLUS_SB(sb).blockoffset + (iblock & mask)); | ||
217 | if (create) { | ||
218 | set_buffer_new(bh_result); | ||
219 | HFSPLUS_I(inode).phys_size += sb->s_blocksize; | ||
220 | HFSPLUS_I(inode).fs_blocks++; | ||
221 | inode_add_bytes(inode, sb->s_blocksize); | ||
222 | mark_inode_dirty(inode); | ||
223 | } | ||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static void hfsplus_dump_extent(struct hfsplus_extent *extent) | ||
228 | { | ||
229 | int i; | ||
230 | |||
231 | dprint(DBG_EXTENT, " "); | ||
232 | for (i = 0; i < 8; i++) | ||
233 | dprint(DBG_EXTENT, " %u:%u", be32_to_cpu(extent[i].start_block), | ||
234 | be32_to_cpu(extent[i].block_count)); | ||
235 | dprint(DBG_EXTENT, "\n"); | ||
236 | } | ||
237 | |||
238 | static int hfsplus_add_extent(struct hfsplus_extent *extent, u32 offset, | ||
239 | u32 alloc_block, u32 block_count) | ||
240 | { | ||
241 | u32 count, start; | ||
242 | int i; | ||
243 | |||
244 | hfsplus_dump_extent(extent); | ||
245 | for (i = 0; i < 8; extent++, i++) { | ||
246 | count = be32_to_cpu(extent->block_count); | ||
247 | if (offset == count) { | ||
248 | start = be32_to_cpu(extent->start_block); | ||
249 | if (alloc_block != start + count) { | ||
250 | if (++i >= 8) | ||
251 | return -ENOSPC; | ||
252 | extent++; | ||
253 | extent->start_block = cpu_to_be32(alloc_block); | ||
254 | } else | ||
255 | block_count += count; | ||
256 | extent->block_count = cpu_to_be32(block_count); | ||
257 | return 0; | ||
258 | } else if (offset < count) | ||
259 | break; | ||
260 | offset -= count; | ||
261 | } | ||
262 | /* panic? */ | ||
263 | return -EIO; | ||
264 | } | ||
265 | |||
266 | static int hfsplus_free_extents(struct super_block *sb, | ||
267 | struct hfsplus_extent *extent, | ||
268 | u32 offset, u32 block_nr) | ||
269 | { | ||
270 | u32 count, start; | ||
271 | int i; | ||
272 | |||
273 | hfsplus_dump_extent(extent); | ||
274 | for (i = 0; i < 8; extent++, i++) { | ||
275 | count = be32_to_cpu(extent->block_count); | ||
276 | if (offset == count) | ||
277 | goto found; | ||
278 | else if (offset < count) | ||
279 | break; | ||
280 | offset -= count; | ||
281 | } | ||
282 | /* panic? */ | ||
283 | return -EIO; | ||
284 | found: | ||
285 | for (;;) { | ||
286 | start = be32_to_cpu(extent->start_block); | ||
287 | if (count <= block_nr) { | ||
288 | hfsplus_block_free(sb, start, count); | ||
289 | extent->block_count = 0; | ||
290 | extent->start_block = 0; | ||
291 | block_nr -= count; | ||
292 | } else { | ||
293 | count -= block_nr; | ||
294 | hfsplus_block_free(sb, start + count, block_nr); | ||
295 | extent->block_count = cpu_to_be32(count); | ||
296 | block_nr = 0; | ||
297 | } | ||
298 | if (!block_nr || !i) | ||
299 | return 0; | ||
300 | i--; | ||
301 | extent--; | ||
302 | count = be32_to_cpu(extent->block_count); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | int hfsplus_free_fork(struct super_block *sb, u32 cnid, struct hfsplus_fork_raw *fork, int type) | ||
307 | { | ||
308 | struct hfs_find_data fd; | ||
309 | hfsplus_extent_rec ext_entry; | ||
310 | u32 total_blocks, blocks, start; | ||
311 | int res, i; | ||
312 | |||
313 | total_blocks = be32_to_cpu(fork->total_blocks); | ||
314 | if (!total_blocks) | ||
315 | return 0; | ||
316 | |||
317 | blocks = 0; | ||
318 | for (i = 0; i < 8; i++) | ||
319 | blocks += be32_to_cpu(fork->extents[i].block_count); | ||
320 | |||
321 | res = hfsplus_free_extents(sb, fork->extents, blocks, blocks); | ||
322 | if (res) | ||
323 | return res; | ||
324 | if (total_blocks == blocks) | ||
325 | return 0; | ||
326 | |||
327 | hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd); | ||
328 | do { | ||
329 | res = __hfsplus_ext_read_extent(&fd, ext_entry, cnid, | ||
330 | total_blocks, type); | ||
331 | if (res) | ||
332 | break; | ||
333 | start = be32_to_cpu(fd.key->ext.start_block); | ||
334 | hfsplus_free_extents(sb, ext_entry, | ||
335 | total_blocks - start, | ||
336 | total_blocks); | ||
337 | hfs_brec_remove(&fd); | ||
338 | total_blocks = start; | ||
339 | } while (total_blocks > blocks); | ||
340 | hfs_find_exit(&fd); | ||
341 | |||
342 | return res; | ||
343 | } | ||
344 | |||
345 | int hfsplus_file_extend(struct inode *inode) | ||
346 | { | ||
347 | struct super_block *sb = inode->i_sb; | ||
348 | u32 start, len, goal; | ||
349 | int res; | ||
350 | |||
351 | if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) { | ||
352 | // extend alloc file | ||
353 | printk("extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8, | ||
354 | HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks); | ||
355 | return -ENOSPC; | ||
356 | //BUG(); | ||
357 | } | ||
358 | |||
359 | down(&HFSPLUS_I(inode).extents_lock); | ||
360 | if (HFSPLUS_I(inode).alloc_blocks == HFSPLUS_I(inode).first_blocks) | ||
361 | goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).first_extents); | ||
362 | else { | ||
363 | res = hfsplus_ext_read_extent(inode, HFSPLUS_I(inode).alloc_blocks); | ||
364 | if (res) | ||
365 | goto out; | ||
366 | goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).cached_extents); | ||
367 | } | ||
368 | |||
369 | len = HFSPLUS_I(inode).clump_blocks; | ||
370 | start = hfsplus_block_allocate(sb, HFSPLUS_SB(sb).total_blocks, goal, &len); | ||
371 | if (start >= HFSPLUS_SB(sb).total_blocks) { | ||
372 | start = hfsplus_block_allocate(sb, goal, 0, &len); | ||
373 | if (start >= goal) { | ||
374 | res = -ENOSPC; | ||
375 | goto out; | ||
376 | } | ||
377 | } | ||
378 | |||
379 | dprint(DBG_EXTENT, "extend %lu: %u,%u\n", inode->i_ino, start, len); | ||
380 | if (HFSPLUS_I(inode).alloc_blocks <= HFSPLUS_I(inode).first_blocks) { | ||
381 | if (!HFSPLUS_I(inode).first_blocks) { | ||
382 | dprint(DBG_EXTENT, "first extents\n"); | ||
383 | /* no extents yet */ | ||
384 | HFSPLUS_I(inode).first_extents[0].start_block = cpu_to_be32(start); | ||
385 | HFSPLUS_I(inode).first_extents[0].block_count = cpu_to_be32(len); | ||
386 | res = 0; | ||
387 | } else { | ||
388 | /* try to append to extents in inode */ | ||
389 | res = hfsplus_add_extent(HFSPLUS_I(inode).first_extents, | ||
390 | HFSPLUS_I(inode).alloc_blocks, | ||
391 | start, len); | ||
392 | if (res == -ENOSPC) | ||
393 | goto insert_extent; | ||
394 | } | ||
395 | if (!res) { | ||
396 | hfsplus_dump_extent(HFSPLUS_I(inode).first_extents); | ||
397 | HFSPLUS_I(inode).first_blocks += len; | ||
398 | } | ||
399 | } else { | ||
400 | res = hfsplus_add_extent(HFSPLUS_I(inode).cached_extents, | ||
401 | HFSPLUS_I(inode).alloc_blocks - | ||
402 | HFSPLUS_I(inode).cached_start, | ||
403 | start, len); | ||
404 | if (!res) { | ||
405 | hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents); | ||
406 | HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY; | ||
407 | HFSPLUS_I(inode).cached_blocks += len; | ||
408 | } else if (res == -ENOSPC) | ||
409 | goto insert_extent; | ||
410 | } | ||
411 | out: | ||
412 | up(&HFSPLUS_I(inode).extents_lock); | ||
413 | if (!res) { | ||
414 | HFSPLUS_I(inode).alloc_blocks += len; | ||
415 | mark_inode_dirty(inode); | ||
416 | } | ||
417 | return res; | ||
418 | |||
419 | insert_extent: | ||
420 | dprint(DBG_EXTENT, "insert new extent\n"); | ||
421 | hfsplus_ext_write_extent(inode); | ||
422 | |||
423 | memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec)); | ||
424 | HFSPLUS_I(inode).cached_extents[0].start_block = cpu_to_be32(start); | ||
425 | HFSPLUS_I(inode).cached_extents[0].block_count = cpu_to_be32(len); | ||
426 | hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents); | ||
427 | HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW; | ||
428 | HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).alloc_blocks; | ||
429 | HFSPLUS_I(inode).cached_blocks = len; | ||
430 | |||
431 | res = 0; | ||
432 | goto out; | ||
433 | } | ||
434 | |||
435 | void hfsplus_file_truncate(struct inode *inode) | ||
436 | { | ||
437 | struct super_block *sb = inode->i_sb; | ||
438 | struct hfs_find_data fd; | ||
439 | u32 alloc_cnt, blk_cnt, start; | ||
440 | int res; | ||
441 | |||
442 | dprint(DBG_INODE, "truncate: %lu, %Lu -> %Lu\n", inode->i_ino, | ||
443 | (long long)HFSPLUS_I(inode).phys_size, inode->i_size); | ||
444 | if (inode->i_size > HFSPLUS_I(inode).phys_size) { | ||
445 | struct address_space *mapping = inode->i_mapping; | ||
446 | struct page *page; | ||
447 | u32 size = inode->i_size - 1; | ||
448 | int res; | ||
449 | |||
450 | page = grab_cache_page(mapping, size >> PAGE_CACHE_SHIFT); | ||
451 | if (!page) | ||
452 | return; | ||
453 | size &= PAGE_CACHE_SIZE - 1; | ||
454 | size++; | ||
455 | res = mapping->a_ops->prepare_write(NULL, page, size, size); | ||
456 | if (!res) | ||
457 | res = mapping->a_ops->commit_write(NULL, page, size, size); | ||
458 | if (res) | ||
459 | inode->i_size = HFSPLUS_I(inode).phys_size; | ||
460 | unlock_page(page); | ||
461 | page_cache_release(page); | ||
462 | mark_inode_dirty(inode); | ||
463 | return; | ||
464 | } | ||
465 | blk_cnt = (inode->i_size + HFSPLUS_SB(sb).alloc_blksz - 1) >> HFSPLUS_SB(sb).alloc_blksz_shift; | ||
466 | alloc_cnt = HFSPLUS_I(inode).alloc_blocks; | ||
467 | if (blk_cnt == alloc_cnt) | ||
468 | goto out; | ||
469 | |||
470 | down(&HFSPLUS_I(inode).extents_lock); | ||
471 | hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd); | ||
472 | while (1) { | ||
473 | if (alloc_cnt == HFSPLUS_I(inode).first_blocks) { | ||
474 | hfsplus_free_extents(sb, HFSPLUS_I(inode).first_extents, | ||
475 | alloc_cnt, alloc_cnt - blk_cnt); | ||
476 | hfsplus_dump_extent(HFSPLUS_I(inode).first_extents); | ||
477 | HFSPLUS_I(inode).first_blocks = blk_cnt; | ||
478 | break; | ||
479 | } | ||
480 | res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt); | ||
481 | if (res) | ||
482 | break; | ||
483 | start = HFSPLUS_I(inode).cached_start; | ||
484 | hfsplus_free_extents(sb, HFSPLUS_I(inode).cached_extents, | ||
485 | alloc_cnt - start, alloc_cnt - blk_cnt); | ||
486 | hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents); | ||
487 | if (blk_cnt > start) { | ||
488 | HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY; | ||
489 | break; | ||
490 | } | ||
491 | alloc_cnt = start; | ||
492 | HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).cached_blocks = 0; | ||
493 | HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); | ||
494 | hfs_brec_remove(&fd); | ||
495 | } | ||
496 | hfs_find_exit(&fd); | ||
497 | up(&HFSPLUS_I(inode).extents_lock); | ||
498 | |||
499 | HFSPLUS_I(inode).alloc_blocks = blk_cnt; | ||
500 | out: | ||
501 | HFSPLUS_I(inode).phys_size = inode->i_size; | ||
502 | HFSPLUS_I(inode).fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; | ||
503 | inode_set_bytes(inode, HFSPLUS_I(inode).fs_blocks << sb->s_blocksize_bits); | ||
504 | mark_inode_dirty(inode); | ||
505 | } | ||
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h new file mode 100644 index 000000000000..533094a570df --- /dev/null +++ b/fs/hfsplus/hfsplus_fs.h | |||
@@ -0,0 +1,414 @@ | |||
1 | /* | ||
2 | * linux/include/linux/hfsplus_fs.h | ||
3 | * | ||
4 | * Copyright (C) 1999 | ||
5 | * Brad Boyer (flar@pants.nu) | ||
6 | * (C) 2003 Ardis Technologies <roman@ardistech.com> | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #ifndef _LINUX_HFSPLUS_FS_H | ||
11 | #define _LINUX_HFSPLUS_FS_H | ||
12 | |||
13 | #include <linux/fs.h> | ||
14 | #include <linux/version.h> | ||
15 | #include <linux/buffer_head.h> | ||
16 | #include "hfsplus_raw.h" | ||
17 | |||
18 | #define DBG_BNODE_REFS 0x00000001 | ||
19 | #define DBG_BNODE_MOD 0x00000002 | ||
20 | #define DBG_CAT_MOD 0x00000004 | ||
21 | #define DBG_INODE 0x00000008 | ||
22 | #define DBG_SUPER 0x00000010 | ||
23 | #define DBG_EXTENT 0x00000020 | ||
24 | #define DBG_BITMAP 0x00000040 | ||
25 | |||
26 | //#define DBG_MASK (DBG_EXTENT|DBG_INODE|DBG_BNODE_MOD) | ||
27 | //#define DBG_MASK (DBG_BNODE_MOD|DBG_CAT_MOD|DBG_INODE) | ||
28 | //#define DBG_MASK (DBG_CAT_MOD|DBG_BNODE_REFS|DBG_INODE|DBG_EXTENT) | ||
29 | #define DBG_MASK (0) | ||
30 | |||
31 | #define dprint(flg, fmt, args...) \ | ||
32 | if (flg & DBG_MASK) printk(fmt , ## args) | ||
33 | |||
34 | /* Runtime config options */ | ||
35 | #define HFSPLUS_DEF_CR_TYPE 0x3F3F3F3F /* '????' */ | ||
36 | |||
37 | #define HFSPLUS_TYPE_DATA 0x00 | ||
38 | #define HFSPLUS_TYPE_RSRC 0xFF | ||
39 | |||
40 | typedef int (*btree_keycmp)(hfsplus_btree_key *, hfsplus_btree_key *); | ||
41 | |||
42 | #define NODE_HASH_SIZE 256 | ||
43 | |||
44 | /* An HFS+ BTree held in memory */ | ||
45 | struct hfs_btree { | ||
46 | struct super_block *sb; | ||
47 | struct inode *inode; | ||
48 | btree_keycmp keycmp; | ||
49 | |||
50 | u32 cnid; | ||
51 | u32 root; | ||
52 | u32 leaf_count; | ||
53 | u32 leaf_head; | ||
54 | u32 leaf_tail; | ||
55 | u32 node_count; | ||
56 | u32 free_nodes; | ||
57 | u32 attributes; | ||
58 | |||
59 | unsigned int node_size; | ||
60 | unsigned int node_size_shift; | ||
61 | unsigned int max_key_len; | ||
62 | unsigned int depth; | ||
63 | |||
64 | //unsigned int map1_size, map_size; | ||
65 | struct semaphore tree_lock; | ||
66 | |||
67 | unsigned int pages_per_bnode; | ||
68 | spinlock_t hash_lock; | ||
69 | struct hfs_bnode *node_hash[NODE_HASH_SIZE]; | ||
70 | int node_hash_cnt; | ||
71 | }; | ||
72 | |||
73 | struct page; | ||
74 | |||
75 | /* An HFS+ BTree node in memory */ | ||
76 | struct hfs_bnode { | ||
77 | struct hfs_btree *tree; | ||
78 | |||
79 | u32 prev; | ||
80 | u32 this; | ||
81 | u32 next; | ||
82 | u32 parent; | ||
83 | |||
84 | u16 num_recs; | ||
85 | u8 type; | ||
86 | u8 height; | ||
87 | |||
88 | struct hfs_bnode *next_hash; | ||
89 | unsigned long flags; | ||
90 | wait_queue_head_t lock_wq; | ||
91 | atomic_t refcnt; | ||
92 | unsigned int page_offset; | ||
93 | struct page *page[0]; | ||
94 | }; | ||
95 | |||
96 | #define HFS_BNODE_LOCK 0 | ||
97 | #define HFS_BNODE_ERROR 1 | ||
98 | #define HFS_BNODE_NEW 2 | ||
99 | #define HFS_BNODE_DIRTY 3 | ||
100 | #define HFS_BNODE_DELETED 4 | ||
101 | |||
102 | /* | ||
103 | * HFS+ superblock info (built from Volume Header on disk) | ||
104 | */ | ||
105 | |||
106 | struct hfsplus_vh; | ||
107 | struct hfs_btree; | ||
108 | |||
109 | struct hfsplus_sb_info { | ||
110 | struct buffer_head *s_vhbh; | ||
111 | struct hfsplus_vh *s_vhdr; | ||
112 | struct hfs_btree *ext_tree; | ||
113 | struct hfs_btree *cat_tree; | ||
114 | struct hfs_btree *attr_tree; | ||
115 | struct inode *alloc_file; | ||
116 | struct inode *hidden_dir; | ||
117 | struct nls_table *nls; | ||
118 | |||
119 | /* Runtime variables */ | ||
120 | u32 blockoffset; | ||
121 | u32 sect_count; | ||
122 | int fs_shift; | ||
123 | |||
124 | /* Stuff in host order from Vol Header */ | ||
125 | u32 alloc_blksz; | ||
126 | int alloc_blksz_shift; | ||
127 | u32 total_blocks; | ||
128 | u32 free_blocks; | ||
129 | u32 next_alloc; | ||
130 | u32 next_cnid; | ||
131 | u32 file_count; | ||
132 | u32 folder_count; | ||
133 | u32 data_clump_blocks, rsrc_clump_blocks; | ||
134 | |||
135 | /* Config options */ | ||
136 | u32 creator; | ||
137 | u32 type; | ||
138 | |||
139 | umode_t umask; | ||
140 | uid_t uid; | ||
141 | gid_t gid; | ||
142 | |||
143 | int part, session; | ||
144 | |||
145 | unsigned long flags; | ||
146 | |||
147 | atomic_t inode_cnt; | ||
148 | u32 last_inode_cnt; | ||
149 | |||
150 | struct hlist_head rsrc_inodes; | ||
151 | }; | ||
152 | |||
153 | #define HFSPLUS_SB_WRITEBACKUP 0x0001 | ||
154 | #define HFSPLUS_SB_NODECOMPOSE 0x0002 | ||
155 | |||
156 | |||
157 | struct hfsplus_inode_info { | ||
158 | struct semaphore extents_lock; | ||
159 | u32 clump_blocks, alloc_blocks; | ||
160 | sector_t fs_blocks; | ||
161 | /* Allocation extents from catalog record or volume header */ | ||
162 | hfsplus_extent_rec first_extents; | ||
163 | u32 first_blocks; | ||
164 | hfsplus_extent_rec cached_extents; | ||
165 | u32 cached_start, cached_blocks; | ||
166 | atomic_t opencnt; | ||
167 | |||
168 | struct inode *rsrc_inode; | ||
169 | unsigned long flags; | ||
170 | |||
171 | /* Device number in hfsplus_permissions in catalog */ | ||
172 | u32 dev; | ||
173 | /* BSD system and user file flags */ | ||
174 | u8 rootflags; | ||
175 | u8 userflags; | ||
176 | |||
177 | struct list_head open_dir_list; | ||
178 | loff_t phys_size; | ||
179 | struct inode vfs_inode; | ||
180 | }; | ||
181 | |||
182 | #define HFSPLUS_FLG_RSRC 0x0001 | ||
183 | #define HFSPLUS_FLG_EXT_DIRTY 0x0002 | ||
184 | #define HFSPLUS_FLG_EXT_NEW 0x0004 | ||
185 | |||
186 | #define HFSPLUS_IS_DATA(inode) (!(HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC)) | ||
187 | #define HFSPLUS_IS_RSRC(inode) (HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC) | ||
188 | |||
189 | struct hfs_find_data { | ||
190 | /* filled by caller */ | ||
191 | hfsplus_btree_key *search_key; | ||
192 | hfsplus_btree_key *key; | ||
193 | /* filled by find */ | ||
194 | struct hfs_btree *tree; | ||
195 | struct hfs_bnode *bnode; | ||
196 | /* filled by findrec */ | ||
197 | int record; | ||
198 | int keyoffset, keylength; | ||
199 | int entryoffset, entrylength; | ||
200 | }; | ||
201 | |||
202 | struct hfsplus_readdir_data { | ||
203 | struct list_head list; | ||
204 | struct file *file; | ||
205 | struct hfsplus_cat_key key; | ||
206 | }; | ||
207 | |||
208 | #define hfs_btree_open hfsplus_btree_open | ||
209 | #define hfs_btree_close hfsplus_btree_close | ||
210 | #define hfs_btree_write hfsplus_btree_write | ||
211 | #define hfs_bmap_alloc hfsplus_bmap_alloc | ||
212 | #define hfs_bmap_free hfsplus_bmap_free | ||
213 | #define hfs_bnode_read hfsplus_bnode_read | ||
214 | #define hfs_bnode_read_u16 hfsplus_bnode_read_u16 | ||
215 | #define hfs_bnode_read_u8 hfsplus_bnode_read_u8 | ||
216 | #define hfs_bnode_read_key hfsplus_bnode_read_key | ||
217 | #define hfs_bnode_write hfsplus_bnode_write | ||
218 | #define hfs_bnode_write_u16 hfsplus_bnode_write_u16 | ||
219 | #define hfs_bnode_clear hfsplus_bnode_clear | ||
220 | #define hfs_bnode_copy hfsplus_bnode_copy | ||
221 | #define hfs_bnode_move hfsplus_bnode_move | ||
222 | #define hfs_bnode_dump hfsplus_bnode_dump | ||
223 | #define hfs_bnode_unlink hfsplus_bnode_unlink | ||
224 | #define hfs_bnode_findhash hfsplus_bnode_findhash | ||
225 | #define hfs_bnode_find hfsplus_bnode_find | ||
226 | #define hfs_bnode_unhash hfsplus_bnode_unhash | ||
227 | #define hfs_bnode_free hfsplus_bnode_free | ||
228 | #define hfs_bnode_create hfsplus_bnode_create | ||
229 | #define hfs_bnode_get hfsplus_bnode_get | ||
230 | #define hfs_bnode_put hfsplus_bnode_put | ||
231 | #define hfs_brec_lenoff hfsplus_brec_lenoff | ||
232 | #define hfs_brec_keylen hfsplus_brec_keylen | ||
233 | #define hfs_brec_insert hfsplus_brec_insert | ||
234 | #define hfs_brec_remove hfsplus_brec_remove | ||
235 | #define hfs_find_init hfsplus_find_init | ||
236 | #define hfs_find_exit hfsplus_find_exit | ||
237 | #define __hfs_brec_find __hplusfs_brec_find | ||
238 | #define hfs_brec_find hfsplus_brec_find | ||
239 | #define hfs_brec_read hfsplus_brec_read | ||
240 | #define hfs_brec_goto hfsplus_brec_goto | ||
241 | #define hfs_part_find hfsplus_part_find | ||
242 | |||
243 | /* | ||
244 | * definitions for ext2 flag ioctls (linux really needs a generic | ||
245 | * interface for this). | ||
246 | */ | ||
247 | |||
248 | /* ext2 ioctls (EXT2_IOC_GETFLAGS and EXT2_IOC_SETFLAGS) to support | ||
249 | * chattr/lsattr */ | ||
250 | #define HFSPLUS_IOC_EXT2_GETFLAGS _IOR('f', 1, long) | ||
251 | #define HFSPLUS_IOC_EXT2_SETFLAGS _IOW('f', 2, long) | ||
252 | |||
253 | #define EXT2_FLAG_IMMUTABLE 0x00000010 /* Immutable file */ | ||
254 | #define EXT2_FLAG_APPEND 0x00000020 /* writes to file may only append */ | ||
255 | #define EXT2_FLAG_NODUMP 0x00000040 /* do not dump file */ | ||
256 | |||
257 | |||
258 | /* | ||
259 | * Functions in any *.c used in other files | ||
260 | */ | ||
261 | |||
262 | /* bitmap.c */ | ||
263 | int hfsplus_block_allocate(struct super_block *, u32, u32, u32 *); | ||
264 | int hfsplus_block_free(struct super_block *, u32, u32); | ||
265 | |||
266 | /* btree.c */ | ||
267 | struct hfs_btree *hfs_btree_open(struct super_block *, u32); | ||
268 | void hfs_btree_close(struct hfs_btree *); | ||
269 | void hfs_btree_write(struct hfs_btree *); | ||
270 | struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *); | ||
271 | void hfs_bmap_free(struct hfs_bnode *); | ||
272 | |||
273 | /* bnode.c */ | ||
274 | void hfs_bnode_read(struct hfs_bnode *, void *, int, int); | ||
275 | u16 hfs_bnode_read_u16(struct hfs_bnode *, int); | ||
276 | u8 hfs_bnode_read_u8(struct hfs_bnode *, int); | ||
277 | void hfs_bnode_read_key(struct hfs_bnode *, void *, int); | ||
278 | void hfs_bnode_write(struct hfs_bnode *, void *, int, int); | ||
279 | void hfs_bnode_write_u16(struct hfs_bnode *, int, u16); | ||
280 | void hfs_bnode_clear(struct hfs_bnode *, int, int); | ||
281 | void hfs_bnode_copy(struct hfs_bnode *, int, | ||
282 | struct hfs_bnode *, int, int); | ||
283 | void hfs_bnode_move(struct hfs_bnode *, int, int, int); | ||
284 | void hfs_bnode_dump(struct hfs_bnode *); | ||
285 | void hfs_bnode_unlink(struct hfs_bnode *); | ||
286 | struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *, u32); | ||
287 | struct hfs_bnode *hfs_bnode_find(struct hfs_btree *, u32); | ||
288 | void hfs_bnode_unhash(struct hfs_bnode *); | ||
289 | void hfs_bnode_free(struct hfs_bnode *); | ||
290 | struct hfs_bnode *hfs_bnode_create(struct hfs_btree *, u32); | ||
291 | void hfs_bnode_get(struct hfs_bnode *); | ||
292 | void hfs_bnode_put(struct hfs_bnode *); | ||
293 | |||
294 | /* brec.c */ | ||
295 | u16 hfs_brec_lenoff(struct hfs_bnode *, u16, u16 *); | ||
296 | u16 hfs_brec_keylen(struct hfs_bnode *, u16); | ||
297 | int hfs_brec_insert(struct hfs_find_data *, void *, int); | ||
298 | int hfs_brec_remove(struct hfs_find_data *); | ||
299 | |||
300 | /* bfind.c */ | ||
301 | int hfs_find_init(struct hfs_btree *, struct hfs_find_data *); | ||
302 | void hfs_find_exit(struct hfs_find_data *); | ||
303 | int __hfs_brec_find(struct hfs_bnode *, struct hfs_find_data *); | ||
304 | int hfs_brec_find(struct hfs_find_data *); | ||
305 | int hfs_brec_read(struct hfs_find_data *, void *, int); | ||
306 | int hfs_brec_goto(struct hfs_find_data *, int); | ||
307 | |||
308 | /* catalog.c */ | ||
309 | int hfsplus_cat_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *); | ||
310 | void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *, u32, struct qstr *); | ||
311 | int hfsplus_find_cat(struct super_block *, u32, struct hfs_find_data *); | ||
312 | int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *); | ||
313 | int hfsplus_delete_cat(u32, struct inode *, struct qstr *); | ||
314 | int hfsplus_rename_cat(u32, struct inode *, struct qstr *, | ||
315 | struct inode *, struct qstr *); | ||
316 | |||
317 | /* extents.c */ | ||
318 | int hfsplus_ext_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *); | ||
319 | void hfsplus_ext_write_extent(struct inode *); | ||
320 | int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int); | ||
321 | int hfsplus_free_fork(struct super_block *, u32, struct hfsplus_fork_raw *, int); | ||
322 | int hfsplus_file_extend(struct inode *); | ||
323 | void hfsplus_file_truncate(struct inode *); | ||
324 | |||
325 | /* inode.c */ | ||
326 | extern struct address_space_operations hfsplus_aops; | ||
327 | extern struct address_space_operations hfsplus_btree_aops; | ||
328 | |||
329 | void hfsplus_inode_read_fork(struct inode *, struct hfsplus_fork_raw *); | ||
330 | void hfsplus_inode_write_fork(struct inode *, struct hfsplus_fork_raw *); | ||
331 | int hfsplus_cat_read_inode(struct inode *, struct hfs_find_data *); | ||
332 | int hfsplus_cat_write_inode(struct inode *); | ||
333 | struct inode *hfsplus_new_inode(struct super_block *, int); | ||
334 | void hfsplus_delete_inode(struct inode *); | ||
335 | |||
336 | /* ioctl.c */ | ||
337 | int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | ||
338 | unsigned long arg); | ||
339 | int hfsplus_setxattr(struct dentry *dentry, const char *name, | ||
340 | const void *value, size_t size, int flags); | ||
341 | ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, | ||
342 | void *value, size_t size); | ||
343 | ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size); | ||
344 | |||
345 | /* options.c */ | ||
346 | int parse_options(char *, struct hfsplus_sb_info *); | ||
347 | void fill_defaults(struct hfsplus_sb_info *); | ||
348 | |||
349 | /* tables.c */ | ||
350 | extern u16 hfsplus_case_fold_table[]; | ||
351 | extern u16 hfsplus_decompose_table[]; | ||
352 | extern u16 hfsplus_compose_table[]; | ||
353 | |||
354 | /* unicode.c */ | ||
355 | int hfsplus_unistrcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *); | ||
356 | int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *); | ||
357 | int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int); | ||
358 | |||
359 | /* wrapper.c */ | ||
360 | int hfsplus_read_wrapper(struct super_block *); | ||
361 | |||
362 | int hfs_part_find(struct super_block *, sector_t *, sector_t *); | ||
363 | |||
364 | /* access macros */ | ||
365 | /* | ||
366 | static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb) | ||
367 | { | ||
368 | return sb->s_fs_info; | ||
369 | } | ||
370 | static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode) | ||
371 | { | ||
372 | return list_entry(inode, struct hfsplus_inode_info, vfs_inode); | ||
373 | } | ||
374 | */ | ||
375 | #define HFSPLUS_SB(super) (*(struct hfsplus_sb_info *)(super)->s_fs_info) | ||
376 | #define HFSPLUS_I(inode) (*list_entry(inode, struct hfsplus_inode_info, vfs_inode)) | ||
377 | |||
378 | #if 1 | ||
379 | #define hfsplus_kmap(p) ({ struct page *__p = (p); kmap(__p); }) | ||
380 | #define hfsplus_kunmap(p) ({ struct page *__p = (p); kunmap(__p); __p; }) | ||
381 | #else | ||
382 | #define hfsplus_kmap(p) kmap(p) | ||
383 | #define hfsplus_kunmap(p) kunmap(p) | ||
384 | #endif | ||
385 | |||
386 | #define sb_bread512(sb, sec, data) ({ \ | ||
387 | struct buffer_head *__bh; \ | ||
388 | sector_t __block; \ | ||
389 | loff_t __start; \ | ||
390 | int __offset; \ | ||
391 | \ | ||
392 | __start = (loff_t)(sec) << HFSPLUS_SECTOR_SHIFT;\ | ||
393 | __block = __start >> (sb)->s_blocksize_bits; \ | ||
394 | __offset = __start & ((sb)->s_blocksize - 1); \ | ||
395 | __bh = sb_bread((sb), __block); \ | ||
396 | if (likely(__bh != NULL)) \ | ||
397 | data = (void *)(__bh->b_data + __offset);\ | ||
398 | else \ | ||
399 | data = NULL; \ | ||
400 | __bh; \ | ||
401 | }) | ||
402 | |||
403 | /* time macros */ | ||
404 | #define __hfsp_mt2ut(t) (be32_to_cpu(t) - 2082844800U) | ||
405 | #define __hfsp_ut2mt(t) (cpu_to_be32(t + 2082844800U)) | ||
406 | |||
407 | /* compatibility */ | ||
408 | #define hfsp_mt2ut(t) (struct timespec){ .tv_sec = __hfsp_mt2ut(t) } | ||
409 | #define hfsp_ut2mt(t) __hfsp_ut2mt((t).tv_sec) | ||
410 | #define hfsp_now2mt() __hfsp_ut2mt(get_seconds()) | ||
411 | |||
412 | #define kdev_t_to_nr(x) (x) | ||
413 | |||
414 | #endif | ||
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h new file mode 100644 index 000000000000..5bad37cfdb29 --- /dev/null +++ b/fs/hfsplus/hfsplus_raw.h | |||
@@ -0,0 +1,326 @@ | |||
1 | /* | ||
2 | * linux/include/linux/hfsplus_raw.h | ||
3 | * | ||
4 | * Copyright (C) 1999 | ||
5 | * Brad Boyer (flar@pants.nu) | ||
6 | * (C) 2003 Ardis Technologies <roman@ardistech.com> | ||
7 | * | ||
8 | * Format of structures on disk | ||
9 | * Information taken from Apple Technote #1150 (HFS Plus Volume Format) | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #ifndef _LINUX_HFSPLUS_RAW_H | ||
14 | #define _LINUX_HFSPLUS_RAW_H | ||
15 | |||
16 | #include <linux/types.h> | ||
17 | |||
18 | #define __packed __attribute__ ((packed)) | ||
19 | |||
20 | /* Some constants */ | ||
21 | #define HFSPLUS_SECTOR_SIZE 512 | ||
22 | #define HFSPLUS_SECTOR_SHIFT 9 | ||
23 | #define HFSPLUS_VOLHEAD_SECTOR 2 | ||
24 | #define HFSPLUS_VOLHEAD_SIG 0x482b | ||
25 | #define HFSPLUS_SUPER_MAGIC 0x482b | ||
26 | #define HFSPLUS_CURRENT_VERSION 4 | ||
27 | |||
28 | #define HFSP_WRAP_MAGIC 0x4244 | ||
29 | #define HFSP_WRAP_ATTRIB_SLOCK 0x8000 | ||
30 | #define HFSP_WRAP_ATTRIB_SPARED 0x0200 | ||
31 | |||
32 | #define HFSP_WRAPOFF_SIG 0x00 | ||
33 | #define HFSP_WRAPOFF_ATTRIB 0x0A | ||
34 | #define HFSP_WRAPOFF_ABLKSIZE 0x14 | ||
35 | #define HFSP_WRAPOFF_ABLKSTART 0x1C | ||
36 | #define HFSP_WRAPOFF_EMBEDSIG 0x7C | ||
37 | #define HFSP_WRAPOFF_EMBEDEXT 0x7E | ||
38 | |||
39 | #define HFSP_HIDDENDIR_NAME "\xe2\x90\x80\xe2\x90\x80\xe2\x90\x80\xe2\x90\x80HFS+ Private Data" | ||
40 | |||
41 | #define HFSP_HARDLINK_TYPE 0x686c6e6b /* 'hlnk' */ | ||
42 | #define HFSP_HFSPLUS_CREATOR 0x6866732b /* 'hfs+' */ | ||
43 | |||
44 | #define HFSP_MOUNT_VERSION 0x482b4c78 /* 'H+Lx' */ | ||
45 | |||
46 | /* Structures used on disk */ | ||
47 | |||
48 | typedef __be32 hfsplus_cnid; | ||
49 | typedef __be16 hfsplus_unichr; | ||
50 | |||
51 | /* A "string" as used in filenames, etc. */ | ||
52 | struct hfsplus_unistr { | ||
53 | __be16 length; | ||
54 | hfsplus_unichr unicode[255]; | ||
55 | } __packed; | ||
56 | |||
57 | #define HFSPLUS_MAX_STRLEN 255 | ||
58 | |||
59 | /* POSIX permissions */ | ||
60 | struct hfsplus_perm { | ||
61 | __be32 owner; | ||
62 | __be32 group; | ||
63 | u8 rootflags; | ||
64 | u8 userflags; | ||
65 | __be16 mode; | ||
66 | __be32 dev; | ||
67 | } __packed; | ||
68 | |||
69 | #define HFSPLUS_FLG_NODUMP 0x01 | ||
70 | #define HFSPLUS_FLG_IMMUTABLE 0x02 | ||
71 | #define HFSPLUS_FLG_APPEND 0x04 | ||
72 | |||
73 | /* A single contiguous area of a file */ | ||
74 | struct hfsplus_extent { | ||
75 | __be32 start_block; | ||
76 | __be32 block_count; | ||
77 | } __packed; | ||
78 | typedef struct hfsplus_extent hfsplus_extent_rec[8]; | ||
79 | |||
80 | /* Information for a "Fork" in a file */ | ||
81 | struct hfsplus_fork_raw { | ||
82 | __be64 total_size; | ||
83 | __be32 clump_size; | ||
84 | __be32 total_blocks; | ||
85 | hfsplus_extent_rec extents; | ||
86 | } __packed; | ||
87 | |||
88 | /* HFS+ Volume Header */ | ||
89 | struct hfsplus_vh { | ||
90 | __be16 signature; | ||
91 | __be16 version; | ||
92 | __be32 attributes; | ||
93 | __be32 last_mount_vers; | ||
94 | u32 reserved; | ||
95 | |||
96 | __be32 create_date; | ||
97 | __be32 modify_date; | ||
98 | __be32 backup_date; | ||
99 | __be32 checked_date; | ||
100 | |||
101 | __be32 file_count; | ||
102 | __be32 folder_count; | ||
103 | |||
104 | __be32 blocksize; | ||
105 | __be32 total_blocks; | ||
106 | __be32 free_blocks; | ||
107 | |||
108 | __be32 next_alloc; | ||
109 | __be32 rsrc_clump_sz; | ||
110 | __be32 data_clump_sz; | ||
111 | hfsplus_cnid next_cnid; | ||
112 | |||
113 | __be32 write_count; | ||
114 | __be64 encodings_bmp; | ||
115 | |||
116 | u8 finder_info[32]; | ||
117 | |||
118 | struct hfsplus_fork_raw alloc_file; | ||
119 | struct hfsplus_fork_raw ext_file; | ||
120 | struct hfsplus_fork_raw cat_file; | ||
121 | struct hfsplus_fork_raw attr_file; | ||
122 | struct hfsplus_fork_raw start_file; | ||
123 | } __packed; | ||
124 | |||
125 | /* HFS+ volume attributes */ | ||
126 | #define HFSPLUS_VOL_UNMNT (1 << 8) | ||
127 | #define HFSPLUS_VOL_SPARE_BLK (1 << 9) | ||
128 | #define HFSPLUS_VOL_NOCACHE (1 << 10) | ||
129 | #define HFSPLUS_VOL_INCNSTNT (1 << 11) | ||
130 | #define HFSPLUS_VOL_SOFTLOCK (1 << 15) | ||
131 | |||
132 | /* HFS+ BTree node descriptor */ | ||
133 | struct hfs_bnode_desc { | ||
134 | __be32 next; | ||
135 | __be32 prev; | ||
136 | s8 type; | ||
137 | u8 height; | ||
138 | __be16 num_recs; | ||
139 | u16 reserved; | ||
140 | } __packed; | ||
141 | |||
142 | /* HFS+ BTree node types */ | ||
143 | #define HFS_NODE_INDEX 0x00 | ||
144 | #define HFS_NODE_HEADER 0x01 | ||
145 | #define HFS_NODE_MAP 0x02 | ||
146 | #define HFS_NODE_LEAF 0xFF | ||
147 | |||
148 | /* HFS+ BTree header */ | ||
149 | struct hfs_btree_header_rec { | ||
150 | __be16 depth; | ||
151 | __be32 root; | ||
152 | __be32 leaf_count; | ||
153 | __be32 leaf_head; | ||
154 | __be32 leaf_tail; | ||
155 | __be16 node_size; | ||
156 | __be16 max_key_len; | ||
157 | __be32 node_count; | ||
158 | __be32 free_nodes; | ||
159 | u16 reserved1; | ||
160 | __be32 clump_size; | ||
161 | u8 btree_type; | ||
162 | u8 reserved2; | ||
163 | __be32 attributes; | ||
164 | u32 reserved3[16]; | ||
165 | } __packed; | ||
166 | |||
167 | /* BTree attributes */ | ||
168 | #define HFS_TREE_BIGKEYS 2 | ||
169 | #define HFS_TREE_VARIDXKEYS 4 | ||
170 | |||
171 | /* HFS+ BTree misc info */ | ||
172 | #define HFSPLUS_TREE_HEAD 0 | ||
173 | #define HFSPLUS_NODE_MXSZ 32768 | ||
174 | |||
175 | /* Some special File ID numbers (stolen from hfs.h) */ | ||
176 | #define HFSPLUS_POR_CNID 1 /* Parent Of the Root */ | ||
177 | #define HFSPLUS_ROOT_CNID 2 /* ROOT directory */ | ||
178 | #define HFSPLUS_EXT_CNID 3 /* EXTents B-tree */ | ||
179 | #define HFSPLUS_CAT_CNID 4 /* CATalog B-tree */ | ||
180 | #define HFSPLUS_BAD_CNID 5 /* BAD blocks file */ | ||
181 | #define HFSPLUS_ALLOC_CNID 6 /* ALLOCation file */ | ||
182 | #define HFSPLUS_START_CNID 7 /* STARTup file */ | ||
183 | #define HFSPLUS_ATTR_CNID 8 /* ATTRibutes file */ | ||
184 | #define HFSPLUS_EXCH_CNID 15 /* ExchangeFiles temp id */ | ||
185 | #define HFSPLUS_FIRSTUSER_CNID 16 /* first available user id */ | ||
186 | |||
187 | /* HFS+ catalog entry key */ | ||
188 | struct hfsplus_cat_key { | ||
189 | __be16 key_len; | ||
190 | hfsplus_cnid parent; | ||
191 | struct hfsplus_unistr name; | ||
192 | } __packed; | ||
193 | |||
194 | |||
195 | /* Structs from hfs.h */ | ||
196 | struct hfsp_point { | ||
197 | __be16 v; | ||
198 | __be16 h; | ||
199 | } __packed; | ||
200 | |||
201 | struct hfsp_rect { | ||
202 | __be16 top; | ||
203 | __be16 left; | ||
204 | __be16 bottom; | ||
205 | __be16 right; | ||
206 | } __packed; | ||
207 | |||
208 | |||
209 | /* HFS directory info (stolen from hfs.h */ | ||
210 | struct DInfo { | ||
211 | struct hfsp_rect frRect; | ||
212 | __be16 frFlags; | ||
213 | struct hfsp_point frLocation; | ||
214 | __be16 frView; | ||
215 | } __packed; | ||
216 | |||
217 | struct DXInfo { | ||
218 | struct hfsp_point frScroll; | ||
219 | __be32 frOpenChain; | ||
220 | __be16 frUnused; | ||
221 | __be16 frComment; | ||
222 | __be32 frPutAway; | ||
223 | } __packed; | ||
224 | |||
225 | /* HFS+ folder data (part of an hfsplus_cat_entry) */ | ||
226 | struct hfsplus_cat_folder { | ||
227 | __be16 type; | ||
228 | __be16 flags; | ||
229 | __be32 valence; | ||
230 | hfsplus_cnid id; | ||
231 | __be32 create_date; | ||
232 | __be32 content_mod_date; | ||
233 | __be32 attribute_mod_date; | ||
234 | __be32 access_date; | ||
235 | __be32 backup_date; | ||
236 | struct hfsplus_perm permissions; | ||
237 | struct DInfo user_info; | ||
238 | struct DXInfo finder_info; | ||
239 | __be32 text_encoding; | ||
240 | u32 reserved; | ||
241 | } __packed; | ||
242 | |||
243 | /* HFS file info (stolen from hfs.h) */ | ||
244 | struct FInfo { | ||
245 | __be32 fdType; | ||
246 | __be32 fdCreator; | ||
247 | __be16 fdFlags; | ||
248 | struct hfsp_point fdLocation; | ||
249 | __be16 fdFldr; | ||
250 | } __packed; | ||
251 | |||
252 | struct FXInfo { | ||
253 | __be16 fdIconID; | ||
254 | u8 fdUnused[8]; | ||
255 | __be16 fdComment; | ||
256 | __be32 fdPutAway; | ||
257 | } __packed; | ||
258 | |||
259 | /* HFS+ file data (part of a cat_entry) */ | ||
260 | struct hfsplus_cat_file { | ||
261 | __be16 type; | ||
262 | __be16 flags; | ||
263 | u32 reserved1; | ||
264 | hfsplus_cnid id; | ||
265 | __be32 create_date; | ||
266 | __be32 content_mod_date; | ||
267 | __be32 attribute_mod_date; | ||
268 | __be32 access_date; | ||
269 | __be32 backup_date; | ||
270 | struct hfsplus_perm permissions; | ||
271 | struct FInfo user_info; | ||
272 | struct FXInfo finder_info; | ||
273 | __be32 text_encoding; | ||
274 | u32 reserved2; | ||
275 | |||
276 | struct hfsplus_fork_raw data_fork; | ||
277 | struct hfsplus_fork_raw rsrc_fork; | ||
278 | } __packed; | ||
279 | |||
280 | /* File attribute bits */ | ||
281 | #define HFSPLUS_FILE_LOCKED 0x0001 | ||
282 | #define HFSPLUS_FILE_THREAD_EXISTS 0x0002 | ||
283 | |||
284 | /* HFS+ catalog thread (part of a cat_entry) */ | ||
285 | struct hfsplus_cat_thread { | ||
286 | __be16 type; | ||
287 | s16 reserved; | ||
288 | hfsplus_cnid parentID; | ||
289 | struct hfsplus_unistr nodeName; | ||
290 | } __packed; | ||
291 | |||
292 | #define HFSPLUS_MIN_THREAD_SZ 10 | ||
293 | |||
294 | /* A data record in the catalog tree */ | ||
295 | typedef union { | ||
296 | __be16 type; | ||
297 | struct hfsplus_cat_folder folder; | ||
298 | struct hfsplus_cat_file file; | ||
299 | struct hfsplus_cat_thread thread; | ||
300 | } __packed hfsplus_cat_entry; | ||
301 | |||
302 | /* HFS+ catalog entry type */ | ||
303 | #define HFSPLUS_FOLDER 0x0001 | ||
304 | #define HFSPLUS_FILE 0x0002 | ||
305 | #define HFSPLUS_FOLDER_THREAD 0x0003 | ||
306 | #define HFSPLUS_FILE_THREAD 0x0004 | ||
307 | |||
308 | /* HFS+ extents tree key */ | ||
309 | struct hfsplus_ext_key { | ||
310 | __be16 key_len; | ||
311 | u8 fork_type; | ||
312 | u8 pad; | ||
313 | hfsplus_cnid cnid; | ||
314 | __be32 start_block; | ||
315 | } __packed; | ||
316 | |||
317 | #define HFSPLUS_EXT_KEYLEN 12 | ||
318 | |||
319 | /* HFS+ generic BTree key */ | ||
320 | typedef union { | ||
321 | __be16 key_len; | ||
322 | struct hfsplus_cat_key cat; | ||
323 | struct hfsplus_ext_key ext; | ||
324 | } __packed hfsplus_btree_key; | ||
325 | |||
326 | #endif | ||
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c new file mode 100644 index 000000000000..d5642705f633 --- /dev/null +++ b/fs/hfsplus/inode.c | |||
@@ -0,0 +1,555 @@ | |||
1 | /* | ||
2 | * linux/fs/hfsplus/inode.c | ||
3 | * | ||
4 | * Copyright (C) 2001 | ||
5 | * Brad Boyer (flar@allandria.com) | ||
6 | * (C) 2003 Ardis Technologies <roman@ardistech.com> | ||
7 | * | ||
8 | * Inode handling routines | ||
9 | */ | ||
10 | |||
11 | #include <linux/mm.h> | ||
12 | #include <linux/fs.h> | ||
13 | #include <linux/pagemap.h> | ||
14 | #include <linux/version.h> | ||
15 | #include <linux/mpage.h> | ||
16 | |||
17 | #include "hfsplus_fs.h" | ||
18 | #include "hfsplus_raw.h" | ||
19 | |||
20 | static int hfsplus_readpage(struct file *file, struct page *page) | ||
21 | { | ||
22 | //printk("readpage: %lu\n", page->index); | ||
23 | return block_read_full_page(page, hfsplus_get_block); | ||
24 | } | ||
25 | |||
26 | static int hfsplus_writepage(struct page *page, struct writeback_control *wbc) | ||
27 | { | ||
28 | //printk("writepage: %lu\n", page->index); | ||
29 | return block_write_full_page(page, hfsplus_get_block, wbc); | ||
30 | } | ||
31 | |||
32 | static int hfsplus_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) | ||
33 | { | ||
34 | return cont_prepare_write(page, from, to, hfsplus_get_block, | ||
35 | &HFSPLUS_I(page->mapping->host).phys_size); | ||
36 | } | ||
37 | |||
38 | static sector_t hfsplus_bmap(struct address_space *mapping, sector_t block) | ||
39 | { | ||
40 | return generic_block_bmap(mapping, block, hfsplus_get_block); | ||
41 | } | ||
42 | |||
43 | static int hfsplus_releasepage(struct page *page, int mask) | ||
44 | { | ||
45 | struct inode *inode = page->mapping->host; | ||
46 | struct super_block *sb = inode->i_sb; | ||
47 | struct hfs_btree *tree; | ||
48 | struct hfs_bnode *node; | ||
49 | u32 nidx; | ||
50 | int i, res = 1; | ||
51 | |||
52 | switch (inode->i_ino) { | ||
53 | case HFSPLUS_EXT_CNID: | ||
54 | tree = HFSPLUS_SB(sb).ext_tree; | ||
55 | break; | ||
56 | case HFSPLUS_CAT_CNID: | ||
57 | tree = HFSPLUS_SB(sb).cat_tree; | ||
58 | break; | ||
59 | case HFSPLUS_ATTR_CNID: | ||
60 | tree = HFSPLUS_SB(sb).attr_tree; | ||
61 | break; | ||
62 | default: | ||
63 | BUG(); | ||
64 | return 0; | ||
65 | } | ||
66 | if (tree->node_size >= PAGE_CACHE_SIZE) { | ||
67 | nidx = page->index >> (tree->node_size_shift - PAGE_CACHE_SHIFT); | ||
68 | spin_lock(&tree->hash_lock); | ||
69 | node = hfs_bnode_findhash(tree, nidx); | ||
70 | if (!node) | ||
71 | ; | ||
72 | else if (atomic_read(&node->refcnt)) | ||
73 | res = 0; | ||
74 | if (res && node) { | ||
75 | hfs_bnode_unhash(node); | ||
76 | hfs_bnode_free(node); | ||
77 | } | ||
78 | spin_unlock(&tree->hash_lock); | ||
79 | } else { | ||
80 | nidx = page->index << (PAGE_CACHE_SHIFT - tree->node_size_shift); | ||
81 | i = 1 << (PAGE_CACHE_SHIFT - tree->node_size_shift); | ||
82 | spin_lock(&tree->hash_lock); | ||
83 | do { | ||
84 | node = hfs_bnode_findhash(tree, nidx++); | ||
85 | if (!node) | ||
86 | continue; | ||
87 | if (atomic_read(&node->refcnt)) { | ||
88 | res = 0; | ||
89 | break; | ||
90 | } | ||
91 | hfs_bnode_unhash(node); | ||
92 | hfs_bnode_free(node); | ||
93 | } while (--i && nidx < tree->node_count); | ||
94 | spin_unlock(&tree->hash_lock); | ||
95 | } | ||
96 | //printk("releasepage: %lu,%x = %d\n", page->index, mask, res); | ||
97 | return res ? try_to_free_buffers(page) : 0; | ||
98 | } | ||
99 | |||
100 | static int hfsplus_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks, | ||
101 | struct buffer_head *bh_result, int create) | ||
102 | { | ||
103 | int ret; | ||
104 | |||
105 | ret = hfsplus_get_block(inode, iblock, bh_result, create); | ||
106 | if (!ret) | ||
107 | bh_result->b_size = (1 << inode->i_blkbits); | ||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb, | ||
112 | const struct iovec *iov, loff_t offset, unsigned long nr_segs) | ||
113 | { | ||
114 | struct file *file = iocb->ki_filp; | ||
115 | struct inode *inode = file->f_dentry->d_inode->i_mapping->host; | ||
116 | |||
117 | return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | ||
118 | offset, nr_segs, hfsplus_get_blocks, NULL); | ||
119 | } | ||
120 | |||
121 | static int hfsplus_writepages(struct address_space *mapping, | ||
122 | struct writeback_control *wbc) | ||
123 | { | ||
124 | return mpage_writepages(mapping, wbc, hfsplus_get_block); | ||
125 | } | ||
126 | |||
127 | struct address_space_operations hfsplus_btree_aops = { | ||
128 | .readpage = hfsplus_readpage, | ||
129 | .writepage = hfsplus_writepage, | ||
130 | .sync_page = block_sync_page, | ||
131 | .prepare_write = hfsplus_prepare_write, | ||
132 | .commit_write = generic_commit_write, | ||
133 | .bmap = hfsplus_bmap, | ||
134 | .releasepage = hfsplus_releasepage, | ||
135 | }; | ||
136 | |||
137 | struct address_space_operations hfsplus_aops = { | ||
138 | .readpage = hfsplus_readpage, | ||
139 | .writepage = hfsplus_writepage, | ||
140 | .sync_page = block_sync_page, | ||
141 | .prepare_write = hfsplus_prepare_write, | ||
142 | .commit_write = generic_commit_write, | ||
143 | .bmap = hfsplus_bmap, | ||
144 | .direct_IO = hfsplus_direct_IO, | ||
145 | .writepages = hfsplus_writepages, | ||
146 | }; | ||
147 | |||
148 | static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dentry, | ||
149 | struct nameidata *nd) | ||
150 | { | ||
151 | struct hfs_find_data fd; | ||
152 | struct super_block *sb = dir->i_sb; | ||
153 | struct inode *inode = NULL; | ||
154 | int err; | ||
155 | |||
156 | if (HFSPLUS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc")) | ||
157 | goto out; | ||
158 | |||
159 | inode = HFSPLUS_I(dir).rsrc_inode; | ||
160 | if (inode) | ||
161 | goto out; | ||
162 | |||
163 | inode = new_inode(sb); | ||
164 | if (!inode) | ||
165 | return ERR_PTR(-ENOMEM); | ||
166 | |||
167 | inode->i_ino = dir->i_ino; | ||
168 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); | ||
169 | init_MUTEX(&HFSPLUS_I(inode).extents_lock); | ||
170 | HFSPLUS_I(inode).flags = HFSPLUS_FLG_RSRC; | ||
171 | |||
172 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | ||
173 | err = hfsplus_find_cat(sb, dir->i_ino, &fd); | ||
174 | if (!err) | ||
175 | err = hfsplus_cat_read_inode(inode, &fd); | ||
176 | hfs_find_exit(&fd); | ||
177 | if (err) { | ||
178 | iput(inode); | ||
179 | return ERR_PTR(err); | ||
180 | } | ||
181 | HFSPLUS_I(inode).rsrc_inode = dir; | ||
182 | HFSPLUS_I(dir).rsrc_inode = inode; | ||
183 | igrab(dir); | ||
184 | hlist_add_head(&inode->i_hash, &HFSPLUS_SB(sb).rsrc_inodes); | ||
185 | mark_inode_dirty(inode); | ||
186 | { | ||
187 | void hfsplus_inode_check(struct super_block *sb); | ||
188 | atomic_inc(&HFSPLUS_SB(sb).inode_cnt); | ||
189 | hfsplus_inode_check(sb); | ||
190 | } | ||
191 | out: | ||
192 | d_add(dentry, inode); | ||
193 | return NULL; | ||
194 | } | ||
195 | |||
196 | static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, int dir) | ||
197 | { | ||
198 | struct super_block *sb = inode->i_sb; | ||
199 | u16 mode; | ||
200 | |||
201 | mode = be16_to_cpu(perms->mode); | ||
202 | |||
203 | inode->i_uid = be32_to_cpu(perms->owner); | ||
204 | if (!inode->i_uid && !mode) | ||
205 | inode->i_uid = HFSPLUS_SB(sb).uid; | ||
206 | |||
207 | inode->i_gid = be32_to_cpu(perms->group); | ||
208 | if (!inode->i_gid && !mode) | ||
209 | inode->i_gid = HFSPLUS_SB(sb).gid; | ||
210 | |||
211 | if (dir) { | ||
212 | mode = mode ? (mode & S_IALLUGO) : | ||
213 | (S_IRWXUGO & ~(HFSPLUS_SB(sb).umask)); | ||
214 | mode |= S_IFDIR; | ||
215 | } else if (!mode) | ||
216 | mode = S_IFREG | ((S_IRUGO|S_IWUGO) & | ||
217 | ~(HFSPLUS_SB(sb).umask)); | ||
218 | inode->i_mode = mode; | ||
219 | |||
220 | HFSPLUS_I(inode).rootflags = perms->rootflags; | ||
221 | HFSPLUS_I(inode).userflags = perms->userflags; | ||
222 | if (perms->rootflags & HFSPLUS_FLG_IMMUTABLE) | ||
223 | inode->i_flags |= S_IMMUTABLE; | ||
224 | else | ||
225 | inode->i_flags &= ~S_IMMUTABLE; | ||
226 | if (perms->rootflags & HFSPLUS_FLG_APPEND) | ||
227 | inode->i_flags |= S_APPEND; | ||
228 | else | ||
229 | inode->i_flags &= ~S_APPEND; | ||
230 | } | ||
231 | |||
232 | static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms) | ||
233 | { | ||
234 | if (inode->i_flags & S_IMMUTABLE) | ||
235 | perms->rootflags |= HFSPLUS_FLG_IMMUTABLE; | ||
236 | else | ||
237 | perms->rootflags &= ~HFSPLUS_FLG_IMMUTABLE; | ||
238 | if (inode->i_flags & S_APPEND) | ||
239 | perms->rootflags |= HFSPLUS_FLG_APPEND; | ||
240 | else | ||
241 | perms->rootflags &= ~HFSPLUS_FLG_APPEND; | ||
242 | perms->userflags = HFSPLUS_I(inode).userflags; | ||
243 | perms->mode = cpu_to_be16(inode->i_mode); | ||
244 | perms->owner = cpu_to_be32(inode->i_uid); | ||
245 | perms->group = cpu_to_be32(inode->i_gid); | ||
246 | perms->dev = cpu_to_be32(HFSPLUS_I(inode).dev); | ||
247 | } | ||
248 | |||
249 | static int hfsplus_permission(struct inode *inode, int mask, struct nameidata *nd) | ||
250 | { | ||
251 | /* MAY_EXEC is also used for lookup, if no x bit is set allow lookup, | ||
252 | * open_exec has the same test, so it's still not executable, if a x bit | ||
253 | * is set fall back to standard permission check. | ||
254 | */ | ||
255 | if (S_ISREG(inode->i_mode) && mask & MAY_EXEC && !(inode->i_mode & 0111)) | ||
256 | return 0; | ||
257 | return generic_permission(inode, mask, NULL); | ||
258 | } | ||
259 | |||
260 | |||
261 | static int hfsplus_file_open(struct inode *inode, struct file *file) | ||
262 | { | ||
263 | if (HFSPLUS_IS_RSRC(inode)) | ||
264 | inode = HFSPLUS_I(inode).rsrc_inode; | ||
265 | if (atomic_read(&file->f_count) != 1) | ||
266 | return 0; | ||
267 | atomic_inc(&HFSPLUS_I(inode).opencnt); | ||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static int hfsplus_file_release(struct inode *inode, struct file *file) | ||
272 | { | ||
273 | struct super_block *sb = inode->i_sb; | ||
274 | |||
275 | if (HFSPLUS_IS_RSRC(inode)) | ||
276 | inode = HFSPLUS_I(inode).rsrc_inode; | ||
277 | if (atomic_read(&file->f_count) != 0) | ||
278 | return 0; | ||
279 | if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) { | ||
280 | down(&inode->i_sem); | ||
281 | hfsplus_file_truncate(inode); | ||
282 | if (inode->i_flags & S_DEAD) { | ||
283 | hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL); | ||
284 | hfsplus_delete_inode(inode); | ||
285 | } | ||
286 | up(&inode->i_sem); | ||
287 | } | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | extern struct inode_operations hfsplus_dir_inode_operations; | ||
292 | extern struct file_operations hfsplus_dir_operations; | ||
293 | |||
294 | static struct inode_operations hfsplus_file_inode_operations = { | ||
295 | .lookup = hfsplus_file_lookup, | ||
296 | .truncate = hfsplus_file_truncate, | ||
297 | .permission = hfsplus_permission, | ||
298 | .setxattr = hfsplus_setxattr, | ||
299 | .getxattr = hfsplus_getxattr, | ||
300 | .listxattr = hfsplus_listxattr, | ||
301 | }; | ||
302 | |||
303 | static struct file_operations hfsplus_file_operations = { | ||
304 | .llseek = generic_file_llseek, | ||
305 | .read = generic_file_read, | ||
306 | .write = generic_file_write, | ||
307 | .mmap = generic_file_mmap, | ||
308 | .sendfile = generic_file_sendfile, | ||
309 | .fsync = file_fsync, | ||
310 | .open = hfsplus_file_open, | ||
311 | .release = hfsplus_file_release, | ||
312 | .ioctl = hfsplus_ioctl, | ||
313 | }; | ||
314 | |||
315 | struct inode *hfsplus_new_inode(struct super_block *sb, int mode) | ||
316 | { | ||
317 | struct inode *inode = new_inode(sb); | ||
318 | if (!inode) | ||
319 | return NULL; | ||
320 | |||
321 | { | ||
322 | void hfsplus_inode_check(struct super_block *sb); | ||
323 | atomic_inc(&HFSPLUS_SB(sb).inode_cnt); | ||
324 | hfsplus_inode_check(sb); | ||
325 | } | ||
326 | inode->i_ino = HFSPLUS_SB(sb).next_cnid++; | ||
327 | inode->i_mode = mode; | ||
328 | inode->i_uid = current->fsuid; | ||
329 | inode->i_gid = current->fsgid; | ||
330 | inode->i_nlink = 1; | ||
331 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; | ||
332 | inode->i_blksize = HFSPLUS_SB(sb).alloc_blksz; | ||
333 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); | ||
334 | init_MUTEX(&HFSPLUS_I(inode).extents_lock); | ||
335 | atomic_set(&HFSPLUS_I(inode).opencnt, 0); | ||
336 | HFSPLUS_I(inode).flags = 0; | ||
337 | memset(HFSPLUS_I(inode).first_extents, 0, sizeof(hfsplus_extent_rec)); | ||
338 | memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec)); | ||
339 | HFSPLUS_I(inode).alloc_blocks = 0; | ||
340 | HFSPLUS_I(inode).first_blocks = 0; | ||
341 | HFSPLUS_I(inode).cached_start = 0; | ||
342 | HFSPLUS_I(inode).cached_blocks = 0; | ||
343 | HFSPLUS_I(inode).phys_size = 0; | ||
344 | HFSPLUS_I(inode).fs_blocks = 0; | ||
345 | HFSPLUS_I(inode).rsrc_inode = NULL; | ||
346 | if (S_ISDIR(inode->i_mode)) { | ||
347 | inode->i_size = 2; | ||
348 | HFSPLUS_SB(sb).folder_count++; | ||
349 | inode->i_op = &hfsplus_dir_inode_operations; | ||
350 | inode->i_fop = &hfsplus_dir_operations; | ||
351 | } else if (S_ISREG(inode->i_mode)) { | ||
352 | HFSPLUS_SB(sb).file_count++; | ||
353 | inode->i_op = &hfsplus_file_inode_operations; | ||
354 | inode->i_fop = &hfsplus_file_operations; | ||
355 | inode->i_mapping->a_ops = &hfsplus_aops; | ||
356 | HFSPLUS_I(inode).clump_blocks = HFSPLUS_SB(sb).data_clump_blocks; | ||
357 | } else if (S_ISLNK(inode->i_mode)) { | ||
358 | HFSPLUS_SB(sb).file_count++; | ||
359 | inode->i_op = &page_symlink_inode_operations; | ||
360 | inode->i_mapping->a_ops = &hfsplus_aops; | ||
361 | HFSPLUS_I(inode).clump_blocks = 1; | ||
362 | } else | ||
363 | HFSPLUS_SB(sb).file_count++; | ||
364 | insert_inode_hash(inode); | ||
365 | mark_inode_dirty(inode); | ||
366 | sb->s_dirt = 1; | ||
367 | |||
368 | return inode; | ||
369 | } | ||
370 | |||
371 | void hfsplus_delete_inode(struct inode *inode) | ||
372 | { | ||
373 | struct super_block *sb = inode->i_sb; | ||
374 | |||
375 | if (S_ISDIR(inode->i_mode)) { | ||
376 | HFSPLUS_SB(sb).folder_count--; | ||
377 | sb->s_dirt = 1; | ||
378 | return; | ||
379 | } | ||
380 | HFSPLUS_SB(sb).file_count--; | ||
381 | if (S_ISREG(inode->i_mode)) { | ||
382 | if (!inode->i_nlink) { | ||
383 | inode->i_size = 0; | ||
384 | hfsplus_file_truncate(inode); | ||
385 | } | ||
386 | } else if (S_ISLNK(inode->i_mode)) { | ||
387 | inode->i_size = 0; | ||
388 | hfsplus_file_truncate(inode); | ||
389 | } | ||
390 | sb->s_dirt = 1; | ||
391 | } | ||
392 | |||
393 | void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork) | ||
394 | { | ||
395 | struct super_block *sb = inode->i_sb; | ||
396 | u32 count; | ||
397 | int i; | ||
398 | |||
399 | memcpy(&HFSPLUS_I(inode).first_extents, &fork->extents, | ||
400 | sizeof(hfsplus_extent_rec)); | ||
401 | for (count = 0, i = 0; i < 8; i++) | ||
402 | count += be32_to_cpu(fork->extents[i].block_count); | ||
403 | HFSPLUS_I(inode).first_blocks = count; | ||
404 | memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec)); | ||
405 | HFSPLUS_I(inode).cached_start = 0; | ||
406 | HFSPLUS_I(inode).cached_blocks = 0; | ||
407 | |||
408 | HFSPLUS_I(inode).alloc_blocks = be32_to_cpu(fork->total_blocks); | ||
409 | inode->i_size = HFSPLUS_I(inode).phys_size = be64_to_cpu(fork->total_size); | ||
410 | HFSPLUS_I(inode).fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; | ||
411 | inode_set_bytes(inode, HFSPLUS_I(inode).fs_blocks << sb->s_blocksize_bits); | ||
412 | HFSPLUS_I(inode).clump_blocks = be32_to_cpu(fork->clump_size) >> HFSPLUS_SB(sb).alloc_blksz_shift; | ||
413 | if (!HFSPLUS_I(inode).clump_blocks) | ||
414 | HFSPLUS_I(inode).clump_blocks = HFSPLUS_IS_RSRC(inode) ? HFSPLUS_SB(sb).rsrc_clump_blocks : | ||
415 | HFSPLUS_SB(sb).data_clump_blocks; | ||
416 | } | ||
417 | |||
418 | void hfsplus_inode_write_fork(struct inode *inode, struct hfsplus_fork_raw *fork) | ||
419 | { | ||
420 | memcpy(&fork->extents, &HFSPLUS_I(inode).first_extents, | ||
421 | sizeof(hfsplus_extent_rec)); | ||
422 | fork->total_size = cpu_to_be64(inode->i_size); | ||
423 | fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode).alloc_blocks); | ||
424 | } | ||
425 | |||
426 | int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) | ||
427 | { | ||
428 | hfsplus_cat_entry entry; | ||
429 | int res = 0; | ||
430 | u16 type; | ||
431 | |||
432 | type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset); | ||
433 | |||
434 | HFSPLUS_I(inode).dev = 0; | ||
435 | inode->i_blksize = HFSPLUS_SB(inode->i_sb).alloc_blksz; | ||
436 | if (type == HFSPLUS_FOLDER) { | ||
437 | struct hfsplus_cat_folder *folder = &entry.folder; | ||
438 | |||
439 | if (fd->entrylength < sizeof(struct hfsplus_cat_folder)) | ||
440 | /* panic? */; | ||
441 | hfs_bnode_read(fd->bnode, &entry, fd->entryoffset, | ||
442 | sizeof(struct hfsplus_cat_folder)); | ||
443 | hfsplus_get_perms(inode, &folder->permissions, 1); | ||
444 | inode->i_nlink = 1; | ||
445 | inode->i_size = 2 + be32_to_cpu(folder->valence); | ||
446 | inode->i_atime = hfsp_mt2ut(folder->access_date); | ||
447 | inode->i_mtime = hfsp_mt2ut(folder->content_mod_date); | ||
448 | inode->i_ctime = inode->i_mtime; | ||
449 | HFSPLUS_I(inode).fs_blocks = 0; | ||
450 | inode->i_op = &hfsplus_dir_inode_operations; | ||
451 | inode->i_fop = &hfsplus_dir_operations; | ||
452 | } else if (type == HFSPLUS_FILE) { | ||
453 | struct hfsplus_cat_file *file = &entry.file; | ||
454 | |||
455 | if (fd->entrylength < sizeof(struct hfsplus_cat_file)) | ||
456 | /* panic? */; | ||
457 | hfs_bnode_read(fd->bnode, &entry, fd->entryoffset, | ||
458 | sizeof(struct hfsplus_cat_file)); | ||
459 | |||
460 | hfsplus_inode_read_fork(inode, HFSPLUS_IS_DATA(inode) ? | ||
461 | &file->data_fork : &file->rsrc_fork); | ||
462 | hfsplus_get_perms(inode, &file->permissions, 0); | ||
463 | inode->i_nlink = 1; | ||
464 | if (S_ISREG(inode->i_mode)) { | ||
465 | if (file->permissions.dev) | ||
466 | inode->i_nlink = be32_to_cpu(file->permissions.dev); | ||
467 | inode->i_op = &hfsplus_file_inode_operations; | ||
468 | inode->i_fop = &hfsplus_file_operations; | ||
469 | inode->i_mapping->a_ops = &hfsplus_aops; | ||
470 | } else if (S_ISLNK(inode->i_mode)) { | ||
471 | inode->i_op = &page_symlink_inode_operations; | ||
472 | inode->i_mapping->a_ops = &hfsplus_aops; | ||
473 | } else { | ||
474 | init_special_inode(inode, inode->i_mode, | ||
475 | be32_to_cpu(file->permissions.dev)); | ||
476 | } | ||
477 | inode->i_atime = hfsp_mt2ut(file->access_date); | ||
478 | inode->i_mtime = hfsp_mt2ut(file->content_mod_date); | ||
479 | inode->i_ctime = inode->i_mtime; | ||
480 | } else { | ||
481 | printk("HFS+-fs: bad catalog entry used to create inode\n"); | ||
482 | res = -EIO; | ||
483 | } | ||
484 | return res; | ||
485 | } | ||
486 | |||
487 | int hfsplus_cat_write_inode(struct inode *inode) | ||
488 | { | ||
489 | struct inode *main_inode = inode; | ||
490 | struct hfs_find_data fd; | ||
491 | hfsplus_cat_entry entry; | ||
492 | |||
493 | if (HFSPLUS_IS_RSRC(inode)) | ||
494 | main_inode = HFSPLUS_I(inode).rsrc_inode; | ||
495 | |||
496 | if (!main_inode->i_nlink) | ||
497 | return 0; | ||
498 | |||
499 | if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb).cat_tree, &fd)) | ||
500 | /* panic? */ | ||
501 | return -EIO; | ||
502 | |||
503 | if (hfsplus_find_cat(main_inode->i_sb, main_inode->i_ino, &fd)) | ||
504 | /* panic? */ | ||
505 | goto out; | ||
506 | |||
507 | if (S_ISDIR(main_inode->i_mode)) { | ||
508 | struct hfsplus_cat_folder *folder = &entry.folder; | ||
509 | |||
510 | if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) | ||
511 | /* panic? */; | ||
512 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, | ||
513 | sizeof(struct hfsplus_cat_folder)); | ||
514 | /* simple node checks? */ | ||
515 | hfsplus_set_perms(inode, &folder->permissions); | ||
516 | folder->access_date = hfsp_ut2mt(inode->i_atime); | ||
517 | folder->content_mod_date = hfsp_ut2mt(inode->i_mtime); | ||
518 | folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime); | ||
519 | folder->valence = cpu_to_be32(inode->i_size - 2); | ||
520 | hfs_bnode_write(fd.bnode, &entry, fd.entryoffset, | ||
521 | sizeof(struct hfsplus_cat_folder)); | ||
522 | } else if (HFSPLUS_IS_RSRC(inode)) { | ||
523 | struct hfsplus_cat_file *file = &entry.file; | ||
524 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, | ||
525 | sizeof(struct hfsplus_cat_file)); | ||
526 | hfsplus_inode_write_fork(inode, &file->rsrc_fork); | ||
527 | hfs_bnode_write(fd.bnode, &entry, fd.entryoffset, | ||
528 | sizeof(struct hfsplus_cat_file)); | ||
529 | } else { | ||
530 | struct hfsplus_cat_file *file = &entry.file; | ||
531 | |||
532 | if (fd.entrylength < sizeof(struct hfsplus_cat_file)) | ||
533 | /* panic? */; | ||
534 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, | ||
535 | sizeof(struct hfsplus_cat_file)); | ||
536 | hfsplus_inode_write_fork(inode, &file->data_fork); | ||
537 | if (S_ISREG(inode->i_mode)) | ||
538 | HFSPLUS_I(inode).dev = inode->i_nlink; | ||
539 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) | ||
540 | HFSPLUS_I(inode).dev = kdev_t_to_nr(inode->i_rdev); | ||
541 | hfsplus_set_perms(inode, &file->permissions); | ||
542 | if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) | ||
543 | file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); | ||
544 | else | ||
545 | file->flags &= cpu_to_be16(~HFSPLUS_FILE_LOCKED); | ||
546 | file->access_date = hfsp_ut2mt(inode->i_atime); | ||
547 | file->content_mod_date = hfsp_ut2mt(inode->i_mtime); | ||
548 | file->attribute_mod_date = hfsp_ut2mt(inode->i_ctime); | ||
549 | hfs_bnode_write(fd.bnode, &entry, fd.entryoffset, | ||
550 | sizeof(struct hfsplus_cat_file)); | ||
551 | } | ||
552 | out: | ||
553 | hfs_find_exit(&fd); | ||
554 | return 0; | ||
555 | } | ||
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c new file mode 100644 index 000000000000..e07aa096e07c --- /dev/null +++ b/fs/hfsplus/ioctl.c | |||
@@ -0,0 +1,188 @@ | |||
1 | /* | ||
2 | * linux/fs/hfsplus/ioctl.c | ||
3 | * | ||
4 | * Copyright (C) 2003 | ||
5 | * Ethan Benson <erbenson@alaska.net> | ||
6 | * partially derived from linux/fs/ext2/ioctl.c | ||
7 | * Copyright (C) 1993, 1994, 1995 | ||
8 | * Remy Card (card@masi.ibp.fr) | ||
9 | * Laboratoire MASI - Institut Blaise Pascal | ||
10 | * Universite Pierre et Marie Curie (Paris VI) | ||
11 | * | ||
12 | * hfsplus ioctls | ||
13 | */ | ||
14 | |||
15 | #include <linux/fs.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/xattr.h> | ||
18 | #include <asm/uaccess.h> | ||
19 | #include "hfsplus_fs.h" | ||
20 | |||
21 | int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | ||
22 | unsigned long arg) | ||
23 | { | ||
24 | unsigned int flags; | ||
25 | |||
26 | switch (cmd) { | ||
27 | case HFSPLUS_IOC_EXT2_GETFLAGS: | ||
28 | flags = 0; | ||
29 | if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_IMMUTABLE) | ||
30 | flags |= EXT2_FLAG_IMMUTABLE; /* EXT2_IMMUTABLE_FL */ | ||
31 | if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_APPEND) | ||
32 | flags |= EXT2_FLAG_APPEND; /* EXT2_APPEND_FL */ | ||
33 | if (HFSPLUS_I(inode).userflags & HFSPLUS_FLG_NODUMP) | ||
34 | flags |= EXT2_FLAG_NODUMP; /* EXT2_NODUMP_FL */ | ||
35 | return put_user(flags, (int __user *)arg); | ||
36 | case HFSPLUS_IOC_EXT2_SETFLAGS: { | ||
37 | if (IS_RDONLY(inode)) | ||
38 | return -EROFS; | ||
39 | |||
40 | if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) | ||
41 | return -EACCES; | ||
42 | |||
43 | if (get_user(flags, (int __user *)arg)) | ||
44 | return -EFAULT; | ||
45 | |||
46 | if (flags & (EXT2_FLAG_IMMUTABLE|EXT2_FLAG_APPEND) || | ||
47 | HFSPLUS_I(inode).rootflags & (HFSPLUS_FLG_IMMUTABLE|HFSPLUS_FLG_APPEND)) { | ||
48 | if (!capable(CAP_LINUX_IMMUTABLE)) | ||
49 | return -EPERM; | ||
50 | } | ||
51 | |||
52 | /* don't silently ignore unsupported ext2 flags */ | ||
53 | if (flags & ~(EXT2_FLAG_IMMUTABLE|EXT2_FLAG_APPEND| | ||
54 | EXT2_FLAG_NODUMP)) | ||
55 | return -EOPNOTSUPP; | ||
56 | |||
57 | if (flags & EXT2_FLAG_IMMUTABLE) { /* EXT2_IMMUTABLE_FL */ | ||
58 | inode->i_flags |= S_IMMUTABLE; | ||
59 | HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_IMMUTABLE; | ||
60 | } else { | ||
61 | inode->i_flags &= ~S_IMMUTABLE; | ||
62 | HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_IMMUTABLE; | ||
63 | } | ||
64 | if (flags & EXT2_FLAG_APPEND) { /* EXT2_APPEND_FL */ | ||
65 | inode->i_flags |= S_APPEND; | ||
66 | HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_APPEND; | ||
67 | } else { | ||
68 | inode->i_flags &= ~S_APPEND; | ||
69 | HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_APPEND; | ||
70 | } | ||
71 | if (flags & EXT2_FLAG_NODUMP) /* EXT2_NODUMP_FL */ | ||
72 | HFSPLUS_I(inode).userflags |= HFSPLUS_FLG_NODUMP; | ||
73 | else | ||
74 | HFSPLUS_I(inode).userflags &= ~HFSPLUS_FLG_NODUMP; | ||
75 | |||
76 | inode->i_ctime = CURRENT_TIME_SEC; | ||
77 | mark_inode_dirty(inode); | ||
78 | return 0; | ||
79 | } | ||
80 | default: | ||
81 | return -ENOTTY; | ||
82 | } | ||
83 | } | ||
84 | |||
85 | int hfsplus_setxattr(struct dentry *dentry, const char *name, | ||
86 | const void *value, size_t size, int flags) | ||
87 | { | ||
88 | struct inode *inode = dentry->d_inode; | ||
89 | struct hfs_find_data fd; | ||
90 | hfsplus_cat_entry entry; | ||
91 | struct hfsplus_cat_file *file; | ||
92 | int res; | ||
93 | |||
94 | if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode)) | ||
95 | return -EOPNOTSUPP; | ||
96 | |||
97 | res = hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd); | ||
98 | if (res) | ||
99 | return res; | ||
100 | res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); | ||
101 | if (res) | ||
102 | goto out; | ||
103 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, | ||
104 | sizeof(struct hfsplus_cat_file)); | ||
105 | file = &entry.file; | ||
106 | |||
107 | if (!strcmp(name, "hfs.type")) { | ||
108 | if (size == 4) | ||
109 | memcpy(&file->user_info.fdType, value, 4); | ||
110 | else | ||
111 | res = -ERANGE; | ||
112 | } else if (!strcmp(name, "hfs.creator")) { | ||
113 | if (size == 4) | ||
114 | memcpy(&file->user_info.fdCreator, value, 4); | ||
115 | else | ||
116 | res = -ERANGE; | ||
117 | } else | ||
118 | res = -EOPNOTSUPP; | ||
119 | if (!res) | ||
120 | hfs_bnode_write(fd.bnode, &entry, fd.entryoffset, | ||
121 | sizeof(struct hfsplus_cat_file)); | ||
122 | out: | ||
123 | hfs_find_exit(&fd); | ||
124 | return res; | ||
125 | } | ||
126 | |||
127 | ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, | ||
128 | void *value, size_t size) | ||
129 | { | ||
130 | struct inode *inode = dentry->d_inode; | ||
131 | struct hfs_find_data fd; | ||
132 | hfsplus_cat_entry entry; | ||
133 | struct hfsplus_cat_file *file; | ||
134 | ssize_t res = 0; | ||
135 | |||
136 | if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode)) | ||
137 | return -EOPNOTSUPP; | ||
138 | |||
139 | if (size) { | ||
140 | res = hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd); | ||
141 | if (res) | ||
142 | return res; | ||
143 | res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); | ||
144 | if (res) | ||
145 | goto out; | ||
146 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, | ||
147 | sizeof(struct hfsplus_cat_file)); | ||
148 | } | ||
149 | file = &entry.file; | ||
150 | |||
151 | if (!strcmp(name, "hfs.type")) { | ||
152 | if (size >= 4) { | ||
153 | memcpy(value, &file->user_info.fdType, 4); | ||
154 | res = 4; | ||
155 | } else | ||
156 | res = size ? -ERANGE : 4; | ||
157 | } else if (!strcmp(name, "hfs.creator")) { | ||
158 | if (size >= 4) { | ||
159 | memcpy(value, &file->user_info.fdCreator, 4); | ||
160 | res = 4; | ||
161 | } else | ||
162 | res = size ? -ERANGE : 4; | ||
163 | } else | ||
164 | res = -ENODATA; | ||
165 | out: | ||
166 | if (size) | ||
167 | hfs_find_exit(&fd); | ||
168 | return res; | ||
169 | } | ||
170 | |||
171 | #define HFSPLUS_ATTRLIST_SIZE (sizeof("hfs.creator")+sizeof("hfs.type")) | ||
172 | |||
173 | ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size) | ||
174 | { | ||
175 | struct inode *inode = dentry->d_inode; | ||
176 | |||
177 | if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode)) | ||
178 | return -EOPNOTSUPP; | ||
179 | |||
180 | if (!buffer || !size) | ||
181 | return HFSPLUS_ATTRLIST_SIZE; | ||
182 | if (size < HFSPLUS_ATTRLIST_SIZE) | ||
183 | return -ERANGE; | ||
184 | strcpy(buffer, "hfs.type"); | ||
185 | strcpy(buffer + sizeof("hfs.type"), "hfs.creator"); | ||
186 | |||
187 | return HFSPLUS_ATTRLIST_SIZE; | ||
188 | } | ||
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c new file mode 100644 index 000000000000..1cca0102c98d --- /dev/null +++ b/fs/hfsplus/options.c | |||
@@ -0,0 +1,162 @@ | |||
1 | /* | ||
2 | * linux/fs/hfsplus/options.c | ||
3 | * | ||
4 | * Copyright (C) 2001 | ||
5 | * Brad Boyer (flar@allandria.com) | ||
6 | * (C) 2003 Ardis Technologies <roman@ardistech.com> | ||
7 | * | ||
8 | * Option parsing | ||
9 | */ | ||
10 | |||
11 | #include <linux/string.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/parser.h> | ||
15 | #include <linux/nls.h> | ||
16 | #include "hfsplus_fs.h" | ||
17 | |||
18 | enum { | ||
19 | opt_creator, opt_type, | ||
20 | opt_umask, opt_uid, opt_gid, | ||
21 | opt_part, opt_session, opt_nls, | ||
22 | opt_nodecompose, opt_decompose, | ||
23 | opt_err | ||
24 | }; | ||
25 | |||
26 | static match_table_t tokens = { | ||
27 | { opt_creator, "creator=%s" }, | ||
28 | { opt_type, "type=%s" }, | ||
29 | { opt_umask, "umask=%o" }, | ||
30 | { opt_uid, "uid=%u" }, | ||
31 | { opt_gid, "gid=%u" }, | ||
32 | { opt_part, "part=%u" }, | ||
33 | { opt_session, "session=%u" }, | ||
34 | { opt_nls, "nls=%s" }, | ||
35 | { opt_decompose, "decompose" }, | ||
36 | { opt_nodecompose, "nodecompose" }, | ||
37 | { opt_err, NULL } | ||
38 | }; | ||
39 | |||
40 | /* Initialize an options object to reasonable defaults */ | ||
41 | void fill_defaults(struct hfsplus_sb_info *opts) | ||
42 | { | ||
43 | if (!opts) | ||
44 | return; | ||
45 | |||
46 | opts->creator = HFSPLUS_DEF_CR_TYPE; | ||
47 | opts->type = HFSPLUS_DEF_CR_TYPE; | ||
48 | opts->umask = current->fs->umask; | ||
49 | opts->uid = current->uid; | ||
50 | opts->gid = current->gid; | ||
51 | opts->part = -1; | ||
52 | opts->session = -1; | ||
53 | } | ||
54 | |||
55 | /* convert a "four byte character" to a 32 bit int with error checks */ | ||
56 | static inline int match_fourchar(substring_t *arg, u32 *result) | ||
57 | { | ||
58 | if (arg->to - arg->from != 4) | ||
59 | return -EINVAL; | ||
60 | memcpy(result, arg->from, 4); | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | /* Parse options from mount. Returns 0 on failure */ | ||
65 | /* input is the options passed to mount() as a string */ | ||
66 | int parse_options(char *input, struct hfsplus_sb_info *sbi) | ||
67 | { | ||
68 | char *p; | ||
69 | substring_t args[MAX_OPT_ARGS]; | ||
70 | int tmp, token; | ||
71 | |||
72 | if (!input) | ||
73 | goto done; | ||
74 | |||
75 | while ((p = strsep(&input, ",")) != NULL) { | ||
76 | if (!*p) | ||
77 | continue; | ||
78 | |||
79 | token = match_token(p, tokens, args); | ||
80 | switch (token) { | ||
81 | case opt_creator: | ||
82 | if (match_fourchar(&args[0], &sbi->creator)) { | ||
83 | printk("HFS+-fs: creator requires a 4 character value\n"); | ||
84 | return 0; | ||
85 | } | ||
86 | break; | ||
87 | case opt_type: | ||
88 | if (match_fourchar(&args[0], &sbi->type)) { | ||
89 | printk("HFS+-fs: type requires a 4 character value\n"); | ||
90 | return 0; | ||
91 | } | ||
92 | break; | ||
93 | case opt_umask: | ||
94 | if (match_octal(&args[0], &tmp)) { | ||
95 | printk("HFS+-fs: umask requires a value\n"); | ||
96 | return 0; | ||
97 | } | ||
98 | sbi->umask = (umode_t)tmp; | ||
99 | break; | ||
100 | case opt_uid: | ||
101 | if (match_int(&args[0], &tmp)) { | ||
102 | printk("HFS+-fs: uid requires an argument\n"); | ||
103 | return 0; | ||
104 | } | ||
105 | sbi->uid = (uid_t)tmp; | ||
106 | break; | ||
107 | case opt_gid: | ||
108 | if (match_int(&args[0], &tmp)) { | ||
109 | printk("HFS+-fs: gid requires an argument\n"); | ||
110 | return 0; | ||
111 | } | ||
112 | sbi->gid = (gid_t)tmp; | ||
113 | break; | ||
114 | case opt_part: | ||
115 | if (match_int(&args[0], &sbi->part)) { | ||
116 | printk("HFS+-fs: part requires an argument\n"); | ||
117 | return 0; | ||
118 | } | ||
119 | break; | ||
120 | case opt_session: | ||
121 | if (match_int(&args[0], &sbi->session)) { | ||
122 | printk("HFS+-fs: session requires an argument\n"); | ||
123 | return 0; | ||
124 | } | ||
125 | break; | ||
126 | case opt_nls: | ||
127 | if (sbi->nls) { | ||
128 | printk("HFS+-fs: unable to change nls mapping\n"); | ||
129 | return 0; | ||
130 | } | ||
131 | p = match_strdup(&args[0]); | ||
132 | sbi->nls = load_nls(p); | ||
133 | if (!sbi->nls) { | ||
134 | printk("HFS+-fs: unable to load nls mapping \"%s\"\n", p); | ||
135 | kfree(p); | ||
136 | return 0; | ||
137 | } | ||
138 | kfree(p); | ||
139 | break; | ||
140 | case opt_decompose: | ||
141 | sbi->flags &= ~HFSPLUS_SB_NODECOMPOSE; | ||
142 | break; | ||
143 | case opt_nodecompose: | ||
144 | sbi->flags |= HFSPLUS_SB_NODECOMPOSE; | ||
145 | break; | ||
146 | default: | ||
147 | return 0; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | done: | ||
152 | if (!sbi->nls) { | ||
153 | /* try utf8 first, as this is the old default behaviour */ | ||
154 | sbi->nls = load_nls("utf8"); | ||
155 | if (!sbi->nls) | ||
156 | sbi->nls = load_nls_default(); | ||
157 | if (!sbi->nls) | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | return 1; | ||
162 | } | ||
diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c new file mode 100644 index 000000000000..ae783066fc3a --- /dev/null +++ b/fs/hfsplus/part_tbl.c | |||
@@ -0,0 +1,133 @@ | |||
1 | /* | ||
2 | * linux/fs/hfs/part_tbl.c | ||
3 | * | ||
4 | * Copyright (C) 1996-1997 Paul H. Hargrove | ||
5 | * This file may be distributed under the terms of the GNU General Public License. | ||
6 | * | ||
7 | * Original code to handle the new style Mac partition table based on | ||
8 | * a patch contributed by Holger Schemel (aeglos@valinor.owl.de). | ||
9 | * | ||
10 | * In function preconditions the term "valid" applied to a pointer to | ||
11 | * a structure means that the pointer is non-NULL and the structure it | ||
12 | * points to has all fields initialized to consistent values. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include "hfsplus_fs.h" | ||
17 | |||
18 | /* offsets to various blocks */ | ||
19 | #define HFS_DD_BLK 0 /* Driver Descriptor block */ | ||
20 | #define HFS_PMAP_BLK 1 /* First block of partition map */ | ||
21 | #define HFS_MDB_BLK 2 /* Block (w/i partition) of MDB */ | ||
22 | |||
23 | /* magic numbers for various disk blocks */ | ||
24 | #define HFS_DRVR_DESC_MAGIC 0x4552 /* "ER": driver descriptor map */ | ||
25 | #define HFS_OLD_PMAP_MAGIC 0x5453 /* "TS": old-type partition map */ | ||
26 | #define HFS_NEW_PMAP_MAGIC 0x504D /* "PM": new-type partition map */ | ||
27 | #define HFS_SUPER_MAGIC 0x4244 /* "BD": HFS MDB (super block) */ | ||
28 | #define HFS_MFS_SUPER_MAGIC 0xD2D7 /* MFS MDB (super block) */ | ||
29 | |||
30 | /* | ||
31 | * The new style Mac partition map | ||
32 | * | ||
33 | * For each partition on the media there is a physical block (512-byte | ||
34 | * block) containing one of these structures. These blocks are | ||
35 | * contiguous starting at block 1. | ||
36 | */ | ||
37 | struct new_pmap { | ||
38 | __be16 pmSig; /* signature */ | ||
39 | __be16 reSigPad; /* padding */ | ||
40 | __be32 pmMapBlkCnt; /* partition blocks count */ | ||
41 | __be32 pmPyPartStart; /* physical block start of partition */ | ||
42 | __be32 pmPartBlkCnt; /* physical block count of partition */ | ||
43 | u8 pmPartName[32]; /* (null terminated?) string | ||
44 | giving the name of this | ||
45 | partition */ | ||
46 | u8 pmPartType[32]; /* (null terminated?) string | ||
47 | giving the type of this | ||
48 | partition */ | ||
49 | /* a bunch more stuff we don't need */ | ||
50 | } __packed; | ||
51 | |||
52 | /* | ||
53 | * The old style Mac partition map | ||
54 | * | ||
55 | * The partition map consists for a 2-byte signature followed by an | ||
56 | * array of these structures. The map is terminated with an all-zero | ||
57 | * one of these. | ||
58 | */ | ||
59 | struct old_pmap { | ||
60 | __be16 pdSig; /* Signature bytes */ | ||
61 | struct old_pmap_entry { | ||
62 | __be32 pdStart; | ||
63 | __be32 pdSize; | ||
64 | __be32 pdFSID; | ||
65 | } pdEntry[42]; | ||
66 | } __packed; | ||
67 | |||
68 | /* | ||
69 | * hfs_part_find() | ||
70 | * | ||
71 | * Parse the partition map looking for the | ||
72 | * start and length of the 'part'th HFS partition. | ||
73 | */ | ||
74 | int hfs_part_find(struct super_block *sb, | ||
75 | sector_t *part_start, sector_t *part_size) | ||
76 | { | ||
77 | struct buffer_head *bh; | ||
78 | __be16 *data; | ||
79 | int i, size, res; | ||
80 | |||
81 | res = -ENOENT; | ||
82 | bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK, data); | ||
83 | if (!bh) | ||
84 | return -EIO; | ||
85 | |||
86 | switch (be16_to_cpu(*data)) { | ||
87 | case HFS_OLD_PMAP_MAGIC: | ||
88 | { | ||
89 | struct old_pmap *pm; | ||
90 | struct old_pmap_entry *p; | ||
91 | |||
92 | pm = (struct old_pmap *)bh->b_data; | ||
93 | p = pm->pdEntry; | ||
94 | size = 42; | ||
95 | for (i = 0; i < size; p++, i++) { | ||
96 | if (p->pdStart && p->pdSize && | ||
97 | p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ && | ||
98 | (HFSPLUS_SB(sb).part < 0 || HFSPLUS_SB(sb).part == i)) { | ||
99 | *part_start += be32_to_cpu(p->pdStart); | ||
100 | *part_size = be32_to_cpu(p->pdSize); | ||
101 | res = 0; | ||
102 | } | ||
103 | } | ||
104 | break; | ||
105 | } | ||
106 | case HFS_NEW_PMAP_MAGIC: | ||
107 | { | ||
108 | struct new_pmap *pm; | ||
109 | |||
110 | pm = (struct new_pmap *)bh->b_data; | ||
111 | size = be32_to_cpu(pm->pmMapBlkCnt); | ||
112 | for (i = 0; i < size;) { | ||
113 | if (!memcmp(pm->pmPartType,"Apple_HFS", 9) && | ||
114 | (HFSPLUS_SB(sb).part < 0 || HFSPLUS_SB(sb).part == i)) { | ||
115 | *part_start += be32_to_cpu(pm->pmPyPartStart); | ||
116 | *part_size = be32_to_cpu(pm->pmPartBlkCnt); | ||
117 | res = 0; | ||
118 | break; | ||
119 | } | ||
120 | brelse(bh); | ||
121 | bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK + ++i, pm); | ||
122 | if (!bh) | ||
123 | return -EIO; | ||
124 | if (pm->pmSig != cpu_to_be16(HFS_NEW_PMAP_MAGIC)) | ||
125 | break; | ||
126 | } | ||
127 | break; | ||
128 | } | ||
129 | } | ||
130 | brelse(bh); | ||
131 | |||
132 | return res; | ||
133 | } | ||
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c new file mode 100644 index 000000000000..5f8044664a3c --- /dev/null +++ b/fs/hfsplus/super.c | |||
@@ -0,0 +1,502 @@ | |||
1 | /* | ||
2 | * linux/fs/hfsplus/super.c | ||
3 | * | ||
4 | * Copyright (C) 2001 | ||
5 | * Brad Boyer (flar@allandria.com) | ||
6 | * (C) 2003 Ardis Technologies <roman@ardistech.com> | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/pagemap.h> | ||
14 | #include <linux/fs.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/version.h> | ||
18 | #include <linux/vfs.h> | ||
19 | #include <linux/nls.h> | ||
20 | |||
21 | static struct inode *hfsplus_alloc_inode(struct super_block *sb); | ||
22 | static void hfsplus_destroy_inode(struct inode *inode); | ||
23 | |||
24 | #include "hfsplus_fs.h" | ||
25 | |||
26 | void hfsplus_inode_check(struct super_block *sb) | ||
27 | { | ||
28 | #if 0 | ||
29 | u32 cnt = atomic_read(&HFSPLUS_SB(sb).inode_cnt); | ||
30 | u32 last_cnt = HFSPLUS_SB(sb).last_inode_cnt; | ||
31 | |||
32 | if (cnt <= (last_cnt / 2) || | ||
33 | cnt >= (last_cnt * 2)) { | ||
34 | HFSPLUS_SB(sb).last_inode_cnt = cnt; | ||
35 | printk("inode_check: %u,%u,%u\n", cnt, last_cnt, | ||
36 | HFSPLUS_SB(sb).cat_tree ? HFSPLUS_SB(sb).cat_tree->node_hash_cnt : 0); | ||
37 | } | ||
38 | #endif | ||
39 | } | ||
40 | |||
41 | static void hfsplus_read_inode(struct inode *inode) | ||
42 | { | ||
43 | struct hfs_find_data fd; | ||
44 | struct hfsplus_vh *vhdr; | ||
45 | int err; | ||
46 | |||
47 | atomic_inc(&HFSPLUS_SB(inode->i_sb).inode_cnt); | ||
48 | hfsplus_inode_check(inode->i_sb); | ||
49 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); | ||
50 | init_MUTEX(&HFSPLUS_I(inode).extents_lock); | ||
51 | HFSPLUS_I(inode).flags = 0; | ||
52 | HFSPLUS_I(inode).rsrc_inode = NULL; | ||
53 | |||
54 | if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) { | ||
55 | read_inode: | ||
56 | hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd); | ||
57 | err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); | ||
58 | if (!err) | ||
59 | err = hfsplus_cat_read_inode(inode, &fd); | ||
60 | hfs_find_exit(&fd); | ||
61 | if (err) | ||
62 | goto bad_inode; | ||
63 | return; | ||
64 | } | ||
65 | vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr; | ||
66 | switch(inode->i_ino) { | ||
67 | case HFSPLUS_ROOT_CNID: | ||
68 | goto read_inode; | ||
69 | case HFSPLUS_EXT_CNID: | ||
70 | hfsplus_inode_read_fork(inode, &vhdr->ext_file); | ||
71 | inode->i_mapping->a_ops = &hfsplus_btree_aops; | ||
72 | break; | ||
73 | case HFSPLUS_CAT_CNID: | ||
74 | hfsplus_inode_read_fork(inode, &vhdr->cat_file); | ||
75 | inode->i_mapping->a_ops = &hfsplus_btree_aops; | ||
76 | break; | ||
77 | case HFSPLUS_ALLOC_CNID: | ||
78 | hfsplus_inode_read_fork(inode, &vhdr->alloc_file); | ||
79 | inode->i_mapping->a_ops = &hfsplus_aops; | ||
80 | break; | ||
81 | case HFSPLUS_START_CNID: | ||
82 | hfsplus_inode_read_fork(inode, &vhdr->start_file); | ||
83 | break; | ||
84 | case HFSPLUS_ATTR_CNID: | ||
85 | hfsplus_inode_read_fork(inode, &vhdr->attr_file); | ||
86 | inode->i_mapping->a_ops = &hfsplus_btree_aops; | ||
87 | break; | ||
88 | default: | ||
89 | goto bad_inode; | ||
90 | } | ||
91 | |||
92 | return; | ||
93 | |||
94 | bad_inode: | ||
95 | make_bad_inode(inode); | ||
96 | } | ||
97 | |||
98 | static int hfsplus_write_inode(struct inode *inode, int unused) | ||
99 | { | ||
100 | struct hfsplus_vh *vhdr; | ||
101 | int ret = 0; | ||
102 | |||
103 | dprint(DBG_INODE, "hfsplus_write_inode: %lu\n", inode->i_ino); | ||
104 | hfsplus_ext_write_extent(inode); | ||
105 | if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) { | ||
106 | return hfsplus_cat_write_inode(inode); | ||
107 | } | ||
108 | vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr; | ||
109 | switch (inode->i_ino) { | ||
110 | case HFSPLUS_ROOT_CNID: | ||
111 | ret = hfsplus_cat_write_inode(inode); | ||
112 | break; | ||
113 | case HFSPLUS_EXT_CNID: | ||
114 | if (vhdr->ext_file.total_size != cpu_to_be64(inode->i_size)) { | ||
115 | HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; | ||
116 | inode->i_sb->s_dirt = 1; | ||
117 | } | ||
118 | hfsplus_inode_write_fork(inode, &vhdr->ext_file); | ||
119 | hfs_btree_write(HFSPLUS_SB(inode->i_sb).ext_tree); | ||
120 | break; | ||
121 | case HFSPLUS_CAT_CNID: | ||
122 | if (vhdr->cat_file.total_size != cpu_to_be64(inode->i_size)) { | ||
123 | HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; | ||
124 | inode->i_sb->s_dirt = 1; | ||
125 | } | ||
126 | hfsplus_inode_write_fork(inode, &vhdr->cat_file); | ||
127 | hfs_btree_write(HFSPLUS_SB(inode->i_sb).cat_tree); | ||
128 | break; | ||
129 | case HFSPLUS_ALLOC_CNID: | ||
130 | if (vhdr->alloc_file.total_size != cpu_to_be64(inode->i_size)) { | ||
131 | HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; | ||
132 | inode->i_sb->s_dirt = 1; | ||
133 | } | ||
134 | hfsplus_inode_write_fork(inode, &vhdr->alloc_file); | ||
135 | break; | ||
136 | case HFSPLUS_START_CNID: | ||
137 | if (vhdr->start_file.total_size != cpu_to_be64(inode->i_size)) { | ||
138 | HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; | ||
139 | inode->i_sb->s_dirt = 1; | ||
140 | } | ||
141 | hfsplus_inode_write_fork(inode, &vhdr->start_file); | ||
142 | break; | ||
143 | case HFSPLUS_ATTR_CNID: | ||
144 | if (vhdr->attr_file.total_size != cpu_to_be64(inode->i_size)) { | ||
145 | HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; | ||
146 | inode->i_sb->s_dirt = 1; | ||
147 | } | ||
148 | hfsplus_inode_write_fork(inode, &vhdr->attr_file); | ||
149 | hfs_btree_write(HFSPLUS_SB(inode->i_sb).attr_tree); | ||
150 | break; | ||
151 | } | ||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | static void hfsplus_clear_inode(struct inode *inode) | ||
156 | { | ||
157 | dprint(DBG_INODE, "hfsplus_clear_inode: %lu\n", inode->i_ino); | ||
158 | atomic_dec(&HFSPLUS_SB(inode->i_sb).inode_cnt); | ||
159 | if (HFSPLUS_IS_RSRC(inode)) { | ||
160 | HFSPLUS_I(HFSPLUS_I(inode).rsrc_inode).rsrc_inode = NULL; | ||
161 | iput(HFSPLUS_I(inode).rsrc_inode); | ||
162 | } | ||
163 | hfsplus_inode_check(inode->i_sb); | ||
164 | } | ||
165 | |||
166 | static void hfsplus_write_super(struct super_block *sb) | ||
167 | { | ||
168 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; | ||
169 | |||
170 | dprint(DBG_SUPER, "hfsplus_write_super\n"); | ||
171 | sb->s_dirt = 0; | ||
172 | if (sb->s_flags & MS_RDONLY) | ||
173 | /* warn? */ | ||
174 | return; | ||
175 | |||
176 | vhdr->free_blocks = cpu_to_be32(HFSPLUS_SB(sb).free_blocks); | ||
177 | vhdr->next_alloc = cpu_to_be32(HFSPLUS_SB(sb).next_alloc); | ||
178 | vhdr->next_cnid = cpu_to_be32(HFSPLUS_SB(sb).next_cnid); | ||
179 | vhdr->folder_count = cpu_to_be32(HFSPLUS_SB(sb).folder_count); | ||
180 | vhdr->file_count = cpu_to_be32(HFSPLUS_SB(sb).file_count); | ||
181 | |||
182 | mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh); | ||
183 | if (HFSPLUS_SB(sb).flags & HFSPLUS_SB_WRITEBACKUP) { | ||
184 | if (HFSPLUS_SB(sb).sect_count) { | ||
185 | struct buffer_head *bh; | ||
186 | u32 block, offset; | ||
187 | |||
188 | block = HFSPLUS_SB(sb).blockoffset; | ||
189 | block += (HFSPLUS_SB(sb).sect_count - 2) >> (sb->s_blocksize_bits - 9); | ||
190 | offset = ((HFSPLUS_SB(sb).sect_count - 2) << 9) & (sb->s_blocksize - 1); | ||
191 | printk("backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset, | ||
192 | HFSPLUS_SB(sb).sect_count, block, offset); | ||
193 | bh = sb_bread(sb, block); | ||
194 | if (bh) { | ||
195 | vhdr = (struct hfsplus_vh *)(bh->b_data + offset); | ||
196 | if (be16_to_cpu(vhdr->signature) == HFSPLUS_VOLHEAD_SIG) { | ||
197 | memcpy(vhdr, HFSPLUS_SB(sb).s_vhdr, sizeof(*vhdr)); | ||
198 | mark_buffer_dirty(bh); | ||
199 | brelse(bh); | ||
200 | } else | ||
201 | printk("backup not found!\n"); | ||
202 | } | ||
203 | } | ||
204 | HFSPLUS_SB(sb).flags &= ~HFSPLUS_SB_WRITEBACKUP; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | static void hfsplus_put_super(struct super_block *sb) | ||
209 | { | ||
210 | dprint(DBG_SUPER, "hfsplus_put_super\n"); | ||
211 | if (!(sb->s_flags & MS_RDONLY)) { | ||
212 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; | ||
213 | |||
214 | vhdr->modify_date = hfsp_now2mt(); | ||
215 | vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_UNMNT); | ||
216 | vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_INCNSTNT); | ||
217 | mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh); | ||
218 | ll_rw_block(WRITE, 1, &HFSPLUS_SB(sb).s_vhbh); | ||
219 | wait_on_buffer(HFSPLUS_SB(sb).s_vhbh); | ||
220 | } | ||
221 | |||
222 | hfs_btree_close(HFSPLUS_SB(sb).cat_tree); | ||
223 | hfs_btree_close(HFSPLUS_SB(sb).ext_tree); | ||
224 | iput(HFSPLUS_SB(sb).alloc_file); | ||
225 | iput(HFSPLUS_SB(sb).hidden_dir); | ||
226 | brelse(HFSPLUS_SB(sb).s_vhbh); | ||
227 | if (HFSPLUS_SB(sb).nls) | ||
228 | unload_nls(HFSPLUS_SB(sb).nls); | ||
229 | } | ||
230 | |||
231 | static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf) | ||
232 | { | ||
233 | buf->f_type = HFSPLUS_SUPER_MAGIC; | ||
234 | buf->f_bsize = sb->s_blocksize; | ||
235 | buf->f_blocks = HFSPLUS_SB(sb).total_blocks << HFSPLUS_SB(sb).fs_shift; | ||
236 | buf->f_bfree = HFSPLUS_SB(sb).free_blocks << HFSPLUS_SB(sb).fs_shift; | ||
237 | buf->f_bavail = buf->f_bfree; | ||
238 | buf->f_files = 0xFFFFFFFF; | ||
239 | buf->f_ffree = 0xFFFFFFFF - HFSPLUS_SB(sb).next_cnid; | ||
240 | buf->f_namelen = HFSPLUS_MAX_STRLEN; | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static int hfsplus_remount(struct super_block *sb, int *flags, char *data) | ||
246 | { | ||
247 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) | ||
248 | return 0; | ||
249 | if (!(*flags & MS_RDONLY)) { | ||
250 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; | ||
251 | |||
252 | if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { | ||
253 | printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " | ||
254 | "running fsck.hfsplus is recommended. leaving read-only.\n"); | ||
255 | sb->s_flags |= MS_RDONLY; | ||
256 | *flags |= MS_RDONLY; | ||
257 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { | ||
258 | printk("HFS+-fs: Filesystem is marked locked, leaving read-only.\n"); | ||
259 | sb->s_flags |= MS_RDONLY; | ||
260 | *flags |= MS_RDONLY; | ||
261 | } | ||
262 | } | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static struct super_operations hfsplus_sops = { | ||
267 | .alloc_inode = hfsplus_alloc_inode, | ||
268 | .destroy_inode = hfsplus_destroy_inode, | ||
269 | .read_inode = hfsplus_read_inode, | ||
270 | .write_inode = hfsplus_write_inode, | ||
271 | .clear_inode = hfsplus_clear_inode, | ||
272 | .put_super = hfsplus_put_super, | ||
273 | .write_super = hfsplus_write_super, | ||
274 | .statfs = hfsplus_statfs, | ||
275 | .remount_fs = hfsplus_remount, | ||
276 | }; | ||
277 | |||
278 | static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | ||
279 | { | ||
280 | struct hfsplus_vh *vhdr; | ||
281 | struct hfsplus_sb_info *sbi; | ||
282 | hfsplus_cat_entry entry; | ||
283 | struct hfs_find_data fd; | ||
284 | struct inode *root; | ||
285 | struct qstr str; | ||
286 | struct nls_table *nls = NULL; | ||
287 | int err = -EINVAL; | ||
288 | |||
289 | sbi = kmalloc(sizeof(struct hfsplus_sb_info), GFP_KERNEL); | ||
290 | if (!sbi) | ||
291 | return -ENOMEM; | ||
292 | |||
293 | memset(sbi, 0, sizeof(HFSPLUS_SB(sb))); | ||
294 | sb->s_fs_info = sbi; | ||
295 | INIT_HLIST_HEAD(&sbi->rsrc_inodes); | ||
296 | fill_defaults(sbi); | ||
297 | if (!parse_options(data, sbi)) { | ||
298 | if (!silent) | ||
299 | printk("HFS+-fs: unable to parse mount options\n"); | ||
300 | err = -EINVAL; | ||
301 | goto cleanup; | ||
302 | } | ||
303 | |||
304 | /* temporarily use utf8 to correctly find the hidden dir below */ | ||
305 | nls = sbi->nls; | ||
306 | sbi->nls = load_nls("utf8"); | ||
307 | if (!nls) { | ||
308 | printk("HFS+: unable to load nls for utf8\n"); | ||
309 | err = -EINVAL; | ||
310 | goto cleanup; | ||
311 | } | ||
312 | |||
313 | /* Grab the volume header */ | ||
314 | if (hfsplus_read_wrapper(sb)) { | ||
315 | if (!silent) | ||
316 | printk("HFS+-fs: unable to find HFS+ superblock\n"); | ||
317 | err = -EINVAL; | ||
318 | goto cleanup; | ||
319 | } | ||
320 | vhdr = HFSPLUS_SB(sb).s_vhdr; | ||
321 | |||
322 | /* Copy parts of the volume header into the superblock */ | ||
323 | sb->s_magic = be16_to_cpu(vhdr->signature); | ||
324 | if (be16_to_cpu(vhdr->version) != HFSPLUS_CURRENT_VERSION) { | ||
325 | if (!silent) | ||
326 | printk("HFS+-fs: wrong filesystem version\n"); | ||
327 | goto cleanup; | ||
328 | } | ||
329 | HFSPLUS_SB(sb).total_blocks = be32_to_cpu(vhdr->total_blocks); | ||
330 | HFSPLUS_SB(sb).free_blocks = be32_to_cpu(vhdr->free_blocks); | ||
331 | HFSPLUS_SB(sb).next_alloc = be32_to_cpu(vhdr->next_alloc); | ||
332 | HFSPLUS_SB(sb).next_cnid = be32_to_cpu(vhdr->next_cnid); | ||
333 | HFSPLUS_SB(sb).file_count = be32_to_cpu(vhdr->file_count); | ||
334 | HFSPLUS_SB(sb).folder_count = be32_to_cpu(vhdr->folder_count); | ||
335 | HFSPLUS_SB(sb).data_clump_blocks = be32_to_cpu(vhdr->data_clump_sz) >> HFSPLUS_SB(sb).alloc_blksz_shift; | ||
336 | if (!HFSPLUS_SB(sb).data_clump_blocks) | ||
337 | HFSPLUS_SB(sb).data_clump_blocks = 1; | ||
338 | HFSPLUS_SB(sb).rsrc_clump_blocks = be32_to_cpu(vhdr->rsrc_clump_sz) >> HFSPLUS_SB(sb).alloc_blksz_shift; | ||
339 | if (!HFSPLUS_SB(sb).rsrc_clump_blocks) | ||
340 | HFSPLUS_SB(sb).rsrc_clump_blocks = 1; | ||
341 | |||
342 | /* Set up operations so we can load metadata */ | ||
343 | sb->s_op = &hfsplus_sops; | ||
344 | sb->s_maxbytes = MAX_LFS_FILESIZE; | ||
345 | |||
346 | if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { | ||
347 | if (!silent) | ||
348 | printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " | ||
349 | "running fsck.hfsplus is recommended. mounting read-only.\n"); | ||
350 | sb->s_flags |= MS_RDONLY; | ||
351 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { | ||
352 | if (!silent) | ||
353 | printk("HFS+-fs: Filesystem is marked locked, mounting read-only.\n"); | ||
354 | sb->s_flags |= MS_RDONLY; | ||
355 | } | ||
356 | |||
357 | /* Load metadata objects (B*Trees) */ | ||
358 | HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); | ||
359 | if (!HFSPLUS_SB(sb).ext_tree) { | ||
360 | if (!silent) | ||
361 | printk("HFS+-fs: failed to load extents file\n"); | ||
362 | goto cleanup; | ||
363 | } | ||
364 | HFSPLUS_SB(sb).cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); | ||
365 | if (!HFSPLUS_SB(sb).cat_tree) { | ||
366 | if (!silent) | ||
367 | printk("HFS+-fs: failed to load catalog file\n"); | ||
368 | goto cleanup; | ||
369 | } | ||
370 | |||
371 | HFSPLUS_SB(sb).alloc_file = iget(sb, HFSPLUS_ALLOC_CNID); | ||
372 | if (!HFSPLUS_SB(sb).alloc_file) { | ||
373 | if (!silent) | ||
374 | printk("HFS+-fs: failed to load allocation file\n"); | ||
375 | goto cleanup; | ||
376 | } | ||
377 | |||
378 | /* Load the root directory */ | ||
379 | root = iget(sb, HFSPLUS_ROOT_CNID); | ||
380 | sb->s_root = d_alloc_root(root); | ||
381 | if (!sb->s_root) { | ||
382 | if (!silent) | ||
383 | printk("HFS+-fs: failed to load root directory\n"); | ||
384 | iput(root); | ||
385 | goto cleanup; | ||
386 | } | ||
387 | |||
388 | str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1; | ||
389 | str.name = HFSP_HIDDENDIR_NAME; | ||
390 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | ||
391 | hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str); | ||
392 | if (!hfs_brec_read(&fd, &entry, sizeof(entry))) { | ||
393 | hfs_find_exit(&fd); | ||
394 | if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) | ||
395 | goto cleanup; | ||
396 | HFSPLUS_SB(sb).hidden_dir = iget(sb, be32_to_cpu(entry.folder.id)); | ||
397 | if (!HFSPLUS_SB(sb).hidden_dir) | ||
398 | goto cleanup; | ||
399 | } else | ||
400 | hfs_find_exit(&fd); | ||
401 | |||
402 | if (sb->s_flags & MS_RDONLY) | ||
403 | goto out; | ||
404 | |||
405 | /* H+LX == hfsplusutils, H+Lx == this driver, H+lx is unused | ||
406 | * all three are registered with Apple for our use | ||
407 | */ | ||
408 | vhdr->last_mount_vers = cpu_to_be32(HFSP_MOUNT_VERSION); | ||
409 | vhdr->modify_date = hfsp_now2mt(); | ||
410 | vhdr->write_count = cpu_to_be32(be32_to_cpu(vhdr->write_count) + 1); | ||
411 | vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT); | ||
412 | vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT); | ||
413 | mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh); | ||
414 | ll_rw_block(WRITE, 1, &HFSPLUS_SB(sb).s_vhbh); | ||
415 | wait_on_buffer(HFSPLUS_SB(sb).s_vhbh); | ||
416 | |||
417 | if (!HFSPLUS_SB(sb).hidden_dir) { | ||
418 | printk("HFS+: create hidden dir...\n"); | ||
419 | HFSPLUS_SB(sb).hidden_dir = hfsplus_new_inode(sb, S_IFDIR); | ||
420 | hfsplus_create_cat(HFSPLUS_SB(sb).hidden_dir->i_ino, sb->s_root->d_inode, | ||
421 | &str, HFSPLUS_SB(sb).hidden_dir); | ||
422 | mark_inode_dirty(HFSPLUS_SB(sb).hidden_dir); | ||
423 | } | ||
424 | out: | ||
425 | unload_nls(sbi->nls); | ||
426 | sbi->nls = nls; | ||
427 | return 0; | ||
428 | |||
429 | cleanup: | ||
430 | hfsplus_put_super(sb); | ||
431 | if (nls) | ||
432 | unload_nls(nls); | ||
433 | return err; | ||
434 | } | ||
435 | |||
436 | MODULE_AUTHOR("Brad Boyer"); | ||
437 | MODULE_DESCRIPTION("Extended Macintosh Filesystem"); | ||
438 | MODULE_LICENSE("GPL"); | ||
439 | |||
440 | static kmem_cache_t *hfsplus_inode_cachep; | ||
441 | |||
442 | static struct inode *hfsplus_alloc_inode(struct super_block *sb) | ||
443 | { | ||
444 | struct hfsplus_inode_info *i; | ||
445 | |||
446 | i = kmem_cache_alloc(hfsplus_inode_cachep, SLAB_KERNEL); | ||
447 | return i ? &i->vfs_inode : NULL; | ||
448 | } | ||
449 | |||
450 | static void hfsplus_destroy_inode(struct inode *inode) | ||
451 | { | ||
452 | kmem_cache_free(hfsplus_inode_cachep, &HFSPLUS_I(inode)); | ||
453 | } | ||
454 | |||
455 | #define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info) | ||
456 | |||
457 | static struct super_block *hfsplus_get_sb(struct file_system_type *fs_type, | ||
458 | int flags, const char *dev_name, void *data) | ||
459 | { | ||
460 | return get_sb_bdev(fs_type, flags, dev_name, data, hfsplus_fill_super); | ||
461 | } | ||
462 | |||
463 | static struct file_system_type hfsplus_fs_type = { | ||
464 | .owner = THIS_MODULE, | ||
465 | .name = "hfsplus", | ||
466 | .get_sb = hfsplus_get_sb, | ||
467 | .kill_sb = kill_block_super, | ||
468 | .fs_flags = FS_REQUIRES_DEV, | ||
469 | }; | ||
470 | |||
471 | static void hfsplus_init_once(void *p, kmem_cache_t *cachep, unsigned long flags) | ||
472 | { | ||
473 | struct hfsplus_inode_info *i = p; | ||
474 | |||
475 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) | ||
476 | inode_init_once(&i->vfs_inode); | ||
477 | } | ||
478 | |||
479 | static int __init init_hfsplus_fs(void) | ||
480 | { | ||
481 | int err; | ||
482 | |||
483 | hfsplus_inode_cachep = kmem_cache_create("hfsplus_icache", | ||
484 | HFSPLUS_INODE_SIZE, 0, SLAB_HWCACHE_ALIGN, | ||
485 | hfsplus_init_once, NULL); | ||
486 | if (!hfsplus_inode_cachep) | ||
487 | return -ENOMEM; | ||
488 | err = register_filesystem(&hfsplus_fs_type); | ||
489 | if (err) | ||
490 | kmem_cache_destroy(hfsplus_inode_cachep); | ||
491 | return err; | ||
492 | } | ||
493 | |||
494 | static void __exit exit_hfsplus_fs(void) | ||
495 | { | ||
496 | unregister_filesystem(&hfsplus_fs_type); | ||
497 | if (kmem_cache_destroy(hfsplus_inode_cachep)) | ||
498 | printk(KERN_INFO "hfsplus_inode_cache: not all structures were freed\n"); | ||
499 | } | ||
500 | |||
501 | module_init(init_hfsplus_fs) | ||
502 | module_exit(exit_hfsplus_fs) | ||
diff --git a/fs/hfsplus/tables.c b/fs/hfsplus/tables.c new file mode 100644 index 000000000000..1b911730a0c1 --- /dev/null +++ b/fs/hfsplus/tables.c | |||
@@ -0,0 +1,3245 @@ | |||
1 | /* | ||
2 | * linux/fs/hfsplus/tables.c | ||
3 | * | ||
4 | * Various data tables | ||
5 | */ | ||
6 | |||
7 | #include "hfsplus_fs.h" | ||
8 | |||
9 | /* | ||
10 | * Unicode case folding table taken from Apple Technote #1150 | ||
11 | * (HFS Plus Volume Format) | ||
12 | */ | ||
13 | |||
14 | u16 hfsplus_case_fold_table[] = { | ||
15 | /* | ||
16 | * The lower case table consists of a 256-entry high-byte table followed by | ||
17 | * some number of 256-entry subtables. The high-byte table contains either an | ||
18 | * offset to the subtable for characters with that high byte or zero, which | ||
19 | * means that there are no case mappings or ignored characters in that block. | ||
20 | * Ignored characters are mapped to zero. | ||
21 | */ | ||
22 | |||
23 | // High-byte indices ( == 0 iff no case mapping and no ignorables ) | ||
24 | |||
25 | |||
26 | /* 0 */ 0x0100, 0x0200, 0x0000, 0x0300, 0x0400, 0x0500, 0x0000, 0x0000, | ||
27 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
28 | /* 1 */ 0x0600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
29 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
30 | /* 2 */ 0x0700, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
31 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
32 | /* 3 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
33 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
34 | /* 4 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
35 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
36 | /* 5 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
37 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
38 | /* 6 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
39 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
40 | /* 7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
41 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
42 | /* 8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
43 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
44 | /* 9 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
45 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
46 | /* A */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
47 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
48 | /* B */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
49 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
50 | /* C */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
51 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
52 | /* D */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
53 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
54 | /* E */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
55 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
56 | /* F */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
57 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0900, 0x0A00, | ||
58 | |||
59 | // Table 1 (for high byte 0x00) | ||
60 | |||
61 | /* 0 */ 0xFFFF, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, | ||
62 | 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, | ||
63 | /* 1 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, | ||
64 | 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, | ||
65 | /* 2 */ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, | ||
66 | 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, | ||
67 | /* 3 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, | ||
68 | 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, | ||
69 | /* 4 */ 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, | ||
70 | 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, | ||
71 | /* 5 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, | ||
72 | 0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, | ||
73 | /* 6 */ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, | ||
74 | 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, | ||
75 | /* 7 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, | ||
76 | 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, | ||
77 | /* 8 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, | ||
78 | 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, | ||
79 | /* 9 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, | ||
80 | 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, | ||
81 | /* A */ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, | ||
82 | 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, | ||
83 | /* B */ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, | ||
84 | 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, | ||
85 | /* C */ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00E6, 0x00C7, | ||
86 | 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, | ||
87 | /* D */ 0x00F0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, | ||
88 | 0x00F8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00FE, 0x00DF, | ||
89 | /* E */ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, | ||
90 | 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, | ||
91 | /* F */ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, | ||
92 | 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, | ||
93 | |||
94 | // Table 2 (for high byte 0x01) | ||
95 | |||
96 | /* 0 */ 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, | ||
97 | 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F, | ||
98 | /* 1 */ 0x0111, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117, | ||
99 | 0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E, 0x011F, | ||
100 | /* 2 */ 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0127, 0x0127, | ||
101 | 0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F, | ||
102 | /* 3 */ 0x0130, 0x0131, 0x0133, 0x0133, 0x0134, 0x0135, 0x0136, 0x0137, | ||
103 | 0x0138, 0x0139, 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x0140, | ||
104 | /* 4 */ 0x0140, 0x0142, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147, | ||
105 | 0x0148, 0x0149, 0x014B, 0x014B, 0x014C, 0x014D, 0x014E, 0x014F, | ||
106 | /* 5 */ 0x0150, 0x0151, 0x0153, 0x0153, 0x0154, 0x0155, 0x0156, 0x0157, | ||
107 | 0x0158, 0x0159, 0x015A, 0x015B, 0x015C, 0x015D, 0x015E, 0x015F, | ||
108 | /* 6 */ 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x0167, 0x0167, | ||
109 | 0x0168, 0x0169, 0x016A, 0x016B, 0x016C, 0x016D, 0x016E, 0x016F, | ||
110 | /* 7 */ 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175, 0x0176, 0x0177, | ||
111 | 0x0178, 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E, 0x017F, | ||
112 | /* 8 */ 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188, | ||
113 | 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259, | ||
114 | /* 9 */ 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268, | ||
115 | 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275, | ||
116 | /* A */ 0x01A0, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x01A6, 0x01A8, | ||
117 | 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01AF, | ||
118 | /* B */ 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292, | ||
119 | 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF, | ||
120 | /* C */ 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9, | ||
121 | 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC, 0x01CD, 0x01CE, 0x01CF, | ||
122 | /* D */ 0x01D0, 0x01D1, 0x01D2, 0x01D3, 0x01D4, 0x01D5, 0x01D6, 0x01D7, | ||
123 | 0x01D8, 0x01D9, 0x01DA, 0x01DB, 0x01DC, 0x01DD, 0x01DE, 0x01DF, | ||
124 | /* E */ 0x01E0, 0x01E1, 0x01E2, 0x01E3, 0x01E5, 0x01E5, 0x01E6, 0x01E7, | ||
125 | 0x01E8, 0x01E9, 0x01EA, 0x01EB, 0x01EC, 0x01ED, 0x01EE, 0x01EF, | ||
126 | /* F */ 0x01F0, 0x01F3, 0x01F3, 0x01F3, 0x01F4, 0x01F5, 0x01F6, 0x01F7, | ||
127 | 0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF, | ||
128 | |||
129 | // Table 3 (for high byte 0x03) | ||
130 | |||
131 | /* 0 */ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, | ||
132 | 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F, | ||
133 | /* 1 */ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, | ||
134 | 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F, | ||
135 | /* 2 */ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, | ||
136 | 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, | ||
137 | /* 3 */ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, | ||
138 | 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F, | ||
139 | /* 4 */ 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347, | ||
140 | 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F, | ||
141 | /* 5 */ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, | ||
142 | 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F, | ||
143 | /* 6 */ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, | ||
144 | 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F, | ||
145 | /* 7 */ 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377, | ||
146 | 0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F, | ||
147 | /* 8 */ 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387, | ||
148 | 0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F, | ||
149 | /* 9 */ 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, | ||
150 | 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, | ||
151 | /* A */ 0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, | ||
152 | 0x03C8, 0x03C9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, | ||
153 | /* B */ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, | ||
154 | 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, | ||
155 | /* C */ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, | ||
156 | 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF, | ||
157 | /* D */ 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7, | ||
158 | 0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF, | ||
159 | /* E */ 0x03E0, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7, | ||
160 | 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF, | ||
161 | /* F */ 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7, | ||
162 | 0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, | ||
163 | |||
164 | // Table 4 (for high byte 0x04) | ||
165 | |||
166 | /* 0 */ 0x0400, 0x0401, 0x0452, 0x0403, 0x0454, 0x0455, 0x0456, 0x0407, | ||
167 | 0x0458, 0x0459, 0x045A, 0x045B, 0x040C, 0x040D, 0x040E, 0x045F, | ||
168 | /* 1 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, | ||
169 | 0x0438, 0x0419, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, | ||
170 | /* 2 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, | ||
171 | 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, | ||
172 | /* 3 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, | ||
173 | 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, | ||
174 | /* 4 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, | ||
175 | 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, | ||
176 | /* 5 */ 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, | ||
177 | 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F, | ||
178 | /* 6 */ 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467, | ||
179 | 0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F, | ||
180 | /* 7 */ 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0476, 0x0477, | ||
181 | 0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F, | ||
182 | /* 8 */ 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, | ||
183 | 0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F, | ||
184 | /* 9 */ 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497, | ||
185 | 0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F, | ||
186 | /* A */ 0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7, | ||
187 | 0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF, | ||
188 | /* B */ 0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7, | ||
189 | 0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF, | ||
190 | /* C */ 0x04C0, 0x04C1, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8, | ||
191 | 0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF, | ||
192 | /* D */ 0x04D0, 0x04D1, 0x04D2, 0x04D3, 0x04D4, 0x04D5, 0x04D6, 0x04D7, | ||
193 | 0x04D8, 0x04D9, 0x04DA, 0x04DB, 0x04DC, 0x04DD, 0x04DE, 0x04DF, | ||
194 | /* E */ 0x04E0, 0x04E1, 0x04E2, 0x04E3, 0x04E4, 0x04E5, 0x04E6, 0x04E7, | ||
195 | 0x04E8, 0x04E9, 0x04EA, 0x04EB, 0x04EC, 0x04ED, 0x04EE, 0x04EF, | ||
196 | /* F */ 0x04F0, 0x04F1, 0x04F2, 0x04F3, 0x04F4, 0x04F5, 0x04F6, 0x04F7, | ||
197 | 0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF, | ||
198 | |||
199 | // Table 5 (for high byte 0x05) | ||
200 | |||
201 | /* 0 */ 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, | ||
202 | 0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F, | ||
203 | /* 1 */ 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517, | ||
204 | 0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F, | ||
205 | /* 2 */ 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527, | ||
206 | 0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F, | ||
207 | /* 3 */ 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, | ||
208 | 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F, | ||
209 | /* 4 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, | ||
210 | 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F, | ||
211 | /* 5 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557, | ||
212 | 0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F, | ||
213 | /* 6 */ 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, | ||
214 | 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F, | ||
215 | /* 7 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, | ||
216 | 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F, | ||
217 | /* 8 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587, | ||
218 | 0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F, | ||
219 | /* 9 */ 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597, | ||
220 | 0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F, | ||
221 | /* A */ 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7, | ||
222 | 0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF, | ||
223 | /* B */ 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, | ||
224 | 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, | ||
225 | /* C */ 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7, | ||
226 | 0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF, | ||
227 | /* D */ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, | ||
228 | 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, | ||
229 | /* E */ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, | ||
230 | 0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF, | ||
231 | /* F */ 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7, | ||
232 | 0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, | ||
233 | |||
234 | // Table 6 (for high byte 0x10) | ||
235 | |||
236 | /* 0 */ 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, | ||
237 | 0x1008, 0x1009, 0x100A, 0x100B, 0x100C, 0x100D, 0x100E, 0x100F, | ||
238 | /* 1 */ 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017, | ||
239 | 0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, 0x101E, 0x101F, | ||
240 | /* 2 */ 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027, | ||
241 | 0x1028, 0x1029, 0x102A, 0x102B, 0x102C, 0x102D, 0x102E, 0x102F, | ||
242 | /* 3 */ 0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037, | ||
243 | 0x1038, 0x1039, 0x103A, 0x103B, 0x103C, 0x103D, 0x103E, 0x103F, | ||
244 | /* 4 */ 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047, | ||
245 | 0x1048, 0x1049, 0x104A, 0x104B, 0x104C, 0x104D, 0x104E, 0x104F, | ||
246 | /* 5 */ 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057, | ||
247 | 0x1058, 0x1059, 0x105A, 0x105B, 0x105C, 0x105D, 0x105E, 0x105F, | ||
248 | /* 6 */ 0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, 0x1066, 0x1067, | ||
249 | 0x1068, 0x1069, 0x106A, 0x106B, 0x106C, 0x106D, 0x106E, 0x106F, | ||
250 | /* 7 */ 0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077, | ||
251 | 0x1078, 0x1079, 0x107A, 0x107B, 0x107C, 0x107D, 0x107E, 0x107F, | ||
252 | /* 8 */ 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087, | ||
253 | 0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F, | ||
254 | /* 9 */ 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097, | ||
255 | 0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x109F, | ||
256 | /* A */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7, | ||
257 | 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF, | ||
258 | /* B */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, | ||
259 | 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF, | ||
260 | /* C */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10C6, 0x10C7, | ||
261 | 0x10C8, 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF, | ||
262 | /* D */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7, | ||
263 | 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF, | ||
264 | /* E */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, | ||
265 | 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF, | ||
266 | /* F */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, 0x10F7, | ||
267 | 0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, 0x10FD, 0x10FE, 0x10FF, | ||
268 | |||
269 | // Table 7 (for high byte 0x20) | ||
270 | |||
271 | /* 0 */ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, | ||
272 | 0x2008, 0x2009, 0x200A, 0x200B, 0x0000, 0x0000, 0x0000, 0x0000, | ||
273 | /* 1 */ 0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017, | ||
274 | 0x2018, 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E, 0x201F, | ||
275 | /* 2 */ 0x2020, 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027, | ||
276 | 0x2028, 0x2029, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x202F, | ||
277 | /* 3 */ 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037, | ||
278 | 0x2038, 0x2039, 0x203A, 0x203B, 0x203C, 0x203D, 0x203E, 0x203F, | ||
279 | /* 4 */ 0x2040, 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047, | ||
280 | 0x2048, 0x2049, 0x204A, 0x204B, 0x204C, 0x204D, 0x204E, 0x204F, | ||
281 | /* 5 */ 0x2050, 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057, | ||
282 | 0x2058, 0x2059, 0x205A, 0x205B, 0x205C, 0x205D, 0x205E, 0x205F, | ||
283 | /* 6 */ 0x2060, 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067, | ||
284 | 0x2068, 0x2069, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
285 | /* 7 */ 0x2070, 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077, | ||
286 | 0x2078, 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F, | ||
287 | /* 8 */ 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087, | ||
288 | 0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, 0x208E, 0x208F, | ||
289 | /* 9 */ 0x2090, 0x2091, 0x2092, 0x2093, 0x2094, 0x2095, 0x2096, 0x2097, | ||
290 | 0x2098, 0x2099, 0x209A, 0x209B, 0x209C, 0x209D, 0x209E, 0x209F, | ||
291 | /* A */ 0x20A0, 0x20A1, 0x20A2, 0x20A3, 0x20A4, 0x20A5, 0x20A6, 0x20A7, | ||
292 | 0x20A8, 0x20A9, 0x20AA, 0x20AB, 0x20AC, 0x20AD, 0x20AE, 0x20AF, | ||
293 | /* B */ 0x20B0, 0x20B1, 0x20B2, 0x20B3, 0x20B4, 0x20B5, 0x20B6, 0x20B7, | ||
294 | 0x20B8, 0x20B9, 0x20BA, 0x20BB, 0x20BC, 0x20BD, 0x20BE, 0x20BF, | ||
295 | /* C */ 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7, | ||
296 | 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF, | ||
297 | /* D */ 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7, | ||
298 | 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x20DF, | ||
299 | /* E */ 0x20E0, 0x20E1, 0x20E2, 0x20E3, 0x20E4, 0x20E5, 0x20E6, 0x20E7, | ||
300 | 0x20E8, 0x20E9, 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF, | ||
301 | /* F */ 0x20F0, 0x20F1, 0x20F2, 0x20F3, 0x20F4, 0x20F5, 0x20F6, 0x20F7, | ||
302 | 0x20F8, 0x20F9, 0x20FA, 0x20FB, 0x20FC, 0x20FD, 0x20FE, 0x20FF, | ||
303 | |||
304 | // Table 8 (for high byte 0x21) | ||
305 | |||
306 | /* 0 */ 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107, | ||
307 | 0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F, | ||
308 | /* 1 */ 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117, | ||
309 | 0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F, | ||
310 | /* 2 */ 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127, | ||
311 | 0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F, | ||
312 | /* 3 */ 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137, | ||
313 | 0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F, | ||
314 | /* 4 */ 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147, | ||
315 | 0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F, | ||
316 | /* 5 */ 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, | ||
317 | 0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F, | ||
318 | /* 6 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, | ||
319 | 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, | ||
320 | /* 7 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, | ||
321 | 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, | ||
322 | /* 8 */ 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187, | ||
323 | 0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F, | ||
324 | /* 9 */ 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197, | ||
325 | 0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F, | ||
326 | /* A */ 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7, | ||
327 | 0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF, | ||
328 | /* B */ 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7, | ||
329 | 0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF, | ||
330 | /* C */ 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7, | ||
331 | 0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF, | ||
332 | /* D */ 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7, | ||
333 | 0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF, | ||
334 | /* E */ 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7, | ||
335 | 0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF, | ||
336 | /* F */ 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7, | ||
337 | 0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF, | ||
338 | |||
339 | // Table 9 (for high byte 0xFE) | ||
340 | |||
341 | /* 0 */ 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, | ||
342 | 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, | ||
343 | /* 1 */ 0xFE10, 0xFE11, 0xFE12, 0xFE13, 0xFE14, 0xFE15, 0xFE16, 0xFE17, | ||
344 | 0xFE18, 0xFE19, 0xFE1A, 0xFE1B, 0xFE1C, 0xFE1D, 0xFE1E, 0xFE1F, | ||
345 | /* 2 */ 0xFE20, 0xFE21, 0xFE22, 0xFE23, 0xFE24, 0xFE25, 0xFE26, 0xFE27, | ||
346 | 0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, 0xFE2E, 0xFE2F, | ||
347 | /* 3 */ 0xFE30, 0xFE31, 0xFE32, 0xFE33, 0xFE34, 0xFE35, 0xFE36, 0xFE37, | ||
348 | 0xFE38, 0xFE39, 0xFE3A, 0xFE3B, 0xFE3C, 0xFE3D, 0xFE3E, 0xFE3F, | ||
349 | /* 4 */ 0xFE40, 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xFE45, 0xFE46, 0xFE47, | ||
350 | 0xFE48, 0xFE49, 0xFE4A, 0xFE4B, 0xFE4C, 0xFE4D, 0xFE4E, 0xFE4F, | ||
351 | /* 5 */ 0xFE50, 0xFE51, 0xFE52, 0xFE53, 0xFE54, 0xFE55, 0xFE56, 0xFE57, | ||
352 | 0xFE58, 0xFE59, 0xFE5A, 0xFE5B, 0xFE5C, 0xFE5D, 0xFE5E, 0xFE5F, | ||
353 | /* 6 */ 0xFE60, 0xFE61, 0xFE62, 0xFE63, 0xFE64, 0xFE65, 0xFE66, 0xFE67, | ||
354 | 0xFE68, 0xFE69, 0xFE6A, 0xFE6B, 0xFE6C, 0xFE6D, 0xFE6E, 0xFE6F, | ||
355 | /* 7 */ 0xFE70, 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE75, 0xFE76, 0xFE77, | ||
356 | 0xFE78, 0xFE79, 0xFE7A, 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F, | ||
357 | /* 8 */ 0xFE80, 0xFE81, 0xFE82, 0xFE83, 0xFE84, 0xFE85, 0xFE86, 0xFE87, | ||
358 | 0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, 0xFE8D, 0xFE8E, 0xFE8F, | ||
359 | /* 9 */ 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95, 0xFE96, 0xFE97, | ||
360 | 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E, 0xFE9F, | ||
361 | /* A */ 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7, | ||
362 | 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF, | ||
363 | /* B */ 0xFEB0, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7, | ||
364 | 0xFEB8, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF, | ||
365 | /* C */ 0xFEC0, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7, | ||
366 | 0xFEC8, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, 0xFECD, 0xFECE, 0xFECF, | ||
367 | /* D */ 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4, 0xFED5, 0xFED6, 0xFED7, | ||
368 | 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD, 0xFEDE, 0xFEDF, | ||
369 | /* E */ 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6, 0xFEE7, | ||
370 | 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF, | ||
371 | /* F */ 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7, | ||
372 | 0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0x0000, | ||
373 | |||
374 | // Table 10 (for high byte 0xFF) | ||
375 | |||
376 | /* 0 */ 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07, | ||
377 | 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F, | ||
378 | /* 1 */ 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17, | ||
379 | 0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F, | ||
380 | /* 2 */ 0xFF20, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, | ||
381 | 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, | ||
382 | /* 3 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, | ||
383 | 0xFF58, 0xFF59, 0xFF5A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F, | ||
384 | /* 4 */ 0xFF40, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, | ||
385 | 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, | ||
386 | /* 5 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, | ||
387 | 0xFF58, 0xFF59, 0xFF5A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F, | ||
388 | /* 6 */ 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, | ||
389 | 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, | ||
390 | /* 7 */ 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, | ||
391 | 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, | ||
392 | /* 8 */ 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, | ||
393 | 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, | ||
394 | /* 9 */ 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, | ||
395 | 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, | ||
396 | /* A */ 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7, | ||
397 | 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF, | ||
398 | /* B */ 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7, | ||
399 | 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF, | ||
400 | /* C */ 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7, | ||
401 | 0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF, | ||
402 | /* D */ 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7, | ||
403 | 0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF, | ||
404 | /* E */ 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7, | ||
405 | 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF, | ||
406 | /* F */ 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7, | ||
407 | 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF, | ||
408 | }; | ||
409 | |||
410 | u16 hfsplus_decompose_table[] = { | ||
411 | /* base table */ | ||
412 | 0x0010, 0x04c0, 0x0000, 0x06f0, 0x0000, 0x0000, 0x0000, 0x0000, | ||
413 | 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x07b0, | ||
414 | /* char table 0x0___ */ | ||
415 | 0x0020, 0x0070, 0x0160, 0x0190, 0x0230, 0x0000, 0x0000, 0x0000, | ||
416 | 0x0000, 0x02d0, 0x0340, 0x0360, 0x03b0, 0x03e0, 0x0400, 0x0430, | ||
417 | /* char table 0x00__ */ | ||
418 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
419 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0030, 0x0040, 0x0050, 0x0060, | ||
420 | /* char values 0x00c_ */ | ||
421 | 0x2042, 0x204a, 0x2052, 0x205a, 0x2062, 0x206a, 0x0000, 0x2072, | ||
422 | 0x207a, 0x2082, 0x208a, 0x2092, 0x209a, 0x20a2, 0x20aa, 0x20b2, | ||
423 | /* char values 0x00d_ */ | ||
424 | 0x0000, 0x20ba, 0x20c2, 0x20ca, 0x20d2, 0x20da, 0x20e2, 0x0000, | ||
425 | 0x0000, 0x20ea, 0x20f2, 0x20fa, 0x2102, 0x210a, 0x0000, 0x0000, | ||
426 | /* char values 0x00e_ */ | ||
427 | 0x2112, 0x211a, 0x2122, 0x212a, 0x2132, 0x213a, 0x0000, 0x2142, | ||
428 | 0x214a, 0x2152, 0x215a, 0x2162, 0x216a, 0x2172, 0x217a, 0x2182, | ||
429 | /* char values 0x00f_ */ | ||
430 | 0x0000, 0x218a, 0x2192, 0x219a, 0x21a2, 0x21aa, 0x21b2, 0x0000, | ||
431 | 0x0000, 0x21ba, 0x21c2, 0x21ca, 0x21d2, 0x21da, 0x0000, 0x21e2, | ||
432 | /* char table 0x01__ */ | ||
433 | 0x0080, 0x0090, 0x00a0, 0x00b0, 0x00c0, 0x00d0, 0x00e0, 0x00f0, | ||
434 | 0x0000, 0x0000, 0x0100, 0x0110, 0x0120, 0x0130, 0x0140, 0x0150, | ||
435 | /* char values 0x010_ */ | ||
436 | 0x21ea, 0x21f2, 0x21fa, 0x2202, 0x220a, 0x2212, 0x221a, 0x2222, | ||
437 | 0x222a, 0x2232, 0x223a, 0x2242, 0x224a, 0x2252, 0x225a, 0x2262, | ||
438 | /* char values 0x011_ */ | ||
439 | 0x0000, 0x0000, 0x226a, 0x2272, 0x227a, 0x2282, 0x228a, 0x2292, | ||
440 | 0x229a, 0x22a2, 0x22aa, 0x22b2, 0x22ba, 0x22c2, 0x22ca, 0x22d2, | ||
441 | /* char values 0x012_ */ | ||
442 | 0x22da, 0x22e2, 0x22ea, 0x22f2, 0x22fa, 0x2302, 0x0000, 0x0000, | ||
443 | 0x230a, 0x2312, 0x231a, 0x2322, 0x232a, 0x2332, 0x233a, 0x2342, | ||
444 | /* char values 0x013_ */ | ||
445 | 0x234a, 0x0000, 0x0000, 0x0000, 0x2352, 0x235a, 0x2362, 0x236a, | ||
446 | 0x0000, 0x2372, 0x237a, 0x2382, 0x238a, 0x2392, 0x239a, 0x0000, | ||
447 | /* char values 0x014_ */ | ||
448 | 0x0000, 0x0000, 0x0000, 0x23a2, 0x23aa, 0x23b2, 0x23ba, 0x23c2, | ||
449 | 0x23ca, 0x0000, 0x0000, 0x0000, 0x23d2, 0x23da, 0x23e2, 0x23ea, | ||
450 | /* char values 0x015_ */ | ||
451 | 0x23f2, 0x23fa, 0x0000, 0x0000, 0x2402, 0x240a, 0x2412, 0x241a, | ||
452 | 0x2422, 0x242a, 0x2432, 0x243a, 0x2442, 0x244a, 0x2452, 0x245a, | ||
453 | /* char values 0x016_ */ | ||
454 | 0x2462, 0x246a, 0x2472, 0x247a, 0x2482, 0x248a, 0x0000, 0x0000, | ||
455 | 0x2492, 0x249a, 0x24a2, 0x24aa, 0x24b2, 0x24ba, 0x24c2, 0x24ca, | ||
456 | /* char values 0x017_ */ | ||
457 | 0x24d2, 0x24da, 0x24e2, 0x24ea, 0x24f2, 0x24fa, 0x2502, 0x250a, | ||
458 | 0x2512, 0x251a, 0x2522, 0x252a, 0x2532, 0x253a, 0x2542, 0x0000, | ||
459 | /* char values 0x01a_ */ | ||
460 | 0x254a, 0x2552, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
461 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x255a, | ||
462 | /* char values 0x01b_ */ | ||
463 | 0x2562, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
464 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
465 | /* char values 0x01c_ */ | ||
466 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
467 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x256a, 0x2572, 0x257a, | ||
468 | /* char values 0x01d_ */ | ||
469 | 0x2582, 0x258a, 0x2592, 0x259a, 0x25a2, 0x25ab, 0x25b7, 0x25c3, | ||
470 | 0x25cf, 0x25db, 0x25e7, 0x25f3, 0x25ff, 0x0000, 0x260b, 0x2617, | ||
471 | /* char values 0x01e_ */ | ||
472 | 0x2623, 0x262f, 0x263a, 0x2642, 0x0000, 0x0000, 0x264a, 0x2652, | ||
473 | 0x265a, 0x2662, 0x266a, 0x2672, 0x267b, 0x2687, 0x2692, 0x269a, | ||
474 | /* char values 0x01f_ */ | ||
475 | 0x26a2, 0x0000, 0x0000, 0x0000, 0x26aa, 0x26b2, 0x0000, 0x0000, | ||
476 | 0x0000, 0x0000, 0x26bb, 0x26c7, 0x26d2, 0x26da, 0x26e2, 0x26ea, | ||
477 | /* char table 0x02__ */ | ||
478 | 0x0170, 0x0180, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
479 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
480 | /* char values 0x020_ */ | ||
481 | 0x26f2, 0x26fa, 0x2702, 0x270a, 0x2712, 0x271a, 0x2722, 0x272a, | ||
482 | 0x2732, 0x273a, 0x2742, 0x274a, 0x2752, 0x275a, 0x2762, 0x276a, | ||
483 | /* char values 0x021_ */ | ||
484 | 0x2772, 0x277a, 0x2782, 0x278a, 0x2792, 0x279a, 0x27a2, 0x27aa, | ||
485 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
486 | /* char table 0x03__ */ | ||
487 | 0x0000, 0x01a0, 0x0000, 0x0000, 0x01b0, 0x0000, 0x0000, 0x01c0, | ||
488 | 0x01d0, 0x01e0, 0x01f0, 0x0200, 0x0210, 0x0220, 0x0000, 0x0000, | ||
489 | /* char values 0x031_ */ | ||
490 | 0x27b2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
491 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
492 | /* char values 0x034_ */ | ||
493 | 0x27b9, 0x27bd, 0x0000, 0x27c1, 0x27c6, 0x0000, 0x0000, 0x0000, | ||
494 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
495 | /* char values 0x037_ */ | ||
496 | 0x0000, 0x0000, 0x0000, 0x0000, 0x27cd, 0x0000, 0x0000, 0x0000, | ||
497 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x27d1, 0x0000, | ||
498 | /* char values 0x038_ */ | ||
499 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x27d6, 0x27de, 0x27e5, | ||
500 | 0x27ea, 0x27f2, 0x27fa, 0x0000, 0x2802, 0x0000, 0x280a, 0x2812, | ||
501 | /* char values 0x039_ */ | ||
502 | 0x281b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
503 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
504 | /* char values 0x03a_ */ | ||
505 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
506 | 0x0000, 0x0000, 0x2826, 0x282e, 0x2836, 0x283e, 0x2846, 0x284e, | ||
507 | /* char values 0x03b_ */ | ||
508 | 0x2857, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
509 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
510 | /* char values 0x03c_ */ | ||
511 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
512 | 0x0000, 0x0000, 0x2862, 0x286a, 0x2872, 0x287a, 0x2882, 0x0000, | ||
513 | /* char values 0x03d_ */ | ||
514 | 0x0000, 0x0000, 0x0000, 0x288a, 0x2892, 0x0000, 0x0000, 0x0000, | ||
515 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
516 | /* char table 0x04__ */ | ||
517 | 0x0240, 0x0250, 0x0000, 0x0260, 0x0000, 0x0270, 0x0000, 0x0280, | ||
518 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0290, 0x02a0, 0x02b0, 0x02c0, | ||
519 | /* char values 0x040_ */ | ||
520 | 0x0000, 0x289a, 0x0000, 0x28a2, 0x0000, 0x0000, 0x0000, 0x28aa, | ||
521 | 0x0000, 0x0000, 0x0000, 0x0000, 0x28b2, 0x0000, 0x28ba, 0x0000, | ||
522 | /* char values 0x041_ */ | ||
523 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
524 | 0x0000, 0x28c2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
525 | /* char values 0x043_ */ | ||
526 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
527 | 0x0000, 0x28ca, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
528 | /* char values 0x045_ */ | ||
529 | 0x0000, 0x28d2, 0x0000, 0x28da, 0x0000, 0x0000, 0x0000, 0x28e2, | ||
530 | 0x0000, 0x0000, 0x0000, 0x0000, 0x28ea, 0x0000, 0x28f2, 0x0000, | ||
531 | /* char values 0x047_ */ | ||
532 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x28fa, 0x2902, | ||
533 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
534 | /* char values 0x04c_ */ | ||
535 | 0x0000, 0x290a, 0x2912, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
536 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
537 | /* char values 0x04d_ */ | ||
538 | 0x291a, 0x2922, 0x292a, 0x2932, 0x2939, 0x293d, 0x2942, 0x294a, | ||
539 | 0x2951, 0x2955, 0x295a, 0x2962, 0x296a, 0x2972, 0x297a, 0x2982, | ||
540 | /* char values 0x04e_ */ | ||
541 | 0x2989, 0x298d, 0x2992, 0x299a, 0x29a2, 0x29aa, 0x29b2, 0x29ba, | ||
542 | 0x29c1, 0x29c5, 0x29ca, 0x29d2, 0x0000, 0x0000, 0x29da, 0x29e2, | ||
543 | /* char values 0x04f_ */ | ||
544 | 0x29ea, 0x29f2, 0x29fa, 0x2a02, 0x2a0a, 0x2a12, 0x0000, 0x0000, | ||
545 | 0x2a1a, 0x2a22, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
546 | /* char table 0x09__ */ | ||
547 | 0x0000, 0x0000, 0x02e0, 0x02f0, 0x0000, 0x0300, 0x0000, 0x0000, | ||
548 | 0x0000, 0x0000, 0x0000, 0x0310, 0x0320, 0x0330, 0x0000, 0x0000, | ||
549 | /* char values 0x092_ */ | ||
550 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
551 | 0x0000, 0x2a2a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
552 | /* char values 0x093_ */ | ||
553 | 0x0000, 0x2a32, 0x0000, 0x0000, 0x2a3a, 0x0000, 0x0000, 0x0000, | ||
554 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
555 | /* char values 0x095_ */ | ||
556 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
557 | 0x2a42, 0x2a4a, 0x2a52, 0x2a5a, 0x2a62, 0x2a6a, 0x2a72, 0x2a7a, | ||
558 | /* char values 0x09b_ */ | ||
559 | 0x2a82, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
560 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
561 | /* char values 0x09c_ */ | ||
562 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
563 | 0x0000, 0x0000, 0x0000, 0x2a8a, 0x2a92, 0x0000, 0x0000, 0x0000, | ||
564 | /* char values 0x09d_ */ | ||
565 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
566 | 0x0000, 0x0000, 0x0000, 0x0000, 0x2a9a, 0x2aa2, 0x0000, 0x2aaa, | ||
567 | /* char table 0x0a__ */ | ||
568 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0350, 0x0000, 0x0000, | ||
569 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
570 | /* char values 0x0a5_ */ | ||
571 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
572 | 0x0000, 0x2ab2, 0x2aba, 0x2ac2, 0x2aca, 0x0000, 0x2ad2, 0x0000, | ||
573 | /* char table 0x0b__ */ | ||
574 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0370, 0x0380, 0x0000, 0x0000, | ||
575 | 0x0000, 0x0390, 0x0000, 0x0000, 0x03a0, 0x0000, 0x0000, 0x0000, | ||
576 | /* char values 0x0b4_ */ | ||
577 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
578 | 0x2ada, 0x0000, 0x0000, 0x2ae2, 0x2aea, 0x0000, 0x0000, 0x0000, | ||
579 | /* char values 0x0b5_ */ | ||
580 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
581 | 0x0000, 0x0000, 0x0000, 0x0000, 0x2af2, 0x2afa, 0x0000, 0x2b02, | ||
582 | /* char values 0x0b9_ */ | ||
583 | 0x0000, 0x0000, 0x0000, 0x0000, 0x2b0a, 0x0000, 0x0000, 0x0000, | ||
584 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
585 | /* char values 0x0bc_ */ | ||
586 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
587 | 0x0000, 0x0000, 0x2b12, 0x2b1a, 0x2b22, 0x0000, 0x0000, 0x0000, | ||
588 | /* char table 0x0c__ */ | ||
589 | 0x0000, 0x0000, 0x0000, 0x0000, 0x03c0, 0x0000, 0x0000, 0x0000, | ||
590 | 0x0000, 0x0000, 0x0000, 0x0000, 0x03d0, 0x0000, 0x0000, 0x0000, | ||
591 | /* char values 0x0c4_ */ | ||
592 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
593 | 0x2b2a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
594 | /* char values 0x0cc_ */ | ||
595 | 0x2b32, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2b3a, | ||
596 | 0x2b42, 0x0000, 0x2b4a, 0x2b53, 0x0000, 0x0000, 0x0000, 0x0000, | ||
597 | /* char table 0x0d__ */ | ||
598 | 0x0000, 0x0000, 0x0000, 0x0000, 0x03f0, 0x0000, 0x0000, 0x0000, | ||
599 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
600 | /* char values 0x0d4_ */ | ||
601 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
602 | 0x0000, 0x0000, 0x2b5e, 0x2b66, 0x2b6e, 0x0000, 0x0000, 0x0000, | ||
603 | /* char table 0x0e__ */ | ||
604 | 0x0000, 0x0000, 0x0000, 0x0410, 0x0000, 0x0000, 0x0000, 0x0000, | ||
605 | 0x0000, 0x0000, 0x0000, 0x0420, 0x0000, 0x0000, 0x0000, 0x0000, | ||
606 | /* char values 0x0e3_ */ | ||
607 | 0x0000, 0x0000, 0x0000, 0x2b76, 0x0000, 0x0000, 0x0000, 0x0000, | ||
608 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
609 | /* char values 0x0eb_ */ | ||
610 | 0x0000, 0x0000, 0x0000, 0x2b7e, 0x0000, 0x0000, 0x0000, 0x0000, | ||
611 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
612 | /* char table 0x0f__ */ | ||
613 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0440, 0x0450, 0x0460, 0x0470, | ||
614 | 0x0480, 0x0490, 0x04a0, 0x04b0, 0x0000, 0x0000, 0x0000, 0x0000, | ||
615 | /* char values 0x0f4_ */ | ||
616 | 0x0000, 0x0000, 0x0000, 0x2b86, 0x0000, 0x0000, 0x0000, 0x0000, | ||
617 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2b8e, 0x0000, 0x0000, | ||
618 | /* char values 0x0f5_ */ | ||
619 | 0x0000, 0x0000, 0x2b96, 0x0000, 0x0000, 0x0000, 0x0000, 0x2b9e, | ||
620 | 0x0000, 0x0000, 0x0000, 0x0000, 0x2ba6, 0x0000, 0x0000, 0x0000, | ||
621 | /* char values 0x0f6_ */ | ||
622 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
623 | 0x0000, 0x2bae, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
624 | /* char values 0x0f7_ */ | ||
625 | 0x0000, 0x0000, 0x0000, 0x2bb6, 0x0000, 0x2bbe, 0x2bc6, 0x2bcf, | ||
626 | 0x2bda, 0x2be3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
627 | /* char values 0x0f8_ */ | ||
628 | 0x0000, 0x2bee, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
629 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
630 | /* char values 0x0f9_ */ | ||
631 | 0x0000, 0x0000, 0x0000, 0x2bf6, 0x0000, 0x0000, 0x0000, 0x0000, | ||
632 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2bfe, 0x0000, 0x0000, | ||
633 | /* char values 0x0fa_ */ | ||
634 | 0x0000, 0x0000, 0x2c06, 0x0000, 0x0000, 0x0000, 0x0000, 0x2c0e, | ||
635 | 0x0000, 0x0000, 0x0000, 0x0000, 0x2c16, 0x0000, 0x0000, 0x0000, | ||
636 | /* char values 0x0fb_ */ | ||
637 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
638 | 0x0000, 0x2c1e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
639 | /* char table 0x1___ */ | ||
640 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
641 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x04d0, 0x05e0, | ||
642 | /* char table 0x1e__ */ | ||
643 | 0x04e0, 0x04f0, 0x0500, 0x0510, 0x0520, 0x0530, 0x0540, 0x0550, | ||
644 | 0x0560, 0x0570, 0x0580, 0x0590, 0x05a0, 0x05b0, 0x05c0, 0x05d0, | ||
645 | /* char values 0x1e0_ */ | ||
646 | 0x2c26, 0x2c2e, 0x2c36, 0x2c3e, 0x2c46, 0x2c4e, 0x2c56, 0x2c5e, | ||
647 | 0x2c67, 0x2c73, 0x2c7e, 0x2c86, 0x2c8e, 0x2c96, 0x2c9e, 0x2ca6, | ||
648 | /* char values 0x1e1_ */ | ||
649 | 0x2cae, 0x2cb6, 0x2cbe, 0x2cc6, 0x2ccf, 0x2cdb, 0x2ce7, 0x2cf3, | ||
650 | 0x2cfe, 0x2d06, 0x2d0e, 0x2d16, 0x2d1f, 0x2d2b, 0x2d36, 0x2d3e, | ||
651 | /* char values 0x1e2_ */ | ||
652 | 0x2d46, 0x2d4e, 0x2d56, 0x2d5e, 0x2d66, 0x2d6e, 0x2d76, 0x2d7e, | ||
653 | 0x2d86, 0x2d8e, 0x2d96, 0x2d9e, 0x2da6, 0x2dae, 0x2db7, 0x2dc3, | ||
654 | /* char values 0x1e3_ */ | ||
655 | 0x2dce, 0x2dd6, 0x2dde, 0x2de6, 0x2dee, 0x2df6, 0x2dfe, 0x2e06, | ||
656 | 0x2e0f, 0x2e1b, 0x2e26, 0x2e2e, 0x2e36, 0x2e3e, 0x2e46, 0x2e4e, | ||
657 | /* char values 0x1e4_ */ | ||
658 | 0x2e56, 0x2e5e, 0x2e66, 0x2e6e, 0x2e76, 0x2e7e, 0x2e86, 0x2e8e, | ||
659 | 0x2e96, 0x2e9e, 0x2ea6, 0x2eae, 0x2eb7, 0x2ec3, 0x2ecf, 0x2edb, | ||
660 | /* char values 0x1e5_ */ | ||
661 | 0x2ee7, 0x2ef3, 0x2eff, 0x2f0b, 0x2f16, 0x2f1e, 0x2f26, 0x2f2e, | ||
662 | 0x2f36, 0x2f3e, 0x2f46, 0x2f4e, 0x2f57, 0x2f63, 0x2f6e, 0x2f76, | ||
663 | /* char values 0x1e6_ */ | ||
664 | 0x2f7e, 0x2f86, 0x2f8e, 0x2f96, 0x2f9f, 0x2fab, 0x2fb7, 0x2fc3, | ||
665 | 0x2fcf, 0x2fdb, 0x2fe6, 0x2fee, 0x2ff6, 0x2ffe, 0x3006, 0x300e, | ||
666 | /* char values 0x1e7_ */ | ||
667 | 0x3016, 0x301e, 0x3026, 0x302e, 0x3036, 0x303e, 0x3046, 0x304e, | ||
668 | 0x3057, 0x3063, 0x306f, 0x307b, 0x3086, 0x308e, 0x3096, 0x309e, | ||
669 | /* char values 0x1e8_ */ | ||
670 | 0x30a6, 0x30ae, 0x30b6, 0x30be, 0x30c6, 0x30ce, 0x30d6, 0x30de, | ||
671 | 0x30e6, 0x30ee, 0x30f6, 0x30fe, 0x3106, 0x310e, 0x3116, 0x311e, | ||
672 | /* char values 0x1e9_ */ | ||
673 | 0x3126, 0x312e, 0x3136, 0x313e, 0x3146, 0x314e, 0x3156, 0x315e, | ||
674 | 0x3166, 0x316e, 0x0000, 0x3176, 0x0000, 0x0000, 0x0000, 0x0000, | ||
675 | /* char values 0x1ea_ */ | ||
676 | 0x317e, 0x3186, 0x318e, 0x3196, 0x319f, 0x31ab, 0x31b7, 0x31c3, | ||
677 | 0x31cf, 0x31db, 0x31e7, 0x31f3, 0x31ff, 0x320b, 0x3217, 0x3223, | ||
678 | /* char values 0x1eb_ */ | ||
679 | 0x322f, 0x323b, 0x3247, 0x3253, 0x325f, 0x326b, 0x3277, 0x3283, | ||
680 | 0x328e, 0x3296, 0x329e, 0x32a6, 0x32ae, 0x32b6, 0x32bf, 0x32cb, | ||
681 | /* char values 0x1ec_ */ | ||
682 | 0x32d7, 0x32e3, 0x32ef, 0x32fb, 0x3307, 0x3313, 0x331f, 0x332b, | ||
683 | 0x3336, 0x333e, 0x3346, 0x334e, 0x3356, 0x335e, 0x3366, 0x336e, | ||
684 | /* char values 0x1ed_ */ | ||
685 | 0x3377, 0x3383, 0x338f, 0x339b, 0x33a7, 0x33b3, 0x33bf, 0x33cb, | ||
686 | 0x33d7, 0x33e3, 0x33ef, 0x33fb, 0x3407, 0x3413, 0x341f, 0x342b, | ||
687 | /* char values 0x1ee_ */ | ||
688 | 0x3437, 0x3443, 0x344f, 0x345b, 0x3466, 0x346e, 0x3476, 0x347e, | ||
689 | 0x3487, 0x3493, 0x349f, 0x34ab, 0x34b7, 0x34c3, 0x34cf, 0x34db, | ||
690 | /* char values 0x1ef_ */ | ||
691 | 0x34e7, 0x34f3, 0x34fe, 0x3506, 0x350e, 0x3516, 0x351e, 0x3526, | ||
692 | 0x352e, 0x3536, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
693 | /* char table 0x1f__ */ | ||
694 | 0x05f0, 0x0600, 0x0610, 0x0620, 0x0630, 0x0640, 0x0650, 0x0660, | ||
695 | 0x0670, 0x0680, 0x0690, 0x06a0, 0x06b0, 0x06c0, 0x06d0, 0x06e0, | ||
696 | /* char values 0x1f0_ */ | ||
697 | 0x353e, 0x3546, 0x354f, 0x355b, 0x3567, 0x3573, 0x357f, 0x358b, | ||
698 | 0x3596, 0x359e, 0x35a7, 0x35b3, 0x35bf, 0x35cb, 0x35d7, 0x35e3, | ||
699 | /* char values 0x1f1_ */ | ||
700 | 0x35ee, 0x35f6, 0x35ff, 0x360b, 0x3617, 0x3623, 0x0000, 0x0000, | ||
701 | 0x362e, 0x3636, 0x363f, 0x364b, 0x3657, 0x3663, 0x0000, 0x0000, | ||
702 | /* char values 0x1f2_ */ | ||
703 | 0x366e, 0x3676, 0x367f, 0x368b, 0x3697, 0x36a3, 0x36af, 0x36bb, | ||
704 | 0x36c6, 0x36ce, 0x36d7, 0x36e3, 0x36ef, 0x36fb, 0x3707, 0x3713, | ||
705 | /* char values 0x1f3_ */ | ||
706 | 0x371e, 0x3726, 0x372f, 0x373b, 0x3747, 0x3753, 0x375f, 0x376b, | ||
707 | 0x3776, 0x377e, 0x3787, 0x3793, 0x379f, 0x37ab, 0x37b7, 0x37c3, | ||
708 | /* char values 0x1f4_ */ | ||
709 | 0x37ce, 0x37d6, 0x37df, 0x37eb, 0x37f7, 0x3803, 0x0000, 0x0000, | ||
710 | 0x380e, 0x3816, 0x381f, 0x382b, 0x3837, 0x3843, 0x0000, 0x0000, | ||
711 | /* char values 0x1f5_ */ | ||
712 | 0x384e, 0x3856, 0x385f, 0x386b, 0x3877, 0x3883, 0x388f, 0x389b, | ||
713 | 0x0000, 0x38a6, 0x0000, 0x38af, 0x0000, 0x38bb, 0x0000, 0x38c7, | ||
714 | /* char values 0x1f6_ */ | ||
715 | 0x38d2, 0x38da, 0x38e3, 0x38ef, 0x38fb, 0x3907, 0x3913, 0x391f, | ||
716 | 0x392a, 0x3932, 0x393b, 0x3947, 0x3953, 0x395f, 0x396b, 0x3977, | ||
717 | /* char values 0x1f7_ */ | ||
718 | 0x3982, 0x398a, 0x3992, 0x399a, 0x39a2, 0x39aa, 0x39b2, 0x39ba, | ||
719 | 0x39c2, 0x39ca, 0x39d2, 0x39da, 0x39e2, 0x39ea, 0x0000, 0x0000, | ||
720 | /* char values 0x1f8_ */ | ||
721 | 0x39f3, 0x39ff, 0x3a0c, 0x3a1c, 0x3a2c, 0x3a3c, 0x3a4c, 0x3a5c, | ||
722 | 0x3a6b, 0x3a77, 0x3a84, 0x3a94, 0x3aa4, 0x3ab4, 0x3ac4, 0x3ad4, | ||
723 | /* char values 0x1f9_ */ | ||
724 | 0x3ae3, 0x3aef, 0x3afc, 0x3b0c, 0x3b1c, 0x3b2c, 0x3b3c, 0x3b4c, | ||
725 | 0x3b5b, 0x3b67, 0x3b74, 0x3b84, 0x3b94, 0x3ba4, 0x3bb4, 0x3bc4, | ||
726 | /* char values 0x1fa_ */ | ||
727 | 0x3bd3, 0x3bdf, 0x3bec, 0x3bfc, 0x3c0c, 0x3c1c, 0x3c2c, 0x3c3c, | ||
728 | 0x3c4b, 0x3c57, 0x3c64, 0x3c74, 0x3c84, 0x3c94, 0x3ca4, 0x3cb4, | ||
729 | /* char values 0x1fb_ */ | ||
730 | 0x3cc2, 0x3cca, 0x3cd3, 0x3cde, 0x3ce7, 0x0000, 0x3cf2, 0x3cfb, | ||
731 | 0x3d06, 0x3d0e, 0x3d16, 0x3d1e, 0x3d26, 0x0000, 0x3d2d, 0x0000, | ||
732 | /* char values 0x1fc_ */ | ||
733 | 0x0000, 0x3d32, 0x3d3b, 0x3d46, 0x3d4f, 0x0000, 0x3d5a, 0x3d63, | ||
734 | 0x3d6e, 0x3d76, 0x3d7e, 0x3d86, 0x3d8e, 0x3d96, 0x3d9e, 0x3da6, | ||
735 | /* char values 0x1fd_ */ | ||
736 | 0x3dae, 0x3db6, 0x3dbf, 0x3dcb, 0x0000, 0x0000, 0x3dd6, 0x3ddf, | ||
737 | 0x3dea, 0x3df2, 0x3dfa, 0x3e02, 0x0000, 0x3e0a, 0x3e12, 0x3e1a, | ||
738 | /* char values 0x1fe_ */ | ||
739 | 0x3e22, 0x3e2a, 0x3e33, 0x3e3f, 0x3e4a, 0x3e52, 0x3e5a, 0x3e63, | ||
740 | 0x3e6e, 0x3e76, 0x3e7e, 0x3e86, 0x3e8e, 0x3e96, 0x3e9e, 0x3ea5, | ||
741 | /* char values 0x1ff_ */ | ||
742 | 0x0000, 0x0000, 0x3eab, 0x3eb6, 0x3ebf, 0x0000, 0x3eca, 0x3ed3, | ||
743 | 0x3ede, 0x3ee6, 0x3eee, 0x3ef6, 0x3efe, 0x3f05, 0x0000, 0x0000, | ||
744 | /* char table 0x3___ */ | ||
745 | 0x0700, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
746 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
747 | /* char table 0x30__ */ | ||
748 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0710, 0x0720, 0x0730, 0x0740, | ||
749 | 0x0000, 0x0750, 0x0760, 0x0770, 0x0780, 0x0790, 0x0000, 0x07a0, | ||
750 | /* char values 0x304_ */ | ||
751 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
752 | 0x0000, 0x0000, 0x0000, 0x0000, 0x3f0a, 0x0000, 0x3f12, 0x0000, | ||
753 | /* char values 0x305_ */ | ||
754 | 0x3f1a, 0x0000, 0x3f22, 0x0000, 0x3f2a, 0x0000, 0x3f32, 0x0000, | ||
755 | 0x3f3a, 0x0000, 0x3f42, 0x0000, 0x3f4a, 0x0000, 0x3f52, 0x0000, | ||
756 | /* char values 0x306_ */ | ||
757 | 0x3f5a, 0x0000, 0x3f62, 0x0000, 0x0000, 0x3f6a, 0x0000, 0x3f72, | ||
758 | 0x0000, 0x3f7a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
759 | /* char values 0x307_ */ | ||
760 | 0x3f82, 0x3f8a, 0x0000, 0x3f92, 0x3f9a, 0x0000, 0x3fa2, 0x3faa, | ||
761 | 0x0000, 0x3fb2, 0x3fba, 0x0000, 0x3fc2, 0x3fca, 0x0000, 0x0000, | ||
762 | /* char values 0x309_ */ | ||
763 | 0x0000, 0x0000, 0x0000, 0x0000, 0x3fd2, 0x0000, 0x0000, 0x0000, | ||
764 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3fda, 0x0000, | ||
765 | /* char values 0x30a_ */ | ||
766 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
767 | 0x0000, 0x0000, 0x0000, 0x0000, 0x3fe2, 0x0000, 0x3fea, 0x0000, | ||
768 | /* char values 0x30b_ */ | ||
769 | 0x3ff2, 0x0000, 0x3ffa, 0x0000, 0x4002, 0x0000, 0x400a, 0x0000, | ||
770 | 0x4012, 0x0000, 0x401a, 0x0000, 0x4022, 0x0000, 0x402a, 0x0000, | ||
771 | /* char values 0x30c_ */ | ||
772 | 0x4032, 0x0000, 0x403a, 0x0000, 0x0000, 0x4042, 0x0000, 0x404a, | ||
773 | 0x0000, 0x4052, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
774 | /* char values 0x30d_ */ | ||
775 | 0x405a, 0x4062, 0x0000, 0x406a, 0x4072, 0x0000, 0x407a, 0x4082, | ||
776 | 0x0000, 0x408a, 0x4092, 0x0000, 0x409a, 0x40a2, 0x0000, 0x0000, | ||
777 | /* char values 0x30f_ */ | ||
778 | 0x0000, 0x0000, 0x0000, 0x0000, 0x40aa, 0x0000, 0x0000, 0x40b2, | ||
779 | 0x40ba, 0x40c2, 0x40ca, 0x0000, 0x0000, 0x0000, 0x40d2, 0x0000, | ||
780 | /* char table 0xf___ */ | ||
781 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
782 | 0x0000, 0x0000, 0x0000, 0x07c0, 0x0000, 0x0000, 0x0000, 0x0000, | ||
783 | /* char table 0xfb__ */ | ||
784 | 0x0000, 0x07d0, 0x07e0, 0x07f0, 0x0800, 0x0000, 0x0000, 0x0000, | ||
785 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
786 | /* char values 0xfb1_ */ | ||
787 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
788 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x40da, | ||
789 | /* char values 0xfb2_ */ | ||
790 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, | ||
791 | 0x0000, 0x0000, 0x40e2, 0x40ea, 0x40f3, 0x40ff, 0x410a, 0x4112, | ||
792 | /* char values 0xfb3_ */ | ||
793 | 0x411a, 0x4122, 0x412a, 0x4132, 0x413a, 0x4142, 0x414a, 0x0000, | ||
794 | 0x4152, 0x415a, 0x4162, 0x416a, 0x4172, 0x0000, 0x417a, 0x0000, | ||
795 | /* char values 0xfb4_ */ | ||
796 | 0x4182, 0x418a, 0x0000, 0x4192, 0x419a, 0x0000, 0x41a2, 0x41aa, | ||
797 | 0x41b2, 0x41ba, 0x41c2, 0x41ca, 0x41d2, 0x41da, 0x41e2, 0x0000, | ||
798 | /* decomposed characters */ | ||
799 | 0x0041, 0x0300, 0x0041, 0x0301, 0x0041, 0x0302, 0x0041, 0x0303, | ||
800 | 0x0041, 0x0308, 0x0041, 0x030a, 0x0043, 0x0327, 0x0045, 0x0300, | ||
801 | 0x0045, 0x0301, 0x0045, 0x0302, 0x0045, 0x0308, 0x0049, 0x0300, | ||
802 | 0x0049, 0x0301, 0x0049, 0x0302, 0x0049, 0x0308, 0x004e, 0x0303, | ||
803 | 0x004f, 0x0300, 0x004f, 0x0301, 0x004f, 0x0302, 0x004f, 0x0303, | ||
804 | 0x004f, 0x0308, 0x0055, 0x0300, 0x0055, 0x0301, 0x0055, 0x0302, | ||
805 | 0x0055, 0x0308, 0x0059, 0x0301, 0x0061, 0x0300, 0x0061, 0x0301, | ||
806 | 0x0061, 0x0302, 0x0061, 0x0303, 0x0061, 0x0308, 0x0061, 0x030a, | ||
807 | 0x0063, 0x0327, 0x0065, 0x0300, 0x0065, 0x0301, 0x0065, 0x0302, | ||
808 | 0x0065, 0x0308, 0x0069, 0x0300, 0x0069, 0x0301, 0x0069, 0x0302, | ||
809 | 0x0069, 0x0308, 0x006e, 0x0303, 0x006f, 0x0300, 0x006f, 0x0301, | ||
810 | 0x006f, 0x0302, 0x006f, 0x0303, 0x006f, 0x0308, 0x0075, 0x0300, | ||
811 | 0x0075, 0x0301, 0x0075, 0x0302, 0x0075, 0x0308, 0x0079, 0x0301, | ||
812 | 0x0079, 0x0308, 0x0041, 0x0304, 0x0061, 0x0304, 0x0041, 0x0306, | ||
813 | 0x0061, 0x0306, 0x0041, 0x0328, 0x0061, 0x0328, 0x0043, 0x0301, | ||
814 | 0x0063, 0x0301, 0x0043, 0x0302, 0x0063, 0x0302, 0x0043, 0x0307, | ||
815 | 0x0063, 0x0307, 0x0043, 0x030c, 0x0063, 0x030c, 0x0044, 0x030c, | ||
816 | 0x0064, 0x030c, 0x0045, 0x0304, 0x0065, 0x0304, 0x0045, 0x0306, | ||
817 | 0x0065, 0x0306, 0x0045, 0x0307, 0x0065, 0x0307, 0x0045, 0x0328, | ||
818 | 0x0065, 0x0328, 0x0045, 0x030c, 0x0065, 0x030c, 0x0047, 0x0302, | ||
819 | 0x0067, 0x0302, 0x0047, 0x0306, 0x0067, 0x0306, 0x0047, 0x0307, | ||
820 | 0x0067, 0x0307, 0x0047, 0x0327, 0x0067, 0x0327, 0x0048, 0x0302, | ||
821 | 0x0068, 0x0302, 0x0049, 0x0303, 0x0069, 0x0303, 0x0049, 0x0304, | ||
822 | 0x0069, 0x0304, 0x0049, 0x0306, 0x0069, 0x0306, 0x0049, 0x0328, | ||
823 | 0x0069, 0x0328, 0x0049, 0x0307, 0x004a, 0x0302, 0x006a, 0x0302, | ||
824 | 0x004b, 0x0327, 0x006b, 0x0327, 0x004c, 0x0301, 0x006c, 0x0301, | ||
825 | 0x004c, 0x0327, 0x006c, 0x0327, 0x004c, 0x030c, 0x006c, 0x030c, | ||
826 | 0x004e, 0x0301, 0x006e, 0x0301, 0x004e, 0x0327, 0x006e, 0x0327, | ||
827 | 0x004e, 0x030c, 0x006e, 0x030c, 0x004f, 0x0304, 0x006f, 0x0304, | ||
828 | 0x004f, 0x0306, 0x006f, 0x0306, 0x004f, 0x030b, 0x006f, 0x030b, | ||
829 | 0x0052, 0x0301, 0x0072, 0x0301, 0x0052, 0x0327, 0x0072, 0x0327, | ||
830 | 0x0052, 0x030c, 0x0072, 0x030c, 0x0053, 0x0301, 0x0073, 0x0301, | ||
831 | 0x0053, 0x0302, 0x0073, 0x0302, 0x0053, 0x0327, 0x0073, 0x0327, | ||
832 | 0x0053, 0x030c, 0x0073, 0x030c, 0x0054, 0x0327, 0x0074, 0x0327, | ||
833 | 0x0054, 0x030c, 0x0074, 0x030c, 0x0055, 0x0303, 0x0075, 0x0303, | ||
834 | 0x0055, 0x0304, 0x0075, 0x0304, 0x0055, 0x0306, 0x0075, 0x0306, | ||
835 | 0x0055, 0x030a, 0x0075, 0x030a, 0x0055, 0x030b, 0x0075, 0x030b, | ||
836 | 0x0055, 0x0328, 0x0075, 0x0328, 0x0057, 0x0302, 0x0077, 0x0302, | ||
837 | 0x0059, 0x0302, 0x0079, 0x0302, 0x0059, 0x0308, 0x005a, 0x0301, | ||
838 | 0x007a, 0x0301, 0x005a, 0x0307, 0x007a, 0x0307, 0x005a, 0x030c, | ||
839 | 0x007a, 0x030c, 0x004f, 0x031b, 0x006f, 0x031b, 0x0055, 0x031b, | ||
840 | 0x0075, 0x031b, 0x0041, 0x030c, 0x0061, 0x030c, 0x0049, 0x030c, | ||
841 | 0x0069, 0x030c, 0x004f, 0x030c, 0x006f, 0x030c, 0x0055, 0x030c, | ||
842 | 0x0075, 0x030c, 0x0055, 0x0308, 0x0304, 0x0075, 0x0308, 0x0304, | ||
843 | 0x0055, 0x0308, 0x0301, 0x0075, 0x0308, 0x0301, 0x0055, 0x0308, | ||
844 | 0x030c, 0x0075, 0x0308, 0x030c, 0x0055, 0x0308, 0x0300, 0x0075, | ||
845 | 0x0308, 0x0300, 0x0041, 0x0308, 0x0304, 0x0061, 0x0308, 0x0304, | ||
846 | 0x0041, 0x0307, 0x0304, 0x0061, 0x0307, 0x0304, 0x00c6, 0x0304, | ||
847 | 0x00e6, 0x0304, 0x0047, 0x030c, 0x0067, 0x030c, 0x004b, 0x030c, | ||
848 | 0x006b, 0x030c, 0x004f, 0x0328, 0x006f, 0x0328, 0x004f, 0x0328, | ||
849 | 0x0304, 0x006f, 0x0328, 0x0304, 0x01b7, 0x030c, 0x0292, 0x030c, | ||
850 | 0x006a, 0x030c, 0x0047, 0x0301, 0x0067, 0x0301, 0x0041, 0x030a, | ||
851 | 0x0301, 0x0061, 0x030a, 0x0301, 0x00c6, 0x0301, 0x00e6, 0x0301, | ||
852 | 0x00d8, 0x0301, 0x00f8, 0x0301, 0x0041, 0x030f, 0x0061, 0x030f, | ||
853 | 0x0041, 0x0311, 0x0061, 0x0311, 0x0045, 0x030f, 0x0065, 0x030f, | ||
854 | 0x0045, 0x0311, 0x0065, 0x0311, 0x0049, 0x030f, 0x0069, 0x030f, | ||
855 | 0x0049, 0x0311, 0x0069, 0x0311, 0x004f, 0x030f, 0x006f, 0x030f, | ||
856 | 0x004f, 0x0311, 0x006f, 0x0311, 0x0052, 0x030f, 0x0072, 0x030f, | ||
857 | 0x0052, 0x0311, 0x0072, 0x0311, 0x0055, 0x030f, 0x0075, 0x030f, | ||
858 | 0x0055, 0x0311, 0x0075, 0x0311, 0x0306, 0x0307, 0x0300, 0x0301, | ||
859 | 0x0313, 0x0308, 0x030d, 0x02b9, 0x003b, 0x00a8, 0x030d, 0x0391, | ||
860 | 0x030d, 0x00b7, 0x0395, 0x030d, 0x0397, 0x030d, 0x0399, 0x030d, | ||
861 | 0x039f, 0x030d, 0x03a5, 0x030d, 0x03a9, 0x030d, 0x03b9, 0x0308, | ||
862 | 0x030d, 0x0399, 0x0308, 0x03a5, 0x0308, 0x03b1, 0x030d, 0x03b5, | ||
863 | 0x030d, 0x03b7, 0x030d, 0x03b9, 0x030d, 0x03c5, 0x0308, 0x030d, | ||
864 | 0x03b9, 0x0308, 0x03c5, 0x0308, 0x03bf, 0x030d, 0x03c5, 0x030d, | ||
865 | 0x03c9, 0x030d, 0x03d2, 0x030d, 0x03d2, 0x0308, 0x0415, 0x0308, | ||
866 | 0x0413, 0x0301, 0x0406, 0x0308, 0x041a, 0x0301, 0x0423, 0x0306, | ||
867 | 0x0418, 0x0306, 0x0438, 0x0306, 0x0435, 0x0308, 0x0433, 0x0301, | ||
868 | 0x0456, 0x0308, 0x043a, 0x0301, 0x0443, 0x0306, 0x0474, 0x030f, | ||
869 | 0x0475, 0x030f, 0x0416, 0x0306, 0x0436, 0x0306, 0x0410, 0x0306, | ||
870 | 0x0430, 0x0306, 0x0410, 0x0308, 0x0430, 0x0308, 0x00c6, 0x00e6, | ||
871 | 0x0415, 0x0306, 0x0435, 0x0306, 0x018f, 0x0259, 0x018f, 0x0308, | ||
872 | 0x0259, 0x0308, 0x0416, 0x0308, 0x0436, 0x0308, 0x0417, 0x0308, | ||
873 | 0x0437, 0x0308, 0x01b7, 0x0292, 0x0418, 0x0304, 0x0438, 0x0304, | ||
874 | 0x0418, 0x0308, 0x0438, 0x0308, 0x041e, 0x0308, 0x043e, 0x0308, | ||
875 | 0x019f, 0x0275, 0x019f, 0x0308, 0x0275, 0x0308, 0x0423, 0x0304, | ||
876 | 0x0443, 0x0304, 0x0423, 0x0308, 0x0443, 0x0308, 0x0423, 0x030b, | ||
877 | 0x0443, 0x030b, 0x0427, 0x0308, 0x0447, 0x0308, 0x042b, 0x0308, | ||
878 | 0x044b, 0x0308, 0x0928, 0x093c, 0x0930, 0x093c, 0x0933, 0x093c, | ||
879 | 0x0915, 0x093c, 0x0916, 0x093c, 0x0917, 0x093c, 0x091c, 0x093c, | ||
880 | 0x0921, 0x093c, 0x0922, 0x093c, 0x092b, 0x093c, 0x092f, 0x093c, | ||
881 | 0x09ac, 0x09bc, 0x09c7, 0x09be, 0x09c7, 0x09d7, 0x09a1, 0x09bc, | ||
882 | 0x09a2, 0x09bc, 0x09af, 0x09bc, 0x0a16, 0x0a3c, 0x0a17, 0x0a3c, | ||
883 | 0x0a1c, 0x0a3c, 0x0a21, 0x0a3c, 0x0a2b, 0x0a3c, 0x0b47, 0x0b56, | ||
884 | 0x0b47, 0x0b3e, 0x0b47, 0x0b57, 0x0b21, 0x0b3c, 0x0b22, 0x0b3c, | ||
885 | 0x0b2f, 0x0b3c, 0x0b92, 0x0bd7, 0x0bc6, 0x0bbe, 0x0bc7, 0x0bbe, | ||
886 | 0x0bc6, 0x0bd7, 0x0c46, 0x0c56, 0x0cbf, 0x0cd5, 0x0cc6, 0x0cd5, | ||
887 | 0x0cc6, 0x0cd6, 0x0cc6, 0x0cc2, 0x0cc6, 0x0cc2, 0x0cd5, 0x0d46, | ||
888 | 0x0d3e, 0x0d47, 0x0d3e, 0x0d46, 0x0d57, 0x0e4d, 0x0e32, 0x0ecd, | ||
889 | 0x0eb2, 0x0f42, 0x0fb7, 0x0f4c, 0x0fb7, 0x0f51, 0x0fb7, 0x0f56, | ||
890 | 0x0fb7, 0x0f5b, 0x0fb7, 0x0f40, 0x0fb5, 0x0f72, 0x0f71, 0x0f74, | ||
891 | 0x0f71, 0x0fb2, 0x0f80, 0x0fb2, 0x0f80, 0x0f71, 0x0fb3, 0x0f80, | ||
892 | 0x0fb3, 0x0f80, 0x0f71, 0x0f80, 0x0f71, 0x0f92, 0x0fb7, 0x0f9c, | ||
893 | 0x0fb7, 0x0fa1, 0x0fb7, 0x0fa6, 0x0fb7, 0x0fab, 0x0fb7, 0x0f90, | ||
894 | 0x0fb5, 0x0041, 0x0325, 0x0061, 0x0325, 0x0042, 0x0307, 0x0062, | ||
895 | 0x0307, 0x0042, 0x0323, 0x0062, 0x0323, 0x0042, 0x0331, 0x0062, | ||
896 | 0x0331, 0x0043, 0x0327, 0x0301, 0x0063, 0x0327, 0x0301, 0x0044, | ||
897 | 0x0307, 0x0064, 0x0307, 0x0044, 0x0323, 0x0064, 0x0323, 0x0044, | ||
898 | 0x0331, 0x0064, 0x0331, 0x0044, 0x0327, 0x0064, 0x0327, 0x0044, | ||
899 | 0x032d, 0x0064, 0x032d, 0x0045, 0x0304, 0x0300, 0x0065, 0x0304, | ||
900 | 0x0300, 0x0045, 0x0304, 0x0301, 0x0065, 0x0304, 0x0301, 0x0045, | ||
901 | 0x032d, 0x0065, 0x032d, 0x0045, 0x0330, 0x0065, 0x0330, 0x0045, | ||
902 | 0x0327, 0x0306, 0x0065, 0x0327, 0x0306, 0x0046, 0x0307, 0x0066, | ||
903 | 0x0307, 0x0047, 0x0304, 0x0067, 0x0304, 0x0048, 0x0307, 0x0068, | ||
904 | 0x0307, 0x0048, 0x0323, 0x0068, 0x0323, 0x0048, 0x0308, 0x0068, | ||
905 | 0x0308, 0x0048, 0x0327, 0x0068, 0x0327, 0x0048, 0x032e, 0x0068, | ||
906 | 0x032e, 0x0049, 0x0330, 0x0069, 0x0330, 0x0049, 0x0308, 0x0301, | ||
907 | 0x0069, 0x0308, 0x0301, 0x004b, 0x0301, 0x006b, 0x0301, 0x004b, | ||
908 | 0x0323, 0x006b, 0x0323, 0x004b, 0x0331, 0x006b, 0x0331, 0x004c, | ||
909 | 0x0323, 0x006c, 0x0323, 0x004c, 0x0323, 0x0304, 0x006c, 0x0323, | ||
910 | 0x0304, 0x004c, 0x0331, 0x006c, 0x0331, 0x004c, 0x032d, 0x006c, | ||
911 | 0x032d, 0x004d, 0x0301, 0x006d, 0x0301, 0x004d, 0x0307, 0x006d, | ||
912 | 0x0307, 0x004d, 0x0323, 0x006d, 0x0323, 0x004e, 0x0307, 0x006e, | ||
913 | 0x0307, 0x004e, 0x0323, 0x006e, 0x0323, 0x004e, 0x0331, 0x006e, | ||
914 | 0x0331, 0x004e, 0x032d, 0x006e, 0x032d, 0x004f, 0x0303, 0x0301, | ||
915 | 0x006f, 0x0303, 0x0301, 0x004f, 0x0303, 0x0308, 0x006f, 0x0303, | ||
916 | 0x0308, 0x004f, 0x0304, 0x0300, 0x006f, 0x0304, 0x0300, 0x004f, | ||
917 | 0x0304, 0x0301, 0x006f, 0x0304, 0x0301, 0x0050, 0x0301, 0x0070, | ||
918 | 0x0301, 0x0050, 0x0307, 0x0070, 0x0307, 0x0052, 0x0307, 0x0072, | ||
919 | 0x0307, 0x0052, 0x0323, 0x0072, 0x0323, 0x0052, 0x0323, 0x0304, | ||
920 | 0x0072, 0x0323, 0x0304, 0x0052, 0x0331, 0x0072, 0x0331, 0x0053, | ||
921 | 0x0307, 0x0073, 0x0307, 0x0053, 0x0323, 0x0073, 0x0323, 0x0053, | ||
922 | 0x0301, 0x0307, 0x0073, 0x0301, 0x0307, 0x0053, 0x030c, 0x0307, | ||
923 | 0x0073, 0x030c, 0x0307, 0x0053, 0x0323, 0x0307, 0x0073, 0x0323, | ||
924 | 0x0307, 0x0054, 0x0307, 0x0074, 0x0307, 0x0054, 0x0323, 0x0074, | ||
925 | 0x0323, 0x0054, 0x0331, 0x0074, 0x0331, 0x0054, 0x032d, 0x0074, | ||
926 | 0x032d, 0x0055, 0x0324, 0x0075, 0x0324, 0x0055, 0x0330, 0x0075, | ||
927 | 0x0330, 0x0055, 0x032d, 0x0075, 0x032d, 0x0055, 0x0303, 0x0301, | ||
928 | 0x0075, 0x0303, 0x0301, 0x0055, 0x0304, 0x0308, 0x0075, 0x0304, | ||
929 | 0x0308, 0x0056, 0x0303, 0x0076, 0x0303, 0x0056, 0x0323, 0x0076, | ||
930 | 0x0323, 0x0057, 0x0300, 0x0077, 0x0300, 0x0057, 0x0301, 0x0077, | ||
931 | 0x0301, 0x0057, 0x0308, 0x0077, 0x0308, 0x0057, 0x0307, 0x0077, | ||
932 | 0x0307, 0x0057, 0x0323, 0x0077, 0x0323, 0x0058, 0x0307, 0x0078, | ||
933 | 0x0307, 0x0058, 0x0308, 0x0078, 0x0308, 0x0059, 0x0307, 0x0079, | ||
934 | 0x0307, 0x005a, 0x0302, 0x007a, 0x0302, 0x005a, 0x0323, 0x007a, | ||
935 | 0x0323, 0x005a, 0x0331, 0x007a, 0x0331, 0x0068, 0x0331, 0x0074, | ||
936 | 0x0308, 0x0077, 0x030a, 0x0079, 0x030a, 0x017f, 0x0307, 0x0041, | ||
937 | 0x0323, 0x0061, 0x0323, 0x0041, 0x0309, 0x0061, 0x0309, 0x0041, | ||
938 | 0x0302, 0x0301, 0x0061, 0x0302, 0x0301, 0x0041, 0x0302, 0x0300, | ||
939 | 0x0061, 0x0302, 0x0300, 0x0041, 0x0302, 0x0309, 0x0061, 0x0302, | ||
940 | 0x0309, 0x0041, 0x0302, 0x0303, 0x0061, 0x0302, 0x0303, 0x0041, | ||
941 | 0x0323, 0x0302, 0x0061, 0x0323, 0x0302, 0x0041, 0x0306, 0x0301, | ||
942 | 0x0061, 0x0306, 0x0301, 0x0041, 0x0306, 0x0300, 0x0061, 0x0306, | ||
943 | 0x0300, 0x0041, 0x0306, 0x0309, 0x0061, 0x0306, 0x0309, 0x0041, | ||
944 | 0x0306, 0x0303, 0x0061, 0x0306, 0x0303, 0x0041, 0x0323, 0x0306, | ||
945 | 0x0061, 0x0323, 0x0306, 0x0045, 0x0323, 0x0065, 0x0323, 0x0045, | ||
946 | 0x0309, 0x0065, 0x0309, 0x0045, 0x0303, 0x0065, 0x0303, 0x0045, | ||
947 | 0x0302, 0x0301, 0x0065, 0x0302, 0x0301, 0x0045, 0x0302, 0x0300, | ||
948 | 0x0065, 0x0302, 0x0300, 0x0045, 0x0302, 0x0309, 0x0065, 0x0302, | ||
949 | 0x0309, 0x0045, 0x0302, 0x0303, 0x0065, 0x0302, 0x0303, 0x0045, | ||
950 | 0x0323, 0x0302, 0x0065, 0x0323, 0x0302, 0x0049, 0x0309, 0x0069, | ||
951 | 0x0309, 0x0049, 0x0323, 0x0069, 0x0323, 0x004f, 0x0323, 0x006f, | ||
952 | 0x0323, 0x004f, 0x0309, 0x006f, 0x0309, 0x004f, 0x0302, 0x0301, | ||
953 | 0x006f, 0x0302, 0x0301, 0x004f, 0x0302, 0x0300, 0x006f, 0x0302, | ||
954 | 0x0300, 0x004f, 0x0302, 0x0309, 0x006f, 0x0302, 0x0309, 0x004f, | ||
955 | 0x0302, 0x0303, 0x006f, 0x0302, 0x0303, 0x004f, 0x0323, 0x0302, | ||
956 | 0x006f, 0x0323, 0x0302, 0x004f, 0x031b, 0x0301, 0x006f, 0x031b, | ||
957 | 0x0301, 0x004f, 0x031b, 0x0300, 0x006f, 0x031b, 0x0300, 0x004f, | ||
958 | 0x031b, 0x0309, 0x006f, 0x031b, 0x0309, 0x004f, 0x031b, 0x0303, | ||
959 | 0x006f, 0x031b, 0x0303, 0x004f, 0x031b, 0x0323, 0x006f, 0x031b, | ||
960 | 0x0323, 0x0055, 0x0323, 0x0075, 0x0323, 0x0055, 0x0309, 0x0075, | ||
961 | 0x0309, 0x0055, 0x031b, 0x0301, 0x0075, 0x031b, 0x0301, 0x0055, | ||
962 | 0x031b, 0x0300, 0x0075, 0x031b, 0x0300, 0x0055, 0x031b, 0x0309, | ||
963 | 0x0075, 0x031b, 0x0309, 0x0055, 0x031b, 0x0303, 0x0075, 0x031b, | ||
964 | 0x0303, 0x0055, 0x031b, 0x0323, 0x0075, 0x031b, 0x0323, 0x0059, | ||
965 | 0x0300, 0x0079, 0x0300, 0x0059, 0x0323, 0x0079, 0x0323, 0x0059, | ||
966 | 0x0309, 0x0079, 0x0309, 0x0059, 0x0303, 0x0079, 0x0303, 0x03b1, | ||
967 | 0x0313, 0x03b1, 0x0314, 0x03b1, 0x0313, 0x0300, 0x03b1, 0x0314, | ||
968 | 0x0300, 0x03b1, 0x0313, 0x0301, 0x03b1, 0x0314, 0x0301, 0x03b1, | ||
969 | 0x0313, 0x0342, 0x03b1, 0x0314, 0x0342, 0x0391, 0x0313, 0x0391, | ||
970 | 0x0314, 0x0391, 0x0313, 0x0300, 0x0391, 0x0314, 0x0300, 0x0391, | ||
971 | 0x0313, 0x0301, 0x0391, 0x0314, 0x0301, 0x0391, 0x0313, 0x0342, | ||
972 | 0x0391, 0x0314, 0x0342, 0x03b5, 0x0313, 0x03b5, 0x0314, 0x03b5, | ||
973 | 0x0313, 0x0300, 0x03b5, 0x0314, 0x0300, 0x03b5, 0x0313, 0x0301, | ||
974 | 0x03b5, 0x0314, 0x0301, 0x0395, 0x0313, 0x0395, 0x0314, 0x0395, | ||
975 | 0x0313, 0x0300, 0x0395, 0x0314, 0x0300, 0x0395, 0x0313, 0x0301, | ||
976 | 0x0395, 0x0314, 0x0301, 0x03b7, 0x0313, 0x03b7, 0x0314, 0x03b7, | ||
977 | 0x0313, 0x0300, 0x03b7, 0x0314, 0x0300, 0x03b7, 0x0313, 0x0301, | ||
978 | 0x03b7, 0x0314, 0x0301, 0x03b7, 0x0313, 0x0342, 0x03b7, 0x0314, | ||
979 | 0x0342, 0x0397, 0x0313, 0x0397, 0x0314, 0x0397, 0x0313, 0x0300, | ||
980 | 0x0397, 0x0314, 0x0300, 0x0397, 0x0313, 0x0301, 0x0397, 0x0314, | ||
981 | 0x0301, 0x0397, 0x0313, 0x0342, 0x0397, 0x0314, 0x0342, 0x03b9, | ||
982 | 0x0313, 0x03b9, 0x0314, 0x03b9, 0x0313, 0x0300, 0x03b9, 0x0314, | ||
983 | 0x0300, 0x03b9, 0x0313, 0x0301, 0x03b9, 0x0314, 0x0301, 0x03b9, | ||
984 | 0x0313, 0x0342, 0x03b9, 0x0314, 0x0342, 0x0399, 0x0313, 0x0399, | ||
985 | 0x0314, 0x0399, 0x0313, 0x0300, 0x0399, 0x0314, 0x0300, 0x0399, | ||
986 | 0x0313, 0x0301, 0x0399, 0x0314, 0x0301, 0x0399, 0x0313, 0x0342, | ||
987 | 0x0399, 0x0314, 0x0342, 0x03bf, 0x0313, 0x03bf, 0x0314, 0x03bf, | ||
988 | 0x0313, 0x0300, 0x03bf, 0x0314, 0x0300, 0x03bf, 0x0313, 0x0301, | ||
989 | 0x03bf, 0x0314, 0x0301, 0x039f, 0x0313, 0x039f, 0x0314, 0x039f, | ||
990 | 0x0313, 0x0300, 0x039f, 0x0314, 0x0300, 0x039f, 0x0313, 0x0301, | ||
991 | 0x039f, 0x0314, 0x0301, 0x03c5, 0x0313, 0x03c5, 0x0314, 0x03c5, | ||
992 | 0x0313, 0x0300, 0x03c5, 0x0314, 0x0300, 0x03c5, 0x0313, 0x0301, | ||
993 | 0x03c5, 0x0314, 0x0301, 0x03c5, 0x0313, 0x0342, 0x03c5, 0x0314, | ||
994 | 0x0342, 0x03a5, 0x0314, 0x03a5, 0x0314, 0x0300, 0x03a5, 0x0314, | ||
995 | 0x0301, 0x03a5, 0x0314, 0x0342, 0x03c9, 0x0313, 0x03c9, 0x0314, | ||
996 | 0x03c9, 0x0313, 0x0300, 0x03c9, 0x0314, 0x0300, 0x03c9, 0x0313, | ||
997 | 0x0301, 0x03c9, 0x0314, 0x0301, 0x03c9, 0x0313, 0x0342, 0x03c9, | ||
998 | 0x0314, 0x0342, 0x03a9, 0x0313, 0x03a9, 0x0314, 0x03a9, 0x0313, | ||
999 | 0x0300, 0x03a9, 0x0314, 0x0300, 0x03a9, 0x0313, 0x0301, 0x03a9, | ||
1000 | 0x0314, 0x0301, 0x03a9, 0x0313, 0x0342, 0x03a9, 0x0314, 0x0342, | ||
1001 | 0x03b1, 0x0300, 0x03b1, 0x0301, 0x03b5, 0x0300, 0x03b5, 0x0301, | ||
1002 | 0x03b7, 0x0300, 0x03b7, 0x0301, 0x03b9, 0x0300, 0x03b9, 0x0301, | ||
1003 | 0x03bf, 0x0300, 0x03bf, 0x0301, 0x03c5, 0x0300, 0x03c5, 0x0301, | ||
1004 | 0x03c9, 0x0300, 0x03c9, 0x0301, 0x03b1, 0x0345, 0x0313, 0x03b1, | ||
1005 | 0x0345, 0x0314, 0x03b1, 0x0345, 0x0313, 0x0300, 0x03b1, 0x0345, | ||
1006 | 0x0314, 0x0300, 0x03b1, 0x0345, 0x0313, 0x0301, 0x03b1, 0x0345, | ||
1007 | 0x0314, 0x0301, 0x03b1, 0x0345, 0x0313, 0x0342, 0x03b1, 0x0345, | ||
1008 | 0x0314, 0x0342, 0x0391, 0x0345, 0x0313, 0x0391, 0x0345, 0x0314, | ||
1009 | 0x0391, 0x0345, 0x0313, 0x0300, 0x0391, 0x0345, 0x0314, 0x0300, | ||
1010 | 0x0391, 0x0345, 0x0313, 0x0301, 0x0391, 0x0345, 0x0314, 0x0301, | ||
1011 | 0x0391, 0x0345, 0x0313, 0x0342, 0x0391, 0x0345, 0x0314, 0x0342, | ||
1012 | 0x03b7, 0x0345, 0x0313, 0x03b7, 0x0345, 0x0314, 0x03b7, 0x0345, | ||
1013 | 0x0313, 0x0300, 0x03b7, 0x0345, 0x0314, 0x0300, 0x03b7, 0x0345, | ||
1014 | 0x0313, 0x0301, 0x03b7, 0x0345, 0x0314, 0x0301, 0x03b7, 0x0345, | ||
1015 | 0x0313, 0x0342, 0x03b7, 0x0345, 0x0314, 0x0342, 0x0397, 0x0345, | ||
1016 | 0x0313, 0x0397, 0x0345, 0x0314, 0x0397, 0x0345, 0x0313, 0x0300, | ||
1017 | 0x0397, 0x0345, 0x0314, 0x0300, 0x0397, 0x0345, 0x0313, 0x0301, | ||
1018 | 0x0397, 0x0345, 0x0314, 0x0301, 0x0397, 0x0345, 0x0313, 0x0342, | ||
1019 | 0x0397, 0x0345, 0x0314, 0x0342, 0x03c9, 0x0345, 0x0313, 0x03c9, | ||
1020 | 0x0345, 0x0314, 0x03c9, 0x0345, 0x0313, 0x0300, 0x03c9, 0x0345, | ||
1021 | 0x0314, 0x0300, 0x03c9, 0x0345, 0x0313, 0x0301, 0x03c9, 0x0345, | ||
1022 | 0x0314, 0x0301, 0x03c9, 0x0345, 0x0313, 0x0342, 0x03c9, 0x0345, | ||
1023 | 0x0314, 0x0342, 0x03a9, 0x0345, 0x0313, 0x03a9, 0x0345, 0x0314, | ||
1024 | 0x03a9, 0x0345, 0x0313, 0x0300, 0x03a9, 0x0345, 0x0314, 0x0300, | ||
1025 | 0x03a9, 0x0345, 0x0313, 0x0301, 0x03a9, 0x0345, 0x0314, 0x0301, | ||
1026 | 0x03a9, 0x0345, 0x0313, 0x0342, 0x03a9, 0x0345, 0x0314, 0x0342, | ||
1027 | 0x03b1, 0x0306, 0x03b1, 0x0304, 0x03b1, 0x0345, 0x0300, 0x03b1, | ||
1028 | 0x0345, 0x03b1, 0x0345, 0x0301, 0x03b1, 0x0342, 0x03b1, 0x0345, | ||
1029 | 0x0342, 0x0391, 0x0306, 0x0391, 0x0304, 0x0391, 0x0300, 0x0391, | ||
1030 | 0x0301, 0x0391, 0x0345, 0x03b9, 0x00a8, 0x0342, 0x03b7, 0x0345, | ||
1031 | 0x0300, 0x03b7, 0x0345, 0x03b7, 0x0345, 0x0301, 0x03b7, 0x0342, | ||
1032 | 0x03b7, 0x0345, 0x0342, 0x0395, 0x0300, 0x0395, 0x0301, 0x0397, | ||
1033 | 0x0300, 0x0397, 0x0301, 0x0397, 0x0345, 0x1fbf, 0x0300, 0x1fbf, | ||
1034 | 0x0301, 0x1fbf, 0x0342, 0x03b9, 0x0306, 0x03b9, 0x0304, 0x03b9, | ||
1035 | 0x0308, 0x0300, 0x03b9, 0x0308, 0x0301, 0x03b9, 0x0342, 0x03b9, | ||
1036 | 0x0308, 0x0342, 0x0399, 0x0306, 0x0399, 0x0304, 0x0399, 0x0300, | ||
1037 | 0x0399, 0x0301, 0x1ffe, 0x0300, 0x1ffe, 0x0301, 0x1ffe, 0x0342, | ||
1038 | 0x03c5, 0x0306, 0x03c5, 0x0304, 0x03c5, 0x0308, 0x0300, 0x03c5, | ||
1039 | 0x0308, 0x0301, 0x03c1, 0x0313, 0x03c1, 0x0314, 0x03c5, 0x0342, | ||
1040 | 0x03c5, 0x0308, 0x0342, 0x03a5, 0x0306, 0x03a5, 0x0304, 0x03a5, | ||
1041 | 0x0300, 0x03a5, 0x0301, 0x03a1, 0x0314, 0x00a8, 0x0300, 0x00a8, | ||
1042 | 0x0301, 0x0060, 0x03c9, 0x0345, 0x0300, 0x03c9, 0x0345, 0x03bf, | ||
1043 | 0x0345, 0x0301, 0x03c9, 0x0342, 0x03c9, 0x0345, 0x0342, 0x039f, | ||
1044 | 0x0300, 0x039f, 0x0301, 0x03a9, 0x0300, 0x03a9, 0x0301, 0x03a9, | ||
1045 | 0x0345, 0x00b4, 0x304b, 0x3099, 0x304d, 0x3099, 0x304f, 0x3099, | ||
1046 | 0x3051, 0x3099, 0x3053, 0x3099, 0x3055, 0x3099, 0x3057, 0x3099, | ||
1047 | 0x3059, 0x3099, 0x305b, 0x3099, 0x305d, 0x3099, 0x305f, 0x3099, | ||
1048 | 0x3061, 0x3099, 0x3064, 0x3099, 0x3066, 0x3099, 0x3068, 0x3099, | ||
1049 | 0x306f, 0x3099, 0x306f, 0x309a, 0x3072, 0x3099, 0x3072, 0x309a, | ||
1050 | 0x3075, 0x3099, 0x3075, 0x309a, 0x3078, 0x3099, 0x3078, 0x309a, | ||
1051 | 0x307b, 0x3099, 0x307b, 0x309a, 0x3046, 0x3099, 0x309d, 0x3099, | ||
1052 | 0x30ab, 0x3099, 0x30ad, 0x3099, 0x30af, 0x3099, 0x30b1, 0x3099, | ||
1053 | 0x30b3, 0x3099, 0x30b5, 0x3099, 0x30b7, 0x3099, 0x30b9, 0x3099, | ||
1054 | 0x30bb, 0x3099, 0x30bd, 0x3099, 0x30bf, 0x3099, 0x30c1, 0x3099, | ||
1055 | 0x30c4, 0x3099, 0x30c6, 0x3099, 0x30c8, 0x3099, 0x30cf, 0x3099, | ||
1056 | 0x30cf, 0x309a, 0x30d2, 0x3099, 0x30d2, 0x309a, 0x30d5, 0x3099, | ||
1057 | 0x30d5, 0x309a, 0x30d8, 0x3099, 0x30d8, 0x309a, 0x30db, 0x3099, | ||
1058 | 0x30db, 0x309a, 0x30a6, 0x3099, 0x30ef, 0x3099, 0x30f0, 0x3099, | ||
1059 | 0x30f1, 0x3099, 0x30f2, 0x3099, 0x30fd, 0x3099, 0x05f2, 0x05b7, | ||
1060 | 0x05e9, 0x05c1, 0x05e9, 0x05c2, 0x05e9, 0x05bc, 0x05c1, 0x05e9, | ||
1061 | 0x05bc, 0x05c2, 0x05d0, 0x05b7, 0x05d0, 0x05b8, 0x05d0, 0x05bc, | ||
1062 | 0x05d1, 0x05bc, 0x05d2, 0x05bc, 0x05d3, 0x05bc, 0x05d4, 0x05bc, | ||
1063 | 0x05d5, 0x05bc, 0x05d6, 0x05bc, 0x05d8, 0x05bc, 0x05d9, 0x05bc, | ||
1064 | 0x05da, 0x05bc, 0x05db, 0x05bc, 0x05dc, 0x05bc, 0x05de, 0x05bc, | ||
1065 | 0x05e0, 0x05bc, 0x05e1, 0x05bc, 0x05e3, 0x05bc, 0x05e4, 0x05bc, | ||
1066 | 0x05e6, 0x05bc, 0x05e7, 0x05bc, 0x05e8, 0x05bc, 0x05e9, 0x05bc, | ||
1067 | 0x05ea, 0x05bc, 0x05d5, 0x05b9, 0x05d1, 0x05bf, 0x05db, 0x05bf, | ||
1068 | 0x05e4, 0x05bf | ||
1069 | }; | ||
1070 | |||
1071 | u16 hfsplus_compose_table[] = { | ||
1072 | /* base */ | ||
1073 | 0x0000, 0x0050, 0x0300, 0x00a4, 0x0301, 0x00e4, 0x0302, 0x015c, | ||
1074 | 0x0303, 0x0192, 0x0304, 0x01b4, 0x0306, 0x01e6, 0x0307, 0x0220, | ||
1075 | 0x0308, 0x0270, 0x0309, 0x02d2, 0x030a, 0x02ec, 0x030b, 0x02fa, | ||
1076 | 0x030c, 0x0308, 0x030d, 0x034c, 0x030f, 0x0370, 0x0311, 0x038e, | ||
1077 | 0x0313, 0x03a8, 0x0314, 0x03c6, 0x031b, 0x03e8, 0x0323, 0x03f2, | ||
1078 | 0x0324, 0x0440, 0x0325, 0x0446, 0x0327, 0x044c, 0x0328, 0x047a, | ||
1079 | 0x032d, 0x0490, 0x032e, 0x04aa, 0x0330, 0x04b0, 0x0331, 0x04be, | ||
1080 | 0x0342, 0x04e2, 0x0345, 0x04f4, 0x05b7, 0x0504, 0x05b8, 0x050a, | ||
1081 | 0x05b9, 0x050e, 0x05bc, 0x0512, 0x05bf, 0x0540, 0x05c1, 0x0548, | ||
1082 | 0x05c2, 0x054c, 0x093c, 0x0550, 0x09bc, 0x0568, 0x09be, 0x0572, | ||
1083 | 0x09d7, 0x0576, 0x0a3c, 0x057a, 0x0b3c, 0x0586, 0x0b3e, 0x058e, | ||
1084 | 0x0b56, 0x0592, 0x0b57, 0x0596, 0x0bbe, 0x059a, 0x0bd7, 0x05a0, | ||
1085 | 0x0c56, 0x05a6, 0x0cc2, 0x05aa, 0x0cd5, 0x05ae, 0x0cd6, 0x05b4, | ||
1086 | 0x0d3e, 0x05b8, 0x0d57, 0x05be, 0x0e32, 0x05c2, 0x0eb2, 0x05c6, | ||
1087 | 0x0f71, 0x05ca, 0x0f80, 0x05d2, 0x0fb5, 0x05d8, 0x0fb7, 0x05de, | ||
1088 | 0x1100, 0x00a2, 0x1101, 0x00a2, 0x1102, 0x00a2, 0x1103, 0x00a2, | ||
1089 | 0x1104, 0x00a2, 0x1105, 0x00a2, 0x1106, 0x00a2, 0x1107, 0x00a2, | ||
1090 | 0x1108, 0x00a2, 0x1109, 0x00a2, 0x110a, 0x00a2, 0x110b, 0x00a2, | ||
1091 | 0x110c, 0x00a2, 0x110d, 0x00a2, 0x110e, 0x00a2, 0x110f, 0x00a2, | ||
1092 | 0x1110, 0x00a2, 0x1111, 0x00a2, 0x1112, 0x00a2, 0x3099, 0x05f4, | ||
1093 | 0x309a, 0x0656, | ||
1094 | /* hangul marker */ | ||
1095 | 0xffff, 0x0000, | ||
1096 | /* 0x0300 */ | ||
1097 | 0x0340, 0x001f, 0x0041, 0x066c, 0x0045, 0x066e, 0x0049, 0x0670, | ||
1098 | 0x004f, 0x0672, 0x0055, 0x0674, 0x0057, 0x0676, 0x0059, 0x0678, | ||
1099 | 0x0061, 0x067a, 0x0065, 0x067c, 0x0069, 0x067e, 0x006f, 0x0680, | ||
1100 | 0x0075, 0x0682, 0x0077, 0x0684, 0x0079, 0x0686, 0x00a8, 0x0688, | ||
1101 | 0x0391, 0x068a, 0x0395, 0x068c, 0x0397, 0x068e, 0x0399, 0x0690, | ||
1102 | 0x039f, 0x0692, 0x03a5, 0x0694, 0x03a9, 0x0696, 0x03b1, 0x0698, | ||
1103 | 0x03b5, 0x069a, 0x03b7, 0x069c, 0x03b9, 0x069e, 0x03bf, 0x06a0, | ||
1104 | 0x03c5, 0x06a2, 0x03c9, 0x06a4, 0x1fbf, 0x06a6, 0x1ffe, 0x06a8, | ||
1105 | /* 0x0301 */ | ||
1106 | 0x0341, 0x003b, 0x0041, 0x06aa, 0x0043, 0x06ac, 0x0045, 0x06ae, | ||
1107 | 0x0047, 0x06b0, 0x0049, 0x06b2, 0x004b, 0x06b4, 0x004c, 0x06b6, | ||
1108 | 0x004d, 0x06b8, 0x004e, 0x06ba, 0x004f, 0x06bc, 0x0050, 0x06be, | ||
1109 | 0x0052, 0x06c0, 0x0053, 0x06c2, 0x0055, 0x06c6, 0x0057, 0x06c8, | ||
1110 | 0x0059, 0x06ca, 0x005a, 0x06cc, 0x0061, 0x06ce, 0x0063, 0x06d0, | ||
1111 | 0x0065, 0x06d2, 0x0067, 0x06d4, 0x0069, 0x06d6, 0x006b, 0x06d8, | ||
1112 | 0x006c, 0x06da, 0x006d, 0x06dc, 0x006e, 0x06de, 0x006f, 0x06e0, | ||
1113 | 0x0070, 0x06e2, 0x0072, 0x06e4, 0x0073, 0x06e6, 0x0075, 0x06ea, | ||
1114 | 0x0077, 0x06ec, 0x0079, 0x06ee, 0x007a, 0x06f0, 0x00a8, 0x06f2, | ||
1115 | 0x00c6, 0x06f4, 0x00d8, 0x06f6, 0x00e6, 0x06f8, 0x00f8, 0x06fa, | ||
1116 | 0x0391, 0x06fc, 0x0395, 0x06fe, 0x0397, 0x0700, 0x0399, 0x0702, | ||
1117 | 0x039f, 0x0704, 0x03a5, 0x0706, 0x03a9, 0x0708, 0x03b1, 0x070a, | ||
1118 | 0x03b5, 0x070c, 0x03b7, 0x070e, 0x03b9, 0x0710, 0x03bf, 0x0712, | ||
1119 | 0x03c5, 0x0714, 0x03c9, 0x0716, 0x0413, 0x0718, 0x041a, 0x071a, | ||
1120 | 0x0433, 0x071c, 0x043a, 0x071e, 0x1fbf, 0x0720, 0x1ffe, 0x0722, | ||
1121 | /* 0x0302 */ | ||
1122 | 0x0000, 0x001a, 0x0041, 0x0724, 0x0043, 0x072e, 0x0045, 0x0730, | ||
1123 | 0x0047, 0x073a, 0x0048, 0x073c, 0x0049, 0x073e, 0x004a, 0x0740, | ||
1124 | 0x004f, 0x0742, 0x0053, 0x074c, 0x0055, 0x074e, 0x0057, 0x0750, | ||
1125 | 0x0059, 0x0752, 0x005a, 0x0754, 0x0061, 0x0756, 0x0063, 0x0760, | ||
1126 | 0x0065, 0x0762, 0x0067, 0x076c, 0x0068, 0x076e, 0x0069, 0x0770, | ||
1127 | 0x006a, 0x0772, 0x006f, 0x0774, 0x0073, 0x077e, 0x0075, 0x0780, | ||
1128 | 0x0077, 0x0782, 0x0079, 0x0784, 0x007a, 0x0786, | ||
1129 | /* 0x0303 */ | ||
1130 | 0x0000, 0x0010, 0x0041, 0x0788, 0x0045, 0x078a, 0x0049, 0x078c, | ||
1131 | 0x004e, 0x078e, 0x004f, 0x0790, 0x0055, 0x0796, 0x0056, 0x079a, | ||
1132 | 0x0059, 0x079c, 0x0061, 0x079e, 0x0065, 0x07a0, 0x0069, 0x07a2, | ||
1133 | 0x006e, 0x07a4, 0x006f, 0x07a6, 0x0075, 0x07ac, 0x0076, 0x07b0, | ||
1134 | 0x0079, 0x07b2, | ||
1135 | /* 0x0304 */ | ||
1136 | 0x0000, 0x0018, 0x0041, 0x07b4, 0x0045, 0x07b6, 0x0047, 0x07bc, | ||
1137 | 0x0049, 0x07be, 0x004f, 0x07c0, 0x0055, 0x07c6, 0x0061, 0x07ca, | ||
1138 | 0x0065, 0x07cc, 0x0067, 0x07d2, 0x0069, 0x07d4, 0x006f, 0x07d6, | ||
1139 | 0x0075, 0x07dc, 0x00c6, 0x07e0, 0x00e6, 0x07e2, 0x0391, 0x07e4, | ||
1140 | 0x0399, 0x07e6, 0x03a5, 0x07e8, 0x03b1, 0x07ea, 0x03b9, 0x07ec, | ||
1141 | 0x03c5, 0x07ee, 0x0418, 0x07f0, 0x0423, 0x07f2, 0x0438, 0x07f4, | ||
1142 | 0x0443, 0x07f6, | ||
1143 | /* 0x0306 */ | ||
1144 | 0x0000, 0x001c, 0x0041, 0x07f8, 0x0045, 0x0802, 0x0047, 0x0804, | ||
1145 | 0x0049, 0x0806, 0x004f, 0x0808, 0x0055, 0x080a, 0x0061, 0x080c, | ||
1146 | 0x0065, 0x0816, 0x0067, 0x0818, 0x0069, 0x081a, 0x006f, 0x081c, | ||
1147 | 0x0075, 0x081e, 0x0391, 0x0820, 0x0399, 0x0822, 0x03a5, 0x0824, | ||
1148 | 0x03b1, 0x0826, 0x03b9, 0x0828, 0x03c5, 0x082a, 0x0410, 0x082c, | ||
1149 | 0x0415, 0x082e, 0x0416, 0x0830, 0x0418, 0x0832, 0x0423, 0x0834, | ||
1150 | 0x0430, 0x0836, 0x0435, 0x0838, 0x0436, 0x083a, 0x0438, 0x083c, | ||
1151 | 0x0443, 0x083e, | ||
1152 | /* 0x0307 */ | ||
1153 | 0x0000, 0x0027, 0x0041, 0x0840, 0x0042, 0x0844, 0x0043, 0x0846, | ||
1154 | 0x0044, 0x0848, 0x0045, 0x084a, 0x0046, 0x084c, 0x0047, 0x084e, | ||
1155 | 0x0048, 0x0850, 0x0049, 0x0852, 0x004d, 0x0854, 0x004e, 0x0856, | ||
1156 | 0x0050, 0x0858, 0x0052, 0x085a, 0x0053, 0x085c, 0x0054, 0x085e, | ||
1157 | 0x0057, 0x0860, 0x0058, 0x0862, 0x0059, 0x0864, 0x005a, 0x0866, | ||
1158 | 0x0061, 0x0868, 0x0062, 0x086c, 0x0063, 0x086e, 0x0064, 0x0870, | ||
1159 | 0x0065, 0x0872, 0x0066, 0x0874, 0x0067, 0x0876, 0x0068, 0x0878, | ||
1160 | 0x006d, 0x087a, 0x006e, 0x087c, 0x0070, 0x087e, 0x0072, 0x0880, | ||
1161 | 0x0073, 0x0882, 0x0074, 0x0884, 0x0077, 0x0886, 0x0078, 0x0888, | ||
1162 | 0x0079, 0x088a, 0x007a, 0x088c, 0x017f, 0x088e, 0x0306, 0x0890, | ||
1163 | /* 0x0308 */ | ||
1164 | 0x0000, 0x0030, 0x0041, 0x0892, 0x0045, 0x0896, 0x0048, 0x0898, | ||
1165 | 0x0049, 0x089a, 0x004f, 0x089e, 0x0055, 0x08a0, 0x0057, 0x08aa, | ||
1166 | 0x0058, 0x08ac, 0x0059, 0x08ae, 0x0061, 0x08b0, 0x0065, 0x08b4, | ||
1167 | 0x0068, 0x08b6, 0x0069, 0x08b8, 0x006f, 0x08bc, 0x0074, 0x08be, | ||
1168 | 0x0075, 0x08c0, 0x0077, 0x08ca, 0x0078, 0x08cc, 0x0079, 0x08ce, | ||
1169 | 0x018f, 0x08d0, 0x019f, 0x08d2, 0x0259, 0x08d4, 0x0275, 0x08d6, | ||
1170 | 0x0399, 0x08d8, 0x03a5, 0x08da, 0x03b9, 0x08dc, 0x03c5, 0x08e6, | ||
1171 | 0x03d2, 0x08f0, 0x0406, 0x08f2, 0x0410, 0x08f4, 0x0415, 0x08f6, | ||
1172 | 0x0416, 0x08f8, 0x0417, 0x08fa, 0x0418, 0x08fc, 0x041e, 0x08fe, | ||
1173 | 0x0423, 0x0900, 0x0427, 0x0902, 0x042b, 0x0904, 0x0430, 0x0906, | ||
1174 | 0x0435, 0x0908, 0x0436, 0x090a, 0x0437, 0x090c, 0x0438, 0x090e, | ||
1175 | 0x043e, 0x0910, 0x0443, 0x0912, 0x0447, 0x0914, 0x044b, 0x0916, | ||
1176 | 0x0456, 0x0918, | ||
1177 | /* 0x0309 */ | ||
1178 | 0x0000, 0x000c, 0x0041, 0x091a, 0x0045, 0x091c, 0x0049, 0x091e, | ||
1179 | 0x004f, 0x0920, 0x0055, 0x0922, 0x0059, 0x0924, 0x0061, 0x0926, | ||
1180 | 0x0065, 0x0928, 0x0069, 0x092a, 0x006f, 0x092c, 0x0075, 0x092e, | ||
1181 | 0x0079, 0x0930, | ||
1182 | /* 0x030a */ | ||
1183 | 0x0000, 0x0006, 0x0041, 0x0932, 0x0055, 0x0936, 0x0061, 0x0938, | ||
1184 | 0x0075, 0x093c, 0x0077, 0x093e, 0x0079, 0x0940, | ||
1185 | /* 0x030b */ | ||
1186 | 0x0000, 0x0006, 0x004f, 0x0942, 0x0055, 0x0944, 0x006f, 0x0946, | ||
1187 | 0x0075, 0x0948, 0x0423, 0x094a, 0x0443, 0x094c, | ||
1188 | /* 0x030c */ | ||
1189 | 0x0000, 0x0021, 0x0041, 0x094e, 0x0043, 0x0950, 0x0044, 0x0952, | ||
1190 | 0x0045, 0x0954, 0x0047, 0x0956, 0x0049, 0x0958, 0x004b, 0x095a, | ||
1191 | 0x004c, 0x095c, 0x004e, 0x095e, 0x004f, 0x0960, 0x0052, 0x0962, | ||
1192 | 0x0053, 0x0964, 0x0054, 0x0968, 0x0055, 0x096a, 0x005a, 0x096c, | ||
1193 | 0x0061, 0x096e, 0x0063, 0x0970, 0x0064, 0x0972, 0x0065, 0x0974, | ||
1194 | 0x0067, 0x0976, 0x0069, 0x0978, 0x006a, 0x097a, 0x006b, 0x097c, | ||
1195 | 0x006c, 0x097e, 0x006e, 0x0980, 0x006f, 0x0982, 0x0072, 0x0984, | ||
1196 | 0x0073, 0x0986, 0x0074, 0x098a, 0x0075, 0x098c, 0x007a, 0x098e, | ||
1197 | 0x01b7, 0x0990, 0x0292, 0x0992, | ||
1198 | /* 0x030d */ | ||
1199 | 0x0000, 0x0011, 0x00a8, 0x0994, 0x0308, 0x0996, 0x0391, 0x0998, | ||
1200 | 0x0395, 0x099a, 0x0397, 0x099c, 0x0399, 0x099e, 0x039f, 0x09a0, | ||
1201 | 0x03a5, 0x09a2, 0x03a9, 0x09a4, 0x03b1, 0x09a6, 0x03b5, 0x09a8, | ||
1202 | 0x03b7, 0x09aa, 0x03b9, 0x09ac, 0x03bf, 0x09ae, 0x03c5, 0x09b0, | ||
1203 | 0x03c9, 0x09b2, 0x03d2, 0x09b4, | ||
1204 | /* 0x030f */ | ||
1205 | 0x0000, 0x000e, 0x0041, 0x09b6, 0x0045, 0x09b8, 0x0049, 0x09ba, | ||
1206 | 0x004f, 0x09bc, 0x0052, 0x09be, 0x0055, 0x09c0, 0x0061, 0x09c2, | ||
1207 | 0x0065, 0x09c4, 0x0069, 0x09c6, 0x006f, 0x09c8, 0x0072, 0x09ca, | ||
1208 | 0x0075, 0x09cc, 0x0474, 0x09ce, 0x0475, 0x09d0, | ||
1209 | /* 0x0311 */ | ||
1210 | 0x0000, 0x000c, 0x0041, 0x09d2, 0x0045, 0x09d4, 0x0049, 0x09d6, | ||
1211 | 0x004f, 0x09d8, 0x0052, 0x09da, 0x0055, 0x09dc, 0x0061, 0x09de, | ||
1212 | 0x0065, 0x09e0, 0x0069, 0x09e2, 0x006f, 0x09e4, 0x0072, 0x09e6, | ||
1213 | 0x0075, 0x09e8, | ||
1214 | /* 0x0313 */ | ||
1215 | 0x0343, 0x000e, 0x0391, 0x09ea, 0x0395, 0x09f2, 0x0397, 0x09f8, | ||
1216 | 0x0399, 0x0a00, 0x039f, 0x0a08, 0x03a9, 0x0a0e, 0x03b1, 0x0a16, | ||
1217 | 0x03b5, 0x0a1e, 0x03b7, 0x0a24, 0x03b9, 0x0a2c, 0x03bf, 0x0a34, | ||
1218 | 0x03c1, 0x0a3a, 0x03c5, 0x0a3c, 0x03c9, 0x0a44, | ||
1219 | /* 0x0314 */ | ||
1220 | 0x0000, 0x0010, 0x0391, 0x0a4c, 0x0395, 0x0a54, 0x0397, 0x0a5a, | ||
1221 | 0x0399, 0x0a62, 0x039f, 0x0a6a, 0x03a1, 0x0a70, 0x03a5, 0x0a72, | ||
1222 | 0x03a9, 0x0a7a, 0x03b1, 0x0a82, 0x03b5, 0x0a8a, 0x03b7, 0x0a90, | ||
1223 | 0x03b9, 0x0a98, 0x03bf, 0x0aa0, 0x03c1, 0x0aa6, 0x03c5, 0x0aa8, | ||
1224 | 0x03c9, 0x0ab0, | ||
1225 | /* 0x031b */ | ||
1226 | 0x0000, 0x0004, 0x004f, 0x0ab8, 0x0055, 0x0ac4, 0x006f, 0x0ad0, | ||
1227 | 0x0075, 0x0adc, | ||
1228 | /* 0x0323 */ | ||
1229 | 0x0000, 0x0026, 0x0041, 0x0ae8, 0x0042, 0x0aee, 0x0044, 0x0af0, | ||
1230 | 0x0045, 0x0af2, 0x0048, 0x0af6, 0x0049, 0x0af8, 0x004b, 0x0afa, | ||
1231 | 0x004c, 0x0afc, 0x004d, 0x0b00, 0x004e, 0x0b02, 0x004f, 0x0b04, | ||
1232 | 0x0052, 0x0b08, 0x0053, 0x0b0c, 0x0054, 0x0b10, 0x0055, 0x0b12, | ||
1233 | 0x0056, 0x0b14, 0x0057, 0x0b16, 0x0059, 0x0b18, 0x005a, 0x0b1a, | ||
1234 | 0x0061, 0x0b1c, 0x0062, 0x0b22, 0x0064, 0x0b24, 0x0065, 0x0b26, | ||
1235 | 0x0068, 0x0b2a, 0x0069, 0x0b2c, 0x006b, 0x0b2e, 0x006c, 0x0b30, | ||
1236 | 0x006d, 0x0b34, 0x006e, 0x0b36, 0x006f, 0x0b38, 0x0072, 0x0b3c, | ||
1237 | 0x0073, 0x0b40, 0x0074, 0x0b44, 0x0075, 0x0b46, 0x0076, 0x0b48, | ||
1238 | 0x0077, 0x0b4a, 0x0079, 0x0b4c, 0x007a, 0x0b4e, | ||
1239 | /* 0x0324 */ | ||
1240 | 0x0000, 0x0002, 0x0055, 0x0b50, 0x0075, 0x0b52, | ||
1241 | /* 0x0325 */ | ||
1242 | 0x0000, 0x0002, 0x0041, 0x0b54, 0x0061, 0x0b56, | ||
1243 | /* 0x0327 */ | ||
1244 | 0x0000, 0x0016, 0x0043, 0x0b58, 0x0044, 0x0b5c, 0x0045, 0x0b5e, | ||
1245 | 0x0047, 0x0b62, 0x0048, 0x0b64, 0x004b, 0x0b66, 0x004c, 0x0b68, | ||
1246 | 0x004e, 0x0b6a, 0x0052, 0x0b6c, 0x0053, 0x0b6e, 0x0054, 0x0b70, | ||
1247 | 0x0063, 0x0b72, 0x0064, 0x0b76, 0x0065, 0x0b78, 0x0067, 0x0b7c, | ||
1248 | 0x0068, 0x0b7e, 0x006b, 0x0b80, 0x006c, 0x0b82, 0x006e, 0x0b84, | ||
1249 | 0x0072, 0x0b86, 0x0073, 0x0b88, 0x0074, 0x0b8a, | ||
1250 | /* 0x0328 */ | ||
1251 | 0x0000, 0x000a, 0x0041, 0x0b8c, 0x0045, 0x0b8e, 0x0049, 0x0b90, | ||
1252 | 0x004f, 0x0b92, 0x0055, 0x0b96, 0x0061, 0x0b98, 0x0065, 0x0b9a, | ||
1253 | 0x0069, 0x0b9c, 0x006f, 0x0b9e, 0x0075, 0x0ba2, | ||
1254 | /* 0x032d */ | ||
1255 | 0x0000, 0x000c, 0x0044, 0x0ba4, 0x0045, 0x0ba6, 0x004c, 0x0ba8, | ||
1256 | 0x004e, 0x0baa, 0x0054, 0x0bac, 0x0055, 0x0bae, 0x0064, 0x0bb0, | ||
1257 | 0x0065, 0x0bb2, 0x006c, 0x0bb4, 0x006e, 0x0bb6, 0x0074, 0x0bb8, | ||
1258 | 0x0075, 0x0bba, | ||
1259 | /* 0x032e */ | ||
1260 | 0x0000, 0x0002, 0x0048, 0x0bbc, 0x0068, 0x0bbe, | ||
1261 | /* 0x0330 */ | ||
1262 | 0x0000, 0x0006, 0x0045, 0x0bc0, 0x0049, 0x0bc2, 0x0055, 0x0bc4, | ||
1263 | 0x0065, 0x0bc6, 0x0069, 0x0bc8, 0x0075, 0x0bca, | ||
1264 | /* 0x0331 */ | ||
1265 | 0x0000, 0x0011, 0x0042, 0x0bcc, 0x0044, 0x0bce, 0x004b, 0x0bd0, | ||
1266 | 0x004c, 0x0bd2, 0x004e, 0x0bd4, 0x0052, 0x0bd6, 0x0054, 0x0bd8, | ||
1267 | 0x005a, 0x0bda, 0x0062, 0x0bdc, 0x0064, 0x0bde, 0x0068, 0x0be0, | ||
1268 | 0x006b, 0x0be2, 0x006c, 0x0be4, 0x006e, 0x0be6, 0x0072, 0x0be8, | ||
1269 | 0x0074, 0x0bea, 0x007a, 0x0bec, | ||
1270 | /* 0x0342 */ | ||
1271 | 0x0000, 0x0008, 0x00a8, 0x0bee, 0x03b1, 0x0bf0, 0x03b7, 0x0bf2, | ||
1272 | 0x03b9, 0x0bf4, 0x03c5, 0x0bf6, 0x03c9, 0x0bf8, 0x1fbf, 0x0bfa, | ||
1273 | 0x1ffe, 0x0bfc, | ||
1274 | /* 0x0345 */ | ||
1275 | 0x0000, 0x0007, 0x0391, 0x0bfe, 0x0397, 0x0c04, 0x03a9, 0x0c0a, | ||
1276 | 0x03b1, 0x0c10, 0x03b7, 0x0c1c, 0x03bf, 0x0c28, 0x03c9, 0x0c2c, | ||
1277 | /* 0x05b7 */ | ||
1278 | 0x0000, 0x0002, 0x05d0, 0x0c36, 0x05f2, 0x0c38, | ||
1279 | /* 0x05b8 */ | ||
1280 | 0x0000, 0x0001, 0x05d0, 0x0c3a, | ||
1281 | /* 0x05b9 */ | ||
1282 | 0x0000, 0x0001, 0x05d5, 0x0c3c, | ||
1283 | /* 0x05bc */ | ||
1284 | 0x0000, 0x0016, 0x05d0, 0x0c3e, 0x05d1, 0x0c40, 0x05d2, 0x0c42, | ||
1285 | 0x05d3, 0x0c44, 0x05d4, 0x0c46, 0x05d5, 0x0c48, 0x05d6, 0x0c4a, | ||
1286 | 0x05d8, 0x0c4c, 0x05d9, 0x0c4e, 0x05da, 0x0c50, 0x05db, 0x0c52, | ||
1287 | 0x05dc, 0x0c54, 0x05de, 0x0c56, 0x05e0, 0x0c58, 0x05e1, 0x0c5a, | ||
1288 | 0x05e3, 0x0c5c, 0x05e4, 0x0c5e, 0x05e6, 0x0c60, 0x05e7, 0x0c62, | ||
1289 | 0x05e8, 0x0c64, 0x05e9, 0x0c66, 0x05ea, 0x0c6c, | ||
1290 | /* 0x05bf */ | ||
1291 | 0x0000, 0x0003, 0x05d1, 0x0c6e, 0x05db, 0x0c70, 0x05e4, 0x0c72, | ||
1292 | /* 0x05c1 */ | ||
1293 | 0x0000, 0x0001, 0x05e9, 0x0c74, | ||
1294 | /* 0x05c2 */ | ||
1295 | 0x0000, 0x0001, 0x05e9, 0x0c76, | ||
1296 | /* 0x093c */ | ||
1297 | 0x0000, 0x000b, 0x0915, 0x0c78, 0x0916, 0x0c7a, 0x0917, 0x0c7c, | ||
1298 | 0x091c, 0x0c7e, 0x0921, 0x0c80, 0x0922, 0x0c82, 0x0928, 0x0c84, | ||
1299 | 0x092b, 0x0c86, 0x092f, 0x0c88, 0x0930, 0x0c8a, 0x0933, 0x0c8c, | ||
1300 | /* 0x09bc */ | ||
1301 | 0x0000, 0x0004, 0x09a1, 0x0c8e, 0x09a2, 0x0c90, 0x09ac, 0x0c92, | ||
1302 | 0x09af, 0x0c94, | ||
1303 | /* 0x09be */ | ||
1304 | 0x0000, 0x0001, 0x09c7, 0x0c96, | ||
1305 | /* 0x09d7 */ | ||
1306 | 0x0000, 0x0001, 0x09c7, 0x0c98, | ||
1307 | /* 0x0a3c */ | ||
1308 | 0x0000, 0x0005, 0x0a16, 0x0c9a, 0x0a17, 0x0c9c, 0x0a1c, 0x0c9e, | ||
1309 | 0x0a21, 0x0ca0, 0x0a2b, 0x0ca2, | ||
1310 | /* 0x0b3c */ | ||
1311 | 0x0000, 0x0003, 0x0b21, 0x0ca4, 0x0b22, 0x0ca6, 0x0b2f, 0x0ca8, | ||
1312 | /* 0x0b3e */ | ||
1313 | 0x0000, 0x0001, 0x0b47, 0x0caa, | ||
1314 | /* 0x0b56 */ | ||
1315 | 0x0000, 0x0001, 0x0b47, 0x0cac, | ||
1316 | /* 0x0b57 */ | ||
1317 | 0x0000, 0x0001, 0x0b47, 0x0cae, | ||
1318 | /* 0x0bbe */ | ||
1319 | 0x0000, 0x0002, 0x0bc6, 0x0cb0, 0x0bc7, 0x0cb2, | ||
1320 | /* 0x0bd7 */ | ||
1321 | 0x0000, 0x0002, 0x0b92, 0x0cb4, 0x0bc6, 0x0cb6, | ||
1322 | /* 0x0c56 */ | ||
1323 | 0x0000, 0x0001, 0x0c46, 0x0cb8, | ||
1324 | /* 0x0cc2 */ | ||
1325 | 0x0000, 0x0001, 0x0cc6, 0x0cba, | ||
1326 | /* 0x0cd5 */ | ||
1327 | 0x0000, 0x0002, 0x0cbf, 0x0cbe, 0x0cc6, 0x0cc0, | ||
1328 | /* 0x0cd6 */ | ||
1329 | 0x0000, 0x0001, 0x0cc6, 0x0cc2, | ||
1330 | /* 0x0d3e */ | ||
1331 | 0x0000, 0x0002, 0x0d46, 0x0cc4, 0x0d47, 0x0cc6, | ||
1332 | /* 0x0d57 */ | ||
1333 | 0x0000, 0x0001, 0x0d46, 0x0cc8, | ||
1334 | /* 0x0e32 */ | ||
1335 | 0x0000, 0x0001, 0x0e4d, 0x0cca, | ||
1336 | /* 0x0eb2 */ | ||
1337 | 0x0000, 0x0001, 0x0ecd, 0x0ccc, | ||
1338 | /* 0x0f71 */ | ||
1339 | 0x0000, 0x0003, 0x0f72, 0x0cce, 0x0f74, 0x0cd0, 0x0f80, 0x0cd2, | ||
1340 | /* 0x0f80 */ | ||
1341 | 0x0000, 0x0002, 0x0fb2, 0x0cd4, 0x0fb3, 0x0cd8, | ||
1342 | /* 0x0fb5 */ | ||
1343 | 0x0000, 0x0002, 0x0f40, 0x0cdc, 0x0f90, 0x0cde, | ||
1344 | /* 0x0fb7 */ | ||
1345 | 0x0000, 0x000a, 0x0f42, 0x0ce0, 0x0f4c, 0x0ce2, 0x0f51, 0x0ce4, | ||
1346 | 0x0f56, 0x0ce6, 0x0f5b, 0x0ce8, 0x0f92, 0x0cea, 0x0f9c, 0x0cec, | ||
1347 | 0x0fa1, 0x0cee, 0x0fa6, 0x0cf0, 0x0fab, 0x0cf2, | ||
1348 | /* 0x3099 */ | ||
1349 | 0x0000, 0x0030, 0x3046, 0x0cf4, 0x304b, 0x0cf6, 0x304d, 0x0cf8, | ||
1350 | 0x304f, 0x0cfa, 0x3051, 0x0cfc, 0x3053, 0x0cfe, 0x3055, 0x0d00, | ||
1351 | 0x3057, 0x0d02, 0x3059, 0x0d04, 0x305b, 0x0d06, 0x305d, 0x0d08, | ||
1352 | 0x305f, 0x0d0a, 0x3061, 0x0d0c, 0x3064, 0x0d0e, 0x3066, 0x0d10, | ||
1353 | 0x3068, 0x0d12, 0x306f, 0x0d14, 0x3072, 0x0d16, 0x3075, 0x0d18, | ||
1354 | 0x3078, 0x0d1a, 0x307b, 0x0d1c, 0x309d, 0x0d1e, 0x30a6, 0x0d20, | ||
1355 | 0x30ab, 0x0d22, 0x30ad, 0x0d24, 0x30af, 0x0d26, 0x30b1, 0x0d28, | ||
1356 | 0x30b3, 0x0d2a, 0x30b5, 0x0d2c, 0x30b7, 0x0d2e, 0x30b9, 0x0d30, | ||
1357 | 0x30bb, 0x0d32, 0x30bd, 0x0d34, 0x30bf, 0x0d36, 0x30c1, 0x0d38, | ||
1358 | 0x30c4, 0x0d3a, 0x30c6, 0x0d3c, 0x30c8, 0x0d3e, 0x30cf, 0x0d40, | ||
1359 | 0x30d2, 0x0d42, 0x30d5, 0x0d44, 0x30d8, 0x0d46, 0x30db, 0x0d48, | ||
1360 | 0x30ef, 0x0d4a, 0x30f0, 0x0d4c, 0x30f1, 0x0d4e, 0x30f2, 0x0d50, | ||
1361 | 0x30fd, 0x0d52, | ||
1362 | /* 0x309a */ | ||
1363 | 0x0000, 0x000a, 0x306f, 0x0d54, 0x3072, 0x0d56, 0x3075, 0x0d58, | ||
1364 | 0x3078, 0x0d5a, 0x307b, 0x0d5c, 0x30cf, 0x0d5e, 0x30d2, 0x0d60, | ||
1365 | 0x30d5, 0x0d62, 0x30d8, 0x0d64, 0x30db, 0x0d66, | ||
1366 | /* 0x0041 0x0300 */ | ||
1367 | 0x00c0, 0x0000, | ||
1368 | /* 0x0045 0x0300 */ | ||
1369 | 0x00c8, 0x0000, | ||
1370 | /* 0x0049 0x0300 */ | ||
1371 | 0x00cc, 0x0000, | ||
1372 | /* 0x004f 0x0300 */ | ||
1373 | 0x00d2, 0x0000, | ||
1374 | /* 0x0055 0x0300 */ | ||
1375 | 0x00d9, 0x0000, | ||
1376 | /* 0x0057 0x0300 */ | ||
1377 | 0x1e80, 0x0000, | ||
1378 | /* 0x0059 0x0300 */ | ||
1379 | 0x1ef2, 0x0000, | ||
1380 | /* 0x0061 0x0300 */ | ||
1381 | 0x00e0, 0x0000, | ||
1382 | /* 0x0065 0x0300 */ | ||
1383 | 0x00e8, 0x0000, | ||
1384 | /* 0x0069 0x0300 */ | ||
1385 | 0x00ec, 0x0000, | ||
1386 | /* 0x006f 0x0300 */ | ||
1387 | 0x00f2, 0x0000, | ||
1388 | /* 0x0075 0x0300 */ | ||
1389 | 0x00f9, 0x0000, | ||
1390 | /* 0x0077 0x0300 */ | ||
1391 | 0x1e81, 0x0000, | ||
1392 | /* 0x0079 0x0300 */ | ||
1393 | 0x1ef3, 0x0000, | ||
1394 | /* 0x00a8 0x0300 */ | ||
1395 | 0x1fed, 0x0000, | ||
1396 | /* 0x0391 0x0300 */ | ||
1397 | 0x1fba, 0x0000, | ||
1398 | /* 0x0395 0x0300 */ | ||
1399 | 0x1fc8, 0x0000, | ||
1400 | /* 0x0397 0x0300 */ | ||
1401 | 0x1fca, 0x0000, | ||
1402 | /* 0x0399 0x0300 */ | ||
1403 | 0x1fda, 0x0000, | ||
1404 | /* 0x039f 0x0300 */ | ||
1405 | 0x1ff8, 0x0000, | ||
1406 | /* 0x03a5 0x0300 */ | ||
1407 | 0x1fea, 0x0000, | ||
1408 | /* 0x03a9 0x0300 */ | ||
1409 | 0x1ffa, 0x0000, | ||
1410 | /* 0x03b1 0x0300 */ | ||
1411 | 0x1f70, 0x0000, | ||
1412 | /* 0x03b5 0x0300 */ | ||
1413 | 0x1f72, 0x0000, | ||
1414 | /* 0x03b7 0x0300 */ | ||
1415 | 0x1f74, 0x0000, | ||
1416 | /* 0x03b9 0x0300 */ | ||
1417 | 0x1f76, 0x0000, | ||
1418 | /* 0x03bf 0x0300 */ | ||
1419 | 0x1f78, 0x0000, | ||
1420 | /* 0x03c5 0x0300 */ | ||
1421 | 0x1f7a, 0x0000, | ||
1422 | /* 0x03c9 0x0300 */ | ||
1423 | 0x1f7c, 0x0000, | ||
1424 | /* 0x1fbf 0x0300 */ | ||
1425 | 0x1fcd, 0x0000, | ||
1426 | /* 0x1ffe 0x0300 */ | ||
1427 | 0x1fdd, 0x0000, | ||
1428 | /* 0x0041 0x0301 */ | ||
1429 | 0x00c1, 0x0000, | ||
1430 | /* 0x0043 0x0301 */ | ||
1431 | 0x0106, 0x0000, | ||
1432 | /* 0x0045 0x0301 */ | ||
1433 | 0x00c9, 0x0000, | ||
1434 | /* 0x0047 0x0301 */ | ||
1435 | 0x01f4, 0x0000, | ||
1436 | /* 0x0049 0x0301 */ | ||
1437 | 0x00cd, 0x0000, | ||
1438 | /* 0x004b 0x0301 */ | ||
1439 | 0x1e30, 0x0000, | ||
1440 | /* 0x004c 0x0301 */ | ||
1441 | 0x0139, 0x0000, | ||
1442 | /* 0x004d 0x0301 */ | ||
1443 | 0x1e3e, 0x0000, | ||
1444 | /* 0x004e 0x0301 */ | ||
1445 | 0x0143, 0x0000, | ||
1446 | /* 0x004f 0x0301 */ | ||
1447 | 0x00d3, 0x0000, | ||
1448 | /* 0x0050 0x0301 */ | ||
1449 | 0x1e54, 0x0000, | ||
1450 | /* 0x0052 0x0301 */ | ||
1451 | 0x0154, 0x0000, | ||
1452 | /* 0x0053 0x0301 */ | ||
1453 | 0x015a, 0x0001, 0x0307, 0x0d68, | ||
1454 | /* 0x0055 0x0301 */ | ||
1455 | 0x00da, 0x0000, | ||
1456 | /* 0x0057 0x0301 */ | ||
1457 | 0x1e82, 0x0000, | ||
1458 | /* 0x0059 0x0301 */ | ||
1459 | 0x00dd, 0x0000, | ||
1460 | /* 0x005a 0x0301 */ | ||
1461 | 0x0179, 0x0000, | ||
1462 | /* 0x0061 0x0301 */ | ||
1463 | 0x00e1, 0x0000, | ||
1464 | /* 0x0063 0x0301 */ | ||
1465 | 0x0107, 0x0000, | ||
1466 | /* 0x0065 0x0301 */ | ||
1467 | 0x00e9, 0x0000, | ||
1468 | /* 0x0067 0x0301 */ | ||
1469 | 0x01f5, 0x0000, | ||
1470 | /* 0x0069 0x0301 */ | ||
1471 | 0x00ed, 0x0000, | ||
1472 | /* 0x006b 0x0301 */ | ||
1473 | 0x1e31, 0x0000, | ||
1474 | /* 0x006c 0x0301 */ | ||
1475 | 0x013a, 0x0000, | ||
1476 | /* 0x006d 0x0301 */ | ||
1477 | 0x1e3f, 0x0000, | ||
1478 | /* 0x006e 0x0301 */ | ||
1479 | 0x0144, 0x0000, | ||
1480 | /* 0x006f 0x0301 */ | ||
1481 | 0x00f3, 0x0000, | ||
1482 | /* 0x0070 0x0301 */ | ||
1483 | 0x1e55, 0x0000, | ||
1484 | /* 0x0072 0x0301 */ | ||
1485 | 0x0155, 0x0000, | ||
1486 | /* 0x0073 0x0301 */ | ||
1487 | 0x015b, 0x0001, 0x0307, 0x0d6a, | ||
1488 | /* 0x0075 0x0301 */ | ||
1489 | 0x00fa, 0x0000, | ||
1490 | /* 0x0077 0x0301 */ | ||
1491 | 0x1e83, 0x0000, | ||
1492 | /* 0x0079 0x0301 */ | ||
1493 | 0x00fd, 0x0000, | ||
1494 | /* 0x007a 0x0301 */ | ||
1495 | 0x017a, 0x0000, | ||
1496 | /* 0x00a8 0x0301 */ | ||
1497 | 0x1fee, 0x0000, | ||
1498 | /* 0x00c6 0x0301 */ | ||
1499 | 0x01fc, 0x0000, | ||
1500 | /* 0x00d8 0x0301 */ | ||
1501 | 0x01fe, 0x0000, | ||
1502 | /* 0x00e6 0x0301 */ | ||
1503 | 0x01fd, 0x0000, | ||
1504 | /* 0x00f8 0x0301 */ | ||
1505 | 0x01ff, 0x0000, | ||
1506 | /* 0x0391 0x0301 */ | ||
1507 | 0x1fbb, 0x0000, | ||
1508 | /* 0x0395 0x0301 */ | ||
1509 | 0x1fc9, 0x0000, | ||
1510 | /* 0x0397 0x0301 */ | ||
1511 | 0x1fcb, 0x0000, | ||
1512 | /* 0x0399 0x0301 */ | ||
1513 | 0x1fdb, 0x0000, | ||
1514 | /* 0x039f 0x0301 */ | ||
1515 | 0x1ff9, 0x0000, | ||
1516 | /* 0x03a5 0x0301 */ | ||
1517 | 0x1feb, 0x0000, | ||
1518 | /* 0x03a9 0x0301 */ | ||
1519 | 0x1ffb, 0x0000, | ||
1520 | /* 0x03b1 0x0301 */ | ||
1521 | 0x1f71, 0x0000, | ||
1522 | /* 0x03b5 0x0301 */ | ||
1523 | 0x1f73, 0x0000, | ||
1524 | /* 0x03b7 0x0301 */ | ||
1525 | 0x1f75, 0x0000, | ||
1526 | /* 0x03b9 0x0301 */ | ||
1527 | 0x1f77, 0x0000, | ||
1528 | /* 0x03bf 0x0301 */ | ||
1529 | 0x1f79, 0x0000, | ||
1530 | /* 0x03c5 0x0301 */ | ||
1531 | 0x1f7b, 0x0000, | ||
1532 | /* 0x03c9 0x0301 */ | ||
1533 | 0x1f7d, 0x0000, | ||
1534 | /* 0x0413 0x0301 */ | ||
1535 | 0x0403, 0x0000, | ||
1536 | /* 0x041a 0x0301 */ | ||
1537 | 0x040c, 0x0000, | ||
1538 | /* 0x0433 0x0301 */ | ||
1539 | 0x0453, 0x0000, | ||
1540 | /* 0x043a 0x0301 */ | ||
1541 | 0x045c, 0x0000, | ||
1542 | /* 0x1fbf 0x0301 */ | ||
1543 | 0x1fce, 0x0000, | ||
1544 | /* 0x1ffe 0x0301 */ | ||
1545 | 0x1fde, 0x0000, | ||
1546 | /* 0x0041 0x0302 */ | ||
1547 | 0x00c2, 0x0004, 0x0300, 0x0d6c, 0x0301, 0x0d6e, 0x0303, 0x0d70, | ||
1548 | 0x0309, 0x0d72, | ||
1549 | /* 0x0043 0x0302 */ | ||
1550 | 0x0108, 0x0000, | ||
1551 | /* 0x0045 0x0302 */ | ||
1552 | 0x00ca, 0x0004, 0x0300, 0x0d74, 0x0301, 0x0d76, 0x0303, 0x0d78, | ||
1553 | 0x0309, 0x0d7a, | ||
1554 | /* 0x0047 0x0302 */ | ||
1555 | 0x011c, 0x0000, | ||
1556 | /* 0x0048 0x0302 */ | ||
1557 | 0x0124, 0x0000, | ||
1558 | /* 0x0049 0x0302 */ | ||
1559 | 0x00ce, 0x0000, | ||
1560 | /* 0x004a 0x0302 */ | ||
1561 | 0x0134, 0x0000, | ||
1562 | /* 0x004f 0x0302 */ | ||
1563 | 0x00d4, 0x0004, 0x0300, 0x0d7c, 0x0301, 0x0d7e, 0x0303, 0x0d80, | ||
1564 | 0x0309, 0x0d82, | ||
1565 | /* 0x0053 0x0302 */ | ||
1566 | 0x015c, 0x0000, | ||
1567 | /* 0x0055 0x0302 */ | ||
1568 | 0x00db, 0x0000, | ||
1569 | /* 0x0057 0x0302 */ | ||
1570 | 0x0174, 0x0000, | ||
1571 | /* 0x0059 0x0302 */ | ||
1572 | 0x0176, 0x0000, | ||
1573 | /* 0x005a 0x0302 */ | ||
1574 | 0x1e90, 0x0000, | ||
1575 | /* 0x0061 0x0302 */ | ||
1576 | 0x00e2, 0x0004, 0x0300, 0x0d84, 0x0301, 0x0d86, 0x0303, 0x0d88, | ||
1577 | 0x0309, 0x0d8a, | ||
1578 | /* 0x0063 0x0302 */ | ||
1579 | 0x0109, 0x0000, | ||
1580 | /* 0x0065 0x0302 */ | ||
1581 | 0x00ea, 0x0004, 0x0300, 0x0d8c, 0x0301, 0x0d8e, 0x0303, 0x0d90, | ||
1582 | 0x0309, 0x0d92, | ||
1583 | /* 0x0067 0x0302 */ | ||
1584 | 0x011d, 0x0000, | ||
1585 | /* 0x0068 0x0302 */ | ||
1586 | 0x0125, 0x0000, | ||
1587 | /* 0x0069 0x0302 */ | ||
1588 | 0x00ee, 0x0000, | ||
1589 | /* 0x006a 0x0302 */ | ||
1590 | 0x0135, 0x0000, | ||
1591 | /* 0x006f 0x0302 */ | ||
1592 | 0x00f4, 0x0004, 0x0300, 0x0d94, 0x0301, 0x0d96, 0x0303, 0x0d98, | ||
1593 | 0x0309, 0x0d9a, | ||
1594 | /* 0x0073 0x0302 */ | ||
1595 | 0x015d, 0x0000, | ||
1596 | /* 0x0075 0x0302 */ | ||
1597 | 0x00fb, 0x0000, | ||
1598 | /* 0x0077 0x0302 */ | ||
1599 | 0x0175, 0x0000, | ||
1600 | /* 0x0079 0x0302 */ | ||
1601 | 0x0177, 0x0000, | ||
1602 | /* 0x007a 0x0302 */ | ||
1603 | 0x1e91, 0x0000, | ||
1604 | /* 0x0041 0x0303 */ | ||
1605 | 0x00c3, 0x0000, | ||
1606 | /* 0x0045 0x0303 */ | ||
1607 | 0x1ebc, 0x0000, | ||
1608 | /* 0x0049 0x0303 */ | ||
1609 | 0x0128, 0x0000, | ||
1610 | /* 0x004e 0x0303 */ | ||
1611 | 0x00d1, 0x0000, | ||
1612 | /* 0x004f 0x0303 */ | ||
1613 | 0x00d5, 0x0002, 0x0301, 0x0d9c, 0x0308, 0x0d9e, | ||
1614 | /* 0x0055 0x0303 */ | ||
1615 | 0x0168, 0x0001, 0x0301, 0x0da0, | ||
1616 | /* 0x0056 0x0303 */ | ||
1617 | 0x1e7c, 0x0000, | ||
1618 | /* 0x0059 0x0303 */ | ||
1619 | 0x1ef8, 0x0000, | ||
1620 | /* 0x0061 0x0303 */ | ||
1621 | 0x00e3, 0x0000, | ||
1622 | /* 0x0065 0x0303 */ | ||
1623 | 0x1ebd, 0x0000, | ||
1624 | /* 0x0069 0x0303 */ | ||
1625 | 0x0129, 0x0000, | ||
1626 | /* 0x006e 0x0303 */ | ||
1627 | 0x00f1, 0x0000, | ||
1628 | /* 0x006f 0x0303 */ | ||
1629 | 0x00f5, 0x0002, 0x0301, 0x0da2, 0x0308, 0x0da4, | ||
1630 | /* 0x0075 0x0303 */ | ||
1631 | 0x0169, 0x0001, 0x0301, 0x0da6, | ||
1632 | /* 0x0076 0x0303 */ | ||
1633 | 0x1e7d, 0x0000, | ||
1634 | /* 0x0079 0x0303 */ | ||
1635 | 0x1ef9, 0x0000, | ||
1636 | /* 0x0041 0x0304 */ | ||
1637 | 0x0100, 0x0000, | ||
1638 | /* 0x0045 0x0304 */ | ||
1639 | 0x0112, 0x0002, 0x0300, 0x0da8, 0x0301, 0x0daa, | ||
1640 | /* 0x0047 0x0304 */ | ||
1641 | 0x1e20, 0x0000, | ||
1642 | /* 0x0049 0x0304 */ | ||
1643 | 0x012a, 0x0000, | ||
1644 | /* 0x004f 0x0304 */ | ||
1645 | 0x014c, 0x0002, 0x0300, 0x0dac, 0x0301, 0x0dae, | ||
1646 | /* 0x0055 0x0304 */ | ||
1647 | 0x016a, 0x0001, 0x0308, 0x0db0, | ||
1648 | /* 0x0061 0x0304 */ | ||
1649 | 0x0101, 0x0000, | ||
1650 | /* 0x0065 0x0304 */ | ||
1651 | 0x0113, 0x0002, 0x0300, 0x0db2, 0x0301, 0x0db4, | ||
1652 | /* 0x0067 0x0304 */ | ||
1653 | 0x1e21, 0x0000, | ||
1654 | /* 0x0069 0x0304 */ | ||
1655 | 0x012b, 0x0000, | ||
1656 | /* 0x006f 0x0304 */ | ||
1657 | 0x014d, 0x0002, 0x0300, 0x0db6, 0x0301, 0x0db8, | ||
1658 | /* 0x0075 0x0304 */ | ||
1659 | 0x016b, 0x0001, 0x0308, 0x0dba, | ||
1660 | /* 0x00c6 0x0304 */ | ||
1661 | 0x01e2, 0x0000, | ||
1662 | /* 0x00e6 0x0304 */ | ||
1663 | 0x01e3, 0x0000, | ||
1664 | /* 0x0391 0x0304 */ | ||
1665 | 0x1fb9, 0x0000, | ||
1666 | /* 0x0399 0x0304 */ | ||
1667 | 0x1fd9, 0x0000, | ||
1668 | /* 0x03a5 0x0304 */ | ||
1669 | 0x1fe9, 0x0000, | ||
1670 | /* 0x03b1 0x0304 */ | ||
1671 | 0x1fb1, 0x0000, | ||
1672 | /* 0x03b9 0x0304 */ | ||
1673 | 0x1fd1, 0x0000, | ||
1674 | /* 0x03c5 0x0304 */ | ||
1675 | 0x1fe1, 0x0000, | ||
1676 | /* 0x0418 0x0304 */ | ||
1677 | 0x04e2, 0x0000, | ||
1678 | /* 0x0423 0x0304 */ | ||
1679 | 0x04ee, 0x0000, | ||
1680 | /* 0x0438 0x0304 */ | ||
1681 | 0x04e3, 0x0000, | ||
1682 | /* 0x0443 0x0304 */ | ||
1683 | 0x04ef, 0x0000, | ||
1684 | /* 0x0041 0x0306 */ | ||
1685 | 0x0102, 0x0004, 0x0300, 0x0dbc, 0x0301, 0x0dbe, 0x0303, 0x0dc0, | ||
1686 | 0x0309, 0x0dc2, | ||
1687 | /* 0x0045 0x0306 */ | ||
1688 | 0x0114, 0x0000, | ||
1689 | /* 0x0047 0x0306 */ | ||
1690 | 0x011e, 0x0000, | ||
1691 | /* 0x0049 0x0306 */ | ||
1692 | 0x012c, 0x0000, | ||
1693 | /* 0x004f 0x0306 */ | ||
1694 | 0x014e, 0x0000, | ||
1695 | /* 0x0055 0x0306 */ | ||
1696 | 0x016c, 0x0000, | ||
1697 | /* 0x0061 0x0306 */ | ||
1698 | 0x0103, 0x0004, 0x0300, 0x0dc4, 0x0301, 0x0dc6, 0x0303, 0x0dc8, | ||
1699 | 0x0309, 0x0dca, | ||
1700 | /* 0x0065 0x0306 */ | ||
1701 | 0x0115, 0x0000, | ||
1702 | /* 0x0067 0x0306 */ | ||
1703 | 0x011f, 0x0000, | ||
1704 | /* 0x0069 0x0306 */ | ||
1705 | 0x012d, 0x0000, | ||
1706 | /* 0x006f 0x0306 */ | ||
1707 | 0x014f, 0x0000, | ||
1708 | /* 0x0075 0x0306 */ | ||
1709 | 0x016d, 0x0000, | ||
1710 | /* 0x0391 0x0306 */ | ||
1711 | 0x1fb8, 0x0000, | ||
1712 | /* 0x0399 0x0306 */ | ||
1713 | 0x1fd8, 0x0000, | ||
1714 | /* 0x03a5 0x0306 */ | ||
1715 | 0x1fe8, 0x0000, | ||
1716 | /* 0x03b1 0x0306 */ | ||
1717 | 0x1fb0, 0x0000, | ||
1718 | /* 0x03b9 0x0306 */ | ||
1719 | 0x1fd0, 0x0000, | ||
1720 | /* 0x03c5 0x0306 */ | ||
1721 | 0x1fe0, 0x0000, | ||
1722 | /* 0x0410 0x0306 */ | ||
1723 | 0x04d0, 0x0000, | ||
1724 | /* 0x0415 0x0306 */ | ||
1725 | 0x04d6, 0x0000, | ||
1726 | /* 0x0416 0x0306 */ | ||
1727 | 0x04c1, 0x0000, | ||
1728 | /* 0x0418 0x0306 */ | ||
1729 | 0x0419, 0x0000, | ||
1730 | /* 0x0423 0x0306 */ | ||
1731 | 0x040e, 0x0000, | ||
1732 | /* 0x0430 0x0306 */ | ||
1733 | 0x04d1, 0x0000, | ||
1734 | /* 0x0435 0x0306 */ | ||
1735 | 0x04d7, 0x0000, | ||
1736 | /* 0x0436 0x0306 */ | ||
1737 | 0x04c2, 0x0000, | ||
1738 | /* 0x0438 0x0306 */ | ||
1739 | 0x0439, 0x0000, | ||
1740 | /* 0x0443 0x0306 */ | ||
1741 | 0x045e, 0x0000, | ||
1742 | /* 0x0041 0x0307 */ | ||
1743 | 0x0000, 0x0001, 0x0304, 0x0dcc, | ||
1744 | /* 0x0042 0x0307 */ | ||
1745 | 0x1e02, 0x0000, | ||
1746 | /* 0x0043 0x0307 */ | ||
1747 | 0x010a, 0x0000, | ||
1748 | /* 0x0044 0x0307 */ | ||
1749 | 0x1e0a, 0x0000, | ||
1750 | /* 0x0045 0x0307 */ | ||
1751 | 0x0116, 0x0000, | ||
1752 | /* 0x0046 0x0307 */ | ||
1753 | 0x1e1e, 0x0000, | ||
1754 | /* 0x0047 0x0307 */ | ||
1755 | 0x0120, 0x0000, | ||
1756 | /* 0x0048 0x0307 */ | ||
1757 | 0x1e22, 0x0000, | ||
1758 | /* 0x0049 0x0307 */ | ||
1759 | 0x0130, 0x0000, | ||
1760 | /* 0x004d 0x0307 */ | ||
1761 | 0x1e40, 0x0000, | ||
1762 | /* 0x004e 0x0307 */ | ||
1763 | 0x1e44, 0x0000, | ||
1764 | /* 0x0050 0x0307 */ | ||
1765 | 0x1e56, 0x0000, | ||
1766 | /* 0x0052 0x0307 */ | ||
1767 | 0x1e58, 0x0000, | ||
1768 | /* 0x0053 0x0307 */ | ||
1769 | 0x1e60, 0x0000, | ||
1770 | /* 0x0054 0x0307 */ | ||
1771 | 0x1e6a, 0x0000, | ||
1772 | /* 0x0057 0x0307 */ | ||
1773 | 0x1e86, 0x0000, | ||
1774 | /* 0x0058 0x0307 */ | ||
1775 | 0x1e8a, 0x0000, | ||
1776 | /* 0x0059 0x0307 */ | ||
1777 | 0x1e8e, 0x0000, | ||
1778 | /* 0x005a 0x0307 */ | ||
1779 | 0x017b, 0x0000, | ||
1780 | /* 0x0061 0x0307 */ | ||
1781 | 0x0000, 0x0001, 0x0304, 0x0dce, | ||
1782 | /* 0x0062 0x0307 */ | ||
1783 | 0x1e03, 0x0000, | ||
1784 | /* 0x0063 0x0307 */ | ||
1785 | 0x010b, 0x0000, | ||
1786 | /* 0x0064 0x0307 */ | ||
1787 | 0x1e0b, 0x0000, | ||
1788 | /* 0x0065 0x0307 */ | ||
1789 | 0x0117, 0x0000, | ||
1790 | /* 0x0066 0x0307 */ | ||
1791 | 0x1e1f, 0x0000, | ||
1792 | /* 0x0067 0x0307 */ | ||
1793 | 0x0121, 0x0000, | ||
1794 | /* 0x0068 0x0307 */ | ||
1795 | 0x1e23, 0x0000, | ||
1796 | /* 0x006d 0x0307 */ | ||
1797 | 0x1e41, 0x0000, | ||
1798 | /* 0x006e 0x0307 */ | ||
1799 | 0x1e45, 0x0000, | ||
1800 | /* 0x0070 0x0307 */ | ||
1801 | 0x1e57, 0x0000, | ||
1802 | /* 0x0072 0x0307 */ | ||
1803 | 0x1e59, 0x0000, | ||
1804 | /* 0x0073 0x0307 */ | ||
1805 | 0x1e61, 0x0000, | ||
1806 | /* 0x0074 0x0307 */ | ||
1807 | 0x1e6b, 0x0000, | ||
1808 | /* 0x0077 0x0307 */ | ||
1809 | 0x1e87, 0x0000, | ||
1810 | /* 0x0078 0x0307 */ | ||
1811 | 0x1e8b, 0x0000, | ||
1812 | /* 0x0079 0x0307 */ | ||
1813 | 0x1e8f, 0x0000, | ||
1814 | /* 0x007a 0x0307 */ | ||
1815 | 0x017c, 0x0000, | ||
1816 | /* 0x017f 0x0307 */ | ||
1817 | 0x1e9b, 0x0000, | ||
1818 | /* 0x0306 0x0307 */ | ||
1819 | 0x0310, 0x0000, | ||
1820 | /* 0x0041 0x0308 */ | ||
1821 | 0x00c4, 0x0001, 0x0304, 0x0dd0, | ||
1822 | /* 0x0045 0x0308 */ | ||
1823 | 0x00cb, 0x0000, | ||
1824 | /* 0x0048 0x0308 */ | ||
1825 | 0x1e26, 0x0000, | ||
1826 | /* 0x0049 0x0308 */ | ||
1827 | 0x00cf, 0x0001, 0x0301, 0x0dd2, | ||
1828 | /* 0x004f 0x0308 */ | ||
1829 | 0x00d6, 0x0000, | ||
1830 | /* 0x0055 0x0308 */ | ||
1831 | 0x00dc, 0x0004, 0x0300, 0x0dd4, 0x0301, 0x0dd6, 0x0304, 0x0dd8, | ||
1832 | 0x030c, 0x0dda, | ||
1833 | /* 0x0057 0x0308 */ | ||
1834 | 0x1e84, 0x0000, | ||
1835 | /* 0x0058 0x0308 */ | ||
1836 | 0x1e8c, 0x0000, | ||
1837 | /* 0x0059 0x0308 */ | ||
1838 | 0x0178, 0x0000, | ||
1839 | /* 0x0061 0x0308 */ | ||
1840 | 0x00e4, 0x0001, 0x0304, 0x0ddc, | ||
1841 | /* 0x0065 0x0308 */ | ||
1842 | 0x00eb, 0x0000, | ||
1843 | /* 0x0068 0x0308 */ | ||
1844 | 0x1e27, 0x0000, | ||
1845 | /* 0x0069 0x0308 */ | ||
1846 | 0x00ef, 0x0001, 0x0301, 0x0dde, | ||
1847 | /* 0x006f 0x0308 */ | ||
1848 | 0x00f6, 0x0000, | ||
1849 | /* 0x0074 0x0308 */ | ||
1850 | 0x1e97, 0x0000, | ||
1851 | /* 0x0075 0x0308 */ | ||
1852 | 0x00fc, 0x0004, 0x0300, 0x0de0, 0x0301, 0x0de2, 0x0304, 0x0de4, | ||
1853 | 0x030c, 0x0de6, | ||
1854 | /* 0x0077 0x0308 */ | ||
1855 | 0x1e85, 0x0000, | ||
1856 | /* 0x0078 0x0308 */ | ||
1857 | 0x1e8d, 0x0000, | ||
1858 | /* 0x0079 0x0308 */ | ||
1859 | 0x00ff, 0x0000, | ||
1860 | /* 0x018f 0x0308 */ | ||
1861 | 0x04da, 0x0000, | ||
1862 | /* 0x019f 0x0308 */ | ||
1863 | 0x04ea, 0x0000, | ||
1864 | /* 0x0259 0x0308 */ | ||
1865 | 0x04db, 0x0000, | ||
1866 | /* 0x0275 0x0308 */ | ||
1867 | 0x04eb, 0x0000, | ||
1868 | /* 0x0399 0x0308 */ | ||
1869 | 0x03aa, 0x0000, | ||
1870 | /* 0x03a5 0x0308 */ | ||
1871 | 0x03ab, 0x0000, | ||
1872 | /* 0x03b9 0x0308 */ | ||
1873 | 0x03ca, 0x0004, 0x0300, 0x0de8, 0x0301, 0x0dea, 0x030d, 0x0dec, | ||
1874 | 0x0342, 0x0dee, | ||
1875 | /* 0x03c5 0x0308 */ | ||
1876 | 0x03cb, 0x0004, 0x0300, 0x0df0, 0x0301, 0x0df2, 0x030d, 0x0df4, | ||
1877 | 0x0342, 0x0df6, | ||
1878 | /* 0x03d2 0x0308 */ | ||
1879 | 0x03d4, 0x0000, | ||
1880 | /* 0x0406 0x0308 */ | ||
1881 | 0x0407, 0x0000, | ||
1882 | /* 0x0410 0x0308 */ | ||
1883 | 0x04d2, 0x0000, | ||
1884 | /* 0x0415 0x0308 */ | ||
1885 | 0x0401, 0x0000, | ||
1886 | /* 0x0416 0x0308 */ | ||
1887 | 0x04dc, 0x0000, | ||
1888 | /* 0x0417 0x0308 */ | ||
1889 | 0x04de, 0x0000, | ||
1890 | /* 0x0418 0x0308 */ | ||
1891 | 0x04e4, 0x0000, | ||
1892 | /* 0x041e 0x0308 */ | ||
1893 | 0x04e6, 0x0000, | ||
1894 | /* 0x0423 0x0308 */ | ||
1895 | 0x04f0, 0x0000, | ||
1896 | /* 0x0427 0x0308 */ | ||
1897 | 0x04f4, 0x0000, | ||
1898 | /* 0x042b 0x0308 */ | ||
1899 | 0x04f8, 0x0000, | ||
1900 | /* 0x0430 0x0308 */ | ||
1901 | 0x04d3, 0x0000, | ||
1902 | /* 0x0435 0x0308 */ | ||
1903 | 0x0451, 0x0000, | ||
1904 | /* 0x0436 0x0308 */ | ||
1905 | 0x04dd, 0x0000, | ||
1906 | /* 0x0437 0x0308 */ | ||
1907 | 0x04df, 0x0000, | ||
1908 | /* 0x0438 0x0308 */ | ||
1909 | 0x04e5, 0x0000, | ||
1910 | /* 0x043e 0x0308 */ | ||
1911 | 0x04e7, 0x0000, | ||
1912 | /* 0x0443 0x0308 */ | ||
1913 | 0x04f1, 0x0000, | ||
1914 | /* 0x0447 0x0308 */ | ||
1915 | 0x04f5, 0x0000, | ||
1916 | /* 0x044b 0x0308 */ | ||
1917 | 0x04f9, 0x0000, | ||
1918 | /* 0x0456 0x0308 */ | ||
1919 | 0x0457, 0x0000, | ||
1920 | /* 0x0041 0x0309 */ | ||
1921 | 0x1ea2, 0x0000, | ||
1922 | /* 0x0045 0x0309 */ | ||
1923 | 0x1eba, 0x0000, | ||
1924 | /* 0x0049 0x0309 */ | ||
1925 | 0x1ec8, 0x0000, | ||
1926 | /* 0x004f 0x0309 */ | ||
1927 | 0x1ece, 0x0000, | ||
1928 | /* 0x0055 0x0309 */ | ||
1929 | 0x1ee6, 0x0000, | ||
1930 | /* 0x0059 0x0309 */ | ||
1931 | 0x1ef6, 0x0000, | ||
1932 | /* 0x0061 0x0309 */ | ||
1933 | 0x1ea3, 0x0000, | ||
1934 | /* 0x0065 0x0309 */ | ||
1935 | 0x1ebb, 0x0000, | ||
1936 | /* 0x0069 0x0309 */ | ||
1937 | 0x1ec9, 0x0000, | ||
1938 | /* 0x006f 0x0309 */ | ||
1939 | 0x1ecf, 0x0000, | ||
1940 | /* 0x0075 0x0309 */ | ||
1941 | 0x1ee7, 0x0000, | ||
1942 | /* 0x0079 0x0309 */ | ||
1943 | 0x1ef7, 0x0000, | ||
1944 | /* 0x0041 0x030a */ | ||
1945 | 0x00c5, 0x0001, 0x0301, 0x0df8, | ||
1946 | /* 0x0055 0x030a */ | ||
1947 | 0x016e, 0x0000, | ||
1948 | /* 0x0061 0x030a */ | ||
1949 | 0x00e5, 0x0001, 0x0301, 0x0dfa, | ||
1950 | /* 0x0075 0x030a */ | ||
1951 | 0x016f, 0x0000, | ||
1952 | /* 0x0077 0x030a */ | ||
1953 | 0x1e98, 0x0000, | ||
1954 | /* 0x0079 0x030a */ | ||
1955 | 0x1e99, 0x0000, | ||
1956 | /* 0x004f 0x030b */ | ||
1957 | 0x0150, 0x0000, | ||
1958 | /* 0x0055 0x030b */ | ||
1959 | 0x0170, 0x0000, | ||
1960 | /* 0x006f 0x030b */ | ||
1961 | 0x0151, 0x0000, | ||
1962 | /* 0x0075 0x030b */ | ||
1963 | 0x0171, 0x0000, | ||
1964 | /* 0x0423 0x030b */ | ||
1965 | 0x04f2, 0x0000, | ||
1966 | /* 0x0443 0x030b */ | ||
1967 | 0x04f3, 0x0000, | ||
1968 | /* 0x0041 0x030c */ | ||
1969 | 0x01cd, 0x0000, | ||
1970 | /* 0x0043 0x030c */ | ||
1971 | 0x010c, 0x0000, | ||
1972 | /* 0x0044 0x030c */ | ||
1973 | 0x010e, 0x0000, | ||
1974 | /* 0x0045 0x030c */ | ||
1975 | 0x011a, 0x0000, | ||
1976 | /* 0x0047 0x030c */ | ||
1977 | 0x01e6, 0x0000, | ||
1978 | /* 0x0049 0x030c */ | ||
1979 | 0x01cf, 0x0000, | ||
1980 | /* 0x004b 0x030c */ | ||
1981 | 0x01e8, 0x0000, | ||
1982 | /* 0x004c 0x030c */ | ||
1983 | 0x013d, 0x0000, | ||
1984 | /* 0x004e 0x030c */ | ||
1985 | 0x0147, 0x0000, | ||
1986 | /* 0x004f 0x030c */ | ||
1987 | 0x01d1, 0x0000, | ||
1988 | /* 0x0052 0x030c */ | ||
1989 | 0x0158, 0x0000, | ||
1990 | /* 0x0053 0x030c */ | ||
1991 | 0x0160, 0x0001, 0x0307, 0x0dfc, | ||
1992 | /* 0x0054 0x030c */ | ||
1993 | 0x0164, 0x0000, | ||
1994 | /* 0x0055 0x030c */ | ||
1995 | 0x01d3, 0x0000, | ||
1996 | /* 0x005a 0x030c */ | ||
1997 | 0x017d, 0x0000, | ||
1998 | /* 0x0061 0x030c */ | ||
1999 | 0x01ce, 0x0000, | ||
2000 | /* 0x0063 0x030c */ | ||
2001 | 0x010d, 0x0000, | ||
2002 | /* 0x0064 0x030c */ | ||
2003 | 0x010f, 0x0000, | ||
2004 | /* 0x0065 0x030c */ | ||
2005 | 0x011b, 0x0000, | ||
2006 | /* 0x0067 0x030c */ | ||
2007 | 0x01e7, 0x0000, | ||
2008 | /* 0x0069 0x030c */ | ||
2009 | 0x01d0, 0x0000, | ||
2010 | /* 0x006a 0x030c */ | ||
2011 | 0x01f0, 0x0000, | ||
2012 | /* 0x006b 0x030c */ | ||
2013 | 0x01e9, 0x0000, | ||
2014 | /* 0x006c 0x030c */ | ||
2015 | 0x013e, 0x0000, | ||
2016 | /* 0x006e 0x030c */ | ||
2017 | 0x0148, 0x0000, | ||
2018 | /* 0x006f 0x030c */ | ||
2019 | 0x01d2, 0x0000, | ||
2020 | /* 0x0072 0x030c */ | ||
2021 | 0x0159, 0x0000, | ||
2022 | /* 0x0073 0x030c */ | ||
2023 | 0x0161, 0x0001, 0x0307, 0x0dfe, | ||
2024 | /* 0x0074 0x030c */ | ||
2025 | 0x0165, 0x0000, | ||
2026 | /* 0x0075 0x030c */ | ||
2027 | 0x01d4, 0x0000, | ||
2028 | /* 0x007a 0x030c */ | ||
2029 | 0x017e, 0x0000, | ||
2030 | /* 0x01b7 0x030c */ | ||
2031 | 0x01ee, 0x0000, | ||
2032 | /* 0x0292 0x030c */ | ||
2033 | 0x01ef, 0x0000, | ||
2034 | /* 0x00a8 0x030d */ | ||
2035 | 0x0385, 0x0000, | ||
2036 | /* 0x0308 0x030d */ | ||
2037 | 0x0344, 0x0000, | ||
2038 | /* 0x0391 0x030d */ | ||
2039 | 0x0386, 0x0000, | ||
2040 | /* 0x0395 0x030d */ | ||
2041 | 0x0388, 0x0000, | ||
2042 | /* 0x0397 0x030d */ | ||
2043 | 0x0389, 0x0000, | ||
2044 | /* 0x0399 0x030d */ | ||
2045 | 0x038a, 0x0000, | ||
2046 | /* 0x039f 0x030d */ | ||
2047 | 0x038c, 0x0000, | ||
2048 | /* 0x03a5 0x030d */ | ||
2049 | 0x038e, 0x0000, | ||
2050 | /* 0x03a9 0x030d */ | ||
2051 | 0x038f, 0x0000, | ||
2052 | /* 0x03b1 0x030d */ | ||
2053 | 0x03ac, 0x0000, | ||
2054 | /* 0x03b5 0x030d */ | ||
2055 | 0x03ad, 0x0000, | ||
2056 | /* 0x03b7 0x030d */ | ||
2057 | 0x03ae, 0x0000, | ||
2058 | /* 0x03b9 0x030d */ | ||
2059 | 0x03af, 0x0000, | ||
2060 | /* 0x03bf 0x030d */ | ||
2061 | 0x03cc, 0x0000, | ||
2062 | /* 0x03c5 0x030d */ | ||
2063 | 0x03cd, 0x0000, | ||
2064 | /* 0x03c9 0x030d */ | ||
2065 | 0x03ce, 0x0000, | ||
2066 | /* 0x03d2 0x030d */ | ||
2067 | 0x03d3, 0x0000, | ||
2068 | /* 0x0041 0x030f */ | ||
2069 | 0x0200, 0x0000, | ||
2070 | /* 0x0045 0x030f */ | ||
2071 | 0x0204, 0x0000, | ||
2072 | /* 0x0049 0x030f */ | ||
2073 | 0x0208, 0x0000, | ||
2074 | /* 0x004f 0x030f */ | ||
2075 | 0x020c, 0x0000, | ||
2076 | /* 0x0052 0x030f */ | ||
2077 | 0x0210, 0x0000, | ||
2078 | /* 0x0055 0x030f */ | ||
2079 | 0x0214, 0x0000, | ||
2080 | /* 0x0061 0x030f */ | ||
2081 | 0x0201, 0x0000, | ||
2082 | /* 0x0065 0x030f */ | ||
2083 | 0x0205, 0x0000, | ||
2084 | /* 0x0069 0x030f */ | ||
2085 | 0x0209, 0x0000, | ||
2086 | /* 0x006f 0x030f */ | ||
2087 | 0x020d, 0x0000, | ||
2088 | /* 0x0072 0x030f */ | ||
2089 | 0x0211, 0x0000, | ||
2090 | /* 0x0075 0x030f */ | ||
2091 | 0x0215, 0x0000, | ||
2092 | /* 0x0474 0x030f */ | ||
2093 | 0x0476, 0x0000, | ||
2094 | /* 0x0475 0x030f */ | ||
2095 | 0x0477, 0x0000, | ||
2096 | /* 0x0041 0x0311 */ | ||
2097 | 0x0202, 0x0000, | ||
2098 | /* 0x0045 0x0311 */ | ||
2099 | 0x0206, 0x0000, | ||
2100 | /* 0x0049 0x0311 */ | ||
2101 | 0x020a, 0x0000, | ||
2102 | /* 0x004f 0x0311 */ | ||
2103 | 0x020e, 0x0000, | ||
2104 | /* 0x0052 0x0311 */ | ||
2105 | 0x0212, 0x0000, | ||
2106 | /* 0x0055 0x0311 */ | ||
2107 | 0x0216, 0x0000, | ||
2108 | /* 0x0061 0x0311 */ | ||
2109 | 0x0203, 0x0000, | ||
2110 | /* 0x0065 0x0311 */ | ||
2111 | 0x0207, 0x0000, | ||
2112 | /* 0x0069 0x0311 */ | ||
2113 | 0x020b, 0x0000, | ||
2114 | /* 0x006f 0x0311 */ | ||
2115 | 0x020f, 0x0000, | ||
2116 | /* 0x0072 0x0311 */ | ||
2117 | 0x0213, 0x0000, | ||
2118 | /* 0x0075 0x0311 */ | ||
2119 | 0x0217, 0x0000, | ||
2120 | /* 0x0391 0x0313 */ | ||
2121 | 0x1f08, 0x0003, 0x0300, 0x0e00, 0x0301, 0x0e02, 0x0342, 0x0e04, | ||
2122 | /* 0x0395 0x0313 */ | ||
2123 | 0x1f18, 0x0002, 0x0300, 0x0e06, 0x0301, 0x0e08, | ||
2124 | /* 0x0397 0x0313 */ | ||
2125 | 0x1f28, 0x0003, 0x0300, 0x0e0a, 0x0301, 0x0e0c, 0x0342, 0x0e0e, | ||
2126 | /* 0x0399 0x0313 */ | ||
2127 | 0x1f38, 0x0003, 0x0300, 0x0e10, 0x0301, 0x0e12, 0x0342, 0x0e14, | ||
2128 | /* 0x039f 0x0313 */ | ||
2129 | 0x1f48, 0x0002, 0x0300, 0x0e16, 0x0301, 0x0e18, | ||
2130 | /* 0x03a9 0x0313 */ | ||
2131 | 0x1f68, 0x0003, 0x0300, 0x0e1a, 0x0301, 0x0e1c, 0x0342, 0x0e1e, | ||
2132 | /* 0x03b1 0x0313 */ | ||
2133 | 0x1f00, 0x0003, 0x0300, 0x0e20, 0x0301, 0x0e22, 0x0342, 0x0e24, | ||
2134 | /* 0x03b5 0x0313 */ | ||
2135 | 0x1f10, 0x0002, 0x0300, 0x0e26, 0x0301, 0x0e28, | ||
2136 | /* 0x03b7 0x0313 */ | ||
2137 | 0x1f20, 0x0003, 0x0300, 0x0e2a, 0x0301, 0x0e2c, 0x0342, 0x0e2e, | ||
2138 | /* 0x03b9 0x0313 */ | ||
2139 | 0x1f30, 0x0003, 0x0300, 0x0e30, 0x0301, 0x0e32, 0x0342, 0x0e34, | ||
2140 | /* 0x03bf 0x0313 */ | ||
2141 | 0x1f40, 0x0002, 0x0300, 0x0e36, 0x0301, 0x0e38, | ||
2142 | /* 0x03c1 0x0313 */ | ||
2143 | 0x1fe4, 0x0000, | ||
2144 | /* 0x03c5 0x0313 */ | ||
2145 | 0x1f50, 0x0003, 0x0300, 0x0e3a, 0x0301, 0x0e3c, 0x0342, 0x0e3e, | ||
2146 | /* 0x03c9 0x0313 */ | ||
2147 | 0x1f60, 0x0003, 0x0300, 0x0e40, 0x0301, 0x0e42, 0x0342, 0x0e44, | ||
2148 | /* 0x0391 0x0314 */ | ||
2149 | 0x1f09, 0x0003, 0x0300, 0x0e46, 0x0301, 0x0e48, 0x0342, 0x0e4a, | ||
2150 | /* 0x0395 0x0314 */ | ||
2151 | 0x1f19, 0x0002, 0x0300, 0x0e4c, 0x0301, 0x0e4e, | ||
2152 | /* 0x0397 0x0314 */ | ||
2153 | 0x1f29, 0x0003, 0x0300, 0x0e50, 0x0301, 0x0e52, 0x0342, 0x0e54, | ||
2154 | /* 0x0399 0x0314 */ | ||
2155 | 0x1f39, 0x0003, 0x0300, 0x0e56, 0x0301, 0x0e58, 0x0342, 0x0e5a, | ||
2156 | /* 0x039f 0x0314 */ | ||
2157 | 0x1f49, 0x0002, 0x0300, 0x0e5c, 0x0301, 0x0e5e, | ||
2158 | /* 0x03a1 0x0314 */ | ||
2159 | 0x1fec, 0x0000, | ||
2160 | /* 0x03a5 0x0314 */ | ||
2161 | 0x1f59, 0x0003, 0x0300, 0x0e60, 0x0301, 0x0e62, 0x0342, 0x0e64, | ||
2162 | /* 0x03a9 0x0314 */ | ||
2163 | 0x1f69, 0x0003, 0x0300, 0x0e66, 0x0301, 0x0e68, 0x0342, 0x0e6a, | ||
2164 | /* 0x03b1 0x0314 */ | ||
2165 | 0x1f01, 0x0003, 0x0300, 0x0e6c, 0x0301, 0x0e6e, 0x0342, 0x0e70, | ||
2166 | /* 0x03b5 0x0314 */ | ||
2167 | 0x1f11, 0x0002, 0x0300, 0x0e72, 0x0301, 0x0e74, | ||
2168 | /* 0x03b7 0x0314 */ | ||
2169 | 0x1f21, 0x0003, 0x0300, 0x0e76, 0x0301, 0x0e78, 0x0342, 0x0e7a, | ||
2170 | /* 0x03b9 0x0314 */ | ||
2171 | 0x1f31, 0x0003, 0x0300, 0x0e7c, 0x0301, 0x0e7e, 0x0342, 0x0e80, | ||
2172 | /* 0x03bf 0x0314 */ | ||
2173 | 0x1f41, 0x0002, 0x0300, 0x0e82, 0x0301, 0x0e84, | ||
2174 | /* 0x03c1 0x0314 */ | ||
2175 | 0x1fe5, 0x0000, | ||
2176 | /* 0x03c5 0x0314 */ | ||
2177 | 0x1f51, 0x0003, 0x0300, 0x0e86, 0x0301, 0x0e88, 0x0342, 0x0e8a, | ||
2178 | /* 0x03c9 0x0314 */ | ||
2179 | 0x1f61, 0x0003, 0x0300, 0x0e8c, 0x0301, 0x0e8e, 0x0342, 0x0e90, | ||
2180 | /* 0x004f 0x031b */ | ||
2181 | 0x01a0, 0x0005, 0x0300, 0x0e92, 0x0301, 0x0e94, 0x0303, 0x0e96, | ||
2182 | 0x0309, 0x0e98, 0x0323, 0x0e9a, | ||
2183 | /* 0x0055 0x031b */ | ||
2184 | 0x01af, 0x0005, 0x0300, 0x0e9c, 0x0301, 0x0e9e, 0x0303, 0x0ea0, | ||
2185 | 0x0309, 0x0ea2, 0x0323, 0x0ea4, | ||
2186 | /* 0x006f 0x031b */ | ||
2187 | 0x01a1, 0x0005, 0x0300, 0x0ea6, 0x0301, 0x0ea8, 0x0303, 0x0eaa, | ||
2188 | 0x0309, 0x0eac, 0x0323, 0x0eae, | ||
2189 | /* 0x0075 0x031b */ | ||
2190 | 0x01b0, 0x0005, 0x0300, 0x0eb0, 0x0301, 0x0eb2, 0x0303, 0x0eb4, | ||
2191 | 0x0309, 0x0eb6, 0x0323, 0x0eb8, | ||
2192 | /* 0x0041 0x0323 */ | ||
2193 | 0x1ea0, 0x0002, 0x0302, 0x0eba, 0x0306, 0x0ebc, | ||
2194 | /* 0x0042 0x0323 */ | ||
2195 | 0x1e04, 0x0000, | ||
2196 | /* 0x0044 0x0323 */ | ||
2197 | 0x1e0c, 0x0000, | ||
2198 | /* 0x0045 0x0323 */ | ||
2199 | 0x1eb8, 0x0001, 0x0302, 0x0ebe, | ||
2200 | /* 0x0048 0x0323 */ | ||
2201 | 0x1e24, 0x0000, | ||
2202 | /* 0x0049 0x0323 */ | ||
2203 | 0x1eca, 0x0000, | ||
2204 | /* 0x004b 0x0323 */ | ||
2205 | 0x1e32, 0x0000, | ||
2206 | /* 0x004c 0x0323 */ | ||
2207 | 0x1e36, 0x0001, 0x0304, 0x0ec0, | ||
2208 | /* 0x004d 0x0323 */ | ||
2209 | 0x1e42, 0x0000, | ||
2210 | /* 0x004e 0x0323 */ | ||
2211 | 0x1e46, 0x0000, | ||
2212 | /* 0x004f 0x0323 */ | ||
2213 | 0x1ecc, 0x0001, 0x0302, 0x0ec2, | ||
2214 | /* 0x0052 0x0323 */ | ||
2215 | 0x1e5a, 0x0001, 0x0304, 0x0ec4, | ||
2216 | /* 0x0053 0x0323 */ | ||
2217 | 0x1e62, 0x0001, 0x0307, 0x0ec6, | ||
2218 | /* 0x0054 0x0323 */ | ||
2219 | 0x1e6c, 0x0000, | ||
2220 | /* 0x0055 0x0323 */ | ||
2221 | 0x1ee4, 0x0000, | ||
2222 | /* 0x0056 0x0323 */ | ||
2223 | 0x1e7e, 0x0000, | ||
2224 | /* 0x0057 0x0323 */ | ||
2225 | 0x1e88, 0x0000, | ||
2226 | /* 0x0059 0x0323 */ | ||
2227 | 0x1ef4, 0x0000, | ||
2228 | /* 0x005a 0x0323 */ | ||
2229 | 0x1e92, 0x0000, | ||
2230 | /* 0x0061 0x0323 */ | ||
2231 | 0x1ea1, 0x0002, 0x0302, 0x0ec8, 0x0306, 0x0eca, | ||
2232 | /* 0x0062 0x0323 */ | ||
2233 | 0x1e05, 0x0000, | ||
2234 | /* 0x0064 0x0323 */ | ||
2235 | 0x1e0d, 0x0000, | ||
2236 | /* 0x0065 0x0323 */ | ||
2237 | 0x1eb9, 0x0001, 0x0302, 0x0ecc, | ||
2238 | /* 0x0068 0x0323 */ | ||
2239 | 0x1e25, 0x0000, | ||
2240 | /* 0x0069 0x0323 */ | ||
2241 | 0x1ecb, 0x0000, | ||
2242 | /* 0x006b 0x0323 */ | ||
2243 | 0x1e33, 0x0000, | ||
2244 | /* 0x006c 0x0323 */ | ||
2245 | 0x1e37, 0x0001, 0x0304, 0x0ece, | ||
2246 | /* 0x006d 0x0323 */ | ||
2247 | 0x1e43, 0x0000, | ||
2248 | /* 0x006e 0x0323 */ | ||
2249 | 0x1e47, 0x0000, | ||
2250 | /* 0x006f 0x0323 */ | ||
2251 | 0x1ecd, 0x0001, 0x0302, 0x0ed0, | ||
2252 | /* 0x0072 0x0323 */ | ||
2253 | 0x1e5b, 0x0001, 0x0304, 0x0ed2, | ||
2254 | /* 0x0073 0x0323 */ | ||
2255 | 0x1e63, 0x0001, 0x0307, 0x0ed4, | ||
2256 | /* 0x0074 0x0323 */ | ||
2257 | 0x1e6d, 0x0000, | ||
2258 | /* 0x0075 0x0323 */ | ||
2259 | 0x1ee5, 0x0000, | ||
2260 | /* 0x0076 0x0323 */ | ||
2261 | 0x1e7f, 0x0000, | ||
2262 | /* 0x0077 0x0323 */ | ||
2263 | 0x1e89, 0x0000, | ||
2264 | /* 0x0079 0x0323 */ | ||
2265 | 0x1ef5, 0x0000, | ||
2266 | /* 0x007a 0x0323 */ | ||
2267 | 0x1e93, 0x0000, | ||
2268 | /* 0x0055 0x0324 */ | ||
2269 | 0x1e72, 0x0000, | ||
2270 | /* 0x0075 0x0324 */ | ||
2271 | 0x1e73, 0x0000, | ||
2272 | /* 0x0041 0x0325 */ | ||
2273 | 0x1e00, 0x0000, | ||
2274 | /* 0x0061 0x0325 */ | ||
2275 | 0x1e01, 0x0000, | ||
2276 | /* 0x0043 0x0327 */ | ||
2277 | 0x00c7, 0x0001, 0x0301, 0x0ed6, | ||
2278 | /* 0x0044 0x0327 */ | ||
2279 | 0x1e10, 0x0000, | ||
2280 | /* 0x0045 0x0327 */ | ||
2281 | 0x0000, 0x0001, 0x0306, 0x0ed8, | ||
2282 | /* 0x0047 0x0327 */ | ||
2283 | 0x0122, 0x0000, | ||
2284 | /* 0x0048 0x0327 */ | ||
2285 | 0x1e28, 0x0000, | ||
2286 | /* 0x004b 0x0327 */ | ||
2287 | 0x0136, 0x0000, | ||
2288 | /* 0x004c 0x0327 */ | ||
2289 | 0x013b, 0x0000, | ||
2290 | /* 0x004e 0x0327 */ | ||
2291 | 0x0145, 0x0000, | ||
2292 | /* 0x0052 0x0327 */ | ||
2293 | 0x0156, 0x0000, | ||
2294 | /* 0x0053 0x0327 */ | ||
2295 | 0x015e, 0x0000, | ||
2296 | /* 0x0054 0x0327 */ | ||
2297 | 0x0162, 0x0000, | ||
2298 | /* 0x0063 0x0327 */ | ||
2299 | 0x00e7, 0x0001, 0x0301, 0x0eda, | ||
2300 | /* 0x0064 0x0327 */ | ||
2301 | 0x1e11, 0x0000, | ||
2302 | /* 0x0065 0x0327 */ | ||
2303 | 0x0000, 0x0001, 0x0306, 0x0edc, | ||
2304 | /* 0x0067 0x0327 */ | ||
2305 | 0x0123, 0x0000, | ||
2306 | /* 0x0068 0x0327 */ | ||
2307 | 0x1e29, 0x0000, | ||
2308 | /* 0x006b 0x0327 */ | ||
2309 | 0x0137, 0x0000, | ||
2310 | /* 0x006c 0x0327 */ | ||
2311 | 0x013c, 0x0000, | ||
2312 | /* 0x006e 0x0327 */ | ||
2313 | 0x0146, 0x0000, | ||
2314 | /* 0x0072 0x0327 */ | ||
2315 | 0x0157, 0x0000, | ||
2316 | /* 0x0073 0x0327 */ | ||
2317 | 0x015f, 0x0000, | ||
2318 | /* 0x0074 0x0327 */ | ||
2319 | 0x0163, 0x0000, | ||
2320 | /* 0x0041 0x0328 */ | ||
2321 | 0x0104, 0x0000, | ||
2322 | /* 0x0045 0x0328 */ | ||
2323 | 0x0118, 0x0000, | ||
2324 | /* 0x0049 0x0328 */ | ||
2325 | 0x012e, 0x0000, | ||
2326 | /* 0x004f 0x0328 */ | ||
2327 | 0x01ea, 0x0001, 0x0304, 0x0ede, | ||
2328 | /* 0x0055 0x0328 */ | ||
2329 | 0x0172, 0x0000, | ||
2330 | /* 0x0061 0x0328 */ | ||
2331 | 0x0105, 0x0000, | ||
2332 | /* 0x0065 0x0328 */ | ||
2333 | 0x0119, 0x0000, | ||
2334 | /* 0x0069 0x0328 */ | ||
2335 | 0x012f, 0x0000, | ||
2336 | /* 0x006f 0x0328 */ | ||
2337 | 0x01eb, 0x0001, 0x0304, 0x0ee0, | ||
2338 | /* 0x0075 0x0328 */ | ||
2339 | 0x0173, 0x0000, | ||
2340 | /* 0x0044 0x032d */ | ||
2341 | 0x1e12, 0x0000, | ||
2342 | /* 0x0045 0x032d */ | ||
2343 | 0x1e18, 0x0000, | ||
2344 | /* 0x004c 0x032d */ | ||
2345 | 0x1e3c, 0x0000, | ||
2346 | /* 0x004e 0x032d */ | ||
2347 | 0x1e4a, 0x0000, | ||
2348 | /* 0x0054 0x032d */ | ||
2349 | 0x1e70, 0x0000, | ||
2350 | /* 0x0055 0x032d */ | ||
2351 | 0x1e76, 0x0000, | ||
2352 | /* 0x0064 0x032d */ | ||
2353 | 0x1e13, 0x0000, | ||
2354 | /* 0x0065 0x032d */ | ||
2355 | 0x1e19, 0x0000, | ||
2356 | /* 0x006c 0x032d */ | ||
2357 | 0x1e3d, 0x0000, | ||
2358 | /* 0x006e 0x032d */ | ||
2359 | 0x1e4b, 0x0000, | ||
2360 | /* 0x0074 0x032d */ | ||
2361 | 0x1e71, 0x0000, | ||
2362 | /* 0x0075 0x032d */ | ||
2363 | 0x1e77, 0x0000, | ||
2364 | /* 0x0048 0x032e */ | ||
2365 | 0x1e2a, 0x0000, | ||
2366 | /* 0x0068 0x032e */ | ||
2367 | 0x1e2b, 0x0000, | ||
2368 | /* 0x0045 0x0330 */ | ||
2369 | 0x1e1a, 0x0000, | ||
2370 | /* 0x0049 0x0330 */ | ||
2371 | 0x1e2c, 0x0000, | ||
2372 | /* 0x0055 0x0330 */ | ||
2373 | 0x1e74, 0x0000, | ||
2374 | /* 0x0065 0x0330 */ | ||
2375 | 0x1e1b, 0x0000, | ||
2376 | /* 0x0069 0x0330 */ | ||
2377 | 0x1e2d, 0x0000, | ||
2378 | /* 0x0075 0x0330 */ | ||
2379 | 0x1e75, 0x0000, | ||
2380 | /* 0x0042 0x0331 */ | ||
2381 | 0x1e06, 0x0000, | ||
2382 | /* 0x0044 0x0331 */ | ||
2383 | 0x1e0e, 0x0000, | ||
2384 | /* 0x004b 0x0331 */ | ||
2385 | 0x1e34, 0x0000, | ||
2386 | /* 0x004c 0x0331 */ | ||
2387 | 0x1e3a, 0x0000, | ||
2388 | /* 0x004e 0x0331 */ | ||
2389 | 0x1e48, 0x0000, | ||
2390 | /* 0x0052 0x0331 */ | ||
2391 | 0x1e5e, 0x0000, | ||
2392 | /* 0x0054 0x0331 */ | ||
2393 | 0x1e6e, 0x0000, | ||
2394 | /* 0x005a 0x0331 */ | ||
2395 | 0x1e94, 0x0000, | ||
2396 | /* 0x0062 0x0331 */ | ||
2397 | 0x1e07, 0x0000, | ||
2398 | /* 0x0064 0x0331 */ | ||
2399 | 0x1e0f, 0x0000, | ||
2400 | /* 0x0068 0x0331 */ | ||
2401 | 0x1e96, 0x0000, | ||
2402 | /* 0x006b 0x0331 */ | ||
2403 | 0x1e35, 0x0000, | ||
2404 | /* 0x006c 0x0331 */ | ||
2405 | 0x1e3b, 0x0000, | ||
2406 | /* 0x006e 0x0331 */ | ||
2407 | 0x1e49, 0x0000, | ||
2408 | /* 0x0072 0x0331 */ | ||
2409 | 0x1e5f, 0x0000, | ||
2410 | /* 0x0074 0x0331 */ | ||
2411 | 0x1e6f, 0x0000, | ||
2412 | /* 0x007a 0x0331 */ | ||
2413 | 0x1e95, 0x0000, | ||
2414 | /* 0x00a8 0x0342 */ | ||
2415 | 0x1fc1, 0x0000, | ||
2416 | /* 0x03b1 0x0342 */ | ||
2417 | 0x1fb6, 0x0000, | ||
2418 | /* 0x03b7 0x0342 */ | ||
2419 | 0x1fc6, 0x0000, | ||
2420 | /* 0x03b9 0x0342 */ | ||
2421 | 0x1fd6, 0x0000, | ||
2422 | /* 0x03c5 0x0342 */ | ||
2423 | 0x1fe6, 0x0000, | ||
2424 | /* 0x03c9 0x0342 */ | ||
2425 | 0x1ff6, 0x0000, | ||
2426 | /* 0x1fbf 0x0342 */ | ||
2427 | 0x1fcf, 0x0000, | ||
2428 | /* 0x1ffe 0x0342 */ | ||
2429 | 0x1fdf, 0x0000, | ||
2430 | /* 0x0391 0x0345 */ | ||
2431 | 0x1fbc, 0x0002, 0x0313, 0x0ee2, 0x0314, 0x0eea, | ||
2432 | /* 0x0397 0x0345 */ | ||
2433 | 0x1fcc, 0x0002, 0x0313, 0x0ef2, 0x0314, 0x0efa, | ||
2434 | /* 0x03a9 0x0345 */ | ||
2435 | 0x1ffc, 0x0002, 0x0313, 0x0f02, 0x0314, 0x0f0a, | ||
2436 | /* 0x03b1 0x0345 */ | ||
2437 | 0x1fb3, 0x0005, 0x0300, 0x0f12, 0x0301, 0x0f14, 0x0313, 0x0f16, | ||
2438 | 0x0314, 0x0f1e, 0x0342, 0x0f26, | ||
2439 | /* 0x03b7 0x0345 */ | ||
2440 | 0x1fc3, 0x0005, 0x0300, 0x0f28, 0x0301, 0x0f2a, 0x0313, 0x0f2c, | ||
2441 | 0x0314, 0x0f34, 0x0342, 0x0f3c, | ||
2442 | /* 0x03bf 0x0345 */ | ||
2443 | 0x0000, 0x0001, 0x0301, 0x0f3e, | ||
2444 | /* 0x03c9 0x0345 */ | ||
2445 | 0x1ff3, 0x0004, 0x0300, 0x0f40, 0x0313, 0x0f42, 0x0314, 0x0f4a, | ||
2446 | 0x0342, 0x0f52, | ||
2447 | /* 0x05d0 0x05b7 */ | ||
2448 | 0xfb2e, 0x0000, | ||
2449 | /* 0x05f2 0x05b7 */ | ||
2450 | 0xfb1f, 0x0000, | ||
2451 | /* 0x05d0 0x05b8 */ | ||
2452 | 0xfb2f, 0x0000, | ||
2453 | /* 0x05d5 0x05b9 */ | ||
2454 | 0xfb4b, 0x0000, | ||
2455 | /* 0x05d0 0x05bc */ | ||
2456 | 0xfb30, 0x0000, | ||
2457 | /* 0x05d1 0x05bc */ | ||
2458 | 0xfb31, 0x0000, | ||
2459 | /* 0x05d2 0x05bc */ | ||
2460 | 0xfb32, 0x0000, | ||
2461 | /* 0x05d3 0x05bc */ | ||
2462 | 0xfb33, 0x0000, | ||
2463 | /* 0x05d4 0x05bc */ | ||
2464 | 0xfb34, 0x0000, | ||
2465 | /* 0x05d5 0x05bc */ | ||
2466 | 0xfb35, 0x0000, | ||
2467 | /* 0x05d6 0x05bc */ | ||
2468 | 0xfb36, 0x0000, | ||
2469 | /* 0x05d8 0x05bc */ | ||
2470 | 0xfb38, 0x0000, | ||
2471 | /* 0x05d9 0x05bc */ | ||
2472 | 0xfb39, 0x0000, | ||
2473 | /* 0x05da 0x05bc */ | ||
2474 | 0xfb3a, 0x0000, | ||
2475 | /* 0x05db 0x05bc */ | ||
2476 | 0xfb3b, 0x0000, | ||
2477 | /* 0x05dc 0x05bc */ | ||
2478 | 0xfb3c, 0x0000, | ||
2479 | /* 0x05de 0x05bc */ | ||
2480 | 0xfb3e, 0x0000, | ||
2481 | /* 0x05e0 0x05bc */ | ||
2482 | 0xfb40, 0x0000, | ||
2483 | /* 0x05e1 0x05bc */ | ||
2484 | 0xfb41, 0x0000, | ||
2485 | /* 0x05e3 0x05bc */ | ||
2486 | 0xfb43, 0x0000, | ||
2487 | /* 0x05e4 0x05bc */ | ||
2488 | 0xfb44, 0x0000, | ||
2489 | /* 0x05e6 0x05bc */ | ||
2490 | 0xfb46, 0x0000, | ||
2491 | /* 0x05e7 0x05bc */ | ||
2492 | 0xfb47, 0x0000, | ||
2493 | /* 0x05e8 0x05bc */ | ||
2494 | 0xfb48, 0x0000, | ||
2495 | /* 0x05e9 0x05bc */ | ||
2496 | 0xfb49, 0x0002, 0x05c1, 0x0f54, 0x05c2, 0x0f56, | ||
2497 | /* 0x05ea 0x05bc */ | ||
2498 | 0xfb4a, 0x0000, | ||
2499 | /* 0x05d1 0x05bf */ | ||
2500 | 0xfb4c, 0x0000, | ||
2501 | /* 0x05db 0x05bf */ | ||
2502 | 0xfb4d, 0x0000, | ||
2503 | /* 0x05e4 0x05bf */ | ||
2504 | 0xfb4e, 0x0000, | ||
2505 | /* 0x05e9 0x05c1 */ | ||
2506 | 0xfb2a, 0x0000, | ||
2507 | /* 0x05e9 0x05c2 */ | ||
2508 | 0xfb2b, 0x0000, | ||
2509 | /* 0x0915 0x093c */ | ||
2510 | 0x0958, 0x0000, | ||
2511 | /* 0x0916 0x093c */ | ||
2512 | 0x0959, 0x0000, | ||
2513 | /* 0x0917 0x093c */ | ||
2514 | 0x095a, 0x0000, | ||
2515 | /* 0x091c 0x093c */ | ||
2516 | 0x095b, 0x0000, | ||
2517 | /* 0x0921 0x093c */ | ||
2518 | 0x095c, 0x0000, | ||
2519 | /* 0x0922 0x093c */ | ||
2520 | 0x095d, 0x0000, | ||
2521 | /* 0x0928 0x093c */ | ||
2522 | 0x0929, 0x0000, | ||
2523 | /* 0x092b 0x093c */ | ||
2524 | 0x095e, 0x0000, | ||
2525 | /* 0x092f 0x093c */ | ||
2526 | 0x095f, 0x0000, | ||
2527 | /* 0x0930 0x093c */ | ||
2528 | 0x0931, 0x0000, | ||
2529 | /* 0x0933 0x093c */ | ||
2530 | 0x0934, 0x0000, | ||
2531 | /* 0x09a1 0x09bc */ | ||
2532 | 0x09dc, 0x0000, | ||
2533 | /* 0x09a2 0x09bc */ | ||
2534 | 0x09dd, 0x0000, | ||
2535 | /* 0x09ac 0x09bc */ | ||
2536 | 0x09b0, 0x0000, | ||
2537 | /* 0x09af 0x09bc */ | ||
2538 | 0x09df, 0x0000, | ||
2539 | /* 0x09c7 0x09be */ | ||
2540 | 0x09cb, 0x0000, | ||
2541 | /* 0x09c7 0x09d7 */ | ||
2542 | 0x09cc, 0x0000, | ||
2543 | /* 0x0a16 0x0a3c */ | ||
2544 | 0x0a59, 0x0000, | ||
2545 | /* 0x0a17 0x0a3c */ | ||
2546 | 0x0a5a, 0x0000, | ||
2547 | /* 0x0a1c 0x0a3c */ | ||
2548 | 0x0a5b, 0x0000, | ||
2549 | /* 0x0a21 0x0a3c */ | ||
2550 | 0x0a5c, 0x0000, | ||
2551 | /* 0x0a2b 0x0a3c */ | ||
2552 | 0x0a5e, 0x0000, | ||
2553 | /* 0x0b21 0x0b3c */ | ||
2554 | 0x0b5c, 0x0000, | ||
2555 | /* 0x0b22 0x0b3c */ | ||
2556 | 0x0b5d, 0x0000, | ||
2557 | /* 0x0b2f 0x0b3c */ | ||
2558 | 0x0b5f, 0x0000, | ||
2559 | /* 0x0b47 0x0b3e */ | ||
2560 | 0x0b4b, 0x0000, | ||
2561 | /* 0x0b47 0x0b56 */ | ||
2562 | 0x0b48, 0x0000, | ||
2563 | /* 0x0b47 0x0b57 */ | ||
2564 | 0x0b4c, 0x0000, | ||
2565 | /* 0x0bc6 0x0bbe */ | ||
2566 | 0x0bca, 0x0000, | ||
2567 | /* 0x0bc7 0x0bbe */ | ||
2568 | 0x0bcb, 0x0000, | ||
2569 | /* 0x0b92 0x0bd7 */ | ||
2570 | 0x0b94, 0x0000, | ||
2571 | /* 0x0bc6 0x0bd7 */ | ||
2572 | 0x0bcc, 0x0000, | ||
2573 | /* 0x0c46 0x0c56 */ | ||
2574 | 0x0c48, 0x0000, | ||
2575 | /* 0x0cc6 0x0cc2 */ | ||
2576 | 0x0cca, 0x0001, 0x0cd5, 0x0f58, | ||
2577 | /* 0x0cbf 0x0cd5 */ | ||
2578 | 0x0cc0, 0x0000, | ||
2579 | /* 0x0cc6 0x0cd5 */ | ||
2580 | 0x0cc7, 0x0000, | ||
2581 | /* 0x0cc6 0x0cd6 */ | ||
2582 | 0x0cc8, 0x0000, | ||
2583 | /* 0x0d46 0x0d3e */ | ||
2584 | 0x0d4a, 0x0000, | ||
2585 | /* 0x0d47 0x0d3e */ | ||
2586 | 0x0d4b, 0x0000, | ||
2587 | /* 0x0d46 0x0d57 */ | ||
2588 | 0x0d4c, 0x0000, | ||
2589 | /* 0x0e4d 0x0e32 */ | ||
2590 | 0x0e33, 0x0000, | ||
2591 | /* 0x0ecd 0x0eb2 */ | ||
2592 | 0x0eb3, 0x0000, | ||
2593 | /* 0x0f72 0x0f71 */ | ||
2594 | 0x0f73, 0x0000, | ||
2595 | /* 0x0f74 0x0f71 */ | ||
2596 | 0x0f75, 0x0000, | ||
2597 | /* 0x0f80 0x0f71 */ | ||
2598 | 0x0f81, 0x0000, | ||
2599 | /* 0x0fb2 0x0f80 */ | ||
2600 | 0x0f76, 0x0001, 0x0f71, 0x0f5a, | ||
2601 | /* 0x0fb3 0x0f80 */ | ||
2602 | 0x0f78, 0x0001, 0x0f71, 0x0f5c, | ||
2603 | /* 0x0f40 0x0fb5 */ | ||
2604 | 0x0f69, 0x0000, | ||
2605 | /* 0x0f90 0x0fb5 */ | ||
2606 | 0x0fb9, 0x0000, | ||
2607 | /* 0x0f42 0x0fb7 */ | ||
2608 | 0x0f43, 0x0000, | ||
2609 | /* 0x0f4c 0x0fb7 */ | ||
2610 | 0x0f4d, 0x0000, | ||
2611 | /* 0x0f51 0x0fb7 */ | ||
2612 | 0x0f52, 0x0000, | ||
2613 | /* 0x0f56 0x0fb7 */ | ||
2614 | 0x0f57, 0x0000, | ||
2615 | /* 0x0f5b 0x0fb7 */ | ||
2616 | 0x0f5c, 0x0000, | ||
2617 | /* 0x0f92 0x0fb7 */ | ||
2618 | 0x0f93, 0x0000, | ||
2619 | /* 0x0f9c 0x0fb7 */ | ||
2620 | 0x0f9d, 0x0000, | ||
2621 | /* 0x0fa1 0x0fb7 */ | ||
2622 | 0x0fa2, 0x0000, | ||
2623 | /* 0x0fa6 0x0fb7 */ | ||
2624 | 0x0fa7, 0x0000, | ||
2625 | /* 0x0fab 0x0fb7 */ | ||
2626 | 0x0fac, 0x0000, | ||
2627 | /* 0x3046 0x3099 */ | ||
2628 | 0x3094, 0x0000, | ||
2629 | /* 0x304b 0x3099 */ | ||
2630 | 0x304c, 0x0000, | ||
2631 | /* 0x304d 0x3099 */ | ||
2632 | 0x304e, 0x0000, | ||
2633 | /* 0x304f 0x3099 */ | ||
2634 | 0x3050, 0x0000, | ||
2635 | /* 0x3051 0x3099 */ | ||
2636 | 0x3052, 0x0000, | ||
2637 | /* 0x3053 0x3099 */ | ||
2638 | 0x3054, 0x0000, | ||
2639 | /* 0x3055 0x3099 */ | ||
2640 | 0x3056, 0x0000, | ||
2641 | /* 0x3057 0x3099 */ | ||
2642 | 0x3058, 0x0000, | ||
2643 | /* 0x3059 0x3099 */ | ||
2644 | 0x305a, 0x0000, | ||
2645 | /* 0x305b 0x3099 */ | ||
2646 | 0x305c, 0x0000, | ||
2647 | /* 0x305d 0x3099 */ | ||
2648 | 0x305e, 0x0000, | ||
2649 | /* 0x305f 0x3099 */ | ||
2650 | 0x3060, 0x0000, | ||
2651 | /* 0x3061 0x3099 */ | ||
2652 | 0x3062, 0x0000, | ||
2653 | /* 0x3064 0x3099 */ | ||
2654 | 0x3065, 0x0000, | ||
2655 | /* 0x3066 0x3099 */ | ||
2656 | 0x3067, 0x0000, | ||
2657 | /* 0x3068 0x3099 */ | ||
2658 | 0x3069, 0x0000, | ||
2659 | /* 0x306f 0x3099 */ | ||
2660 | 0x3070, 0x0000, | ||
2661 | /* 0x3072 0x3099 */ | ||
2662 | 0x3073, 0x0000, | ||
2663 | /* 0x3075 0x3099 */ | ||
2664 | 0x3076, 0x0000, | ||
2665 | /* 0x3078 0x3099 */ | ||
2666 | 0x3079, 0x0000, | ||
2667 | /* 0x307b 0x3099 */ | ||
2668 | 0x307c, 0x0000, | ||
2669 | /* 0x309d 0x3099 */ | ||
2670 | 0x309e, 0x0000, | ||
2671 | /* 0x30a6 0x3099 */ | ||
2672 | 0x30f4, 0x0000, | ||
2673 | /* 0x30ab 0x3099 */ | ||
2674 | 0x30ac, 0x0000, | ||
2675 | /* 0x30ad 0x3099 */ | ||
2676 | 0x30ae, 0x0000, | ||
2677 | /* 0x30af 0x3099 */ | ||
2678 | 0x30b0, 0x0000, | ||
2679 | /* 0x30b1 0x3099 */ | ||
2680 | 0x30b2, 0x0000, | ||
2681 | /* 0x30b3 0x3099 */ | ||
2682 | 0x30b4, 0x0000, | ||
2683 | /* 0x30b5 0x3099 */ | ||
2684 | 0x30b6, 0x0000, | ||
2685 | /* 0x30b7 0x3099 */ | ||
2686 | 0x30b8, 0x0000, | ||
2687 | /* 0x30b9 0x3099 */ | ||
2688 | 0x30ba, 0x0000, | ||
2689 | /* 0x30bb 0x3099 */ | ||
2690 | 0x30bc, 0x0000, | ||
2691 | /* 0x30bd 0x3099 */ | ||
2692 | 0x30be, 0x0000, | ||
2693 | /* 0x30bf 0x3099 */ | ||
2694 | 0x30c0, 0x0000, | ||
2695 | /* 0x30c1 0x3099 */ | ||
2696 | 0x30c2, 0x0000, | ||
2697 | /* 0x30c4 0x3099 */ | ||
2698 | 0x30c5, 0x0000, | ||
2699 | /* 0x30c6 0x3099 */ | ||
2700 | 0x30c7, 0x0000, | ||
2701 | /* 0x30c8 0x3099 */ | ||
2702 | 0x30c9, 0x0000, | ||
2703 | /* 0x30cf 0x3099 */ | ||
2704 | 0x30d0, 0x0000, | ||
2705 | /* 0x30d2 0x3099 */ | ||
2706 | 0x30d3, 0x0000, | ||
2707 | /* 0x30d5 0x3099 */ | ||
2708 | 0x30d6, 0x0000, | ||
2709 | /* 0x30d8 0x3099 */ | ||
2710 | 0x30d9, 0x0000, | ||
2711 | /* 0x30db 0x3099 */ | ||
2712 | 0x30dc, 0x0000, | ||
2713 | /* 0x30ef 0x3099 */ | ||
2714 | 0x30f7, 0x0000, | ||
2715 | /* 0x30f0 0x3099 */ | ||
2716 | 0x30f8, 0x0000, | ||
2717 | /* 0x30f1 0x3099 */ | ||
2718 | 0x30f9, 0x0000, | ||
2719 | /* 0x30f2 0x3099 */ | ||
2720 | 0x30fa, 0x0000, | ||
2721 | /* 0x30fd 0x3099 */ | ||
2722 | 0x30fe, 0x0000, | ||
2723 | /* 0x306f 0x309a */ | ||
2724 | 0x3071, 0x0000, | ||
2725 | /* 0x3072 0x309a */ | ||
2726 | 0x3074, 0x0000, | ||
2727 | /* 0x3075 0x309a */ | ||
2728 | 0x3077, 0x0000, | ||
2729 | /* 0x3078 0x309a */ | ||
2730 | 0x307a, 0x0000, | ||
2731 | /* 0x307b 0x309a */ | ||
2732 | 0x307d, 0x0000, | ||
2733 | /* 0x30cf 0x309a */ | ||
2734 | 0x30d1, 0x0000, | ||
2735 | /* 0x30d2 0x309a */ | ||
2736 | 0x30d4, 0x0000, | ||
2737 | /* 0x30d5 0x309a */ | ||
2738 | 0x30d7, 0x0000, | ||
2739 | /* 0x30d8 0x309a */ | ||
2740 | 0x30da, 0x0000, | ||
2741 | /* 0x30db 0x309a */ | ||
2742 | 0x30dd, 0x0000, | ||
2743 | /* 0x0307 0x0053 0x0301 */ | ||
2744 | 0x1e64, 0x0000, | ||
2745 | /* 0x0307 0x0073 0x0301 */ | ||
2746 | 0x1e65, 0x0000, | ||
2747 | /* 0x0300 0x0041 0x0302 */ | ||
2748 | 0x1ea6, 0x0000, | ||
2749 | /* 0x0301 0x0041 0x0302 */ | ||
2750 | 0x1ea4, 0x0000, | ||
2751 | /* 0x0303 0x0041 0x0302 */ | ||
2752 | 0x1eaa, 0x0000, | ||
2753 | /* 0x0309 0x0041 0x0302 */ | ||
2754 | 0x1ea8, 0x0000, | ||
2755 | /* 0x0300 0x0045 0x0302 */ | ||
2756 | 0x1ec0, 0x0000, | ||
2757 | /* 0x0301 0x0045 0x0302 */ | ||
2758 | 0x1ebe, 0x0000, | ||
2759 | /* 0x0303 0x0045 0x0302 */ | ||
2760 | 0x1ec4, 0x0000, | ||
2761 | /* 0x0309 0x0045 0x0302 */ | ||
2762 | 0x1ec2, 0x0000, | ||
2763 | /* 0x0300 0x004f 0x0302 */ | ||
2764 | 0x1ed2, 0x0000, | ||
2765 | /* 0x0301 0x004f 0x0302 */ | ||
2766 | 0x1ed0, 0x0000, | ||
2767 | /* 0x0303 0x004f 0x0302 */ | ||
2768 | 0x1ed6, 0x0000, | ||
2769 | /* 0x0309 0x004f 0x0302 */ | ||
2770 | 0x1ed4, 0x0000, | ||
2771 | /* 0x0300 0x0061 0x0302 */ | ||
2772 | 0x1ea7, 0x0000, | ||
2773 | /* 0x0301 0x0061 0x0302 */ | ||
2774 | 0x1ea5, 0x0000, | ||
2775 | /* 0x0303 0x0061 0x0302 */ | ||
2776 | 0x1eab, 0x0000, | ||
2777 | /* 0x0309 0x0061 0x0302 */ | ||
2778 | 0x1ea9, 0x0000, | ||
2779 | /* 0x0300 0x0065 0x0302 */ | ||
2780 | 0x1ec1, 0x0000, | ||
2781 | /* 0x0301 0x0065 0x0302 */ | ||
2782 | 0x1ebf, 0x0000, | ||
2783 | /* 0x0303 0x0065 0x0302 */ | ||
2784 | 0x1ec5, 0x0000, | ||
2785 | /* 0x0309 0x0065 0x0302 */ | ||
2786 | 0x1ec3, 0x0000, | ||
2787 | /* 0x0300 0x006f 0x0302 */ | ||
2788 | 0x1ed3, 0x0000, | ||
2789 | /* 0x0301 0x006f 0x0302 */ | ||
2790 | 0x1ed1, 0x0000, | ||
2791 | /* 0x0303 0x006f 0x0302 */ | ||
2792 | 0x1ed7, 0x0000, | ||
2793 | /* 0x0309 0x006f 0x0302 */ | ||
2794 | 0x1ed5, 0x0000, | ||
2795 | /* 0x0301 0x004f 0x0303 */ | ||
2796 | 0x1e4c, 0x0000, | ||
2797 | /* 0x0308 0x004f 0x0303 */ | ||
2798 | 0x1e4e, 0x0000, | ||
2799 | /* 0x0301 0x0055 0x0303 */ | ||
2800 | 0x1e78, 0x0000, | ||
2801 | /* 0x0301 0x006f 0x0303 */ | ||
2802 | 0x1e4d, 0x0000, | ||
2803 | /* 0x0308 0x006f 0x0303 */ | ||
2804 | 0x1e4f, 0x0000, | ||
2805 | /* 0x0301 0x0075 0x0303 */ | ||
2806 | 0x1e79, 0x0000, | ||
2807 | /* 0x0300 0x0045 0x0304 */ | ||
2808 | 0x1e14, 0x0000, | ||
2809 | /* 0x0301 0x0045 0x0304 */ | ||
2810 | 0x1e16, 0x0000, | ||
2811 | /* 0x0300 0x004f 0x0304 */ | ||
2812 | 0x1e50, 0x0000, | ||
2813 | /* 0x0301 0x004f 0x0304 */ | ||
2814 | 0x1e52, 0x0000, | ||
2815 | /* 0x0308 0x0055 0x0304 */ | ||
2816 | 0x1e7a, 0x0000, | ||
2817 | /* 0x0300 0x0065 0x0304 */ | ||
2818 | 0x1e15, 0x0000, | ||
2819 | /* 0x0301 0x0065 0x0304 */ | ||
2820 | 0x1e17, 0x0000, | ||
2821 | /* 0x0300 0x006f 0x0304 */ | ||
2822 | 0x1e51, 0x0000, | ||
2823 | /* 0x0301 0x006f 0x0304 */ | ||
2824 | 0x1e53, 0x0000, | ||
2825 | /* 0x0308 0x0075 0x0304 */ | ||
2826 | 0x1e7b, 0x0000, | ||
2827 | /* 0x0300 0x0041 0x0306 */ | ||
2828 | 0x1eb0, 0x0000, | ||
2829 | /* 0x0301 0x0041 0x0306 */ | ||
2830 | 0x1eae, 0x0000, | ||
2831 | /* 0x0303 0x0041 0x0306 */ | ||
2832 | 0x1eb4, 0x0000, | ||
2833 | /* 0x0309 0x0041 0x0306 */ | ||
2834 | 0x1eb2, 0x0000, | ||
2835 | /* 0x0300 0x0061 0x0306 */ | ||
2836 | 0x1eb1, 0x0000, | ||
2837 | /* 0x0301 0x0061 0x0306 */ | ||
2838 | 0x1eaf, 0x0000, | ||
2839 | /* 0x0303 0x0061 0x0306 */ | ||
2840 | 0x1eb5, 0x0000, | ||
2841 | /* 0x0309 0x0061 0x0306 */ | ||
2842 | 0x1eb3, 0x0000, | ||
2843 | /* 0x0304 0x0041 0x0307 */ | ||
2844 | 0x01e0, 0x0000, | ||
2845 | /* 0x0304 0x0061 0x0307 */ | ||
2846 | 0x01e1, 0x0000, | ||
2847 | /* 0x0304 0x0041 0x0308 */ | ||
2848 | 0x01de, 0x0000, | ||
2849 | /* 0x0301 0x0049 0x0308 */ | ||
2850 | 0x1e2e, 0x0000, | ||
2851 | /* 0x0300 0x0055 0x0308 */ | ||
2852 | 0x01db, 0x0000, | ||
2853 | /* 0x0301 0x0055 0x0308 */ | ||
2854 | 0x01d7, 0x0000, | ||
2855 | /* 0x0304 0x0055 0x0308 */ | ||
2856 | 0x01d5, 0x0000, | ||
2857 | /* 0x030c 0x0055 0x0308 */ | ||
2858 | 0x01d9, 0x0000, | ||
2859 | /* 0x0304 0x0061 0x0308 */ | ||
2860 | 0x01df, 0x0000, | ||
2861 | /* 0x0301 0x0069 0x0308 */ | ||
2862 | 0x1e2f, 0x0000, | ||
2863 | /* 0x0300 0x0075 0x0308 */ | ||
2864 | 0x01dc, 0x0000, | ||
2865 | /* 0x0301 0x0075 0x0308 */ | ||
2866 | 0x01d8, 0x0000, | ||
2867 | /* 0x0304 0x0075 0x0308 */ | ||
2868 | 0x01d6, 0x0000, | ||
2869 | /* 0x030c 0x0075 0x0308 */ | ||
2870 | 0x01da, 0x0000, | ||
2871 | /* 0x0300 0x03b9 0x0308 */ | ||
2872 | 0x1fd2, 0x0000, | ||
2873 | /* 0x0301 0x03b9 0x0308 */ | ||
2874 | 0x1fd3, 0x0000, | ||
2875 | /* 0x030d 0x03b9 0x0308 */ | ||
2876 | 0x0390, 0x0000, | ||
2877 | /* 0x0342 0x03b9 0x0308 */ | ||
2878 | 0x1fd7, 0x0000, | ||
2879 | /* 0x0300 0x03c5 0x0308 */ | ||
2880 | 0x1fe2, 0x0000, | ||
2881 | /* 0x0301 0x03c5 0x0308 */ | ||
2882 | 0x1fe3, 0x0000, | ||
2883 | /* 0x030d 0x03c5 0x0308 */ | ||
2884 | 0x03b0, 0x0000, | ||
2885 | /* 0x0342 0x03c5 0x0308 */ | ||
2886 | 0x1fe7, 0x0000, | ||
2887 | /* 0x0301 0x0041 0x030a */ | ||
2888 | 0x01fa, 0x0000, | ||
2889 | /* 0x0301 0x0061 0x030a */ | ||
2890 | 0x01fb, 0x0000, | ||
2891 | /* 0x0307 0x0053 0x030c */ | ||
2892 | 0x1e66, 0x0000, | ||
2893 | /* 0x0307 0x0073 0x030c */ | ||
2894 | 0x1e67, 0x0000, | ||
2895 | /* 0x0300 0x0391 0x0313 */ | ||
2896 | 0x1f0a, 0x0000, | ||
2897 | /* 0x0301 0x0391 0x0313 */ | ||
2898 | 0x1f0c, 0x0000, | ||
2899 | /* 0x0342 0x0391 0x0313 */ | ||
2900 | 0x1f0e, 0x0000, | ||
2901 | /* 0x0300 0x0395 0x0313 */ | ||
2902 | 0x1f1a, 0x0000, | ||
2903 | /* 0x0301 0x0395 0x0313 */ | ||
2904 | 0x1f1c, 0x0000, | ||
2905 | /* 0x0300 0x0397 0x0313 */ | ||
2906 | 0x1f2a, 0x0000, | ||
2907 | /* 0x0301 0x0397 0x0313 */ | ||
2908 | 0x1f2c, 0x0000, | ||
2909 | /* 0x0342 0x0397 0x0313 */ | ||
2910 | 0x1f2e, 0x0000, | ||
2911 | /* 0x0300 0x0399 0x0313 */ | ||
2912 | 0x1f3a, 0x0000, | ||
2913 | /* 0x0301 0x0399 0x0313 */ | ||
2914 | 0x1f3c, 0x0000, | ||
2915 | /* 0x0342 0x0399 0x0313 */ | ||
2916 | 0x1f3e, 0x0000, | ||
2917 | /* 0x0300 0x039f 0x0313 */ | ||
2918 | 0x1f4a, 0x0000, | ||
2919 | /* 0x0301 0x039f 0x0313 */ | ||
2920 | 0x1f4c, 0x0000, | ||
2921 | /* 0x0300 0x03a9 0x0313 */ | ||
2922 | 0x1f6a, 0x0000, | ||
2923 | /* 0x0301 0x03a9 0x0313 */ | ||
2924 | 0x1f6c, 0x0000, | ||
2925 | /* 0x0342 0x03a9 0x0313 */ | ||
2926 | 0x1f6e, 0x0000, | ||
2927 | /* 0x0300 0x03b1 0x0313 */ | ||
2928 | 0x1f02, 0x0000, | ||
2929 | /* 0x0301 0x03b1 0x0313 */ | ||
2930 | 0x1f04, 0x0000, | ||
2931 | /* 0x0342 0x03b1 0x0313 */ | ||
2932 | 0x1f06, 0x0000, | ||
2933 | /* 0x0300 0x03b5 0x0313 */ | ||
2934 | 0x1f12, 0x0000, | ||
2935 | /* 0x0301 0x03b5 0x0313 */ | ||
2936 | 0x1f14, 0x0000, | ||
2937 | /* 0x0300 0x03b7 0x0313 */ | ||
2938 | 0x1f22, 0x0000, | ||
2939 | /* 0x0301 0x03b7 0x0313 */ | ||
2940 | 0x1f24, 0x0000, | ||
2941 | /* 0x0342 0x03b7 0x0313 */ | ||
2942 | 0x1f26, 0x0000, | ||
2943 | /* 0x0300 0x03b9 0x0313 */ | ||
2944 | 0x1f32, 0x0000, | ||
2945 | /* 0x0301 0x03b9 0x0313 */ | ||
2946 | 0x1f34, 0x0000, | ||
2947 | /* 0x0342 0x03b9 0x0313 */ | ||
2948 | 0x1f36, 0x0000, | ||
2949 | /* 0x0300 0x03bf 0x0313 */ | ||
2950 | 0x1f42, 0x0000, | ||
2951 | /* 0x0301 0x03bf 0x0313 */ | ||
2952 | 0x1f44, 0x0000, | ||
2953 | /* 0x0300 0x03c5 0x0313 */ | ||
2954 | 0x1f52, 0x0000, | ||
2955 | /* 0x0301 0x03c5 0x0313 */ | ||
2956 | 0x1f54, 0x0000, | ||
2957 | /* 0x0342 0x03c5 0x0313 */ | ||
2958 | 0x1f56, 0x0000, | ||
2959 | /* 0x0300 0x03c9 0x0313 */ | ||
2960 | 0x1f62, 0x0000, | ||
2961 | /* 0x0301 0x03c9 0x0313 */ | ||
2962 | 0x1f64, 0x0000, | ||
2963 | /* 0x0342 0x03c9 0x0313 */ | ||
2964 | 0x1f66, 0x0000, | ||
2965 | /* 0x0300 0x0391 0x0314 */ | ||
2966 | 0x1f0b, 0x0000, | ||
2967 | /* 0x0301 0x0391 0x0314 */ | ||
2968 | 0x1f0d, 0x0000, | ||
2969 | /* 0x0342 0x0391 0x0314 */ | ||
2970 | 0x1f0f, 0x0000, | ||
2971 | /* 0x0300 0x0395 0x0314 */ | ||
2972 | 0x1f1b, 0x0000, | ||
2973 | /* 0x0301 0x0395 0x0314 */ | ||
2974 | 0x1f1d, 0x0000, | ||
2975 | /* 0x0300 0x0397 0x0314 */ | ||
2976 | 0x1f2b, 0x0000, | ||
2977 | /* 0x0301 0x0397 0x0314 */ | ||
2978 | 0x1f2d, 0x0000, | ||
2979 | /* 0x0342 0x0397 0x0314 */ | ||
2980 | 0x1f2f, 0x0000, | ||
2981 | /* 0x0300 0x0399 0x0314 */ | ||
2982 | 0x1f3b, 0x0000, | ||
2983 | /* 0x0301 0x0399 0x0314 */ | ||
2984 | 0x1f3d, 0x0000, | ||
2985 | /* 0x0342 0x0399 0x0314 */ | ||
2986 | 0x1f3f, 0x0000, | ||
2987 | /* 0x0300 0x039f 0x0314 */ | ||
2988 | 0x1f4b, 0x0000, | ||
2989 | /* 0x0301 0x039f 0x0314 */ | ||
2990 | 0x1f4d, 0x0000, | ||
2991 | /* 0x0300 0x03a5 0x0314 */ | ||
2992 | 0x1f5b, 0x0000, | ||
2993 | /* 0x0301 0x03a5 0x0314 */ | ||
2994 | 0x1f5d, 0x0000, | ||
2995 | /* 0x0342 0x03a5 0x0314 */ | ||
2996 | 0x1f5f, 0x0000, | ||
2997 | /* 0x0300 0x03a9 0x0314 */ | ||
2998 | 0x1f6b, 0x0000, | ||
2999 | /* 0x0301 0x03a9 0x0314 */ | ||
3000 | 0x1f6d, 0x0000, | ||
3001 | /* 0x0342 0x03a9 0x0314 */ | ||
3002 | 0x1f6f, 0x0000, | ||
3003 | /* 0x0300 0x03b1 0x0314 */ | ||
3004 | 0x1f03, 0x0000, | ||
3005 | /* 0x0301 0x03b1 0x0314 */ | ||
3006 | 0x1f05, 0x0000, | ||
3007 | /* 0x0342 0x03b1 0x0314 */ | ||
3008 | 0x1f07, 0x0000, | ||
3009 | /* 0x0300 0x03b5 0x0314 */ | ||
3010 | 0x1f13, 0x0000, | ||
3011 | /* 0x0301 0x03b5 0x0314 */ | ||
3012 | 0x1f15, 0x0000, | ||
3013 | /* 0x0300 0x03b7 0x0314 */ | ||
3014 | 0x1f23, 0x0000, | ||
3015 | /* 0x0301 0x03b7 0x0314 */ | ||
3016 | 0x1f25, 0x0000, | ||
3017 | /* 0x0342 0x03b7 0x0314 */ | ||
3018 | 0x1f27, 0x0000, | ||
3019 | /* 0x0300 0x03b9 0x0314 */ | ||
3020 | 0x1f33, 0x0000, | ||
3021 | /* 0x0301 0x03b9 0x0314 */ | ||
3022 | 0x1f35, 0x0000, | ||
3023 | /* 0x0342 0x03b9 0x0314 */ | ||
3024 | 0x1f37, 0x0000, | ||
3025 | /* 0x0300 0x03bf 0x0314 */ | ||
3026 | 0x1f43, 0x0000, | ||
3027 | /* 0x0301 0x03bf 0x0314 */ | ||
3028 | 0x1f45, 0x0000, | ||
3029 | /* 0x0300 0x03c5 0x0314 */ | ||
3030 | 0x1f53, 0x0000, | ||
3031 | /* 0x0301 0x03c5 0x0314 */ | ||
3032 | 0x1f55, 0x0000, | ||
3033 | /* 0x0342 0x03c5 0x0314 */ | ||
3034 | 0x1f57, 0x0000, | ||
3035 | /* 0x0300 0x03c9 0x0314 */ | ||
3036 | 0x1f63, 0x0000, | ||
3037 | /* 0x0301 0x03c9 0x0314 */ | ||
3038 | 0x1f65, 0x0000, | ||
3039 | /* 0x0342 0x03c9 0x0314 */ | ||
3040 | 0x1f67, 0x0000, | ||
3041 | /* 0x0300 0x004f 0x031b */ | ||
3042 | 0x1edc, 0x0000, | ||
3043 | /* 0x0301 0x004f 0x031b */ | ||
3044 | 0x1eda, 0x0000, | ||
3045 | /* 0x0303 0x004f 0x031b */ | ||
3046 | 0x1ee0, 0x0000, | ||
3047 | /* 0x0309 0x004f 0x031b */ | ||
3048 | 0x1ede, 0x0000, | ||
3049 | /* 0x0323 0x004f 0x031b */ | ||
3050 | 0x1ee2, 0x0000, | ||
3051 | /* 0x0300 0x0055 0x031b */ | ||
3052 | 0x1eea, 0x0000, | ||
3053 | /* 0x0301 0x0055 0x031b */ | ||
3054 | 0x1ee8, 0x0000, | ||
3055 | /* 0x0303 0x0055 0x031b */ | ||
3056 | 0x1eee, 0x0000, | ||
3057 | /* 0x0309 0x0055 0x031b */ | ||
3058 | 0x1eec, 0x0000, | ||
3059 | /* 0x0323 0x0055 0x031b */ | ||
3060 | 0x1ef0, 0x0000, | ||
3061 | /* 0x0300 0x006f 0x031b */ | ||
3062 | 0x1edd, 0x0000, | ||
3063 | /* 0x0301 0x006f 0x031b */ | ||
3064 | 0x1edb, 0x0000, | ||
3065 | /* 0x0303 0x006f 0x031b */ | ||
3066 | 0x1ee1, 0x0000, | ||
3067 | /* 0x0309 0x006f 0x031b */ | ||
3068 | 0x1edf, 0x0000, | ||
3069 | /* 0x0323 0x006f 0x031b */ | ||
3070 | 0x1ee3, 0x0000, | ||
3071 | /* 0x0300 0x0075 0x031b */ | ||
3072 | 0x1eeb, 0x0000, | ||
3073 | /* 0x0301 0x0075 0x031b */ | ||
3074 | 0x1ee9, 0x0000, | ||
3075 | /* 0x0303 0x0075 0x031b */ | ||
3076 | 0x1eef, 0x0000, | ||
3077 | /* 0x0309 0x0075 0x031b */ | ||
3078 | 0x1eed, 0x0000, | ||
3079 | /* 0x0323 0x0075 0x031b */ | ||
3080 | 0x1ef1, 0x0000, | ||
3081 | /* 0x0302 0x0041 0x0323 */ | ||
3082 | 0x1eac, 0x0000, | ||
3083 | /* 0x0306 0x0041 0x0323 */ | ||
3084 | 0x1eb6, 0x0000, | ||
3085 | /* 0x0302 0x0045 0x0323 */ | ||
3086 | 0x1ec6, 0x0000, | ||
3087 | /* 0x0304 0x004c 0x0323 */ | ||
3088 | 0x1e38, 0x0000, | ||
3089 | /* 0x0302 0x004f 0x0323 */ | ||
3090 | 0x1ed8, 0x0000, | ||
3091 | /* 0x0304 0x0052 0x0323 */ | ||
3092 | 0x1e5c, 0x0000, | ||
3093 | /* 0x0307 0x0053 0x0323 */ | ||
3094 | 0x1e68, 0x0000, | ||
3095 | /* 0x0302 0x0061 0x0323 */ | ||
3096 | 0x1ead, 0x0000, | ||
3097 | /* 0x0306 0x0061 0x0323 */ | ||
3098 | 0x1eb7, 0x0000, | ||
3099 | /* 0x0302 0x0065 0x0323 */ | ||
3100 | 0x1ec7, 0x0000, | ||
3101 | /* 0x0304 0x006c 0x0323 */ | ||
3102 | 0x1e39, 0x0000, | ||
3103 | /* 0x0302 0x006f 0x0323 */ | ||
3104 | 0x1ed9, 0x0000, | ||
3105 | /* 0x0304 0x0072 0x0323 */ | ||
3106 | 0x1e5d, 0x0000, | ||
3107 | /* 0x0307 0x0073 0x0323 */ | ||
3108 | 0x1e69, 0x0000, | ||
3109 | /* 0x0301 0x0043 0x0327 */ | ||
3110 | 0x1e08, 0x0000, | ||
3111 | /* 0x0306 0x0045 0x0327 */ | ||
3112 | 0x1e1c, 0x0000, | ||
3113 | /* 0x0301 0x0063 0x0327 */ | ||
3114 | 0x1e09, 0x0000, | ||
3115 | /* 0x0306 0x0065 0x0327 */ | ||
3116 | 0x1e1d, 0x0000, | ||
3117 | /* 0x0304 0x004f 0x0328 */ | ||
3118 | 0x01ec, 0x0000, | ||
3119 | /* 0x0304 0x006f 0x0328 */ | ||
3120 | 0x01ed, 0x0000, | ||
3121 | /* 0x0313 0x0391 0x0345 */ | ||
3122 | 0x1f88, 0x0003, 0x0300, 0x0f5e, 0x0301, 0x0f60, 0x0342, 0x0f62, | ||
3123 | /* 0x0314 0x0391 0x0345 */ | ||
3124 | 0x1f89, 0x0003, 0x0300, 0x0f64, 0x0301, 0x0f66, 0x0342, 0x0f68, | ||
3125 | /* 0x0313 0x0397 0x0345 */ | ||
3126 | 0x1f98, 0x0003, 0x0300, 0x0f6a, 0x0301, 0x0f6c, 0x0342, 0x0f6e, | ||
3127 | /* 0x0314 0x0397 0x0345 */ | ||
3128 | 0x1f99, 0x0003, 0x0300, 0x0f70, 0x0301, 0x0f72, 0x0342, 0x0f74, | ||
3129 | /* 0x0313 0x03a9 0x0345 */ | ||
3130 | 0x1fa8, 0x0003, 0x0300, 0x0f76, 0x0301, 0x0f78, 0x0342, 0x0f7a, | ||
3131 | /* 0x0314 0x03a9 0x0345 */ | ||
3132 | 0x1fa9, 0x0003, 0x0300, 0x0f7c, 0x0301, 0x0f7e, 0x0342, 0x0f80, | ||
3133 | /* 0x0300 0x03b1 0x0345 */ | ||
3134 | 0x1fb2, 0x0000, | ||
3135 | /* 0x0301 0x03b1 0x0345 */ | ||
3136 | 0x1fb4, 0x0000, | ||
3137 | /* 0x0313 0x03b1 0x0345 */ | ||
3138 | 0x1f80, 0x0003, 0x0300, 0x0f82, 0x0301, 0x0f84, 0x0342, 0x0f86, | ||
3139 | /* 0x0314 0x03b1 0x0345 */ | ||
3140 | 0x1f81, 0x0003, 0x0300, 0x0f88, 0x0301, 0x0f8a, 0x0342, 0x0f8c, | ||
3141 | /* 0x0342 0x03b1 0x0345 */ | ||
3142 | 0x1fb7, 0x0000, | ||
3143 | /* 0x0300 0x03b7 0x0345 */ | ||
3144 | 0x1fc2, 0x0000, | ||
3145 | /* 0x0301 0x03b7 0x0345 */ | ||
3146 | 0x1fc4, 0x0000, | ||
3147 | /* 0x0313 0x03b7 0x0345 */ | ||
3148 | 0x1f90, 0x0003, 0x0300, 0x0f8e, 0x0301, 0x0f90, 0x0342, 0x0f92, | ||
3149 | /* 0x0314 0x03b7 0x0345 */ | ||
3150 | 0x1f91, 0x0003, 0x0300, 0x0f94, 0x0301, 0x0f96, 0x0342, 0x0f98, | ||
3151 | /* 0x0342 0x03b7 0x0345 */ | ||
3152 | 0x1fc7, 0x0000, | ||
3153 | /* 0x0301 0x03bf 0x0345 */ | ||
3154 | 0x1ff4, 0x0000, | ||
3155 | /* 0x0300 0x03c9 0x0345 */ | ||
3156 | 0x1ff2, 0x0000, | ||
3157 | /* 0x0313 0x03c9 0x0345 */ | ||
3158 | 0x1fa0, 0x0003, 0x0300, 0x0f9a, 0x0301, 0x0f9c, 0x0342, 0x0f9e, | ||
3159 | /* 0x0314 0x03c9 0x0345 */ | ||
3160 | 0x1fa1, 0x0003, 0x0300, 0x0fa0, 0x0301, 0x0fa2, 0x0342, 0x0fa4, | ||
3161 | /* 0x0342 0x03c9 0x0345 */ | ||
3162 | 0x1ff7, 0x0000, | ||
3163 | /* 0x05c1 0x05e9 0x05bc */ | ||
3164 | 0xfb2c, 0x0000, | ||
3165 | /* 0x05c2 0x05e9 0x05bc */ | ||
3166 | 0xfb2d, 0x0000, | ||
3167 | /* 0x0cd5 0x0cc6 0x0cc2 */ | ||
3168 | 0x0ccb, 0x0000, | ||
3169 | /* 0x0f71 0x0fb2 0x0f80 */ | ||
3170 | 0x0f77, 0x0000, | ||
3171 | /* 0x0f71 0x0fb3 0x0f80 */ | ||
3172 | 0x0f79, 0x0000, | ||
3173 | /* 0x0300 0x0313 0x0391 0x0345 */ | ||
3174 | 0x1f8a, 0x0000, | ||
3175 | /* 0x0301 0x0313 0x0391 0x0345 */ | ||
3176 | 0x1f8c, 0x0000, | ||
3177 | /* 0x0342 0x0313 0x0391 0x0345 */ | ||
3178 | 0x1f8e, 0x0000, | ||
3179 | /* 0x0300 0x0314 0x0391 0x0345 */ | ||
3180 | 0x1f8b, 0x0000, | ||
3181 | /* 0x0301 0x0314 0x0391 0x0345 */ | ||
3182 | 0x1f8d, 0x0000, | ||
3183 | /* 0x0342 0x0314 0x0391 0x0345 */ | ||
3184 | 0x1f8f, 0x0000, | ||
3185 | /* 0x0300 0x0313 0x0397 0x0345 */ | ||
3186 | 0x1f9a, 0x0000, | ||
3187 | /* 0x0301 0x0313 0x0397 0x0345 */ | ||
3188 | 0x1f9c, 0x0000, | ||
3189 | /* 0x0342 0x0313 0x0397 0x0345 */ | ||
3190 | 0x1f9e, 0x0000, | ||
3191 | /* 0x0300 0x0314 0x0397 0x0345 */ | ||
3192 | 0x1f9b, 0x0000, | ||
3193 | /* 0x0301 0x0314 0x0397 0x0345 */ | ||
3194 | 0x1f9d, 0x0000, | ||
3195 | /* 0x0342 0x0314 0x0397 0x0345 */ | ||
3196 | 0x1f9f, 0x0000, | ||
3197 | /* 0x0300 0x0313 0x03a9 0x0345 */ | ||
3198 | 0x1faa, 0x0000, | ||
3199 | /* 0x0301 0x0313 0x03a9 0x0345 */ | ||
3200 | 0x1fac, 0x0000, | ||
3201 | /* 0x0342 0x0313 0x03a9 0x0345 */ | ||
3202 | 0x1fae, 0x0000, | ||
3203 | /* 0x0300 0x0314 0x03a9 0x0345 */ | ||
3204 | 0x1fab, 0x0000, | ||
3205 | /* 0x0301 0x0314 0x03a9 0x0345 */ | ||
3206 | 0x1fad, 0x0000, | ||
3207 | /* 0x0342 0x0314 0x03a9 0x0345 */ | ||
3208 | 0x1faf, 0x0000, | ||
3209 | /* 0x0300 0x0313 0x03b1 0x0345 */ | ||
3210 | 0x1f82, 0x0000, | ||
3211 | /* 0x0301 0x0313 0x03b1 0x0345 */ | ||
3212 | 0x1f84, 0x0000, | ||
3213 | /* 0x0342 0x0313 0x03b1 0x0345 */ | ||
3214 | 0x1f86, 0x0000, | ||
3215 | /* 0x0300 0x0314 0x03b1 0x0345 */ | ||
3216 | 0x1f83, 0x0000, | ||
3217 | /* 0x0301 0x0314 0x03b1 0x0345 */ | ||
3218 | 0x1f85, 0x0000, | ||
3219 | /* 0x0342 0x0314 0x03b1 0x0345 */ | ||
3220 | 0x1f87, 0x0000, | ||
3221 | /* 0x0300 0x0313 0x03b7 0x0345 */ | ||
3222 | 0x1f92, 0x0000, | ||
3223 | /* 0x0301 0x0313 0x03b7 0x0345 */ | ||
3224 | 0x1f94, 0x0000, | ||
3225 | /* 0x0342 0x0313 0x03b7 0x0345 */ | ||
3226 | 0x1f96, 0x0000, | ||
3227 | /* 0x0300 0x0314 0x03b7 0x0345 */ | ||
3228 | 0x1f93, 0x0000, | ||
3229 | /* 0x0301 0x0314 0x03b7 0x0345 */ | ||
3230 | 0x1f95, 0x0000, | ||
3231 | /* 0x0342 0x0314 0x03b7 0x0345 */ | ||
3232 | 0x1f97, 0x0000, | ||
3233 | /* 0x0300 0x0313 0x03c9 0x0345 */ | ||
3234 | 0x1fa2, 0x0000, | ||
3235 | /* 0x0301 0x0313 0x03c9 0x0345 */ | ||
3236 | 0x1fa4, 0x0000, | ||
3237 | /* 0x0342 0x0313 0x03c9 0x0345 */ | ||
3238 | 0x1fa6, 0x0000, | ||
3239 | /* 0x0300 0x0314 0x03c9 0x0345 */ | ||
3240 | 0x1fa3, 0x0000, | ||
3241 | /* 0x0301 0x0314 0x03c9 0x0345 */ | ||
3242 | 0x1fa5, 0x0000, | ||
3243 | /* 0x0342 0x0314 0x03c9 0x0345 */ | ||
3244 | 0x1fa7, 0x0000, | ||
3245 | }; | ||
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c new file mode 100644 index 000000000000..060c69048c3d --- /dev/null +++ b/fs/hfsplus/unicode.c | |||
@@ -0,0 +1,271 @@ | |||
1 | /* | ||
2 | * linux/fs/hfsplus/unicode.c | ||
3 | * | ||
4 | * Copyright (C) 2001 | ||
5 | * Brad Boyer (flar@allandria.com) | ||
6 | * (C) 2003 Ardis Technologies <roman@ardistech.com> | ||
7 | * | ||
8 | * Handler routines for unicode strings | ||
9 | */ | ||
10 | |||
11 | #include <linux/types.h> | ||
12 | #include <linux/nls.h> | ||
13 | #include "hfsplus_fs.h" | ||
14 | #include "hfsplus_raw.h" | ||
15 | |||
16 | /* Fold the case of a unicode char, given the 16 bit value */ | ||
17 | /* Returns folded char, or 0 if ignorable */ | ||
18 | static inline u16 case_fold(u16 c) | ||
19 | { | ||
20 | u16 tmp; | ||
21 | |||
22 | tmp = hfsplus_case_fold_table[c >> 8]; | ||
23 | if (tmp) | ||
24 | tmp = hfsplus_case_fold_table[tmp + (c & 0xff)]; | ||
25 | else | ||
26 | tmp = c; | ||
27 | return tmp; | ||
28 | } | ||
29 | |||
30 | /* Compare unicode strings, return values like normal strcmp */ | ||
31 | int hfsplus_unistrcmp(const struct hfsplus_unistr *s1, const struct hfsplus_unistr *s2) | ||
32 | { | ||
33 | u16 len1, len2, c1, c2; | ||
34 | const hfsplus_unichr *p1, *p2; | ||
35 | |||
36 | len1 = be16_to_cpu(s1->length); | ||
37 | len2 = be16_to_cpu(s2->length); | ||
38 | p1 = s1->unicode; | ||
39 | p2 = s2->unicode; | ||
40 | |||
41 | while (1) { | ||
42 | c1 = c2 = 0; | ||
43 | |||
44 | while (len1 && !c1) { | ||
45 | c1 = case_fold(be16_to_cpu(*p1)); | ||
46 | p1++; | ||
47 | len1--; | ||
48 | } | ||
49 | while (len2 && !c2) { | ||
50 | c2 = case_fold(be16_to_cpu(*p2)); | ||
51 | p2++; | ||
52 | len2--; | ||
53 | } | ||
54 | |||
55 | if (c1 != c2) | ||
56 | return (c1 < c2) ? -1 : 1; | ||
57 | if (!c1 && !c2) | ||
58 | return 0; | ||
59 | } | ||
60 | } | ||
61 | |||
62 | #define Hangul_SBase 0xac00 | ||
63 | #define Hangul_LBase 0x1100 | ||
64 | #define Hangul_VBase 0x1161 | ||
65 | #define Hangul_TBase 0x11a7 | ||
66 | #define Hangul_SCount 11172 | ||
67 | #define Hangul_LCount 19 | ||
68 | #define Hangul_VCount 21 | ||
69 | #define Hangul_TCount 28 | ||
70 | #define Hangul_NCount (Hangul_VCount * Hangul_TCount) | ||
71 | |||
72 | |||
73 | static u16 *hfsplus_compose_lookup(u16 *p, u16 cc) | ||
74 | { | ||
75 | int i, s, e; | ||
76 | |||
77 | s = 1; | ||
78 | e = p[1]; | ||
79 | if (!e || cc < p[s * 2] || cc > p[e * 2]) | ||
80 | return NULL; | ||
81 | do { | ||
82 | i = (s + e) / 2; | ||
83 | if (cc > p[i * 2]) | ||
84 | s = i + 1; | ||
85 | else if (cc < p[i * 2]) | ||
86 | e = i - 1; | ||
87 | else | ||
88 | return hfsplus_compose_table + p[i * 2 + 1]; | ||
89 | } while (s <= e); | ||
90 | return NULL; | ||
91 | } | ||
92 | |||
93 | int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, char *astr, int *len_p) | ||
94 | { | ||
95 | const hfsplus_unichr *ip; | ||
96 | struct nls_table *nls = HFSPLUS_SB(sb).nls; | ||
97 | u8 *op; | ||
98 | u16 cc, c0, c1; | ||
99 | u16 *ce1, *ce2; | ||
100 | int i, len, ustrlen, res, compose; | ||
101 | |||
102 | op = astr; | ||
103 | ip = ustr->unicode; | ||
104 | ustrlen = be16_to_cpu(ustr->length); | ||
105 | len = *len_p; | ||
106 | ce1 = NULL; | ||
107 | compose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); | ||
108 | |||
109 | while (ustrlen > 0) { | ||
110 | c0 = be16_to_cpu(*ip++); | ||
111 | ustrlen--; | ||
112 | /* search for single decomposed char */ | ||
113 | if (likely(compose)) | ||
114 | ce1 = hfsplus_compose_lookup(hfsplus_compose_table, c0); | ||
115 | if (ce1 && (cc = ce1[0])) { | ||
116 | /* start of a possibly decomposed Hangul char */ | ||
117 | if (cc != 0xffff) | ||
118 | goto done; | ||
119 | if (!ustrlen) | ||
120 | goto same; | ||
121 | c1 = be16_to_cpu(*ip) - Hangul_VBase; | ||
122 | if (c1 < Hangul_VCount) { | ||
123 | /* compose the Hangul char */ | ||
124 | cc = (c0 - Hangul_LBase) * Hangul_VCount; | ||
125 | cc = (cc + c1) * Hangul_TCount; | ||
126 | cc += Hangul_SBase; | ||
127 | ip++; | ||
128 | ustrlen--; | ||
129 | if (!ustrlen) | ||
130 | goto done; | ||
131 | c1 = be16_to_cpu(*ip) - Hangul_TBase; | ||
132 | if (c1 > 0 && c1 < Hangul_TCount) { | ||
133 | cc += c1; | ||
134 | ip++; | ||
135 | ustrlen--; | ||
136 | } | ||
137 | goto done; | ||
138 | } | ||
139 | } | ||
140 | while (1) { | ||
141 | /* main loop for common case of not composed chars */ | ||
142 | if (!ustrlen) | ||
143 | goto same; | ||
144 | c1 = be16_to_cpu(*ip); | ||
145 | if (likely(compose)) | ||
146 | ce1 = hfsplus_compose_lookup(hfsplus_compose_table, c1); | ||
147 | if (ce1) | ||
148 | break; | ||
149 | switch (c0) { | ||
150 | case 0: | ||
151 | c0 = 0x2400; | ||
152 | break; | ||
153 | case '/': | ||
154 | c0 = ':'; | ||
155 | break; | ||
156 | } | ||
157 | res = nls->uni2char(c0, op, len); | ||
158 | if (res < 0) { | ||
159 | if (res == -ENAMETOOLONG) | ||
160 | goto out; | ||
161 | *op = '?'; | ||
162 | res = 1; | ||
163 | } | ||
164 | op += res; | ||
165 | len -= res; | ||
166 | c0 = c1; | ||
167 | ip++; | ||
168 | ustrlen--; | ||
169 | } | ||
170 | ce2 = hfsplus_compose_lookup(ce1, c0); | ||
171 | if (ce2) { | ||
172 | i = 1; | ||
173 | while (i < ustrlen) { | ||
174 | ce1 = hfsplus_compose_lookup(ce2, be16_to_cpu(ip[i])); | ||
175 | if (!ce1) | ||
176 | break; | ||
177 | i++; | ||
178 | ce2 = ce1; | ||
179 | } | ||
180 | if ((cc = ce2[0])) { | ||
181 | ip += i; | ||
182 | ustrlen -= i; | ||
183 | goto done; | ||
184 | } | ||
185 | } | ||
186 | same: | ||
187 | switch (c0) { | ||
188 | case 0: | ||
189 | cc = 0x2400; | ||
190 | break; | ||
191 | case '/': | ||
192 | cc = ':'; | ||
193 | break; | ||
194 | default: | ||
195 | cc = c0; | ||
196 | } | ||
197 | done: | ||
198 | res = nls->uni2char(cc, op, len); | ||
199 | if (res < 0) { | ||
200 | if (res == -ENAMETOOLONG) | ||
201 | goto out; | ||
202 | *op = '?'; | ||
203 | res = 1; | ||
204 | } | ||
205 | op += res; | ||
206 | len -= res; | ||
207 | } | ||
208 | res = 0; | ||
209 | out: | ||
210 | *len_p = (char *)op - astr; | ||
211 | return res; | ||
212 | } | ||
213 | |||
214 | int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr, const char *astr, int len) | ||
215 | { | ||
216 | struct nls_table *nls = HFSPLUS_SB(sb).nls; | ||
217 | int size, off, decompose; | ||
218 | wchar_t c; | ||
219 | u16 outlen = 0; | ||
220 | |||
221 | decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); | ||
222 | |||
223 | while (outlen < HFSPLUS_MAX_STRLEN && len > 0) { | ||
224 | size = nls->char2uni(astr, len, &c); | ||
225 | if (size <= 0) { | ||
226 | c = '?'; | ||
227 | size = 1; | ||
228 | } | ||
229 | astr += size; | ||
230 | len -= size; | ||
231 | switch (c) { | ||
232 | case 0x2400: | ||
233 | c = 0; | ||
234 | break; | ||
235 | case ':': | ||
236 | c = '/'; | ||
237 | break; | ||
238 | } | ||
239 | if (c >= 0xc0 && decompose) { | ||
240 | off = hfsplus_decompose_table[(c >> 12) & 0xf]; | ||
241 | if (!off) | ||
242 | goto done; | ||
243 | if (off == 0xffff) { | ||
244 | goto done; | ||
245 | } | ||
246 | off = hfsplus_decompose_table[off + ((c >> 8) & 0xf)]; | ||
247 | if (!off) | ||
248 | goto done; | ||
249 | off = hfsplus_decompose_table[off + ((c >> 4) & 0xf)]; | ||
250 | if (!off) | ||
251 | goto done; | ||
252 | off = hfsplus_decompose_table[off + (c & 0xf)]; | ||
253 | size = off & 3; | ||
254 | if (!size) | ||
255 | goto done; | ||
256 | off /= 4; | ||
257 | if (outlen + size > HFSPLUS_MAX_STRLEN) | ||
258 | break; | ||
259 | do { | ||
260 | ustr->unicode[outlen++] = cpu_to_be16(hfsplus_decompose_table[off++]); | ||
261 | } while (--size > 0); | ||
262 | continue; | ||
263 | } | ||
264 | done: | ||
265 | ustr->unicode[outlen++] = cpu_to_be16(c); | ||
266 | } | ||
267 | ustr->length = cpu_to_be16(outlen); | ||
268 | if (len > 0) | ||
269 | return -ENAMETOOLONG; | ||
270 | return 0; | ||
271 | } | ||
diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c new file mode 100644 index 000000000000..0c51d6338b0b --- /dev/null +++ b/fs/hfsplus/wrapper.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /* | ||
2 | * linux/fs/hfsplus/wrapper.c | ||
3 | * | ||
4 | * Copyright (C) 2001 | ||
5 | * Brad Boyer (flar@allandria.com) | ||
6 | * (C) 2003 Ardis Technologies <roman@ardistech.com> | ||
7 | * | ||
8 | * Handling of HFS wrappers around HFS+ volumes | ||
9 | */ | ||
10 | |||
11 | #include <linux/fs.h> | ||
12 | #include <linux/blkdev.h> | ||
13 | #include <linux/cdrom.h> | ||
14 | #include <linux/genhd.h> | ||
15 | #include <linux/version.h> | ||
16 | #include <asm/unaligned.h> | ||
17 | |||
18 | #include "hfsplus_fs.h" | ||
19 | #include "hfsplus_raw.h" | ||
20 | |||
21 | struct hfsplus_wd { | ||
22 | u32 ablk_size; | ||
23 | u16 ablk_start; | ||
24 | u16 embed_start; | ||
25 | u16 embed_count; | ||
26 | }; | ||
27 | |||
28 | static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd) | ||
29 | { | ||
30 | u32 extent; | ||
31 | u16 attrib; | ||
32 | |||
33 | if (be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG)) != HFSPLUS_VOLHEAD_SIG) | ||
34 | return 0; | ||
35 | |||
36 | attrib = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ATTRIB)); | ||
37 | if (!(attrib & HFSP_WRAP_ATTRIB_SLOCK) || | ||
38 | !(attrib & HFSP_WRAP_ATTRIB_SPARED)) | ||
39 | return 0; | ||
40 | |||
41 | wd->ablk_size = be32_to_cpu(*(__be32 *)(bufptr + HFSP_WRAPOFF_ABLKSIZE)); | ||
42 | if (wd->ablk_size < HFSPLUS_SECTOR_SIZE) | ||
43 | return 0; | ||
44 | if (wd->ablk_size % HFSPLUS_SECTOR_SIZE) | ||
45 | return 0; | ||
46 | wd->ablk_start = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ABLKSTART)); | ||
47 | |||
48 | extent = be32_to_cpu(get_unaligned((__be32 *)(bufptr + HFSP_WRAPOFF_EMBEDEXT))); | ||
49 | wd->embed_start = (extent >> 16) & 0xFFFF; | ||
50 | wd->embed_count = extent & 0xFFFF; | ||
51 | |||
52 | return 1; | ||
53 | } | ||
54 | |||
55 | static int hfsplus_get_last_session(struct super_block *sb, | ||
56 | sector_t *start, sector_t *size) | ||
57 | { | ||
58 | struct cdrom_multisession ms_info; | ||
59 | struct cdrom_tocentry te; | ||
60 | int res; | ||
61 | |||
62 | /* default values */ | ||
63 | *start = 0; | ||
64 | *size = sb->s_bdev->bd_inode->i_size >> 9; | ||
65 | |||
66 | if (HFSPLUS_SB(sb).session >= 0) { | ||
67 | te.cdte_track = HFSPLUS_SB(sb).session; | ||
68 | te.cdte_format = CDROM_LBA; | ||
69 | res = ioctl_by_bdev(sb->s_bdev, CDROMREADTOCENTRY, (unsigned long)&te); | ||
70 | if (!res && (te.cdte_ctrl & CDROM_DATA_TRACK) == 4) { | ||
71 | *start = (sector_t)te.cdte_addr.lba << 2; | ||
72 | return 0; | ||
73 | } | ||
74 | printk(KERN_ERR "HFS: Invalid session number or type of track\n"); | ||
75 | return -EINVAL; | ||
76 | } | ||
77 | ms_info.addr_format = CDROM_LBA; | ||
78 | res = ioctl_by_bdev(sb->s_bdev, CDROMMULTISESSION, (unsigned long)&ms_info); | ||
79 | if (!res && ms_info.xa_flag) | ||
80 | *start = (sector_t)ms_info.addr.lba << 2; | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | /* Find the volume header and fill in some minimum bits in superblock */ | ||
85 | /* Takes in super block, returns true if good data read */ | ||
86 | int hfsplus_read_wrapper(struct super_block *sb) | ||
87 | { | ||
88 | struct buffer_head *bh; | ||
89 | struct hfsplus_vh *vhdr; | ||
90 | struct hfsplus_wd wd; | ||
91 | sector_t part_start, part_size; | ||
92 | u32 blocksize; | ||
93 | |||
94 | blocksize = sb_min_blocksize(sb, HFSPLUS_SECTOR_SIZE); | ||
95 | if (!blocksize) | ||
96 | return -EINVAL; | ||
97 | |||
98 | if (hfsplus_get_last_session(sb, &part_start, &part_size)) | ||
99 | return -EINVAL; | ||
100 | while (1) { | ||
101 | bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr); | ||
102 | if (!bh) | ||
103 | return -EIO; | ||
104 | |||
105 | if (vhdr->signature == cpu_to_be16(HFSP_WRAP_MAGIC)) { | ||
106 | if (!hfsplus_read_mdb(vhdr, &wd)) | ||
107 | goto error; | ||
108 | wd.ablk_size >>= HFSPLUS_SECTOR_SHIFT; | ||
109 | part_start += wd.ablk_start + wd.embed_start * wd.ablk_size; | ||
110 | part_size = wd.embed_count * wd.ablk_size; | ||
111 | brelse(bh); | ||
112 | bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr); | ||
113 | if (!bh) | ||
114 | return -EIO; | ||
115 | } | ||
116 | if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG)) | ||
117 | break; | ||
118 | brelse(bh); | ||
119 | |||
120 | /* check for a partition block | ||
121 | * (should do this only for cdrom/loop though) | ||
122 | */ | ||
123 | if (hfs_part_find(sb, &part_start, &part_size)) | ||
124 | return -EINVAL; | ||
125 | } | ||
126 | |||
127 | blocksize = be32_to_cpu(vhdr->blocksize); | ||
128 | brelse(bh); | ||
129 | |||
130 | /* block size must be at least as large as a sector | ||
131 | * and a multiple of 2 | ||
132 | */ | ||
133 | if (blocksize < HFSPLUS_SECTOR_SIZE || | ||
134 | ((blocksize - 1) & blocksize)) | ||
135 | return -EINVAL; | ||
136 | HFSPLUS_SB(sb).alloc_blksz = blocksize; | ||
137 | HFSPLUS_SB(sb).alloc_blksz_shift = 0; | ||
138 | while ((blocksize >>= 1) != 0) | ||
139 | HFSPLUS_SB(sb).alloc_blksz_shift++; | ||
140 | blocksize = min(HFSPLUS_SB(sb).alloc_blksz, (u32)PAGE_SIZE); | ||
141 | |||
142 | /* align block size to block offset */ | ||
143 | while (part_start & ((blocksize >> HFSPLUS_SECTOR_SHIFT) - 1)) | ||
144 | blocksize >>= 1; | ||
145 | |||
146 | if (sb_set_blocksize(sb, blocksize) != blocksize) { | ||
147 | printk("HFS+: unable to blocksize to %u!\n", blocksize); | ||
148 | return -EINVAL; | ||
149 | } | ||
150 | |||
151 | HFSPLUS_SB(sb).blockoffset = part_start >> | ||
152 | (sb->s_blocksize_bits - HFSPLUS_SECTOR_SHIFT); | ||
153 | HFSPLUS_SB(sb).sect_count = part_size; | ||
154 | HFSPLUS_SB(sb).fs_shift = HFSPLUS_SB(sb).alloc_blksz_shift - | ||
155 | sb->s_blocksize_bits; | ||
156 | |||
157 | bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr); | ||
158 | if (!bh) | ||
159 | return -EIO; | ||
160 | |||
161 | /* should still be the same... */ | ||
162 | if (be16_to_cpu(vhdr->signature) != HFSPLUS_VOLHEAD_SIG) | ||
163 | goto error; | ||
164 | HFSPLUS_SB(sb).s_vhbh = bh; | ||
165 | HFSPLUS_SB(sb).s_vhdr = vhdr; | ||
166 | |||
167 | return 0; | ||
168 | error: | ||
169 | brelse(bh); | ||
170 | return -EINVAL; | ||
171 | } | ||