]> git.pld-linux.org Git - packages/kernel.git/blame - hfsplus-20011213.patch
- added description of djurban's branch
[packages/kernel.git] / hfsplus-20011213.patch
CommitLineData
1eec6804 1diff -urN -x CVS linux-bk/Documentation/Configure.help linux-hfsplus/Documentation/Configure.help
2--- linux-bk/Documentation/Configure.help Sun Mar 4 16:18:35 2001
3+++ linux-hfsplus/Documentation/Configure.help Sat Sep 15 17:03:12 2001
4@@ -11383,6 +11383,24 @@
5 compile it as a module, say M here and read
6 Documentation/modules.txt.
7
8+Apple Extended file system support (read-only) (EXPERIMENTAL)
9+CONFIG_HFSPLUS_FS
10+ If you say Y here, you will be able to mount extended format
11+ Macintosh-formatted hard drive partitions with read-only access.
12+ Most of the UNIX related filesystem data saved by Mac OSX should
13+ be readable.
14+
15+ This file system is often called HFS+ and was introduced with
16+ MacOS 8. It includes all Mac specific filesystem data such as
17+ data forks and creator codes, but it also has several UNIX
18+ style features such as file ownership and permissions. No Mac
19+ specific data can currently be accessed with this driver.
20+
21+ This file system is also available as a module ( = code which can
22+ be inserted in and removed from the running kernel whenever you
23+ want). The module is called hfsplus.o. If you want to compile it
24+ as a module, say M here and read Documentation/modules.txt.
25+
26 ROM file system support
27 CONFIG_ROMFS_FS
28 This is a very small read-only file system mainly intended for
29diff -urN -x CVS linux-bk/MAINTAINERS linux-hfsplus/MAINTAINERS
30--- linux-bk/MAINTAINERS Sun Mar 4 16:18:16 2001
31+++ linux-hfsplus/MAINTAINERS Sat Sep 15 17:03:52 2001
32@@ -503,6 +503,12 @@
33 L: linux-kernel@vger.kernel.org
34 S: Maintained
35
36+HFSPLUS FILESYSTEM
37+P: Brad Boyer
38+M: flar@allandria.com
39+W: http://sourceforge.net/projects/linux-hfsplus/
40+S: Maintained
41+
42 HGA FRAMEBUFFER DRIVER
43 P: Ferenc Bakonyi
44 M: fero@drama.obuda.kando.hu
45diff -urN -x CVS linux-bk/fs/Config.in linux-hfsplus/fs/Config.in
46--- linux-bk/fs/Config.in Sun Mar 4 16:26:05 2001
47+++ linux-hfsplus/fs/Config.in Tue Apr 10 22:48:28 2001
48@@ -18,6 +18,8 @@
49
50 dep_tristate 'Apple Macintosh file system support (EXPERIMENTAL)' CONFIG_HFS_FS $CONFIG_EXPERIMENTAL
51
52+dep_tristate 'Apple Extended HFS file system support (EXPERIMENTAL)' CONFIG_HFSPLUS_FS $CONFIG_EXPERIMENTAL
53+
54 dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
55
56 # msdos file systems
57diff -urN -x CVS linux-bk/fs/Makefile linux-hfsplus/fs/Makefile
58--- linux-bk/fs/Makefile Sun Mar 4 16:26:05 2001
59+++ linux-hfsplus/fs/Makefile Tue Apr 10 22:48:28 2001
60@@ -38,6 +38,7 @@
61 subdir-$(CONFIG_ISO9660_FS) += isofs
62 subdir-$(CONFIG_DEVFS_FS) += devfs
63 subdir-$(CONFIG_HFS_FS) += hfs
64+subdir-$(CONFIG_HFSPLUS_FS) += hfsplus
600b3a7c 65 subdir-$(CONFIG_VXFS_FS) += freevxfs
1eec6804 66 subdir-$(CONFIG_NFS_FS) += nfs
67 subdir-$(CONFIG_NFSD) += nfsd
68diff -urN -x CVS linux-bk/fs/hfsplus/Makefile linux-hfsplus/fs/hfsplus/Makefile
69--- linux-bk/fs/hfsplus/Makefile Wed Dec 31 16:00:00 1969
70+++ linux-hfsplus/fs/hfsplus/Makefile Fri Sep 21 00:42:03 2001
71@@ -0,0 +1,17 @@
72+#
73+# Makefile for the Linux hfsplus filesystem routines.
74+#
75+# Note! Dependencies are done automagically by 'make dep', which also
76+# removes any old dependencies. DON'T put your own dependencies here
77+# unless it's something special (not a .c file).
78+#
79+# Note 2! The CFLAGS definitions are now in the main makefile.
80+
81+O_TARGET := hfsplus.o
82+
83+obj-y := super.o options.o inode.o extents.o catalog.o dir.o btree.o \
84+ bnode.o brec.o bfind.o btiter.o tables.o unicode.o wrapper.o
85+
86+obj-m := $(O_TARGET)
87+
88+include $(TOPDIR)/Rules.make
89diff -urN -x CVS linux-bk/fs/hfsplus/bfind.c linux-hfsplus/fs/hfsplus/bfind.c
90--- linux-bk/fs/hfsplus/bfind.c Wed Dec 31 16:00:00 1969
91+++ linux-hfsplus/fs/hfsplus/bfind.c Mon Nov 5 00:09:43 2001
92@@ -0,0 +1,236 @@
93+/*
94+ * linux/fs/hfsplus/bfind.c
95+ *
96+ * Copyright (C) 2001
97+ * Brad Boyer (flar@allandria.com)
98+ *
99+ * Search routines for btrees
100+ */
101+
102+#include <linux/hfsplus_fs.h>
103+
104+/* Find the record in bnode that best matches key (not greater than...)*/
105+static hfsp_u16 hfsplus_find_rec(hfsplus_bnode *bnode, hfsplus_btree_key *key,
106+ int *error)
107+{
108+ hfsplus_btree_key tmpkey;
109+ int cmpval;
110+ hfsp_u16 b, m, e, keylen;
111+
112+ b = 0;
113+ e = bnode->num_recs - 1;
114+ *error = 0;
115+ while(b <= e) {
116+ m = (e + b) / 2;
117+ keylen = hfsplus_brec_key(bnode, m, &tmpkey, sizeof(tmpkey));
118+ if(!keylen) {
119+ printk("HFS+-fs: missing key in B*Tree\n");
120+ *error = -EIO;
121+ return 0xFFFF;
122+ }
123+ cmpval = bnode->tree->keycmp(&tmpkey, key);
124+ if(!cmpval)
125+ return m;
126+ if(cmpval < 0) {
127+ b = m + 1;
128+ } else {
129+ e = m - 1;
130+ }
131+ }
132+ if(e == 0xFFFF) {
133+ *error = -ENOENT;
134+ return 0xFFFF;
135+ }
136+ return e;
137+}
138+
139+/* Traverse a B*Tree from the root to a leaf finding best fit to key */
140+/* Return allocated copy of node found, set recnum to best record */
141+static hfsplus_bnode *hfsplus_find_leaf(hfsplus_btree *tree,
142+ hfsplus_btree_key *key,
143+ hfsp_u16 *recnum, int *error)
144+{
145+ hfsplus_bnode *curr, *last, *retval;
146+ int localerr;
147+ hfsp_u32 next;
148+ hfsp_u16 rec, off, klen;
149+ hfsp_lword data;
150+
151+ *error = -EIO;
152+ last = retval = NULL;
153+ curr = hfsplus_get_bnode(tree, tree->root);
154+ if(!curr || !curr->height || (curr->height > tree->depth)) {
155+ printk("HFS+-fs: Found bad root node in B*Tree\n");
156+ return NULL;
157+ }
158+
159+ for(;;) {
160+ rec = hfsplus_find_rec(curr, key, &localerr);
161+ if(rec >= curr->num_recs) {
162+ if(localerr)
163+ *error = localerr;
164+ goto cleanup;
165+ }
166+ if(curr->kind == HFSPLUS_NODE_LEAF) {
167+ /* Found it */
168+ retval = curr;
169+ *recnum = rec;
170+ *error = 0;
171+ goto cleanup;
172+ }
173+ if(curr->kind != HFSPLUS_NODE_NDX) {
174+ printk("HFS+-fs: non-keyed B*Tree node in index\n");
175+ goto cleanup;
176+ }
177+ if(last) {
178+ hfsplus_put_bnode(last);
179+ last = NULL;
180+ }
181+
182+ klen = hfsplus_brec_keylen(curr, rec);
183+ if(!klen) {
184+ printk("HFS+-fs: bad index key in B*Tree\n");
185+ goto cleanup;
186+ }
187+ if(hfsplus_brec_lenoff(curr, rec, &off) < klen + 4) {
188+ printk("HFS+-fs: invalid index record in B*Tree\n");
189+ goto cleanup;
190+ }
191+ if(hfsplus_bnode_copybytes(curr, data, off + klen, 4) != 4) {
192+ printk("HFS+-fs: unable to follow index in B*Tree\n");
193+ goto cleanup;
194+ }
195+ next = hfsp_get_hl(data);
196+
197+ last = curr;
198+ curr = hfsplus_get_bnode(tree, next);
199+ if(!curr) {
200+ printk("HFS+-fs: failed to get next node in B*Tree\n");
201+ goto cleanup;
202+ }
203+ if(!curr->height || (curr->height != (last->height - 1))) {
204+ printk("HFS+-fs: inconsistency in B*Tree height\n");
205+ goto cleanup;
206+ }
207+ } /* end of for(;;) */
208+ cleanup:
209+ if(last && (last != retval))
210+ hfsplus_put_bnode(last);
211+ if(curr && (curr != retval))
212+ hfsplus_put_bnode(curr);
213+ return retval;
214+}
215+
216+/* take in tree, key to find, buffer, sizeof buffer */
217+/* return error code, set entry_len to actual value on success */
218+/* will only return an exact match */
219+int hfsplus_btfind_exact(hfsplus_btree *tree, hfsplus_btree_key *key,
220+ void *entry, int *entry_len)
221+{
222+ hfsplus_bnode *node;
223+ hfsplus_btree_key tmpkey;
224+ int err;
225+ hfsp_u16 rec, off, keylen, datalen;
226+
227+ if(!tree || !key || !entry || !entry_len)
228+ return -EIO;
229+
230+ node = hfsplus_find_leaf(tree, key, &rec, &err);
231+ if(!node)
232+ return err;
233+ err = -EIO;
234+ if(!(keylen = hfsplus_brec_key(node, rec, &tmpkey, sizeof(tmpkey)))) {
235+ printk("HFS+-fs: unable to read key from B*Tree record\n");
236+ goto out;
237+ }
238+ if(tree->keycmp(key, &tmpkey)) {
239+ err = -ENOENT;
240+ goto out;
241+ }
242+
243+ datalen = hfsplus_brec_lenoff(node, rec, &off) - keylen;
244+ if((datalen <= 0) || (datalen > *entry_len)) {
245+ printk("HFS+-fs: bad entry length in B*Tree\n");
246+ goto out;
247+ }
248+ if(!hfsplus_bnode_copybytes(node, entry, off + keylen, datalen)) {
249+ printk("HFS+-fs: unable to read record in B*Tree\n");
250+ goto out;
251+ }
252+ *entry_len = datalen;
253+ err = 0;
254+ out:
255+ hfsplus_put_bnode(node);
256+ return err;
257+}
258+
259+/* take in tree, key to find, buffer, sizeof buffer; return error code */
260+/* updates key to actual record found, updates length of actual entry */
261+/* will return largest key not greater than search key */
262+int hfsplus_btfind(hfsplus_btree *tree, hfsplus_btree_key *key, void *entry,
263+ int *entry_len)
264+{
265+ hfsplus_bnode *node;
266+ int err;
267+ hfsp_u16 rec, off, keylen, datalen;
268+
269+ if(!tree || !key || !entry || !entry_len)
270+ return -EIO;
271+
272+ node = hfsplus_find_leaf(tree, key, &rec, &err);
273+ if(!node)
274+ return err;
275+ err = -EIO;
276+ if(!(keylen = hfsplus_brec_keylen(node, rec))) {
277+ printk("HFS+-fs: unable to read key from B*Tree record\n");
278+ goto out;
279+ }
280+
281+ datalen = hfsplus_brec_lenoff(node, rec, &off) - keylen;
282+ if((datalen <= 0) || (datalen > *entry_len)) {
283+ printk("HFS+-fs: bad entry length in B*Tree\n");
284+ goto out;
285+ }
286+ if(!hfsplus_bnode_copybytes(node, key, off, keylen)) {
287+ printk("HFS+-fs: unable to copy key from B*Tree\n");
288+ goto out;
289+ }
290+ if(!hfsplus_bnode_copybytes(node, entry, off + keylen, datalen)) {
291+ printk("HFS+-fs: unable to read record in B*Tree\n");
292+ goto out;
293+ }
294+ *entry_len = datalen;
295+ err = 0;
296+ out:
297+ hfsplus_put_bnode(node);
298+ return err;
299+}
300+
301+int hfsplus_btiter_find(hfsplus_btiter *iter, hfsplus_btree_key *key)
302+{
303+ hfsplus_bnode *node;
304+ int err;
305+ hfsplus_btree_key tmpkey;
306+ hfsp_u16 rec, keylen;
307+
308+ if(!iter || !key || !iter->tree)
309+ return -EIO;
310+
311+ if((node = hfsplus_find_leaf(iter->tree, key, &rec, &err)) == NULL)
312+ return err;
313+ if(!(keylen = hfsplus_brec_key(node, rec, &tmpkey, sizeof(tmpkey)))) {
314+ printk("HFS+-fs: unable to read key from B*Tree record\n");
315+ err = -EIO;
316+ goto out;
317+ }
318+ if(node->tree->keycmp(key, &tmpkey)) {
319+ err = -ENOENT;
320+ goto out;
321+ }
322+ iter->node = node->this;
323+ iter->rec = rec;
324+ err = 0;
325+ out:
326+ hfsplus_put_bnode(node);
327+ return err;
328+}
329diff -urN -x CVS linux-bk/fs/hfsplus/bnode.c linux-hfsplus/fs/hfsplus/bnode.c
330--- linux-bk/fs/hfsplus/bnode.c Wed Dec 31 16:00:00 1969
331+++ linux-hfsplus/fs/hfsplus/bnode.c Mon Nov 5 00:07:58 2001
332@@ -0,0 +1,195 @@
333+/*
334+ * linux/fs/hfsplus/bnode.c
335+ *
336+ * Copyright (C) 2001
337+ * Brad Boyer (flar@allandria.com)
338+ *
339+ * Handle basic btree node operations
340+ */
341+
342+#include <linux/string.h>
343+#include <linux/slab.h>
344+#include <linux/pagemap.h>
345+#include <linux/fs.h>
346+#include <linux/hfsplus_fs.h>
347+#include <linux/hfsplus_raw.h>
348+
349+/* Convert a node, offset to page number in tree */
350+static inline unsigned long hfsplus_pagenum(hfsplus_bnode *node, hfsp_u16 off)
351+{
352+ return ((node->this * node->tree->node_size) + off) >> PAGE_SHIFT;
353+}
354+
355+/* Convert a node, offset to page offset */
356+static inline unsigned long hfsplus_pageoff(hfsplus_bnode *node, hfsp_u16 off)
357+{
358+ return ((node->this * node->tree->node_size) + off) & (PAGE_SIZE - 1);
359+}
360+
361+/* Dump a page we loaded with hfsplus_get_page */
362+static inline void hfsplus_put_page(hfsplus_bnode *node)
363+{
364+ if(node->page) {
365+ UnlockPage(node->page);
366+ kunmap(node->page);
367+ page_cache_release(node->page);
368+ node->page = NULL;
369+ }
370+}
371+
372+/* Get the give page associated with the inode */
373+static struct page *hfsplus_get_page(hfsplus_bnode *node, unsigned long n)
374+{
375+ struct address_space *mapping;
376+ struct page *page;
377+
378+ if(!node || !node->tree)
379+ return NULL;
380+
381+ if(!node->inode) {
382+ node->inode = iget(node->tree->sb, node->tree->cnid);
383+ if(!node->inode) {
384+ printk("HFS+-fs: Failed load of B*Tree data\n");
385+ return NULL;
386+ }
387+ }
388+ mapping = node->inode->i_mapping;
389+ if(node->page) {
390+ if(node->page->index == n) {
391+ page = node->page;
392+ goto check_page;
393+ }
394+ hfsplus_put_page(node);
395+ }
396+ page = read_cache_page(mapping, n, mapping->a_ops->readpage, NULL);
397+ if(!IS_ERR(page)) {
398+ lock_page(page);
399+ kmap(page);
400+ check_page:
401+ if(!Page_Uptodate(page))
402+ goto put_page;
403+ if(PageError(page))
404+ goto put_page;
405+ }
406+ node->page = page;
407+ return page;
408+ put_page:
409+ hfsplus_put_page(node);
410+ return NULL;
411+}
412+
413+/* Fill the node->page element for the given offset */
414+static inline struct page *hfsplus_fill_page(hfsplus_bnode *node, hfsp_u16 off)
415+{
416+ return hfsplus_get_page(node, hfsplus_pagenum(node, off));
417+}
418+
419+/* Copy a specified range of bytes from the raw data of a node */
420+hfsp_u16 hfsplus_bnode_copybytes(hfsplus_bnode *node, void *buf,
421+ hfsp_u16 off, hfsp_u16 len)
422+{
423+ char *kaddr;
424+
425+ if(hfsplus_pagenum(node, off) == hfsplus_pagenum(node, off+len-1)) {
426+ /* All on one page */
427+ if(!hfsplus_fill_page(node, off)) {
428+ return 0;
429+ }
430+ kaddr = (char *)page_address(node->page);
431+ memcpy(buf, kaddr + hfsplus_pageoff(node, off), len);
432+ } else {
433+ /* Multiple pages (should be rare) */
434+ unsigned long poff;
435+ size_t tocopy;
436+ hfsp_u16 curr = 0;
437+
438+ while(curr < len) {
439+ if(!hfsplus_fill_page(node, off + curr)) {
440+ return curr;
441+ }
442+ poff = hfsplus_pageoff(node, off + curr);
443+ tocopy = PAGE_SIZE - poff;
444+ if(curr + tocopy > len)
445+ tocopy = len - curr;
446+ kaddr = (char *)page_address(node->page);
447+ memcpy(buf + curr, kaddr + poff, tocopy);
448+ curr += tocopy;
449+ }
450+ }
451+
452+ return len;
453+}
454+
455+/* Check for valid kind/height pairs , return 0 for bad pairings */
456+static int hfsplus_check_kh(hfsplus_btree *tree, hfsp_u8 kind, hfsp_u8 height)
457+{
458+ if((kind == HFSPLUS_NODE_HEAD) || (kind == HFSPLUS_NODE_MAP)) {
459+ if(height != 0)
460+ goto hk_error;
461+ } else if(kind == HFSPLUS_NODE_LEAF) {
462+ if(height != 1)
463+ goto hk_error;
464+ } else if(kind == HFSPLUS_NODE_NDX) {
465+ if((height <= 1) || (height > tree->depth))
466+ goto hk_error;
467+ } else {
468+ printk("HFS+-fs: unknown node type in B*Tree\n");
469+ return 0;
470+ }
471+ return 1;
472+ hk_error:
473+ printk("HFS+-fs: corrupt node height in B*Tree\n");
474+ return 0;
475+}
476+
477+/* Load a particular node out of a tree */
478+hfsplus_bnode *hfsplus_get_bnode(hfsplus_btree *tree, hfsp_u32 num)
479+{
480+ hfsplus_bnode *node;
481+ hfsplus_btree_node_desc desc;
482+ hfsp_u16 bytes;
483+
484+ if(num >= tree->node_count) {
485+ printk("HFS+-fs: request for non-existent node in B*Tree\n");
486+ return NULL;
487+ }
488+
489+ node = kmalloc(sizeof(hfsplus_bnode), GFP_KERNEL);
490+ if(!node)
491+ return NULL;
492+ node->tree = tree;
493+ node->page = NULL;
494+ node->inode = NULL;
495+ node->this = num;
496+ bytes = hfsplus_bnode_copybytes(node, &desc, 0,
497+ sizeof(hfsplus_btree_node_desc));
498+ if(bytes != sizeof(hfsplus_btree_node_desc)) {
499+ printk("HFS+-fs: failed to read node descriptor in B*Tree\n");
500+ goto free_node;
501+ }
502+ node->prev = hfsp_get_hl(desc.prev);
503+ node->next = hfsp_get_hl(desc.next);
504+ node->num_recs = hfsp_get_hs(desc.num_rec);
505+ node->kind = desc.kind;
506+ node->height = desc.height;
507+ if(!hfsplus_check_kh(tree, desc.kind, desc.height))
508+ goto free_node;
509+ return node;
510+ free_node:
511+ kfree(node);
512+ return NULL;
513+}
514+
515+/* Dispose of resources used by a node */
516+void hfsplus_put_bnode(hfsplus_bnode *node)
517+{
518+ if(node) {
519+ if(node->page)
520+ hfsplus_put_page(node);
521+ if(node->inode) {
522+ iput(node->inode);
523+ node->inode = NULL;
524+ }
525+ kfree(node);
526+ }
527+}
528diff -urN -x CVS linux-bk/fs/hfsplus/brec.c linux-hfsplus/fs/hfsplus/brec.c
529--- linux-bk/fs/hfsplus/brec.c Wed Dec 31 16:00:00 1969
530+++ linux-hfsplus/fs/hfsplus/brec.c Mon Nov 5 00:09:43 2001
531@@ -0,0 +1,111 @@
532+/*
533+ * linux/fs/hfsplus/brec.c
534+ *
535+ * Copyright (C) 2001
536+ * Brad Boyer (flar@allandria.com)
537+ *
538+ * Handle individual btree records
539+ */
540+
541+#include <linux/hfsplus_fs.h>
542+#include <linux/hfsplus_raw.h>
543+
544+/* Get the offset of the given record in the given node */
545+hfsp_u16 hfsplus_brec_off(hfsplus_bnode *node, hfsp_u16 rec)
546+{
547+ hfsp_word retval;
548+ hfsp_u16 dataoff;
549+
550+ dataoff = node->tree->node_size - (rec + 1) * 2;
551+ if(hfsplus_bnode_copybytes(node, retval, dataoff, 2) != 2)
552+ return 0;
553+ return hfsp_get_hs(retval);
554+}
555+
556+/* Get the length of the given record in the given node */
557+hfsp_u16 hfsplus_brec_len(hfsplus_bnode *node, hfsp_u16 rec)
558+{
559+ unsigned char retval[4];
560+ hfsp_u16 dataoff;
561+
562+ dataoff = node->tree->node_size - (rec + 2) * 2;
563+ if(hfsplus_bnode_copybytes(node, retval, dataoff, 4) != 4)
564+ return 0;
565+ return hfsp_get_hs(retval) - hfsp_get_hs(retval + 2);
566+}
567+
568+/* Get the length and offset of the given record in the given node */
569+hfsp_u16 hfsplus_brec_lenoff(hfsplus_bnode *node, hfsp_u16 rec, hfsp_u16 *off)
570+{
571+ unsigned char retval[4];
572+ hfsp_u16 dataoff;
573+
574+ dataoff = node->tree->node_size - (rec + 2) * 2;
575+ if(hfsplus_bnode_copybytes(node, retval, dataoff, 4) != 4) {
576+ return 0;
577+ }
578+ *off = hfsp_get_hs(retval + 2);
579+ return hfsp_get_hs(retval) - *off;
580+}
581+
582+/* Copy a record from a node into a buffer, return the actual length */
583+hfsp_u16 hfsplus_brec_data(hfsplus_bnode *node, hfsp_u16 rec, char *buf,
584+ hfsp_u16 len)
585+{
586+ hfsp_u16 recoff, reclen, cplen;
587+
588+ reclen = hfsplus_brec_lenoff(node, rec, &recoff);
589+ if(!reclen)
590+ return 0;
591+ cplen = (reclen>len) ? len : reclen;
592+ if(hfsplus_bnode_copybytes(node, buf, recoff, cplen) != cplen)
593+ return 0;
594+ return reclen;
595+}
596+
597+/* Get the length of the key from a keyed record */
598+hfsp_u16 hfsplus_brec_keylen(hfsplus_bnode *node, hfsp_u16 rec)
599+{
600+ hfsp_u16 klsz, retval, recoff;
601+ unsigned char buf[2];
602+
603+ if((node->kind != HFSPLUS_NODE_NDX)&&(node->kind != HFSPLUS_NODE_LEAF))
604+ return 0;
605+
606+ klsz = (node->tree->attributes & HFSPLUS_TREE_BIGKEYS) ? 2 : 1;
607+ if((node->kind == HFSPLUS_NODE_NDX) &&
608+ !(node->tree->attributes & HFSPLUS_TREE_VAR_NDXKEY_SIZE)) {
609+ retval = node->tree->max_key_len;
610+ } else {
611+ recoff = hfsplus_brec_off(node, rec);
612+ if(!recoff)
613+ return 0;
614+ if(hfsplus_bnode_copybytes(node, buf, recoff, klsz) != klsz)
615+ return 0;
616+ if(klsz == 1)
617+ retval = buf[0];
618+ else
619+ retval = hfsp_get_hs(buf);
620+ }
621+ return (retval + klsz + 1) & 0xFFFE;
622+}
623+
624+/* Get a copy of the key of the given record, returns real key length */
625+hfsp_u16 hfsplus_brec_key(hfsplus_bnode *node, hfsp_u16 rec, void *buf,
626+ hfsp_u16 len)
627+{
628+ hfsp_u16 recoff, reclen, keylen, tocopy;
629+
630+ reclen = hfsplus_brec_lenoff(node, rec, &recoff);
631+ keylen = hfsplus_brec_keylen(node, rec);
632+ if(!reclen || !keylen)
633+ return 0;
634+ if(keylen > reclen) {
635+ printk("HFS+-fs: corrupt key length in B*Tree\n");
636+ return 0;
637+ }
638+ tocopy = (len > keylen) ? keylen : len;
639+ if(hfsplus_bnode_copybytes(node, buf, recoff, tocopy) != tocopy)
640+ return 0;
641+ return keylen;
642+}
643diff -urN -x CVS linux-bk/fs/hfsplus/btiter.c linux-hfsplus/fs/hfsplus/btiter.c
644--- linux-bk/fs/hfsplus/btiter.c Wed Dec 31 16:00:00 1969
645+++ linux-hfsplus/fs/hfsplus/btiter.c Fri Sep 21 20:56:21 2001
646@@ -0,0 +1,115 @@
647+/*
648+ * linux/fs/hfsplus/btiter.c
649+ *
650+ * Copyright (C) 2001
651+ * Brad Boyer (flar@allandria.com)
652+ *
653+ * Iterators for btrees
654+ */
655+
656+#include <linux/hfsplus_fs.h>
657+
658+void hfsplus_btiter_setup(hfsplus_btiter *iter, hfsplus_btree *tree)
659+{
660+ iter->tree = tree;
661+ iter->node = 0;
662+ iter->rec = 0;
663+}
664+
665+int hfsplus_btiter_move(hfsplus_btiter *iter, int cnt)
666+{
667+ hfsplus_bnode *node;
668+ int err = -EIO;
669+
670+ if(!iter || !iter->tree)
671+ return err;
672+ if((cnt < -0xFFFF) || (cnt > 0xFFFF))
673+ return err;
674+ if(!iter->node)
675+ return -ENOENT;
676+
677+ get_node:
678+ if(!(node = hfsplus_get_bnode(iter->tree, iter->node)))
679+ return err;
680+ start_node:
681+ if(node->kind != HFSPLUS_NODE_LEAF) {
682+ printk("HFS+-fs: found entry of bad type\n");
683+ goto out;
684+ }
685+ if(iter->rec >= node->num_recs)
686+ goto out;
687+
688+ if((iter->rec + cnt >= 0) && (iter->rec + cnt < node->num_recs)) {
689+ iter->rec += cnt;
690+ err = 0;
691+ goto out;
692+ }
693+ if(cnt < 0) {
694+ iter->node = node->prev;
695+ if(!iter->node) {
696+ err = -ENOENT;
697+ goto out;
698+ }
699+ hfsplus_put_bnode(node);
700+ if(!(node = hfsplus_get_bnode(iter->tree, iter->node)))
701+ return err;
702+ cnt += iter->rec + 1;
703+ iter->rec = node->num_recs - 1;
704+ goto start_node;
705+ }
706+ iter->node = node->next;
707+ if(!iter->node) {
708+ err = -ENOENT;
709+ goto out;
710+ }
711+ cnt -= node->num_recs - iter->rec;
712+ iter->rec = 0;
713+ hfsplus_put_bnode(node);
714+ goto get_node;
715+ out:
716+ hfsplus_put_bnode(node);
717+ return err;
718+}
719+
720+int hfsplus_btiter_get(hfsplus_btiter *iter, hfsplus_btree_key *key,
721+ void *entry, int *entry_len)
722+{
723+ hfsplus_bnode *node;
724+ int err = -EIO;
725+ hfsp_u16 rec, off, keylen, datalen;
726+
727+ if(!iter || !iter->tree || !key || !entry || !entry_len)
728+ return err;
729+
730+ if((node = hfsplus_get_bnode(iter->tree, iter->node)) == NULL)
731+ return err;
732+ if(node->kind != HFSPLUS_NODE_LEAF) {
733+ printk("HFS+-fs: found entry of bad type\n");
734+ goto out;
735+ }
736+
737+ rec = iter->rec;
738+ if(!(keylen = hfsplus_brec_keylen(node, rec))) {
739+ printk("HFS+-fs: unable to read key from B*Tree record\n");
740+ goto out;
741+ }
742+ datalen = hfsplus_brec_lenoff(node, rec, &off) - keylen;
743+ if((datalen <= 0) || (datalen > *entry_len)) {
744+ printk("HFS+-fs: bad entry length in B*Tree\n");
745+ goto out;
746+ }
747+ if(!hfsplus_bnode_copybytes(node, key, off, keylen)) {
748+ printk("HFS+-fs: unable to copy key from B*Tree\n");
749+ goto out;
750+ }
751+ if(!hfsplus_bnode_copybytes(node, entry, off + keylen, datalen)) {
752+ printk("HFS+-fs: unable to read record in B*Tree\n");
753+ goto out;
754+ }
755+ *entry_len = datalen;
756+ err = 0;
757+ out:
758+ hfsplus_put_bnode(node);
759+ return err;
760+}
761+
762diff -urN -x CVS linux-bk/fs/hfsplus/btree.c linux-hfsplus/fs/hfsplus/btree.c
763--- linux-bk/fs/hfsplus/btree.c Wed Dec 31 16:00:00 1969
764+++ linux-hfsplus/fs/hfsplus/btree.c Mon Nov 5 00:07:58 2001
765@@ -0,0 +1,89 @@
766+/*
767+ * linux/fs/hfsplus/btree.c
768+ *
769+ * Copyright (C) 2001
770+ * Brad Boyer (flar@allandria.com)
771+ *
772+ * Handle opening/closing btree
773+ */
774+
775+#include <linux/slab.h>
776+#include <linux/pagemap.h>
777+#include <linux/hfsplus_fs.h>
778+#include <linux/hfsplus_raw.h>
779+
780+/* Release resources used by a btree */
781+void hfsplus_close_btree(struct hfsplus_btree *tree)
782+{
783+ if(tree) {
784+ kfree(tree);
785+ }
786+}
787+
788+/* Fill in extra data in tree structure from header node */
789+static void hfsplus_fill_treeinfo(hfsplus_btree *tree, hfsplus_btree_head *hdr)
790+{
791+ if (!tree || !hdr)
792+ return;
793+
794+ tree->root = hfsp_get_hl(hdr->root);
795+ tree->node_count = hfsp_get_hl(hdr->node_count);
796+ tree->free_nodes = hfsp_get_hl(hdr->free_nodes);
797+ tree->attributes = hfsp_get_hl(hdr->attributes);
798+ tree->node_size = hfsp_get_hs(hdr->node_size);
799+ tree->max_key_len = hfsp_get_hs(hdr->max_key_len);
800+ tree->depth = hfsp_get_hs(hdr->depth);
801+}
802+
803+/* Get a reference to a B*Tree and do some initial checks */
804+hfsplus_btree *hfsplus_open_btree(struct super_block *sb, hfsp_cnid id)
805+{
806+ hfsplus_btree *tree;
807+ hfsplus_bnode *hnode;
808+ hfsplus_btree_head head;
809+ hfsp_u16 bytes;
810+
811+ tree = kmalloc(sizeof(struct hfsplus_btree), GFP_KERNEL);
812+ if(!tree)
813+ return NULL;
814+
815+ /* Set the correct compare function */
816+ tree->sb = sb;
817+ tree->cnid = id;
818+ if(id == HFSPLUS_EXT_CNID) {
819+ tree->keycmp = hfsplus_cmp_ext_key;
820+ } else if(id == HFSPLUS_CAT_CNID) {
821+ tree->keycmp = hfsplus_cmp_cat_key;
822+ } else {
823+ printk("HFS+-fs: unknown B*Tree requested\n");
824+ goto free_tree;
825+ }
826+
827+ /* Set up some dummy values */
828+ tree->node_count = 1;
829+ if(PAGE_SIZE > HFSPLUS_NODE_MXSZ)
830+ tree->node_size = HFSPLUS_NODE_MXSZ;
831+ else
832+ tree->node_size = PAGE_SIZE;
833+
834+ /* Load the header */
835+ hnode = hfsplus_get_bnode(tree, HFSPLUS_TREE_HEAD);
836+ if(!hnode)
837+ goto free_tree;
838+ bytes = hfsplus_bnode_copybytes(hnode, &head,
839+ sizeof(hfsplus_btree_node_desc),
840+ sizeof(hfsplus_btree_head));
841+ if(bytes != sizeof(hfsplus_btree_head)) {
842+ printk("HFS+-fs: unable to read B*Tree header\n");
843+ goto put_hnode;
844+ }
845+ hfsplus_fill_treeinfo(tree, &head);
846+ hfsplus_put_bnode(hnode);
847+ return tree;
848+
849+ put_hnode:
850+ hfsplus_put_bnode(hnode);
851+ free_tree:
852+ kfree(tree);
853+ return NULL;
854+}
855diff -urN -x CVS linux-bk/fs/hfsplus/catalog.c linux-hfsplus/fs/hfsplus/catalog.c
856--- linux-bk/fs/hfsplus/catalog.c Wed Dec 31 16:00:00 1969
857+++ linux-hfsplus/fs/hfsplus/catalog.c Mon Nov 5 00:09:43 2001
858@@ -0,0 +1,95 @@
859+/*
860+ * linux/fs/hfsplus/catalog.c
861+ *
862+ * Copyright (C) 2001
863+ * Brad Boyer (flar@allandria.com)
864+ *
865+ * Handling of catalog records
866+ */
867+
868+#include <linux/hfsplus_fs.h>
869+#include <linux/hfsplus_raw.h>
870+
871+int hfsplus_cmp_cat_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
872+{
873+ hfsp_cnid k1p, k2p;
874+
875+ k1p = hfsp_get_hl(k1->u.cat.parent);
876+ k2p = hfsp_get_hl(k2->u.cat.parent);
877+ if(k1p != k2p) {
878+ return (k1p < k2p) ? -1 : 1;
879+ }
880+ return hfsplus_unistrcmp(&(k1->u.cat.name), &(k2->u.cat.name));
881+}
882+
883+int hfsplus_fill_cat_key(hfsplus_btree_key *key, hfsp_cnid parent, char *name,
884+ int namelen)
885+{
886+ int err;
887+
888+ hfsp_put_hl(parent, key->u.cat.parent);
889+ if(!name || !namelen) {
890+ hfsp_put_hs(0, key->u.cat.name.length);
891+ } else {
892+ err = hfsplus_asc2uni(&(key->u.cat.name), name, namelen);
893+ if(err)
894+ return err;
895+ }
896+ hfsp_put_hs(6 + 2 * hfsp_get_hs(key->u.cat.name.length), key->key_len);
897+ return 0;
898+}
899+
900+static void hfsplus_fill_cat_key_uni(hfsplus_btree_key *key, hfsp_cnid parent,
901+ hfsplus_unistr *name)
902+{
903+ hfsp_u16 ustrlen;
904+
905+ ustrlen = hfsp_get_hs(name->length);
906+ hfsp_put_hs(6 + 2 * ustrlen, key->key_len);
907+ hfsp_put_hl(parent, key->u.cat.parent);
908+ hfsp_put_hs(ustrlen, key->u.cat.name.length);
909+ memcpy(key->u.cat.name.unicode, name->unicode,
910+ 2 * ustrlen);
911+}
912+
913+/* Try to get a catalog entry for given catalog id */
914+int hfsplus_find_cat(struct super_block *sb, unsigned long cnid,
915+ hfsplus_cat_entry *entry)
916+{
917+ hfsplus_btree_key key;
918+ hfsplus_cat_entry tmp;
919+ int err, sz;
920+ hfsp_u16 type;
921+
922+ hfsplus_fill_cat_key(&key, cnid, NULL, 0);
923+ sz = sizeof(hfsplus_cat_entry);
924+ err = hfsplus_btfind_exact(HFSPLUS_SB(sb).cat_tree, &key, &tmp, &sz);
925+ if(err)
926+ return err;
927+
928+ type = hfsp_get_hs(tmp.type);
929+ if((type != HFSPLUS_FOLDER_THREAD) && (type != HFSPLUS_FILE_THREAD)) {
930+ printk("HFS+-fs: Found bad thread record in catalog\n");
931+ return -EIO;
932+ }
933+
934+ hfsplus_fill_cat_key_uni(&key, hfsp_get_hl(tmp.u.thread.parentID),
935+ &(tmp.u.thread.nodeName));
936+ sz = sizeof(hfsplus_cat_entry);
937+ err = hfsplus_btfind_exact(HFSPLUS_SB(sb).cat_tree, &key, entry, &sz);
938+ if(err) {
939+ printk("HFS+-fs: Unable to find record listed in thread\n");
940+ return err;
941+ }
942+ type = hfsp_get_hs(entry->type);
943+ if((type != HFSPLUS_FOLDER) && (type != HFSPLUS_FILE)) {
944+ printk("HFS+-fs: Found bad entry in catalog\n");
945+ return -EIO;
946+ }
947+ if(((type == HFSPLUS_FILE) && (sz < 2+sizeof(hfsplus_cat_file))) ||
948+ ((type == HFSPLUS_FOLDER) && (sz < 2+sizeof(hfsplus_cat_folder)))) {
949+ printk("HFS+-fs: Found truncated entry in catalog\n");
950+ return -EIO;
951+ }
952+ return 0;
953+}
954diff -urN -x CVS linux-bk/fs/hfsplus/dir.c linux-hfsplus/fs/hfsplus/dir.c
955--- linux-bk/fs/hfsplus/dir.c Wed Dec 31 16:00:00 1969
956+++ linux-hfsplus/fs/hfsplus/dir.c Thu Dec 13 22:11:55 2001
957@@ -0,0 +1,156 @@
958+/*
959+ * linux/fs/hfsplus/dir.c
960+ *
961+ * Copyright (C) 2001
962+ * Brad Boyer (flar@allandria.com)
963+ *
964+ * Handling of directories
965+ */
966+
967+#include <linux/errno.h>
968+#include <linux/fs.h>
969+#include <linux/hfsplus_fs.h>
970+#include <linux/hfsplus_raw.h>
971+
972+/* Find the entry inside dir named dentry->d_name */
973+static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry)
974+{
975+ struct inode *inode = NULL;
976+ hfsplus_btree_key key;
977+ hfsplus_cat_entry entry;
978+ int err, sz;
979+ hfsp_u32 cnid;
980+ hfsp_u16 type;
981+
982+ if((err = hfsplus_fill_cat_key(&key, dir->i_ino, dentry->d_name.name,
983+ dentry->d_name.len)) != 0)
984+ return ERR_PTR(err);
985+ sz = sizeof(entry);
986+ if((err = hfsplus_btfind_exact(HFSPLUS_SB(dir->i_sb).cat_tree, &key,
987+ &entry, &sz)) != 0) {
988+ if(err == -ENOENT) {
989+ /* No such entry */
990+ inode = NULL;
991+ goto out;
992+ }
993+ return ERR_PTR(err);
994+ }
995+ type = hfsp_get_hs(entry.type);
996+ if(type == HFSPLUS_FOLDER) {
997+ if(sz < 2 + sizeof(hfsplus_cat_folder))
998+ return ERR_PTR(-EIO);
999+ cnid = hfsp_get_hl(entry.u.folder.id);
1000+ } else if(type == HFSPLUS_FILE) {
1001+ if(sz < 2 + sizeof(hfsplus_cat_file))
1002+ return ERR_PTR(-EIO);
1003+ cnid = hfsp_get_hl(entry.u.file.id);
1004+ } else {
1005+ printk("HFS+-fs: Illegal catalog entry type in lookup\n");
1006+ return ERR_PTR(-EIO);
1007+ }
1008+ inode = iget(dir->i_sb, cnid);
1009+ if(!inode)
1010+ return ERR_PTR(-EACCES);
1011+ out:
1012+ d_add(dentry, inode);
1013+ return NULL;
1014+}
1015+
1016+static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
1017+{
1018+ struct inode *inode = filp->f_dentry->d_inode;
1019+ int len, sz, err, done = 0;
1020+ char strbuf[HFSPLUS_MAX_STRLEN + 1];
1021+ hfsplus_cat_entry entry;
1022+ hfsplus_btree_key key;
1023+ hfsplus_btiter iter;
1024+ hfsp_u16 type;
1025+
1026+ if(filp->f_pos >= inode->i_size)
1027+ return 0;
1028+
1029+ hfsplus_fill_cat_key(&key, inode->i_ino, NULL, 0);
1030+ hfsplus_btiter_setup(&iter, HFSPLUS_SB(inode->i_sb).cat_tree);
1031+ if((err = hfsplus_btiter_find(&iter, &key)) != 0) {
1032+ return err;
1033+ }
1034+ if(filp->f_pos > 1)
1035+ if((err = hfsplus_btiter_move(&iter, filp->f_pos - 1)))
1036+ return err;
1037+
1038+ while(!done) {
1039+ if(!filp->f_pos) {
1040+ /* This is completely artificial... */
1041+ if(filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR))
1042+ done = 1;
1043+ filp->f_pos++;
1044+ continue;
1045+ }
1046+ sz = sizeof(entry);
1047+ if((err = hfsplus_btiter_get(&iter, &key, &entry, &sz)))
1048+ return err;
1049+ if(hfsp_get_hl(key.u.cat.parent) != inode->i_ino) {
1050+ printk("HFS+-fs: walked past end of dir\n");
1051+ return 0;
1052+ }
1053+ if(sz < 2)
1054+ return -EIO;
1055+ type = hfsp_get_hs(entry.type);
1056+ if(filp->f_pos == 1) {
1057+ if(type != HFSPLUS_FOLDER_THREAD) {
1058+ printk("HFS+-fs: bad catalog folder thread\n");
1059+ return -EIO;
1060+ }
1061+ if(sz < HFSPLUS_MIN_THREAD_SZ) {
1062+ printk("HFS+-fs: truncated catalog thread\n");
1063+ return -EIO;
1064+ }
1065+ if(filldir(dirent, "..", 2, 1,
1066+ hfsp_get_hl(entry.u.thread.parentID),
1067+ DT_DIR))
1068+ done = 1;
1069+ } else {
1070+ len = HFSPLUS_MAX_STRLEN;
1071+ err = hfsplus_uni2asc(&(key.u.cat.name), strbuf, &len);
1072+ if(err)
1073+ return err;
1074+ if(type == HFSPLUS_FOLDER) {
1075+ if(sz < 2 + sizeof(hfsplus_cat_folder)) {
1076+ printk("HFS+-fs: small dir entry\n");
1077+ return -EIO;
1078+ }
1079+ if(filldir(dirent, strbuf, len, filp->f_pos,
1080+ hfsp_get_hl(entry.u.folder.id),
1081+ DT_DIR))
1082+ done = 1;
1083+ } else if(type == HFSPLUS_FILE) {
1084+ if(sz < 2 + sizeof(hfsplus_cat_file)) {
1085+ printk("HFS+-fs: small file entry\n");
1086+ return -EIO;
1087+ }
1088+ if(filldir(dirent, strbuf, len, filp->f_pos,
1089+ hfsp_get_hl(entry.u.file.id),
1090+ DT_REG))
1091+ done = 1;
1092+ } else {
1093+ printk("HFS+-fs: bad catalog entry type\n");
1094+ return -EIO;
1095+ }
1096+ } /* if(filp->f_pos == 1) */
1097+ filp->f_pos++;
1098+ if(filp->f_pos >= inode->i_size)
1099+ break;
1100+ if((err = hfsplus_btiter_move(&iter, 1)))
1101+ return err;
1102+ } /* while(!done) */
1103+ return 0;
1104+}
1105+
1106+struct inode_operations hfsplus_dir_inode_operations = {
1107+ lookup: hfsplus_lookup,
1108+};
1109+
1110+struct file_operations hfsplus_dir_operations = {
1111+ read: generic_read_dir,
1112+ readdir: hfsplus_readdir,
1113+};
1114diff -urN -x CVS linux-bk/fs/hfsplus/extents.c linux-hfsplus/fs/hfsplus/extents.c
1115--- linux-bk/fs/hfsplus/extents.c Wed Dec 31 16:00:00 1969
1116+++ linux-hfsplus/fs/hfsplus/extents.c Mon Nov 5 00:03:59 2001
1117@@ -0,0 +1,162 @@
1118+/*
1119+ * linux/fs/hfsplus/extents.c
1120+ *
1121+ * Copyright (C) 2001
1122+ * Brad Boyer (flar@allandria.com)
1123+ *
1124+ * Handling of Extents both in catalog and extents overflow trees
1125+ */
1126+
1127+#include <linux/errno.h>
1128+#include <linux/fs.h>
1129+#include <linux/hfsplus_fs.h>
1130+#include <linux/hfsplus_raw.h>
1131+
1132+/* Compare two extents keys, returns 0 on same, pos/neg for difference */
1133+int hfsplus_cmp_ext_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
1134+{
1135+ hfsp_cnid k1id, k2id;
1136+ hfsp_u32 k1s, k2s;
1137+
1138+ k1id = hfsp_get_hl(k1->u.ext.cnid);
1139+ k2id = hfsp_get_hl(k2->u.ext.cnid);
1140+ if(k1id != k2id) {
1141+ return (k1id < k2id) ? -1 : 1;
1142+ }
1143+ if(k1->u.ext.fork_type != k2->u.ext.fork_type) {
1144+ return (k1->u.ext.fork_type < k2->u.ext.fork_type) ? -1 : 1;
1145+ }
1146+ k1s = hfsp_get_hl(k1->u.ext.start_block);
1147+ k2s = hfsp_get_hl(k2->u.ext.start_block);
1148+ if(k1s == k2s)
1149+ return 0;
1150+ return (k1s < k2s) ? -1 : 1;
1151+}
1152+
1153+void hfsplus_fill_ext_key(hfsplus_btree_key *key, hfsp_u32 cnid,
1154+ hfsp_u32 block, hfsp_u8 type)
1155+{
1156+ hfsp_put_hl(HFSPLUS_EXT_KEYLEN, key->key_len);
1157+ hfsp_put_hl(cnid, key->u.ext.cnid);
1158+ hfsp_put_hl(block, key->u.ext.start_block);
1159+ key->u.ext.fork_type = type;
1160+ key->u.ext.pad = 0;
1161+}
1162+
1163+/* Get a block at iblock for inode, possibly allocating if create */
1164+int hfsplus_get_block(struct inode *inode, long iblock,
1165+ struct buffer_head *bh_result, int create)
1166+{
1167+ struct super_block *s;
1168+ hfsplus_extent *extents, ext_entry[8];
1169+ hfsplus_btree_key key;
1170+ hfsplus_cat_entry cat_entry;
1171+ unsigned long ino;
1172+ long remain;
1173+ int i, sz, localerr, search_tree = 1, err = -EIO;
1174+ hfsp_u32 curr, tmp, ablock, dblock, dbpab, dbo;
1175+ hfsp_u8 forktype;
1176+
1177+ if(!inode || !bh_result)
1178+ goto out;
1179+
1180+ ino = inode->i_ino;
1181+ s = inode->i_sb;
1182+
1183+ /* Convert inode block to disk allocation block */
1184+ dbo = HFSPLUS_SB(s).dboff;
1185+ dbpab = HFSPLUS_SB(s).dbpab;
1186+ ablock = iblock / dbpab;
1187+ remain = iblock % dbpab;
1188+
1189+ /* Some files have extents in volume header */
1190+ if(ino <= HFSPLUS_ATTR_CNID) {
1191+ switch(ino) {
1192+ case HFSPLUS_EXT_CNID:
1193+ extents = HFSPLUS_SB(s).s_vhdr->ext_file.extents;
1194+ search_tree = 0;
1195+ break;
1196+ case HFSPLUS_CAT_CNID:
1197+ extents = HFSPLUS_SB(s).s_vhdr->cat_file.extents;
1198+ break;
1199+ case HFSPLUS_ALLOC_CNID:
1200+ extents = HFSPLUS_SB(s).s_vhdr->alloc_file.extents;
1201+ break;
1202+ case HFSPLUS_START_CNID:
1203+ extents = HFSPLUS_SB(s).s_vhdr->start_file.extents;
1204+ break;
1205+ case HFSPLUS_ATTR_CNID:
1206+ extents = HFSPLUS_SB(s).s_vhdr->attr_file.extents;
1207+ break;
1208+ default:
1209+ /* Nothing else in this block is valid */
1210+ goto out;
1211+ break;
1212+ }
1213+ } else {
1214+ if((localerr = hfsplus_find_cat(s, ino, &cat_entry)) != 0) {
1215+ err = localerr;
1216+ goto out;
1217+ }
1218+ if(hfsp_get_hs(cat_entry.type) != HFSPLUS_FILE)
1219+ goto out;
1220+ if(HFSPLUS_IS_DATA(inode)) {
1221+ extents = cat_entry.u.file.data_fork.extents;
1222+ } else if(HFSPLUS_IS_RSRC(inode)) {
1223+ extents = cat_entry.u.file.res_fork.extents;
1224+ } else {
1225+ goto out;
1226+ }
1227+ }
1228+
1229+ /* Look in extent record for block */
1230+ curr = 0;
1231+ search_extent:
1232+ for(i = 0; i < 8; i++) {
1233+ tmp = hfsp_get_hl(extents[i].block_count);
1234+ if(tmp && (ablock < curr + tmp)) {
1235+ /* Found it */
1236+ dblock = hfsp_get_hl(extents[i].start_block);
1237+ dblock += ablock - curr;
1238+ bh_result->b_dev = inode->i_dev;
1239+ bh_result->b_blocknr = dblock * dbpab + remain + dbo;
1240+ bh_result->b_state |= (1UL << BH_Mapped);
1241+ err = 0;
1242+ goto out;
1243+ }
1244+ curr += tmp;
1245+ }
1246+
1247+ /* Look for extents in tree */
1248+ if(!search_tree)
1249+ goto not_found;
1250+ forktype = HFSPLUS_IS_RSRC(inode) ? HFSPLUS_TYPE_RSRC :
1251+ HFSPLUS_TYPE_DATA;
1252+ hfsplus_fill_ext_key(&key, ino, ablock, forktype);
1253+ sz = sizeof(ext_entry);
1254+ if((localerr = hfsplus_btfind(HFSPLUS_SB(s).ext_tree, &key, ext_entry,
1255+ &sz))) {
1256+ if(localerr == -ENOENT)
1257+ goto not_found;
1258+ printk("HFS+-fs: Unknown problem searching extents B*Tree\n");
1259+ err = localerr;
1260+ goto out;
1261+ }
1262+ if((hfsp_get_hl(key.u.ext.cnid) != ino) ||
1263+ (key.u.ext.fork_type != forktype)) {
1264+ goto not_found;
1265+ }
1266+ search_tree = 0;
1267+ curr = hfsp_get_hl(key.u.ext.start_block);
1268+ extents = ext_entry;
1269+ goto search_extent;
1270+ not_found:
1271+ if(!create) {
1272+ err = 0;
1273+ goto out;
1274+ }
1275+ /* FIXME: Should allocate blocks here... */
1276+ printk("HFS+-fs: no file writes, but block allocation attempted\n");
1277+ out:
1278+ return err;
1279+}
1280diff -urN -x CVS linux-bk/fs/hfsplus/inode.c linux-hfsplus/fs/hfsplus/inode.c
1281--- linux-bk/fs/hfsplus/inode.c Wed Dec 31 16:00:00 1969
1282+++ linux-hfsplus/fs/hfsplus/inode.c Thu Dec 13 22:32:32 2001
1283@@ -0,0 +1,126 @@
1284+/*
1285+ * linux/fs/hfsplus/inode.c
1286+ *
1287+ * Copyright (C) 2001
1288+ * Brad Boyer (flar@allandria.com)
1289+ *
1290+ * Inode handling routines
1291+ */
1292+
1293+#include <linux/fs.h>
1294+#include <linux/hfsplus_fs.h>
1295+#include <linux/hfsplus_raw.h>
1296+
1297+static int hfsplus_readpage(struct file *file, struct page *page)
1298+{
1299+ return block_read_full_page(page, hfsplus_get_block);
1300+}
1301+
1302+static int hfsplus_bmap(struct address_space *mapping, long block)
1303+{
1304+ return generic_block_bmap(mapping, block, hfsplus_get_block);
1305+}
1306+
1307+struct address_space_operations hfsplus_aops = {
1308+ readpage: hfsplus_readpage,
1309+ bmap: hfsplus_bmap,
1310+};
1311+
1312+static void hfsplus_fill_perms(struct inode *inode, hfsplus_perm *perms)
1313+{
1314+ struct super_block *s = inode->i_sb;
1315+
1316+ inode->i_mode = hfsp_get_hl(perms->mode);
1317+ if(inode->i_mode) {
1318+ inode->i_mode &= ~(S_IFMT);
1319+ } else {
1320+ inode->i_mode = S_IRWXUGO & ~(HFSPLUS_SB(s).umask);
1321+ }
1322+ inode->i_uid = hfsp_get_hl(perms->owner);
1323+ if(!(inode->i_uid))
1324+ inode->i_uid = HFSPLUS_SB(s).uid;
1325+ inode->i_gid = hfsp_get_hl(perms->group);
1326+ if(!(inode->i_gid))
1327+ inode->i_gid = HFSPLUS_SB(s).gid;
1328+ HFSPLUS_I(inode).dev = hfsp_get_hl(perms->dev);
1329+}
1330+
1331+extern struct inode_operations hfsplus_dir_inode_operations;
1332+extern struct file_operations hfsplus_dir_operations;
1333+
1334+struct inode_operations hfsplus_file_inode_operations = {
1335+};
1336+struct file_operations hfsplus_file_operations = {
1337+ read: generic_file_read,
1338+ mmap: generic_file_mmap,
1339+};
1340+
1341+static void hfsplus_count_subdirs(struct inode *inode)
1342+{
1343+ hfsplus_btree_key key;
1344+ hfsplus_cat_entry entry;
1345+ hfsplus_btiter iter;
1346+ int sz;
1347+
1348+ hfsplus_fill_cat_key(&key, inode->i_ino, NULL, 0);
1349+ hfsplus_btiter_setup(&iter, HFSPLUS_SB(inode->i_sb).cat_tree);
1350+ if(hfsplus_btiter_find(&iter, &key))
1351+ return;
1352+ while(1) {
1353+ sz = sizeof(hfsplus_cat_entry);
1354+ if(hfsplus_btiter_get(&iter, &key, &entry, &sz) || (sz < 2))
1355+ return;
1356+
1357+ if(hfsp_get_hl(key.u.cat.parent) != inode->i_ino)
1358+ return;
1359+ if(hfsp_get_hs(entry.type) == HFSPLUS_FOLDER)
1360+ HFSPLUS_I(inode).ndirs++;
1361+
1362+ if(hfsplus_btiter_move(&iter, 1))
1363+ return;
1364+ }
1365+}
1366+
1367+int hfsplus_cat_fill_inode(struct inode *inode, hfsplus_cat_entry *entry)
1368+{
1369+ hfsplus_cat_folder *folder;
1370+ hfsplus_cat_file *file;
1371+ hfsp_u16 type;
1372+
1373+ type = hfsp_get_hs(entry->type);
1374+ HFSPLUS_I(inode).ndirs = 0;
1375+ HFSPLUS_I(inode).dev = 0;
1376+ inode->i_blksize = PAGE_SIZE; /* Doesn't seem to be useful... */
1377+ if(type == HFSPLUS_FOLDER) {
1378+ folder = &(entry->u.folder);
1379+ hfsplus_fill_perms(inode, &(folder->permissions));
1380+ inode->i_mode |= S_IFDIR;
1381+ hfsplus_count_subdirs(inode);
1382+ inode->i_nlink = 2 + HFSPLUS_I(inode).ndirs;
1383+ inode->i_size = 2 + hfsp_get_hl(folder->valence);
1384+ inode->i_atime = hfsp_mt2ut(folder->access_date);
1385+ inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
1386+ inode->i_ctime = inode->i_mtime;
1387+ inode->i_blocks = 0;
1388+ inode->i_op = &hfsplus_dir_inode_operations;
1389+ inode->i_fop = &hfsplus_dir_operations;
1390+ } else if(type == HFSPLUS_FILE) {
1391+ file = &(entry->u.file);
1392+ hfsplus_fill_perms(inode, &(file->permissions));
1393+ inode->i_mode |= S_IFREG;
1394+ inode->i_nlink = 1;
1395+ inode->i_size = hfsp_get_hll(file->data_fork.total_size);
1396+ inode->i_atime = hfsp_mt2ut(file->access_date);
1397+ inode->i_mtime = hfsp_mt2ut(file->content_mod_date);
1398+ inode->i_ctime = inode->i_mtime;
1399+ inode->i_blocks = hfsp_get_hl(file->data_fork.total_blocks);
1400+ inode->i_op = &hfsplus_file_inode_operations;
1401+ inode->i_fop = &hfsplus_file_operations;
1402+ inode->i_mapping->a_ops = &hfsplus_aops;
1403+ } else {
1404+ printk("HFS+-fs: bad catalog entry used to create inode\n");
1405+ return -EIO;
1406+ }
1407+ return 0;
1408+}
1409+
1410diff -urN -x CVS linux-bk/fs/hfsplus/options.c linux-hfsplus/fs/hfsplus/options.c
1411--- linux-bk/fs/hfsplus/options.c Wed Dec 31 16:00:00 1969
1412+++ linux-hfsplus/fs/hfsplus/options.c Fri Sep 21 00:42:03 2001
1413@@ -0,0 +1,147 @@
1414+/*
1415+ * linux/fs/hfsplus/options.c
1416+ *
1417+ * Copyright (C) 2001
1418+ * Brad Boyer (flar@allandria.com)
1419+ *
1420+ * Option parsing
1421+ */
1422+
1423+#include <linux/string.h>
1424+#include <linux/kernel.h>
1425+#include <linux/sched.h>
1426+#include <linux/hfsplus_fs.h>
1427+
1428+/* Initialize an options object to reasonable defaults */
1429+void fill_defaults(struct hfsplus_sb_info *opts)
1430+{
1431+ if(!opts)
1432+ return;
1433+
1434+ opts->creator = HFSPLUS_DEF_CR_TYPE;
1435+ opts->type = HFSPLUS_DEF_CR_TYPE;
1436+ opts->charcase = HFSPLUS_CASE_ASIS;
1437+ opts->fork = HFSPLUS_FORK_RAW;
1438+ opts->namemap = HFSPLUS_NAMES_TRIVIAL;
1439+ opts->umask = current->fs->umask;
1440+ opts->uid = current->uid;
1441+ opts->gid = current->gid;
1442+}
1443+
1444+/* Copy settings from one hfsplus_sb_info object to another */
1445+void fill_current(struct hfsplus_sb_info *curopts,
1446+ struct hfsplus_sb_info *opts)
1447+{
1448+ if(!curopts || !opts)
1449+ return;
1450+
1451+ opts->creator = curopts->creator;
1452+ opts->type = curopts->type;
1453+ opts->charcase = curopts->charcase;
1454+ opts->fork = curopts->fork;
1455+ opts->namemap = curopts->namemap;
1456+ opts->umask = curopts->umask;
1457+ opts->uid = curopts->uid;
1458+ opts->gid = curopts->gid;
1459+}
1460+
1461+/* My own little ultra-paranoid version of strtok (yes, there is strtok...) */
1462+static char *my_strtok(char *input, char **next, char delim)
1463+{
1464+ char *d;
1465+
1466+ if(!input || !*input || !next)
1467+ return NULL;
1468+
1469+ *next = NULL;
1470+ d = strchr(input, delim);
1471+ if(d) {
1472+ *d = '\0';
1473+ *next = d+1;
1474+ }
1475+ return input;
1476+}
1477+
1478+/* convert a "four byte character" to a 32 bit int with error checks */
1479+static int fill_fourchar(hfsp_u32 *result, char *input)
1480+{
1481+ hfsp_u32 out;
1482+ int i;
1483+
1484+ if(!result || !input || !*input || (strlen(input) != 4))
1485+ return 0;
1486+
1487+ for(out = 0, i = 0; i < 4; i++) {
1488+ out <<= 8;
1489+ out |= ((int)(input[i])) & 0xFF;
1490+ }
1491+ *result = out;
1492+ return 1;
1493+}
1494+
1495+/* convert a string to int with error checks */
1496+static int fill_int(int *result, char *input, int base)
1497+{
1498+ char *tmp = input;
1499+ int intval;
1500+
1501+ if(!result || !input || !*input)
1502+ return 0;
1503+
1504+ intval = simple_strtoul(tmp, &tmp, base);
1505+ if(*tmp)
1506+ return 0;
1507+
1508+ *result = intval;
1509+ return 1;
1510+}
1511+
1512+/* Parse options from mount. Returns 0 on failure */
1513+/* input is the options passed to mount() as a string */
1514+int parse_options(char *input, struct hfsplus_sb_info *results)
1515+{
1516+ char *next, *curropt, *value;
1517+
1518+ if(!input)
1519+ return 1;
1520+
1521+ for(curropt = my_strtok(input, &next, ','); curropt != NULL;
1522+ curropt = my_strtok(next, &next, ',')) {
1523+ if((value = strchr(curropt, '=')) != NULL)
1524+ *value++ = '\0';
1525+
1526+ if(!strcmp(curropt, "creator")) {
1527+ if(!fill_fourchar(&(results->creator), value)) {
1528+ printk("HFS+-fs: creator requires a value\n");
1529+ return 0;
1530+ }
1531+ } else if(!strcmp(curropt, "type")) {
1532+ if(!fill_fourchar(&(results->type), value)) {
1533+ printk("HFS+-fs: type requires a value\n");
1534+ return 0;
1535+ }
1536+ } else if(!strcmp(curropt, "case")) {
1537+ } else if(!strcmp(curropt, "fork")) {
1538+ } else if(!strcmp(curropt, "names")) {
1539+ } else if(!strcmp(curropt, "umask")) {
1540+ if(!fill_int(&(results->umask), value, 8))
1541+ printk("HFS+-fs: umask requires a value\n");
1542+ return 0;
1543+ } else if(!strcmp(curropt, "uid")) {
1544+ if(!fill_int(&(results->uid), value, 0)) {
1545+ printk("HFS+-fs: uid requires an argument\n");
1546+ return 0;
1547+ }
1548+ } else if(!strcmp(curropt, "gid")) {
1549+ if(!fill_int(&(results->gid), value, 0)) {
1550+ printk("HFS+-fs: gid requires an argument\n");
1551+ return 0;
1552+ }
1553+ } else {
1554+ printk("HFS+-fs: unknown option %s\n", curropt);
1555+ return 0;
1556+ }
1557+ }
1558+
1559+ return 1;
1560+}
1561diff -urN -x CVS linux-bk/fs/hfsplus/super.c linux-hfsplus/fs/hfsplus/super.c
1562--- linux-bk/fs/hfsplus/super.c Wed Dec 31 16:00:00 1969
1563+++ linux-hfsplus/fs/hfsplus/super.c Mon Nov 5 00:11:34 2001
1564@@ -0,0 +1,164 @@
1565+/*
1566+ * linux/fs/hfsplus/super.c
1567+ *
1568+ * Copyright (C) 2001
1569+ * Brad Boyer (flar@allandria.com)
1570+ *
1571+ */
1572+
1573+#include <linux/config.h>
1574+#include <linux/init.h>
1575+#include <linux/module.h>
1576+#include <linux/fs.h>
1577+#include <linux/hfsplus_fs.h>
1578+
1579+static void hfsplus_read_inode(struct inode *inode)
1580+{
1581+ hfsplus_cat_entry entry;
1582+
1583+ memset(&entry, 0, sizeof(entry));
1584+ hfsp_put_hs(HFSPLUS_FILE, entry.type);
1585+ switch(inode->i_ino) {
1586+ case HFSPLUS_EXT_CNID:
1587+ memcpy(&(entry.u.file.data_fork),
1588+ &(HFSPLUS_SB(inode->i_sb).s_vhdr->ext_file.extents),
1589+ sizeof(hfsplus_fork_raw));
1590+ break;
1591+ case HFSPLUS_CAT_CNID:
1592+ memcpy(&(entry.u.file.data_fork),
1593+ &(HFSPLUS_SB(inode->i_sb).s_vhdr->cat_file.extents),
1594+ sizeof(hfsplus_fork_raw));
1595+ break;
1596+ default:
1597+ if(hfsplus_find_cat(inode->i_sb, inode->i_ino, &entry))
1598+ goto bad_inode;
1599+ break;
1600+ }
1601+ if(hfsplus_cat_fill_inode(inode, &entry))
1602+ goto bad_inode;
1603+ return;
1604+
1605+ bad_inode:
1606+ make_bad_inode(inode);
1607+}
1608+
1609+static void hfsplus_put_super(struct super_block *sb)
1610+{
1611+ hfsplus_close_btree(HFSPLUS_SB(sb).cat_tree);
1612+ HFSPLUS_SB(sb).cat_tree = NULL;
1613+ hfsplus_close_btree(HFSPLUS_SB(sb).ext_tree);
1614+ HFSPLUS_SB(sb).ext_tree = NULL;
1615+
1616+ if(HFSPLUS_SB(sb).s_vhbh)
1617+ brelse(HFSPLUS_SB(sb).s_vhbh);
1618+ HFSPLUS_SB(sb).s_vhbh = NULL;
1619+ HFSPLUS_SB(sb).s_vhdr = NULL;
1620+}
1621+
1622+static int hfsplus_statfs(struct super_block *sb, struct statfs *buf)
1623+{
1624+ buf->f_type = HFSPLUS_SUPER_MAGIC;
1625+ buf->f_bsize = sb->s_blocksize;
1626+ buf->f_blocks = hfsp_get_ahl(HFSPLUS_SB(sb).s_vhdr->total_blocks);
1627+ buf->f_bfree = HFSPLUS_SB(sb).free_blocks;
1628+ buf->f_bavail = buf->f_bfree;
1629+ buf->f_files = HFSPLUS_SB(sb).file_count + HFSPLUS_SB(sb).folder_count;
1630+ buf->f_ffree = 0xFFFFFFFF - HFSPLUS_SB(sb).next_cnid;
1631+ buf->f_namelen = HFSPLUS_MAX_STRLEN;
1632+
1633+ return 0;
1634+}
1635+
1636+static struct super_operations hfsplus_sops = {
1637+ read_inode: hfsplus_read_inode,
1638+ put_super: hfsplus_put_super,
1639+ statfs: hfsplus_statfs,
1640+};
1641+
1642+struct super_block *hfsplus_read_super(struct super_block *sb, void *data,
1643+ int silent)
1644+{
1645+ struct hfsplus_vh *vhdr;
1646+ struct hfsplus_sb_info opts;
1647+
1648+ fill_defaults(&opts);
1649+ if(!parse_options(data, &opts)) {
1650+ if(!silent)
1651+ printk("HFS+-fs: unable to parse mount options\n");
1652+ return NULL;
1653+ }
1654+ fill_current(&opts, &(HFSPLUS_SB(sb)));
1655+
1656+ HFSPLUS_SB(sb).s_vhdr = NULL;
1657+ HFSPLUS_SB(sb).s_vhbh = NULL;
1658+ HFSPLUS_SB(sb).ext_tree = NULL;
1659+ HFSPLUS_SB(sb).cat_tree = NULL;
1660+
1661+ /* Grab the volume header */
1662+ if(!hfsplus_read_wrapper(sb)) {
1663+ if(!silent)
1664+ printk("HFS+-fs: unable to find HFS+ superblock\n");
1665+ return NULL;
1666+ }
1667+ vhdr = HFSPLUS_SB(sb).s_vhdr;
1668+
1669+ /* Copy parts of the volume header into the superblock */
1670+ sb->s_magic = hfsp_get_hs(vhdr->signature);
1671+ if(hfsp_get_hs(vhdr->version) != HFSPLUS_CURRENT_VERSION) {
1672+ if(!silent)
1673+ printk("HFS+-fs: wrong filesystem version\n");
1674+ goto cleanup;
1675+ }
1676+ HFSPLUS_SB(sb).free_blocks = hfsp_get_ahl(vhdr->free_blocks);
1677+ HFSPLUS_SB(sb).next_cnid = hfsp_get_ahl(vhdr->next_cnid);
1678+ HFSPLUS_SB(sb).file_count = hfsp_get_ahl(vhdr->file_count);
1679+ HFSPLUS_SB(sb).folder_count = hfsp_get_ahl(vhdr->folder_count);
1680+
1681+ /* Set up operations so we can load metadata */
1682+ sb->s_op = &hfsplus_sops;
1683+
1684+ /* Load metadata objects (B*Trees) */
1685+ HFSPLUS_SB(sb).ext_tree = hfsplus_open_btree(sb, HFSPLUS_EXT_CNID);
1686+ if(!HFSPLUS_SB(sb).ext_tree) {
1687+ if(!silent)
1688+ printk("HFS+-fs: failed to load extents file\n");
1689+ goto cleanup;
1690+ }
1691+ HFSPLUS_SB(sb).cat_tree = hfsplus_open_btree(sb, HFSPLUS_CAT_CNID);
1692+ if(!HFSPLUS_SB(sb).cat_tree) {
1693+ if(!silent)
1694+ printk("HFS+-fs: failed to load catalog file\n");
1695+ goto cleanup;
1696+ }
1697+
1698+ /* Load the root directory */
1699+ sb->s_root = d_alloc_root(iget(sb, HFSPLUS_ROOT_CNID));
1700+ if(!sb->s_root) {
1701+ if(!silent)
1702+ printk("HFS+-fs: failed to load root directory\n");
1703+ goto cleanup;
1704+ }
1705+
1706+ return sb;
1707+
1708+ cleanup:
1709+ hfsplus_put_super(sb);
1710+ return NULL;
1711+}
1712+
1713+static DECLARE_FSTYPE_DEV(hfsplus_fs_type, "hfsplus", hfsplus_read_super);
1714+
1715+static int __init init_hfsplus_fs(void)
1716+{
1717+ return register_filesystem(&hfsplus_fs_type);
1718+}
1719+
1720+static void __exit exit_hfsplus_fs(void)
1721+{
1722+ unregister_filesystem(&hfsplus_fs_type);
1723+}
1724+
1725+EXPORT_NO_SYMBOLS;
1726+
1727+module_init(init_hfsplus_fs)
1728+module_exit(exit_hfsplus_fs)
1729diff -urN -x CVS linux-bk/fs/hfsplus/tables.c linux-hfsplus/fs/hfsplus/tables.c
1730--- linux-bk/fs/hfsplus/tables.c Wed Dec 31 16:00:00 1969
1731+++ linux-hfsplus/fs/hfsplus/tables.c Fri Sep 21 00:42:03 2001
1732@@ -0,0 +1,408 @@
1733+/*
1734+ * linux/fs/hfsplus/tables.c
1735+ *
1736+ * Various data tables
1737+ */
1738+
1739+#include <linux/hfsplus_fs.h>
1740+
1741+/*
1742+ * Unicode case folding table taken from Apple Technote #1150
1743+ * (HFS Plus Volume Format)
1744+ */
1745+
1746+hfsp_u16 case_fold_table[] = {
1747+/*
1748+ * The lower case table consists of a 256-entry high-byte table followed by
1749+ * some number of 256-entry subtables. The high-byte table contains either an
1750+ * offset to the subtable for characters with that high byte or zero, which
1751+ * means that there are no case mappings or ignored characters in that block.
1752+ * Ignored characters are mapped to zero.
1753+ */
1754+
1755+ // High-byte indices ( == 0 iff no case mapping and no ignorables )
1756+
1757+
1758+ /* 0 */ 0x0100, 0x0200, 0x0000, 0x0300, 0x0400, 0x0500, 0x0000, 0x0000,
1759+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1760+ /* 1 */ 0x0600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1761+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1762+ /* 2 */ 0x0700, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1763+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1764+ /* 3 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1765+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1766+ /* 4 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1767+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1768+ /* 5 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1769+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1770+ /* 6 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1771+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1772+ /* 7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1773+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1774+ /* 8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1775+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1776+ /* 9 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1777+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1778+ /* A */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1779+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1780+ /* B */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1781+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1782+ /* C */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1783+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1784+ /* D */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1785+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1786+ /* E */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1787+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1788+ /* F */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1789+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0900, 0x0A00,
1790+
1791+ // Table 1 (for high byte 0x00)
1792+
1793+ /* 0 */ 0xFFFF, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
1794+ 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
1795+ /* 1 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
1796+ 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
1797+ /* 2 */ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1798+ 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
1799+ /* 3 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1800+ 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
1801+ /* 4 */ 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1802+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
1803+ /* 5 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1804+ 0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
1805+ /* 6 */ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1806+ 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
1807+ /* 7 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1808+ 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
1809+ /* 8 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
1810+ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F,
1811+ /* 9 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
1812+ 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F,
1813+ /* A */ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
1814+ 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
1815+ /* B */ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
1816+ 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
1817+ /* C */ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00E6, 0x00C7,
1818+ 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
1819+ /* D */ 0x00F0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
1820+ 0x00F8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00FE, 0x00DF,
1821+ /* E */ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
1822+ 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
1823+ /* F */ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
1824+ 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
1825+
1826+ // Table 2 (for high byte 0x01)
1827+
1828+ /* 0 */ 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107,
1829+ 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F,
1830+ /* 1 */ 0x0111, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117,
1831+ 0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E, 0x011F,
1832+ /* 2 */ 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0127, 0x0127,
1833+ 0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F,
1834+ /* 3 */ 0x0130, 0x0131, 0x0133, 0x0133, 0x0134, 0x0135, 0x0136, 0x0137,
1835+ 0x0138, 0x0139, 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x0140,
1836+ /* 4 */ 0x0140, 0x0142, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147,
1837+ 0x0148, 0x0149, 0x014B, 0x014B, 0x014C, 0x014D, 0x014E, 0x014F,
1838+ /* 5 */ 0x0150, 0x0151, 0x0153, 0x0153, 0x0154, 0x0155, 0x0156, 0x0157,
1839+ 0x0158, 0x0159, 0x015A, 0x015B, 0x015C, 0x015D, 0x015E, 0x015F,
1840+ /* 6 */ 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x0167, 0x0167,
1841+ 0x0168, 0x0169, 0x016A, 0x016B, 0x016C, 0x016D, 0x016E, 0x016F,
1842+ /* 7 */ 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175, 0x0176, 0x0177,
1843+ 0x0178, 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E, 0x017F,
1844+ /* 8 */ 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
1845+ 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,
1846+ /* 9 */ 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
1847+ 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,
1848+ /* A */ 0x01A0, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x01A6, 0x01A8,
1849+ 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01AF,
1850+ /* B */ 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,
1851+ 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
1852+ /* C */ 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9,
1853+ 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC, 0x01CD, 0x01CE, 0x01CF,
1854+ /* D */ 0x01D0, 0x01D1, 0x01D2, 0x01D3, 0x01D4, 0x01D5, 0x01D6, 0x01D7,
1855+ 0x01D8, 0x01D9, 0x01DA, 0x01DB, 0x01DC, 0x01DD, 0x01DE, 0x01DF,
1856+ /* E */ 0x01E0, 0x01E1, 0x01E2, 0x01E3, 0x01E5, 0x01E5, 0x01E6, 0x01E7,
1857+ 0x01E8, 0x01E9, 0x01EA, 0x01EB, 0x01EC, 0x01ED, 0x01EE, 0x01EF,
1858+ /* F */ 0x01F0, 0x01F3, 0x01F3, 0x01F3, 0x01F4, 0x01F5, 0x01F6, 0x01F7,
1859+ 0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF,
1860+
1861+ // Table 3 (for high byte 0x03)
1862+
1863+ /* 0 */ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307,
1864+ 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F,
1865+ /* 1 */ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317,
1866+ 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F,
1867+ /* 2 */ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327,
1868+ 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F,
1869+ /* 3 */ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337,
1870+ 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F,
1871+ /* 4 */ 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347,
1872+ 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F,
1873+ /* 5 */ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357,
1874+ 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F,
1875+ /* 6 */ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367,
1876+ 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F,
1877+ /* 7 */ 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377,
1878+ 0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F,
1879+ /* 8 */ 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387,
1880+ 0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F,
1881+ /* 9 */ 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
1882+ 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
1883+ /* A */ 0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
1884+ 0x03C8, 0x03C9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
1885+ /* B */ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
1886+ 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
1887+ /* C */ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
1888+ 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF,
1889+ /* D */ 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
1890+ 0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF,
1891+ /* E */ 0x03E0, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,
1892+ 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
1893+ /* F */ 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7,
1894+ 0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF,
1895+
1896+ // Table 4 (for high byte 0x04)
1897+
1898+ /* 0 */ 0x0400, 0x0401, 0x0452, 0x0403, 0x0454, 0x0455, 0x0456, 0x0407,
1899+ 0x0458, 0x0459, 0x045A, 0x045B, 0x040C, 0x040D, 0x040E, 0x045F,
1900+ /* 1 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
1901+ 0x0438, 0x0419, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
1902+ /* 2 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
1903+ 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
1904+ /* 3 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
1905+ 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
1906+ /* 4 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
1907+ 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
1908+ /* 5 */ 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
1909+ 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F,
1910+ /* 6 */ 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467,
1911+ 0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F,
1912+ /* 7 */ 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0476, 0x0477,
1913+ 0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F,
1914+ /* 8 */ 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,
1915+ 0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F,
1916+ /* 9 */ 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497,
1917+ 0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F,
1918+ /* A */ 0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7,
1919+ 0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF,
1920+ /* B */ 0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7,
1921+ 0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF,
1922+ /* C */ 0x04C0, 0x04C1, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8,
1923+ 0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF,
1924+ /* D */ 0x04D0, 0x04D1, 0x04D2, 0x04D3, 0x04D4, 0x04D5, 0x04D6, 0x04D7,
1925+ 0x04D8, 0x04D9, 0x04DA, 0x04DB, 0x04DC, 0x04DD, 0x04DE, 0x04DF,
1926+ /* E */ 0x04E0, 0x04E1, 0x04E2, 0x04E3, 0x04E4, 0x04E5, 0x04E6, 0x04E7,
1927+ 0x04E8, 0x04E9, 0x04EA, 0x04EB, 0x04EC, 0x04ED, 0x04EE, 0x04EF,
1928+ /* F */ 0x04F0, 0x04F1, 0x04F2, 0x04F3, 0x04F4, 0x04F5, 0x04F6, 0x04F7,
1929+ 0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF,
1930+
1931+ // Table 5 (for high byte 0x05)
1932+
1933+ /* 0 */ 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507,
1934+ 0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F,
1935+ /* 1 */ 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517,
1936+ 0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F,
1937+ /* 2 */ 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527,
1938+ 0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F,
1939+ /* 3 */ 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
1940+ 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
1941+ /* 4 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
1942+ 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
1943+ /* 5 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557,
1944+ 0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F,
1945+ /* 6 */ 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,
1946+ 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,
1947+ /* 7 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,
1948+ 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,
1949+ /* 8 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587,
1950+ 0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F,
1951+ /* 9 */ 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597,
1952+ 0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F,
1953+ /* A */ 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7,
1954+ 0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF,
1955+ /* B */ 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
1956+ 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
1957+ /* C */ 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7,
1958+ 0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF,
1959+ /* D */ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
1960+ 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
1961+ /* E */ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
1962+ 0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF,
1963+ /* F */ 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7,
1964+ 0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF,
1965+
1966+ // Table 6 (for high byte 0x10)
1967+
1968+ /* 0 */ 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
1969+ 0x1008, 0x1009, 0x100A, 0x100B, 0x100C, 0x100D, 0x100E, 0x100F,
1970+ /* 1 */ 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017,
1971+ 0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, 0x101E, 0x101F,
1972+ /* 2 */ 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
1973+ 0x1028, 0x1029, 0x102A, 0x102B, 0x102C, 0x102D, 0x102E, 0x102F,
1974+ /* 3 */ 0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037,
1975+ 0x1038, 0x1039, 0x103A, 0x103B, 0x103C, 0x103D, 0x103E, 0x103F,
1976+ /* 4 */ 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047,
1977+ 0x1048, 0x1049, 0x104A, 0x104B, 0x104C, 0x104D, 0x104E, 0x104F,
1978+ /* 5 */ 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057,
1979+ 0x1058, 0x1059, 0x105A, 0x105B, 0x105C, 0x105D, 0x105E, 0x105F,
1980+ /* 6 */ 0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, 0x1066, 0x1067,
1981+ 0x1068, 0x1069, 0x106A, 0x106B, 0x106C, 0x106D, 0x106E, 0x106F,
1982+ /* 7 */ 0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077,
1983+ 0x1078, 0x1079, 0x107A, 0x107B, 0x107C, 0x107D, 0x107E, 0x107F,
1984+ /* 8 */ 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087,
1985+ 0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F,
1986+ /* 9 */ 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097,
1987+ 0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x109F,
1988+ /* A */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7,
1989+ 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
1990+ /* B */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7,
1991+ 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
1992+ /* C */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10C6, 0x10C7,
1993+ 0x10C8, 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF,
1994+ /* D */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7,
1995+ 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF,
1996+ /* E */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7,
1997+ 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF,
1998+ /* F */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, 0x10F7,
1999+ 0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, 0x10FD, 0x10FE, 0x10FF,
2000+
2001+ // Table 7 (for high byte 0x20)
2002+
2003+ /* 0 */ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
2004+ 0x2008, 0x2009, 0x200A, 0x200B, 0x0000, 0x0000, 0x0000, 0x0000,
2005+ /* 1 */ 0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017,
2006+ 0x2018, 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E, 0x201F,
2007+ /* 2 */ 0x2020, 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027,
2008+ 0x2028, 0x2029, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x202F,
2009+ /* 3 */ 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037,
2010+ 0x2038, 0x2039, 0x203A, 0x203B, 0x203C, 0x203D, 0x203E, 0x203F,
2011+ /* 4 */ 0x2040, 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047,
2012+ 0x2048, 0x2049, 0x204A, 0x204B, 0x204C, 0x204D, 0x204E, 0x204F,
2013+ /* 5 */ 0x2050, 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057,
2014+ 0x2058, 0x2059, 0x205A, 0x205B, 0x205C, 0x205D, 0x205E, 0x205F,
2015+ /* 6 */ 0x2060, 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067,
2016+ 0x2068, 0x2069, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2017+ /* 7 */ 0x2070, 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077,
2018+ 0x2078, 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F,
2019+ /* 8 */ 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087,
2020+ 0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, 0x208E, 0x208F,
2021+ /* 9 */ 0x2090, 0x2091, 0x2092, 0x2093, 0x2094, 0x2095, 0x2096, 0x2097,
2022+ 0x2098, 0x2099, 0x209A, 0x209B, 0x209C, 0x209D, 0x209E, 0x209F,
2023+ /* A */ 0x20A0, 0x20A1, 0x20A2, 0x20A3, 0x20A4, 0x20A5, 0x20A6, 0x20A7,
2024+ 0x20A8, 0x20A9, 0x20AA, 0x20AB, 0x20AC, 0x20AD, 0x20AE, 0x20AF,
2025+ /* B */ 0x20B0, 0x20B1, 0x20B2, 0x20B3, 0x20B4, 0x20B5, 0x20B6, 0x20B7,
2026+ 0x20B8, 0x20B9, 0x20BA, 0x20BB, 0x20BC, 0x20BD, 0x20BE, 0x20BF,
2027+ /* C */ 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7,
2028+ 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF,
2029+ /* D */ 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7,
2030+ 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x20DF,
2031+ /* E */ 0x20E0, 0x20E1, 0x20E2, 0x20E3, 0x20E4, 0x20E5, 0x20E6, 0x20E7,
2032+ 0x20E8, 0x20E9, 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF,
2033+ /* F */ 0x20F0, 0x20F1, 0x20F2, 0x20F3, 0x20F4, 0x20F5, 0x20F6, 0x20F7,
2034+ 0x20F8, 0x20F9, 0x20FA, 0x20FB, 0x20FC, 0x20FD, 0x20FE, 0x20FF,
2035+
2036+ // Table 8 (for high byte 0x21)
2037+
2038+ /* 0 */ 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107,
2039+ 0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F,
2040+ /* 1 */ 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117,
2041+ 0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F,
2042+ /* 2 */ 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127,
2043+ 0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F,
2044+ /* 3 */ 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137,
2045+ 0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F,
2046+ /* 4 */ 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147,
2047+ 0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F,
2048+ /* 5 */ 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157,
2049+ 0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F,
2050+ /* 6 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
2051+ 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
2052+ /* 7 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,
2053+ 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,
2054+ /* 8 */ 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187,
2055+ 0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F,
2056+ /* 9 */ 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197,
2057+ 0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F,
2058+ /* A */ 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7,
2059+ 0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF,
2060+ /* B */ 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7,
2061+ 0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF,
2062+ /* C */ 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7,
2063+ 0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF,
2064+ /* D */ 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7,
2065+ 0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF,
2066+ /* E */ 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7,
2067+ 0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF,
2068+ /* F */ 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7,
2069+ 0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF,
2070+
2071+ // Table 9 (for high byte 0xFE)
2072+
2073+ /* 0 */ 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07,
2074+ 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F,
2075+ /* 1 */ 0xFE10, 0xFE11, 0xFE12, 0xFE13, 0xFE14, 0xFE15, 0xFE16, 0xFE17,
2076+ 0xFE18, 0xFE19, 0xFE1A, 0xFE1B, 0xFE1C, 0xFE1D, 0xFE1E, 0xFE1F,
2077+ /* 2 */ 0xFE20, 0xFE21, 0xFE22, 0xFE23, 0xFE24, 0xFE25, 0xFE26, 0xFE27,
2078+ 0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, 0xFE2E, 0xFE2F,
2079+ /* 3 */ 0xFE30, 0xFE31, 0xFE32, 0xFE33, 0xFE34, 0xFE35, 0xFE36, 0xFE37,
2080+ 0xFE38, 0xFE39, 0xFE3A, 0xFE3B, 0xFE3C, 0xFE3D, 0xFE3E, 0xFE3F,
2081+ /* 4 */ 0xFE40, 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xFE45, 0xFE46, 0xFE47,
2082+ 0xFE48, 0xFE49, 0xFE4A, 0xFE4B, 0xFE4C, 0xFE4D, 0xFE4E, 0xFE4F,
2083+ /* 5 */ 0xFE50, 0xFE51, 0xFE52, 0xFE53, 0xFE54, 0xFE55, 0xFE56, 0xFE57,
2084+ 0xFE58, 0xFE59, 0xFE5A, 0xFE5B, 0xFE5C, 0xFE5D, 0xFE5E, 0xFE5F,
2085+ /* 6 */ 0xFE60, 0xFE61, 0xFE62, 0xFE63, 0xFE64, 0xFE65, 0xFE66, 0xFE67,
2086+ 0xFE68, 0xFE69, 0xFE6A, 0xFE6B, 0xFE6C, 0xFE6D, 0xFE6E, 0xFE6F,
2087+ /* 7 */ 0xFE70, 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE75, 0xFE76, 0xFE77,
2088+ 0xFE78, 0xFE79, 0xFE7A, 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F,
2089+ /* 8 */ 0xFE80, 0xFE81, 0xFE82, 0xFE83, 0xFE84, 0xFE85, 0xFE86, 0xFE87,
2090+ 0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, 0xFE8D, 0xFE8E, 0xFE8F,
2091+ /* 9 */ 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95, 0xFE96, 0xFE97,
2092+ 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E, 0xFE9F,
2093+ /* A */ 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7,
2094+ 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF,
2095+ /* B */ 0xFEB0, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7,
2096+ 0xFEB8, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF,
2097+ /* C */ 0xFEC0, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7,
2098+ 0xFEC8, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, 0xFECD, 0xFECE, 0xFECF,
2099+ /* D */ 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4, 0xFED5, 0xFED6, 0xFED7,
2100+ 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD, 0xFEDE, 0xFEDF,
2101+ /* E */ 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6, 0xFEE7,
2102+ 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF,
2103+ /* F */ 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7,
2104+ 0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0x0000,
2105+
2106+ // Table 10 (for high byte 0xFF)
2107+
2108+ /* 0 */ 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07,
2109+ 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F,
2110+ /* 1 */ 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17,
2111+ 0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F,
2112+ /* 2 */ 0xFF20, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
2113+ 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
2114+ /* 3 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
2115+ 0xFF58, 0xFF59, 0xFF5A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F,
2116+ /* 4 */ 0xFF40, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,
2117+ 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,
2118+ /* 5 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,
2119+ 0xFF58, 0xFF59, 0xFF5A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F,
2120+ /* 6 */ 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,
2121+ 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F,
2122+ /* 7 */ 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77,
2123+ 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F,
2124+ /* 8 */ 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87,
2125+ 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F,
2126+ /* 9 */ 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97,
2127+ 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F,
2128+ /* A */ 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7,
2129+ 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF,
2130+ /* B */ 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7,
2131+ 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF,
2132+ /* C */ 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7,
2133+ 0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF,
2134+ /* D */ 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7,
2135+ 0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF,
2136+ /* E */ 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7,
2137+ 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF,
2138+ /* F */ 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7,
2139+ 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF,
2140+};
2141diff -urN -x CVS linux-bk/fs/hfsplus/unicode.c linux-hfsplus/fs/hfsplus/unicode.c
2142--- linux-bk/fs/hfsplus/unicode.c Wed Dec 31 16:00:00 1969
2143+++ linux-hfsplus/fs/hfsplus/unicode.c Thu Dec 13 22:32:32 2001
2144@@ -0,0 +1,122 @@
2145+/*
2146+ * linux/fs/hfsplus/unicode.c
2147+ *
2148+ * Copyright (C) 2001
2149+ * Brad Boyer (flar@allandria.com)
2150+ *
2151+ * Handler routines for unicode strings
2152+ */
2153+
2154+#include <linux/types.h>
2155+#include <linux/nls.h>
2156+#include <linux/hfsplus_fs.h>
2157+#include <linux/hfsplus_raw.h>
2158+
2159+/* Fold the case of a unicode char, given the 16 bit value */
2160+/* Returns folded char, or 0 if ignorable */
2161+static inline hfsp_u16 case_fold(hfsp_u16 c)
2162+{
2163+ hfsp_u16 tmp;
2164+
2165+ tmp = case_fold_table[(c>>8)];
2166+ if(tmp)
2167+ tmp = case_fold_table[tmp + (c & 0xFF)];
2168+ else
2169+ tmp = c;
2170+ return tmp;
2171+}
2172+
2173+/* Compare unicode strings, return values like normal strcmp */
2174+int hfsplus_unistrcmp(hfsplus_unistr *s1, hfsplus_unistr *s2)
2175+{
2176+ hfsp_u16 len1, len2, c1, c2;
2177+ hfsplus_unichr *p1, *p2;
2178+
2179+ len1 = hfsp_get_hs(s1->length);
2180+ len2 = hfsp_get_hs(s2->length);
2181+ p1 = s1->unicode;
2182+ p2 = s2->unicode;
2183+
2184+ while(1) {
2185+ c1 = c2 = 0;
2186+
2187+ while(len1 && !c1) {
2188+ c1 = case_fold(hfsp_get_hs(p1++));
2189+ len1--;
2190+ }
2191+ while(len2 && !c2) {
2192+ c2 = case_fold(hfsp_get_hs(p2++));
2193+ len2--;
2194+ }
2195+
2196+ if(c1 != c2)
2197+ return (c1 < c2) ? -1 : 1;
2198+ if(!c1 && !c2)
2199+ return 0;
2200+ }
2201+}
2202+
2203+int hfsplus_uni2asc(hfsplus_unistr *ustr, char *astr, int *len)
2204+{
2205+ const hfsp_u16 *ip;
2206+ hfsp_u8 *op;
2207+ hfsp_u16 ustrlen, cc;
2208+ int size, tmp;
2209+
2210+ op = astr;
2211+ ip = (hfsp_u16 *)(ustr->unicode);
2212+ ustrlen = hfsp_get_hs(ustr->length);
2213+ tmp = *len;
2214+ while((ustrlen > 0) && (tmp > 0)) {
2215+ cc = hfsp_get_hs(ip);
2216+ if(cc > 0x7f) {
2217+ size = utf8_wctomb(op, cc, tmp);
2218+ if(size == -1) {
2219+ /* ignore */
2220+ } else {
2221+ op += size;
2222+ tmp -= size;
2223+ }
2224+ } else {
2225+ *op++ = (hfsp_u8) cc;
2226+ tmp--;
2227+ }
2228+ ip++;
2229+ ustrlen--;
2230+ }
2231+ *len = (char *)op - astr;
2232+ if(ustrlen)
2233+ return -ENAMETOOLONG;
2234+ return 0;
2235+}
2236+
2237+int hfsplus_asc2uni(hfsplus_unistr *ustr, char *astr, int len)
2238+{
2239+ int tmp;
2240+ wchar_t c;
2241+ hfsp_u16 outlen = 0;
2242+
2243+ while((outlen <= HFSPLUS_MAX_STRLEN) && (len > 0)) {
2244+ if(*astr & 0x80) {
2245+ if((tmp = utf8_mbtowc(&c, astr, len)) < 0) {
2246+ astr++;
2247+ len--;
2248+ continue;
2249+ } else {
2250+ astr += tmp;
2251+ len -= tmp;
2252+ }
2253+ } else {
2254+ c = *astr++;
2255+ len--;
2256+ }
2257+ hfsp_put_hs(c, ustr->unicode + outlen);
2258+ outlen++;
2259+ }
2260+ hfsp_put_hs(outlen, ustr->length);
2261+ if(len > 0)
2262+ return -ENAMETOOLONG;
2263+ return 0;
2264+}
2265+
2266+
2267diff -urN -x CVS linux-bk/fs/hfsplus/wrapper.c linux-hfsplus/fs/hfsplus/wrapper.c
2268--- linux-bk/fs/hfsplus/wrapper.c Wed Dec 31 16:00:00 1969
2269+++ linux-hfsplus/fs/hfsplus/wrapper.c Mon Nov 5 00:11:34 2001
d2cc4c33 2270@@ -0,0 +1,121 @@
1eec6804 2271+/*
2272+ * linux/fs/hfsplus/wrapper.c
2273+ *
2274+ * Copyright (C) 2001
2275+ * Brad Boyer (flar@allandria.com)
2276+ *
2277+ * Handling of HFS wrappers around HFS+ volumes
2278+ */
2279+
2280+#include <linux/fs.h>
2281+#include <linux/hfsplus_fs.h>
2282+#include <linux/hfsplus_raw.h>
d2cc4c33 2283+#include <linux/blkdev.h>
1eec6804 2284+
2285+struct hfsplus_wd {
2286+ hfsp_u32 ablk_size;
2287+ hfsp_u16 ablk_start;
2288+ hfsp_u16 embed_start;
2289+ hfsp_u16 embed_count;
2290+};
2291+
2292+static int hfsplus_read_mdb(unsigned char *bufptr, struct hfsplus_wd *wd)
2293+{
2294+ hfsp_u32 extent;
2295+ hfsp_u16 attrib;
2296+
2297+ if(hfsp_get_hs(bufptr + HFSP_WRAPOFF_EMBEDSIG) != HFSPLUS_VOLHEAD_SIG)
2298+ return 0;
2299+
2300+ attrib = hfsp_get_hs(bufptr + HFSP_WRAPOFF_ATTRIB);
2301+ if(!(attrib & HFSP_WRAP_ATTRIB_SLOCK) ||
2302+ !(attrib & HFSP_WRAP_ATTRIB_SPARED))
2303+ return 0;
2304+
2305+ wd->ablk_size = hfsp_get_hl(bufptr + HFSP_WRAPOFF_ABLKSIZE);
2306+ if(wd->ablk_size < HFSPLUS_SECTOR_SIZE)
2307+ return 0;
2308+ if(wd->ablk_size % HFSPLUS_SECTOR_SIZE)
2309+ return 0;
2310+ wd->ablk_start = hfsp_get_hs(bufptr + HFSP_WRAPOFF_ABLKSTART);
2311+
2312+ extent = hfsp_get_hl(bufptr + HFSP_WRAPOFF_EMBEDEXT);
2313+ wd->embed_start = (extent >> 16) & 0xFFFF;
2314+ wd->embed_count = extent & 0xFFFF;
2315+
2316+ return 1;
2317+}
2318+
2319+/* Find the volume header and fill in some minimum bits in superblock */
2320+/* Takes in super block, returns true if good data read */
2321+int hfsplus_read_wrapper(struct super_block *sb)
2322+{
2323+ struct buffer_head *bh;
2324+ struct hfsplus_vh *vhdr;
2325+ unsigned char *bufptr;
2326+ unsigned long block, offset, vhsect;
2327+ kdev_t dev = sb->s_dev;
2328+ struct hfsplus_wd wd;
2329+ int blocksize;
2330+ hfsp_u32 dblksz;
2331+ hfsp_u16 sig;
2332+
4f80396b 2333+ blocksize = get_hardsect_size(dev);
1eec6804 2334+ if((blocksize == 0) || (blocksize < HFSPLUS_SECTOR_SIZE)) {
2335+ blocksize = HFSPLUS_SECTOR_SIZE;
2336+ }
2337+ set_blocksize(dev, blocksize);
2338+
2339+ block = (HFSPLUS_VOLHEAD_SECTOR * HFSPLUS_SECTOR_SIZE) / blocksize;
2340+ offset = (HFSPLUS_VOLHEAD_SECTOR * HFSPLUS_SECTOR_SIZE) % blocksize;
2341+
2342+ if(!(bh = bread(dev, block, blocksize))) {
2343+ printk("HFS+-fs: unable to read VHDR or MDB\n");
2344+ return 0;
2345+ }
2346+
2347+ bufptr = ((unsigned char *)bh->b_data) + offset;
2348+ sig = hfsp_get_hs(bufptr + HFSP_WRAPOFF_SIG);
2349+ if(sig == HFSP_WRAP_MAGIC) {
2350+ if(!hfsplus_read_mdb(bufptr, &wd))
2351+ goto error;
2352+ vhsect = (wd.ablk_start + wd.embed_start * (wd.ablk_size >> 9))
2353+ + HFSPLUS_VOLHEAD_SECTOR;
2354+ block = (vhsect * HFSPLUS_SECTOR_SIZE) / blocksize;
2355+ offset = (vhsect * HFSPLUS_SECTOR_SIZE) % blocksize;
2356+ brelse(bh);
2357+ if(!(bh = bread(dev, block, blocksize))) {
2358+ printk("HFS+-fs: unable to read VHDR\n");
2359+ return 0;
2360+ }
2361+ } else {
2362+ wd.ablk_start = 0;
2363+ wd.ablk_size = blocksize;
2364+ wd.embed_start = 0;
2365+ }
2366+ vhdr = (struct hfsplus_vh *)(((char *)bh->b_data) + offset);
2367+ if(hfsp_get_hs(vhdr->signature) != HFSPLUS_VOLHEAD_SIG)
2368+ goto error;
2369+ dblksz = hfsp_get_hl(vhdr->blocksize);
2370+ if(wd.ablk_size && (wd.ablk_size % dblksz)) {
2371+ printk("HFS+-fs: embedded blocks not aligned with wrapper\n");
2372+ goto error;
2373+ }
2374+ if((blocksize > dblksz) && (dblksz % blocksize)) {
2375+ printk("HFS+-fs: volume blocks not aligned on device\n");
2376+ goto error;
2377+ }
2378+ HFSPLUS_SB(sb).dbpab = dblksz / blocksize;
2379+ HFSPLUS_SB(sb).dboff = (wd.ablk_start + wd.embed_start *
2380+ (wd.ablk_size >> 9)) * (blocksize >> 9);
2381+ sb->s_blocksize = blocksize;
2382+ sb->s_blocksize_bits = ffz(~(blocksize));
2383+
2384+ HFSPLUS_SB(sb).s_vhbh = bh;
2385+ HFSPLUS_SB(sb).s_vhdr = vhdr;
2386+
2387+ return 1;
2388+ error:
2389+ brelse(bh);
2390+ return 0;
2391+}
2392diff -urN -x CVS linux-bk/include/linux/fs.h linux-hfsplus/include/linux/fs.h
2393--- linux-bk/include/linux/fs.h Sun Mar 4 16:50:00 2001
2394+++ linux-hfsplus/include/linux/fs.h Tue Apr 10 22:48:28 2001
2395@@ -294,6 +294,7 @@
2396 #include <linux/shmem_fs.h>
2397 #include <linux/smb_fs_i.h>
2398 #include <linux/hfs_fs_i.h>
2399+#include <linux/hfsplus_fs_i.h>
2400 #include <linux/adfs_fs_i.h>
2401 #include <linux/qnx4_fs_i.h>
2402 #include <linux/reiserfs_fs_i.h>
2403@@ -457,6 +458,7 @@
2404 struct coda_inode_info coda_i;
2405 struct smb_inode_info smbfs_i;
2406 struct hfs_inode_info hfs_i;
2407+ struct hfsplus_inode_info hfsplus_i;
2408 struct adfs_inode_info adfs_i;
2409 struct qnx4_inode_info qnx4_i;
2410 struct reiserfs_inode_info reiserfs_i;
2411@@ -635,6 +637,7 @@
2412 #include <linux/romfs_fs_sb.h>
2413 #include <linux/smb_fs_sb.h>
2414 #include <linux/hfs_fs_sb.h>
2415+#include <linux/hfsplus_fs_sb.h>
2416 #include <linux/adfs_fs_sb.h>
2417 #include <linux/qnx4_fs_sb.h>
2418 #include <linux/reiserfs_fs_sb.h>
2419@@ -685,6 +688,7 @@
2420 struct romfs_sb_info romfs_sb;
2421 struct smb_sb_info smbfs_sb;
2422 struct hfs_sb_info hfs_sb;
2423+ struct hfsplus_sb_info hfsplus_sb;
2424 struct adfs_sb_info adfs_sb;
2425 struct qnx4_sb_info qnx4_sb;
2426 struct reiserfs_sb_info reiserfs_sb;
2427diff -urN -x CVS linux-bk/include/linux/hfsplus_fs.h linux-hfsplus/include/linux/hfsplus_fs.h
2428--- linux-bk/include/linux/hfsplus_fs.h Wed Dec 31 16:00:00 1969
2429+++ linux-hfsplus/include/linux/hfsplus_fs.h Mon Nov 5 00:01:52 2001
2430@@ -0,0 +1,170 @@
2431+/*
2432+ * linux/include/linux/hfsplus_fs.h
2433+ *
2434+ * Copyright (C) 1999
2435+ * Brad Boyer (flar@pants.nu)
2436+ *
2437+ */
2438+
2439+#ifndef _LINUX_HFSPLUS_FS_H
2440+#define _LINUX_HFSPLUS_FS_H
2441+
2442+#include <linux/fs.h>
2443+
2444+#include <asm/unaligned.h>
2445+
2446+#include <linux/hfsplus_raw.h>
2447+#include <linux/hfsplus_fs_sb.h>
2448+
2449+typedef __u8 hfsp_u8;
2450+typedef __u16 hfsp_u16;
2451+typedef __u32 hfsp_u32;
2452+typedef __u64 hfsp_u64;
2453+typedef __u32 hfsp_cnid;
2454+
2455+/* Runtime config options */
2456+#define HFSPLUS_CASE_ASIS 0
2457+#define HFSPLUS_CASE_LOWER 1
2458+
2459+#define HFSPLUS_FORK_RAW 0
2460+#define HFSPLUS_FORK_CAP 1
2461+#define HFSPLUS_FORK_DOUBLE 2
2462+#define HFSPLUS_FORK_NETATALK 3
2463+
2464+#define HFSPLUS_NAMES_TRIVIAL 0
2465+#define HFSPLUS_NAMES_CAP 1
2466+#define HFSPLUS_NAMES_NETATALK 2
2467+#define HFSPLUS_NAMES_7BIT 3
2468+
2469+#define HFSPLUS_DEF_CR_TYPE 0x3F3F3F3F /* '????' */
2470+
2471+#define HFSPLUS_TYPE_DATA 0x00
2472+#define HFSPLUS_TYPE_RSRC 0xFF
2473+
2474+struct hfsplus_btree;
2475+struct page;
2476+
2477+/* An HFS+ BTree node in memory */
2478+typedef struct {
2479+ struct hfsplus_btree *tree;
2480+ struct page *page;
2481+ struct inode *inode;
2482+
2483+ hfsp_u32 prev;
2484+ hfsp_u32 this;
2485+ hfsp_u32 next;
2486+
2487+ hfsp_u16 num_recs;
2488+ hfsp_u8 kind;
2489+ hfsp_u8 height;
2490+} hfsplus_bnode;
2491+
2492+typedef int (*btree_keycmp)(hfsplus_btree_key *, hfsplus_btree_key *);
2493+
2494+/* An HFS+ BTree held in memory */
2495+typedef struct hfsplus_btree {
2496+ struct super_block *sb;
2497+ btree_keycmp keycmp;
2498+
2499+ hfsp_u32 cnid;
2500+ hfsp_u32 root;
2501+ hfsp_u32 node_count;
2502+ hfsp_u32 free_nodes;
2503+ hfsp_u32 attributes;
2504+
2505+ hfsp_u16 node_size;
2506+ hfsp_u16 max_key_len;
2507+ hfsp_u16 depth;
2508+} hfsplus_btree;
2509+
2510+/* An iterator for walking an HFS+ BTree */
2511+typedef struct {
2512+ hfsplus_btree *tree;
2513+ hfsp_u32 node;
2514+ hfsp_u16 rec;
2515+} hfsplus_btiter;
2516+
2517+/*
2518+ * Functions in any *.c used in other files
2519+ */
2520+
2521+/* bfind.c */
2522+int hfsplus_btfind(hfsplus_btree *, hfsplus_btree_key *, void *, int *);
2523+int hfsplus_btfind_exact(hfsplus_btree *, hfsplus_btree_key *, void *, int *);
2524+int hfsplus_btiter_find(hfsplus_btiter *, hfsplus_btree_key *);
2525+
2526+/* bnode.c */
2527+hfsplus_bnode *hfsplus_get_bnode(hfsplus_btree *, hfsp_u32);
2528+void hfsplus_put_bnode(hfsplus_bnode *);
2529+hfsp_u16 hfsplus_bnode_copybytes(hfsplus_bnode *, void *, hfsp_u16, hfsp_u16);
2530+
2531+/* brec.c */
2532+hfsp_u16 hfsplus_brec_off(hfsplus_bnode *, hfsp_u16);
2533+hfsp_u16 hfsplus_brec_len(hfsplus_bnode *, hfsp_u16);
2534+hfsp_u16 hfsplus_brec_lenoff(hfsplus_bnode *, hfsp_u16, hfsp_u16 *);
2535+hfsp_u16 hfsplus_brec_data(hfsplus_bnode *, hfsp_u16, char *, hfsp_u16);
2536+hfsp_u16 hfsplus_brec_keylen(hfsplus_bnode *, hfsp_u16);
2537+hfsp_u16 hfsplus_brec_key(hfsplus_bnode *, hfsp_u16, void *, hfsp_u16);
2538+
2539+/* btiter.c */
2540+void hfsplus_btiter_setup(hfsplus_btiter *, hfsplus_btree *);
2541+int hfsplus_btiter_move(hfsplus_btiter *, int);
2542+int hfsplus_btiter_get(hfsplus_btiter *, hfsplus_btree_key *, void *, int *);
2543+
2544+/* btree.c */
2545+hfsplus_btree *hfsplus_open_btree(struct super_block *, hfsp_cnid);
2546+void hfsplus_close_btree(struct hfsplus_btree *);
2547+
2548+/* catalog.c */
2549+int hfsplus_cmp_cat_key(hfsplus_btree_key *, hfsplus_btree_key *);
2550+int hfsplus_fill_cat_key(hfsplus_btree_key *, hfsp_cnid, char *, int);
2551+int hfsplus_find_cat(struct super_block *, unsigned long, hfsplus_cat_entry *);
2552+
2553+/* extents.c */
2554+int hfsplus_cmp_ext_key(hfsplus_btree_key *, hfsplus_btree_key *);
2555+void hfsplus_fill_ext_key(hfsplus_btree_key *, hfsp_u32, hfsp_u32, hfsp_u8);
2556+int hfsplus_get_block(struct inode *, long, struct buffer_head *, int);
2557+
2558+/* inode.c */
2559+int hfsplus_cat_fill_inode(struct inode *, hfsplus_cat_entry *);
2560+
2561+/* options.c */
2562+int parse_options(char *, struct hfsplus_sb_info *);
2563+void fill_defaults(struct hfsplus_sb_info *);
2564+void fill_current(struct hfsplus_sb_info *, struct hfsplus_sb_info *);
2565+
2566+/* tables.c */
2567+extern hfsp_u16 case_fold_table[];
2568+
2569+/* unicode.c */
2570+int hfsplus_unistrcmp(hfsplus_unistr *, hfsplus_unistr *);
2571+int hfsplus_uni2asc(hfsplus_unistr *, char *, int *);
2572+int hfsplus_asc2uni(hfsplus_unistr *, char *, int);
2573+
2574+/* wrapper.c */
2575+int hfsplus_read_wrapper(struct super_block *);
2576+
2577+/* access macros */
2578+#define HFSPLUS_SB(super) ((super)->u.hfsplus_sb)
2579+#define HFSPLUS_I(inode) ((inode)->u.hfsplus_i)
2580+
2581+#define HFSPLUS_IS_DATA(inode) (1)
2582+#define HFSPLUS_IS_RSRC(inode) (0)
2583+
2584+#define hfsp_get_hs(addr) ntohs(*((hfsp_u16 *)(addr)))
2585+#define hfsp_get_hl(addr) ntohl(get_unaligned((hfsp_u32 *)(addr)))
2586+#define hfsp_get_ahl(addr) ntohl(*((hfsp_u32 *)(addr)))
2587+#define hfsp_get_hll(addr) __be64_to_cpu(get_unaligned((hfsp_u64 *)(addr)))
2588+#define hfsp_get_ahll(addr) __be64_to_cpu(*((hfsp_u64 *)(addr)))
2589+#define hfsp_put_hs(val, addr) ((void)(*((hfsp_u16 *)(addr)) = ntohs(val)))
2590+#define hfsp_put_hl(val, addr) put_unaligned(htonl(val), (hfsp_u32 *)(addr))
2591+#define hfsp_put_ahl(val, addr) ((void)(*((hfsp_u32 *)(addr)) = ntohl(val)))
2592+#define hfsp_put_hll(val, addr) put_unaligned(__cpu_to_be64(val), \
2593+ (hfsp_u64 *)(addr))
2594+#define hfsp_put_ahll(val, addr) ((void)(*((hfsp_u64 *)(addr)) = \
2595+ __cpu_to_be64(val)))
2596+
2597+/* time macros */
2598+#define hfsp_mt2ut(t) (hfsp_get_hl(t) - 2082844800U)
2599+
2600+#endif
2601diff -urN -x CVS linux-bk/include/linux/hfsplus_fs_i.h linux-hfsplus/include/linux/hfsplus_fs_i.h
2602--- linux-bk/include/linux/hfsplus_fs_i.h Wed Dec 31 16:00:00 1969
2603+++ linux-hfsplus/include/linux/hfsplus_fs_i.h Mon Sep 3 22:57:43 2001
2604@@ -0,0 +1,23 @@
2605+/*
2606+ * linux/include/linux/hfsplus_fs_i.h
2607+ *
2608+ * Copyright (C) 1999
2609+ * Brad Boyer (flar@pants.nu)
2610+ *
2611+ */
2612+
2613+#ifndef _LINUX_HFSPLUS_FS_I_H
2614+#define _LINUX_HFSPLUS_FS_I_H
2615+
2616+#include <linux/types.h>
2617+
2618+struct hfsplus_fork;
2619+
2620+struct hfsplus_inode_info {
2621+ /* Number of subdirectories in a directory */
2622+ nlink_t ndirs;
2623+ /* Device number in hfsplus_permissions in catalog */
2624+ __u32 dev;
2625+};
2626+
2627+#endif
2628diff -urN -x CVS linux-bk/include/linux/hfsplus_fs_sb.h linux-hfsplus/include/linux/hfsplus_fs_sb.h
2629--- linux-bk/include/linux/hfsplus_fs_sb.h Wed Dec 31 16:00:00 1969
2630+++ linux-hfsplus/include/linux/hfsplus_fs_sb.h Sat Oct 20 23:33:18 2001
2631@@ -0,0 +1,50 @@
2632+/*
2633+ * linux/include/linux/hfsplus_fs_sb.h
2634+ *
2635+ * Copyright (C) 1999
2636+ * Brad Boyer (flar@pants.nu)
2637+ *
2638+ */
2639+
2640+#ifndef _LINUX_HFSPLUS_FS_SB_H
2641+#define _LINUX_HFSPLUS_FS_SB_H
2642+
2643+#include <asm/types.h>
2644+
2645+/*
2646+ * HFS+ superblock info (built from Volume Header on disk)
2647+ */
2648+
2649+struct hfsplus_vh;
2650+struct hfsplus_btree;
2651+
2652+struct hfsplus_sb_info {
2653+ struct buffer_head *s_vhbh;
2654+ struct hfsplus_vh *s_vhdr;
2655+ struct hfsplus_btree *ext_tree;
2656+ struct hfsplus_btree *cat_tree;
2657+
2658+ /* Runtime variables */
2659+ __u32 dbpab; /* Device blocks per allocation block */
2660+ __u32 dboff; /* Offset to actual HFS+ blocks */
2661+
2662+ /* Stuff in host order from Vol Header */
2663+ __u32 free_blocks;
2664+ __u32 next_cnid;
2665+ __u32 file_count;
2666+ __u32 folder_count;
2667+
2668+ /* Config options */
2669+ __u32 creator;
2670+ __u32 type;
2671+
2672+ int charcase;
2673+ int fork;
2674+ int namemap;
2675+
2676+ umode_t umask;
2677+ uid_t uid;
2678+ gid_t gid;
2679+};
2680+
2681+#endif
2682diff -urN -x CVS linux-bk/include/linux/hfsplus_raw.h linux-hfsplus/include/linux/hfsplus_raw.h
2683--- linux-bk/include/linux/hfsplus_raw.h Wed Dec 31 16:00:00 1969
2684+++ linux-hfsplus/include/linux/hfsplus_raw.h Thu Dec 13 22:11:55 2001
2685@@ -0,0 +1,314 @@
2686+/*
2687+ * linux/include/linux/hfsplus_raw.h
2688+ *
2689+ * Copyright (C) 1999
2690+ * Brad Boyer (flar@pants.nu)
2691+ *
2692+ * Format of structures on disk
2693+ * Information taken from Apple Technote #1150 (HFS Plus Volume Format)
2694+ *
2695+ */
2696+
2697+#ifndef _LINUX_HFSPLUS_RAW_H
2698+#define _LINUX_HFSPLUS_RAW_H
2699+
2700+#include <asm/types.h>
2701+
2702+/* Some constants */
2703+#define HFSPLUS_SECTOR_SIZE 512
2704+#define HFSPLUS_VOLHEAD_SECTOR 2
2705+#define HFSPLUS_VOLHEAD_SIG 0x482b
2706+#define HFSPLUS_SUPER_MAGIC 0x482b
2707+#define HFSPLUS_CURRENT_VERSION 4
2708+
2709+#define HFSP_WRAP_MAGIC 0x4244
2710+#define HFSP_WRAP_ATTRIB_SLOCK 0x8000
2711+#define HFSP_WRAP_ATTRIB_SPARED 0x0200
2712+
2713+#define HFSP_WRAPOFF_SIG 0x00
2714+#define HFSP_WRAPOFF_ATTRIB 0x0A
2715+#define HFSP_WRAPOFF_ABLKSIZE 0x14
2716+#define HFSP_WRAPOFF_ABLKSTART 0x1C
2717+#define HFSP_WRAPOFF_EMBEDSIG 0x7C
2718+#define HFSP_WRAPOFF_EMBEDEXT 0x7E
2719+
2720+/* Structures used on disk */
2721+
2722+typedef unsigned char hfsp_byte;
2723+typedef unsigned char hfsp_word[2];
2724+typedef unsigned char hfsp_lword[4];
2725+typedef unsigned char hfsp_llword[8];
2726+
2727+typedef hfsp_lword hfsplus_cnid;
2728+typedef hfsp_word hfsplus_unichr;
2729+
2730+/* A "string" as used in filenames, etc. */
2731+typedef struct {
2732+ hfsp_word length;
2733+ hfsplus_unichr unicode[255];
2734+} hfsplus_unistr;
2735+
2736+#define HFSPLUS_MAX_STRLEN 255
2737+
2738+/* POSIX permissions */
2739+typedef struct {
2740+ hfsp_lword owner;
2741+ hfsp_lword group;
2742+ hfsp_lword mode;
2743+ hfsp_lword dev;
2744+} hfsplus_perm;
2745+
2746+/* A single contiguous area of a file */
2747+typedef struct {
2748+ hfsp_lword start_block;
2749+ hfsp_lword block_count;
2750+} hfsplus_extent;
2751+typedef hfsplus_extent hfsplus_extent_rec[8];
2752+
2753+/* Information for a "Fork" in a file */
2754+typedef struct {
2755+ hfsp_llword total_size;
2756+ hfsp_lword clump_size;
2757+ hfsp_lword total_blocks;
2758+ hfsplus_extent_rec extents;
2759+} hfsplus_fork_raw;
2760+
2761+/* HFS+ Volume Header */
2762+typedef struct hfsplus_vh{
2763+ hfsp_word signature;
2764+ hfsp_word version;
2765+ hfsp_lword attributes;
2766+ hfsp_lword last_mount_vers;
2767+ hfsp_lword reserved;
2768+
2769+ hfsp_lword create_date;
2770+ hfsp_lword modify_date;
2771+ hfsp_lword backup_date;
2772+ hfsp_lword checked_date;
2773+
2774+ hfsp_lword file_count;
2775+ hfsp_lword folder_count;
2776+
2777+ hfsp_lword blocksize;
2778+ hfsp_lword total_blocks;
2779+ hfsp_lword free_blocks;
2780+
2781+ hfsp_lword next_alloc;
2782+ hfsp_lword rsrc_clump_sz;
2783+ hfsp_lword data_clump_sz;
2784+ hfsplus_cnid next_cnid;
2785+
2786+ hfsp_lword write_count;
2787+ hfsp_llword encodings_bmp;
2788+
2789+ hfsp_byte finder_info[32];
2790+
2791+ hfsplus_fork_raw alloc_file;
2792+ hfsplus_fork_raw ext_file;
2793+ hfsplus_fork_raw cat_file;
2794+ hfsplus_fork_raw attr_file;
2795+ hfsplus_fork_raw start_file;
2796+} hfsplus_vh;
2797+
2798+/* HFS+ volume attributes */
2799+#define HFSPLUS_VOL_UNMNT (1 << 8)
2800+#define HFSPLUS_VOL_SPARE_BLK (1 << 9)
2801+#define HFSPLUS_VOL_NOCACHE (1 << 10)
2802+#define HFSPLUS_VOL_INCNSTNT (1 << 11)
2803+#define HFSPLUS_VOL_SOFTLOCK (1 << 15)
2804+
2805+/* HFS+ BTree node descriptor */
2806+typedef struct {
2807+ hfsp_lword next;
2808+ hfsp_lword prev;
2809+ hfsp_byte kind;
2810+ hfsp_byte height;
2811+ hfsp_word num_rec;
2812+ hfsp_word reserved;
2813+} hfsplus_btree_node_desc;
2814+
2815+/* HFS+ BTree node types */
2816+#define HFSPLUS_NODE_NDX 0x00
2817+#define HFSPLUS_NODE_HEAD 0x01
2818+#define HFSPLUS_NODE_MAP 0x02
2819+#define HFSPLUS_NODE_LEAF 0xFF
2820+
2821+/* HFS+ BTree header */
2822+typedef struct {
2823+ hfsp_word depth;
2824+ hfsp_lword root;
2825+ hfsp_lword leaf_count;
2826+ hfsp_lword leaf_head;
2827+ hfsp_lword leaf_tail;
2828+ hfsp_word node_size;
2829+ hfsp_word max_key_len;
2830+ hfsp_lword node_count;
2831+ hfsp_lword free_nodes;
2832+ hfsp_word reserved1;
2833+ hfsp_lword clump_size;
2834+ hfsp_byte btree_type;
2835+ hfsp_byte reserved2;
2836+ hfsp_lword attributes;
2837+ hfsp_lword reserved3[16];
2838+} hfsplus_btree_head;
2839+
2840+/* BTree attributes */
2841+#define HFSPLUS_TREE_BIGKEYS 2
2842+#define HFSPLUS_TREE_VAR_NDXKEY_SIZE 4
2843+
2844+/* HFS+ BTree misc info */
2845+#define HFSPLUS_TREE_HEAD 0
2846+#define HFSPLUS_NODE_MXSZ 32768
2847+
2848+/* Some special File ID numbers (stolen from hfs.h) */
2849+#define HFSPLUS_POR_CNID 1 /* Parent Of the Root */
2850+#define HFSPLUS_ROOT_CNID 2 /* ROOT directory */
2851+#define HFSPLUS_EXT_CNID 3 /* EXTents B-tree */
2852+#define HFSPLUS_CAT_CNID 4 /* CATalog B-tree */
2853+#define HFSPLUS_BAD_CNID 5 /* BAD blocks file */
2854+#define HFSPLUS_ALLOC_CNID 6 /* ALLOCation file */
2855+#define HFSPLUS_START_CNID 7 /* STARTup file */
2856+#define HFSPLUS_ATTR_CNID 8 /* ATTRibutes file */
2857+#define HFSPLUS_EXCH_CNID 15 /* ExchangeFiles temp id */
2858+
2859+/* HFS+ catalog entry key */
2860+typedef struct {
2861+ hfsplus_cnid parent;
2862+ hfsplus_unistr name;
2863+} hfsplus_cat_key;
2864+
2865+
2866+/* Structs from hfs.h */
2867+typedef struct {
2868+ hfsp_word v;
2869+ hfsp_word h;
2870+} hfsp_point;
2871+
2872+typedef struct {
2873+ hfsp_word top;
2874+ hfsp_word left;
2875+ hfsp_word bottom;
2876+ hfsp_word right;
2877+} hfsp_rect;
2878+
2879+
2880+/* HFS directory info (stolen from hfs.h */
2881+typedef struct {
2882+ hfsp_rect frRect;
2883+ hfsp_word frFlags;
2884+ hfsp_point frLocation;
2885+ hfsp_word frView;
2886+} DInfo;
2887+
2888+typedef struct {
2889+ hfsp_point frScroll;
2890+ hfsp_lword frOpenChain;
2891+ hfsp_word frUnused;
2892+ hfsp_word frComment;
2893+ hfsp_lword frPutAway;
2894+} DXInfo;
2895+
2896+/* HFS+ folder data (part of an hfsplus_cat_entry) */
2897+typedef struct {
2898+ hfsp_word flags;
2899+ hfsp_lword valence;
2900+ hfsplus_cnid id;
2901+ hfsp_lword create_date;
2902+ hfsp_lword content_mod_date;
2903+ hfsp_lword attribute_mod_date;
2904+ hfsp_lword access_date;
2905+ hfsp_lword backup_date;
2906+ hfsplus_perm permissions;
2907+ DInfo user_info;
2908+ DXInfo finder_info;
2909+ hfsp_lword text_encoding;
2910+ hfsp_lword reserved;
2911+} hfsplus_cat_folder;
2912+
2913+/* HFS file info (stolen from hfs.h) */
2914+typedef struct {
2915+ hfsp_lword fdType;
2916+ hfsp_lword fdCreator;
2917+ hfsp_word fdFlags;
2918+ hfsp_point fdLocation;
2919+ hfsp_word fdFldr;
2920+} FInfo;
2921+
2922+typedef struct {
2923+ hfsp_word fdIconID;
2924+ hfsp_byte fdUnused[8];
2925+ hfsp_word fdComment;
2926+ hfsp_lword fdPutAway;
2927+} FXInfo;
2928+
2929+/* HFS+ file data (part of a cat_entry) */
2930+typedef struct {
2931+ hfsp_word flags;
2932+ hfsp_lword reserved1;
2933+ hfsplus_cnid id;
2934+ hfsp_lword create_date;
2935+ hfsp_lword content_mod_date;
2936+ hfsp_lword attribute_mod_date;
2937+ hfsp_lword access_date;
2938+ hfsp_lword backup_date;
2939+ hfsplus_perm permissions;
2940+ FInfo user_info;
2941+ FXInfo finder_info;
2942+ hfsp_lword text_encoding;
2943+ hfsp_lword reserved2;
2944+
2945+ hfsplus_fork_raw data_fork;
2946+ hfsplus_fork_raw res_fork;
2947+} hfsplus_cat_file;
2948+
2949+/* File attribute bits */
2950+#define kHFSFileLockedBit 0x0000
2951+#define kHFSFileLockedMask 0x0001
2952+#define kHFSThreadExistsBit 0x0001
2953+#define kHFSThreadExistsMask 0x0002
2954+
2955+/* HFS+ catalog thread (part of a cat_entry) */
2956+typedef struct {
2957+ hfsp_word reserved;
2958+ hfsplus_cnid parentID;
2959+ hfsplus_unistr nodeName;
2960+} hfsplus_cat_thread;
2961+
2962+#define HFSPLUS_MIN_THREAD_SZ 10
2963+
2964+/* A data record in the catalog tree */
2965+typedef struct {
2966+ hfsp_word type;
2967+ union {
2968+ hfsplus_cat_folder folder;
2969+ hfsplus_cat_file file;
2970+ hfsplus_cat_thread thread;
2971+ } u;
2972+} hfsplus_cat_entry;
2973+
2974+/* HFS+ catalog entry type */
2975+#define HFSPLUS_FOLDER 0x0001
2976+#define HFSPLUS_FILE 0x0002
2977+#define HFSPLUS_FOLDER_THREAD 0x0003
2978+#define HFSPLUS_FILE_THREAD 0x0004
2979+
2980+/* HFS+ extents tree key */
2981+typedef struct {
2982+ hfsp_byte fork_type;
2983+ hfsp_byte pad;
2984+ hfsplus_cnid cnid;
2985+ hfsp_lword start_block;
2986+} hfsplus_ext_key;
2987+
2988+#define HFSPLUS_EXT_KEYLEN 10
2989+
2990+/* HFS+ generic BTree key */
2991+typedef struct {
2992+ hfsp_word key_len;
2993+ union {
2994+ hfsplus_cat_key cat;
2995+ hfsplus_ext_key ext;
2996+ } u;
2997+} hfsplus_btree_key;
2998+
2999+#endif
This page took 2.03671 seconds and 4 git commands to generate.