aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /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/Makefile9
-rw-r--r--fs/hfsplus/bfind.c210
-rw-r--r--fs/hfsplus/bitmap.c221
-rw-r--r--fs/hfsplus/bnode.c662
-rw-r--r--fs/hfsplus/brec.c491
-rw-r--r--fs/hfsplus/btree.c319
-rw-r--r--fs/hfsplus/catalog.c358
-rw-r--r--fs/hfsplus/dir.c484
-rw-r--r--fs/hfsplus/extents.c505
-rw-r--r--fs/hfsplus/hfsplus_fs.h414
-rw-r--r--fs/hfsplus/hfsplus_raw.h326
-rw-r--r--fs/hfsplus/inode.c555
-rw-r--r--fs/hfsplus/ioctl.c188
-rw-r--r--fs/hfsplus/options.c162
-rw-r--r--fs/hfsplus/part_tbl.c133
-rw-r--r--fs/hfsplus/super.c502
-rw-r--r--fs/hfsplus/tables.c3245
-rw-r--r--fs/hfsplus/unicode.c271
-rw-r--r--fs/hfsplus/wrapper.c171
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
5obj-$(CONFIG_HFSPLUS_FS) += hfsplus.o
6
7hfsplus-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
14int 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
30void 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...)*/
40int __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 }
73done:
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 */
84int 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
129invalid:
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;
133release:
134 hfs_bnode_put(bnode);
135 return res;
136}
137
138int 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
151int 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);
207out:
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
18int 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
87found:
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 }
128last:
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 }
137done:
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);
145out:
146 up(&HFSPLUS_SB(sb).alloc_file->i_sem);
147 return start;
148}
149
150int 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 }
207done:
208 /* do any partial u32 at end */
209 if (count) {
210 mask = 0xffffffffU >> count;
211 *curr &= cpu_to_be32(mask);
212 }
213out:
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 */
24void 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
45u16 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
53u8 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
61void 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
76void 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
99void 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
106void 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
128void 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
188void 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
297void 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
333void 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
373static 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
380struct 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
398static 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;
460fail:
461 set_bit(HFS_BNODE_ERROR, &node->flags);
462 return node;
463}
464
465void 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 */
481struct 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
556node_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
564void 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
574struct 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
611void 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 */
628void 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
14static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd);
15static int hfs_brec_update_parent(struct hfs_find_data *fd);
16static int hfs_btree_inc_height(struct hfs_btree *);
17
18/* Get the length and offset of the given record in the given node */
19u16 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 */
31u16 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
53int 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;
73again:
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
117skip:
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
163int 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;
171again:
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);
209skip:
210 hfs_bnode_dump(node);
211 if (!fd->record)
212 hfs_brec_update_parent(fd);
213 return 0;
214}
215
216static 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
325static 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
339again:
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);
386skip:
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;
416out:
417 fd->bnode = node;
418 return 0;
419}
420
421static 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 */
19struct 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 */
90void 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
112void 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
140static 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
173struct 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
262void 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
16int 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
28void 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
44static 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
57static 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
74static 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
116static 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 */
128int 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
151int 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
196err1:
197 hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
198 if (!hfs_brec_find(&fd))
199 hfs_brec_remove(&fd);
200err2:
201 hfs_find_exit(&fd);
202 return err;
203}
204
205int 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);
275out:
276 hfs_find_exit(&fd);
277
278 return err;
279}
280
281int 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);
354out:
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
21static 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 */
29static 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);
44again:
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;
98out:
99 d_add(dentry, inode);
100 return NULL;
101fail:
102 hfs_find_exit(&fd);
103 return ERR_PTR(err);
104}
105
106static 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));
216out:
217 hfs_find_exit(&fd);
218 return err;
219}
220
221static 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
231static 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
253static 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
306static 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
350static 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
371static 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
389static 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
420static 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
446static 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
466struct 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
478struct 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 */
20int 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
40static 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
50static 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
65static 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
75static 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
86static 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
106void 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
117static 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
137static 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
156static 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 */
172int 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
213done:
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
227static 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
238static 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
266static 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;
284found:
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
306int 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
345int 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 }
411out:
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
419insert_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
435void 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;
500out:
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
40typedef int (*btree_keycmp)(hfsplus_btree_key *, hfsplus_btree_key *);
41
42#define NODE_HASH_SIZE 256
43
44/* An HFS+ BTree held in memory */
45struct 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
73struct page;
74
75/* An HFS+ BTree node in memory */
76struct 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
106struct hfsplus_vh;
107struct hfs_btree;
108
109struct 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
157struct 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
189struct 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
202struct 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 */
263int hfsplus_block_allocate(struct super_block *, u32, u32, u32 *);
264int hfsplus_block_free(struct super_block *, u32, u32);
265
266/* btree.c */
267struct hfs_btree *hfs_btree_open(struct super_block *, u32);
268void hfs_btree_close(struct hfs_btree *);
269void hfs_btree_write(struct hfs_btree *);
270struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *);
271void hfs_bmap_free(struct hfs_bnode *);
272
273/* bnode.c */
274void hfs_bnode_read(struct hfs_bnode *, void *, int, int);
275u16 hfs_bnode_read_u16(struct hfs_bnode *, int);
276u8 hfs_bnode_read_u8(struct hfs_bnode *, int);
277void hfs_bnode_read_key(struct hfs_bnode *, void *, int);
278void hfs_bnode_write(struct hfs_bnode *, void *, int, int);
279void hfs_bnode_write_u16(struct hfs_bnode *, int, u16);
280void hfs_bnode_clear(struct hfs_bnode *, int, int);
281void hfs_bnode_copy(struct hfs_bnode *, int,
282 struct hfs_bnode *, int, int);
283void hfs_bnode_move(struct hfs_bnode *, int, int, int);
284void hfs_bnode_dump(struct hfs_bnode *);
285void hfs_bnode_unlink(struct hfs_bnode *);
286struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *, u32);
287struct hfs_bnode *hfs_bnode_find(struct hfs_btree *, u32);
288void hfs_bnode_unhash(struct hfs_bnode *);
289void hfs_bnode_free(struct hfs_bnode *);
290struct hfs_bnode *hfs_bnode_create(struct hfs_btree *, u32);
291void hfs_bnode_get(struct hfs_bnode *);
292void hfs_bnode_put(struct hfs_bnode *);
293
294/* brec.c */
295u16 hfs_brec_lenoff(struct hfs_bnode *, u16, u16 *);
296u16 hfs_brec_keylen(struct hfs_bnode *, u16);
297int hfs_brec_insert(struct hfs_find_data *, void *, int);
298int hfs_brec_remove(struct hfs_find_data *);
299
300/* bfind.c */
301int hfs_find_init(struct hfs_btree *, struct hfs_find_data *);
302void hfs_find_exit(struct hfs_find_data *);
303int __hfs_brec_find(struct hfs_bnode *, struct hfs_find_data *);
304int hfs_brec_find(struct hfs_find_data *);
305int hfs_brec_read(struct hfs_find_data *, void *, int);
306int hfs_brec_goto(struct hfs_find_data *, int);
307
308/* catalog.c */
309int hfsplus_cat_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *);
310void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *, u32, struct qstr *);
311int hfsplus_find_cat(struct super_block *, u32, struct hfs_find_data *);
312int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *);
313int hfsplus_delete_cat(u32, struct inode *, struct qstr *);
314int hfsplus_rename_cat(u32, struct inode *, struct qstr *,
315 struct inode *, struct qstr *);
316
317/* extents.c */
318int hfsplus_ext_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *);
319void hfsplus_ext_write_extent(struct inode *);
320int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int);
321int hfsplus_free_fork(struct super_block *, u32, struct hfsplus_fork_raw *, int);
322int hfsplus_file_extend(struct inode *);
323void hfsplus_file_truncate(struct inode *);
324
325/* inode.c */
326extern struct address_space_operations hfsplus_aops;
327extern struct address_space_operations hfsplus_btree_aops;
328
329void hfsplus_inode_read_fork(struct inode *, struct hfsplus_fork_raw *);
330void hfsplus_inode_write_fork(struct inode *, struct hfsplus_fork_raw *);
331int hfsplus_cat_read_inode(struct inode *, struct hfs_find_data *);
332int hfsplus_cat_write_inode(struct inode *);
333struct inode *hfsplus_new_inode(struct super_block *, int);
334void hfsplus_delete_inode(struct inode *);
335
336/* ioctl.c */
337int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
338 unsigned long arg);
339int hfsplus_setxattr(struct dentry *dentry, const char *name,
340 const void *value, size_t size, int flags);
341ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
342 void *value, size_t size);
343ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size);
344
345/* options.c */
346int parse_options(char *, struct hfsplus_sb_info *);
347void fill_defaults(struct hfsplus_sb_info *);
348
349/* tables.c */
350extern u16 hfsplus_case_fold_table[];
351extern u16 hfsplus_decompose_table[];
352extern u16 hfsplus_compose_table[];
353
354/* unicode.c */
355int hfsplus_unistrcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
356int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *);
357int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int);
358
359/* wrapper.c */
360int hfsplus_read_wrapper(struct super_block *);
361
362int hfs_part_find(struct super_block *, sector_t *, sector_t *);
363
364/* access macros */
365/*
366static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb)
367{
368 return sb->s_fs_info;
369}
370static 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
48typedef __be32 hfsplus_cnid;
49typedef __be16 hfsplus_unichr;
50
51/* A "string" as used in filenames, etc. */
52struct hfsplus_unistr {
53 __be16 length;
54 hfsplus_unichr unicode[255];
55} __packed;
56
57#define HFSPLUS_MAX_STRLEN 255
58
59/* POSIX permissions */
60struct 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 */
74struct hfsplus_extent {
75 __be32 start_block;
76 __be32 block_count;
77} __packed;
78typedef struct hfsplus_extent hfsplus_extent_rec[8];
79
80/* Information for a "Fork" in a file */
81struct 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 */
89struct 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 */
133struct 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 */
149struct 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 */
188struct 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 */
196struct hfsp_point {
197 __be16 v;
198 __be16 h;
199} __packed;
200
201struct 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 */
210struct DInfo {
211 struct hfsp_rect frRect;
212 __be16 frFlags;
213 struct hfsp_point frLocation;
214 __be16 frView;
215} __packed;
216
217struct 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) */
226struct 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) */
244struct FInfo {
245 __be32 fdType;
246 __be32 fdCreator;
247 __be16 fdFlags;
248 struct hfsp_point fdLocation;
249 __be16 fdFldr;
250} __packed;
251
252struct 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) */
260struct 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) */
285struct 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 */
295typedef 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 */
309struct 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 */
320typedef 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
20static 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
26static 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
32static 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
38static sector_t hfsplus_bmap(struct address_space *mapping, sector_t block)
39{
40 return generic_block_bmap(mapping, block, hfsplus_get_block);
41}
42
43static 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
100static 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
111static 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
121static int hfsplus_writepages(struct address_space *mapping,
122 struct writeback_control *wbc)
123{
124 return mpage_writepages(mapping, wbc, hfsplus_get_block);
125}
126
127struct 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
137struct 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
148static 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 }
191out:
192 d_add(dentry, inode);
193 return NULL;
194}
195
196static 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
232static 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
249static 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
261static 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
271static 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
291extern struct inode_operations hfsplus_dir_inode_operations;
292extern struct file_operations hfsplus_dir_operations;
293
294static 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
303static 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
315struct 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
371void 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
393void 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
418void 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
426int 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
487int 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 }
552out:
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
21int 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
85int 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));
122out:
123 hfs_find_exit(&fd);
124 return res;
125}
126
127ssize_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;
165out:
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
173ssize_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
18enum {
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
26static 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 */
41void 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 */
56static 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 */
66int 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
151done:
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 */
37struct 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 */
59struct 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 */
74int 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
21static struct inode *hfsplus_alloc_inode(struct super_block *sb);
22static void hfsplus_destroy_inode(struct inode *inode);
23
24#include "hfsplus_fs.h"
25
26void 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
41static 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
98static 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
155static 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
166static 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
208static 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
231static 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
245static 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
266static 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
278static 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 }
424out:
425 unload_nls(sbi->nls);
426 sbi->nls = nls;
427 return 0;
428
429cleanup:
430 hfsplus_put_super(sb);
431 if (nls)
432 unload_nls(nls);
433 return err;
434}
435
436MODULE_AUTHOR("Brad Boyer");
437MODULE_DESCRIPTION("Extended Macintosh Filesystem");
438MODULE_LICENSE("GPL");
439
440static kmem_cache_t *hfsplus_inode_cachep;
441
442static 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
450static 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
457static 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
463static 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
471static 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
479static 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
494static 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
501module_init(init_hfsplus_fs)
502module_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
14u16 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
410u16 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
1071u16 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 */
18static 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 */
31int 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
73static 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
93int 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;
209out:
210 *len_p = (char *)op - astr;
211 return res;
212}
213
214int 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
21struct hfsplus_wd {
22 u32 ablk_size;
23 u16 ablk_start;
24 u16 embed_start;
25 u16 embed_count;
26};
27
28static 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
55static 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 */
86int 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}