[OpenBIOS] [PATCH] Rename conflicting hfsplus files

Blue Swirl blauwirbel at gmail.com
Wed Nov 17 21:31:50 CET 2010


Files in fs/hfs and fs/hfsplus have same names, this causes problems
during linkage.

Use prefix 'hfsp_' for the conflicting files.

Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
---
 fs/hfsplus/btree.c       |  372 -----------------------
 fs/hfsplus/build.xml     |    6 +-
 fs/hfsplus/hfsp_btree.c  |  372 +++++++++++++++++++++++
 fs/hfsplus/hfsp_record.c |  759 ++++++++++++++++++++++++++++++++++++++++++++++
 fs/hfsplus/hfsp_volume.c |  314 +++++++++++++++++++
 fs/hfsplus/record.c      |  759 ----------------------------------------------
 fs/hfsplus/volume.c      |  314 -------------------
 7 files changed, 1448 insertions(+), 1448 deletions(-)
 delete mode 100644 fs/hfsplus/btree.c
 create mode 100644 fs/hfsplus/hfsp_btree.c
 create mode 100644 fs/hfsplus/hfsp_record.c
 create mode 100644 fs/hfsplus/hfsp_volume.c
 delete mode 100644 fs/hfsplus/record.c
 delete mode 100644 fs/hfsplus/volume.c

diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
deleted file mode 100644
index 5409418..0000000
--- a/fs/hfsplus/btree.c
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * libhfs - library for reading and writing Macintosh HFS volumes
- * The fucntions are used to handle the various forms of btrees
- * found on HFS+ volumes.
- *
- * The fucntions are used to handle the various forms of btrees
- * found on HFS+ volumes.
- *
- * Copyright (C) 2000 Klaus Halfmann <khalfmann at libra.de>
- * Original 1996-1998 Robert Leslie <rob at mars.org>
- * Additional work by  Brad Boyer (flar at pants.nu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
- * MA 02110-1301, USA.
- *
- * $Id: btree.c,v 1.14 2000/10/25 05:43:04 hasi Exp $
- */
-
-#include "config.h"
-#include "libhfsp.h"
-#include "volume.h"
-#include "btree.h"
-#include "record.h"
-#include "swab.h"
-
-/* Read the node from the given buffer and swap the bytes.
- *
- * return pointer after reading the structure
- */
-static void* btree_readnode(btree_node_desc* node, void *p)
-{
-    node->next	    = bswabU32_inc(p);
-    node->prev	    = bswabU32_inc(p);
-    node->kind	    = bswabU8_inc(p);
-    node->height    = bswabU8_inc(p);
-    node->num_rec   = bswabU16_inc(p);
-    node->reserved  = bswabU16_inc(p);
-    return p;
-}
-
-/* read a btree header from the given buffer and swap the bytes.
- *
- * return pointer after reading the structure
- */
-static void* btree_readhead(btree_head* head, void *p)
-{
-	UInt32 *q;
-        head->depth	    = bswabU16_inc(p);
-        head->root	    = bswabU32_inc(p);
-        head->leaf_count    = bswabU32_inc(p);
-        head->leaf_head	    = bswabU32_inc(p);
-        head->leaf_tail	    = bswabU32_inc(p);
-        head->node_size	    = bswabU16_inc(p);
-        head->max_key_len   = bswabU16_inc(p);
-        head->node_count    = bswabU32_inc(p);
-        head->free_nodes    = bswabU32_inc(p);
-        head->reserved1	    = bswabU16_inc(p);
-        head->clump_size    = bswabU32_inc(p);
-        head->btree_type    = bswabU8_inc(p);
-        head->reserved2	    = bswabU8_inc(p);
-        head->attributes    = bswabU32_inc(p);
-	    // skip reserved bytes
-	q=((UInt32*) p);
-	// ((UInt32*) p) += 16;
-	q+=16;
-	return q;
-}
-
-/* Priority of the depth of the node compared to LRU value.
- * Should be the average number of keys per node but these vary. */
-#define DEPTH_FACTOR	1000
-
-/* Cache size is height of tree + this value
- * Really big numbers wont help in case of ls -R
- */
-#define EXTRA_CACHESIZE	3
-
-/* Not in use by now ... */
-#define CACHE_DIRTY 0x0001
-
-/* Intialize cache with default cache Size,
- * must call node_cache_close to deallocate memory */
-static int node_cache_init(node_cache* cache, btree* tree, int size)
-{
-    int nodebufsize;
-    char * buf;
-
-    cache->size		= size;
-    cache->currindex	= 0;
-    nodebufsize = tree->head.node_size + sizeof(node_buf);
-    buf = malloc(size *(sizeof(node_entry) + nodebufsize));
-    if (!buf)
-	return -1;
-    cache -> nodebufsize = nodebufsize;
-    cache -> entries = (node_entry*) buf;
-    cache -> buffers = (char*) &cache->entries[size];
-    bzero(cache->entries, size*sizeof(node_entry));
-    return 0;
-}
-
-/* Like cache->buffers[i], since size of node_buf is variable */
-static inline node_buf* node_buf_get(node_cache* cache, int i)
-{
-    return (node_buf*) (cache->buffers + (i * cache->nodebufsize));
-}
-
-/* flush the node at index */
-static void node_cache_flush_node(node_cache* cache, int index)
-{
-    // NYI
-    cache -> entries[index].index = 0;	// invalidate entry
-}
-
-static void node_cache_close(node_cache* cache)
-{
-    if (!cache->entries) // not (fully) intialized ?
-	return;
-    free(cache->entries);
-}
-
-/* Load the cach node indentified by index with
- * the node identified by node_index */
-
-static node_buf* node_cache_load_buf
-    (btree* bt, node_cache* cache, int index, UInt16 node_index)
-{
-    node_buf	*result	    = node_buf_get(cache ,index);
-    UInt32	blkpernode  = bt->blkpernode;
-    UInt32	block	    = node_index * blkpernode;
-    void*	p	    = volume_readfromfork(bt->vol, result->node, bt->fork,
-			     block, blkpernode, HFSP_EXTENT_DATA, bt->cnid);
-    node_entry	*e	    = &cache->entries[index];
-
-    if (!p)
-	return NULL;	// evil ...
-
-    result->index   = node_index;
-    btree_readnode(&result->desc, p);
-
-    e -> priority   = result->desc.height * DEPTH_FACTOR;
-    e -> index	    = node_index;
-    return result;
-}
-
-/* Read node at given index, using cache.
- */
-node_buf* btree_node_by_index(btree* bt, UInt16 index)
-{
-    node_cache*	cache = &bt->cache;
-    int		oldindex, lruindex;
-    int		currindex = cache->currindex;
-    UInt32	prio;
-    node_entry	*e;
-
-    // Shortcut acces to current node, will not change priorities
-    if (cache->entries[currindex].index == index)
-	return node_buf_get(cache ,currindex);
-    oldindex = currindex;
-    if (currindex == 0)
-	currindex = cache->size;
-    currindex--;
-    lruindex = oldindex;	    // entry to be flushed when needed
-    prio     = 0;		    // current priority
-    while (currindex != oldindex)   // round robin
-    {
-	e = &cache->entries[currindex];
-	if (e->index == index)	    // got it
-	{
-	    if (e->priority != 0)   // already top, uuh
-		e->priority--;
-	    cache->currindex = currindex;
-	    return node_buf_get(cache ,currindex);
-	}
-	else
-	{
-	    if (!e->index)
-	    {
-		lruindex = currindex;
-		break;	// empty entry, load it
-	    }
-	    if (e->priority != UINT_MAX) // already least, uuh
-		e->priority++;
-	}
-	if (prio < e->priority)
-	{
-	    lruindex = currindex;
-	    prio = e->priority;
-	}
-	if (currindex == 0)
-	    currindex = cache->size;
-	currindex--;
-    }
-    e = &cache->entries[lruindex];
-    cache->currindex = lruindex;
-    if (e->flags & CACHE_DIRTY)
-           node_cache_flush_node(    cache, lruindex);
-    return node_cache_load_buf  (bt, cache, lruindex, index);
-}
-
-/** intialize the btree with the first entry in the fork */
-static int btree_init(btree* bt, volume* vol, hfsp_fork_raw* fork)
-{
-    void	    *p;
-    char	    buf[vol->blksize];
-    UInt16	    node_size;
-    btree_node_desc node;
-
-    bt->vol	= vol;
-    bt->fork	= fork;
-    p	= volume_readfromfork(vol, buf, fork, 0, 1,
-		 HFSP_EXTENT_DATA, bt->cnid);
-    if (!p)
-	return -1;
-    p = btree_readnode(&node, p);
-    if (node.kind != HFSP_NODE_HEAD)
-	return -1;   // should not happen ?
-    btree_readhead(&bt->head, p);
-
-    node_size = bt->head.node_size;
-    bt->blkpernode = node_size / vol->blksize;
-
-    if (bt->blkpernode == 0 || vol->blksize *
-	    bt->blkpernode != node_size)
-	return -1;  // should never happen ...
-
-    node_cache_init(&bt->cache, bt, bt->head.depth + EXTRA_CACHESIZE);
-
-    // Allocate buffer
-    // bt->buf = malloc(node_size);
-    // if (!bt->buf)
-    //	return ENOMEM;
-
-    return 0;
-}
-
-/** Intialize catalog btree, so that btree_close can safely be called. */
-void btree_reset(btree* bt)
-{
-    bt->cache.entries = NULL;
-}
-
-/** Intialize catalog btree */
-int btree_init_cat(btree* bt, volume* vol, hfsp_fork_raw* fork)
-{
-    int result = btree_init(bt,vol,fork);	// super (...)
-    bt->cnid  = HFSP_CAT_CNID;
-    bt->kcomp = record_key_compare;
-    bt->kread = record_readkey;
-    return result;
-}
-
-/** Intialize catalog btree */
-int btree_init_extent(btree* bt, volume* vol, hfsp_fork_raw* fork)
-{
-    int result = btree_init(bt,vol,fork);	// super (...)
-    bt->cnid  = HFSP_EXT_CNID;
-    bt->kcomp = record_extent_key_compare;
-    bt->kread = record_extent_readkey;
-    return result;
-}
-
-/** close the btree and free any resources */
-void btree_close(btree* bt)
-{
-    node_cache_close(&bt->cache);
-    // free(bt->buf);
-}
-
-/* returns pointer to key given by index in current node.
- *
- * Assumes that current node is not NODE_HEAD ...
- */
-void* btree_key_by_index(btree* bt, node_buf* buf, UInt16 index)
-{
-    UInt16  node_size	    = bt->head.node_size;
-	// The offsets are found at the end of the node ...
-    UInt16  off_pos	    = node_size - (index +1) * sizeof(btree_record_offset);
- 	// position of offset at end of node
-    btree_record_offset* offset =
-	(btree_record_offset*) (buf->node + off_pos);
-
-    // now we have the offset and can read the key ...
-#ifdef CONFIG_LITTLE_ENDIAN
-    return buf->node + bswabU16(*offset);
-#else
-    return buf->node + *offset;
-#endif
-}
-
-
-#ifdef DEBUG
-
-/* print btree header node information */
-void btree_printhead(btree_head* head)
-{
-    UInt32 attr;
-    printf("  depth       : %#X\n",  head->depth);
-    printf("  root        : %#lX\n", head->root);
-    printf("  leaf_count  : %#lX\n", head->leaf_count);
-    printf("  leaf_head   : %#lX\n", head->leaf_head);
-    printf("  leaf_tail   : %#lX\n", head->leaf_tail);
-    printf("  node_size   : %#X\n",  head->node_size);
-    printf("  max_key_len : %#X\n",  head->max_key_len);
-    printf("  node_count  : %#lX\n", head->node_count);
-    printf("  free_nodes  : %#lX\n", head->free_nodes);
-    printf("  reserved1   : %#X\n",  head->reserved1);
-    printf("  clump_size  : %#lX\n", head->clump_size);
-    printf("  btree_type  : %#X\n",  head->btree_type);
-    attr = head->attributes;
-    printf("  reserved2   : %#X\n",  head->reserved2);
-    if (attr & HFSPLUS_BAD_CLOSE)
-        printf(" HFSPLUS_BAD_CLOSE *** ");
-    else
-        printf(" !HFSPLUS_BAD_CLOSE");
-    if (attr & HFSPLUS_TREE_BIGKEYS)
-        printf(" HFSPLUS_TREE_BIGKEYS ");
-    else
-        printf("  !HFSPLUS_TREE_BIGKEYS");
-    if (attr & HFSPLUS_TREE_VAR_NDXKEY_SIZE)
-        printf(" HFSPLUS_TREE_VAR_NDXKEY_SIZE");
-    else
-        printf(" !HFSPLUS_TREE_VAR_NDXKEY_SIZE");
-    if (attr & HFSPLUS_TREE_UNUSED)
-        printf(" HFSPLUS_TREE_UNUSED ***\n");
-    printf("\n");
-}
-
-/* Dump all the node information to stdout */
-void btree_print(btree* bt)
-{
-    btree_node_desc* node;
-
-    btree_printhead(&bt->head);
-
-    node = &bt->node;
-    printf("next     : %#lX\n", node->next);
-    printf("prev     : %#lX\n", node->prev);
-    printf("height   : %#X\n",  node->height);
-    printf("num_rec  : %#X\n",  node->num_rec);
-    printf("reserved : %#X\n",  node->reserved);
-    printf("height   : %#X\n",  node->height);
              switch(node->kind)
-    {
-	case HFSP_NODE_NDX  :
-	    printf("HFSP_NODE_NDX\n");
-	    break;
-	case HFSP_NODE_HEAD :
-	    printf("HFSP_NODE_HEAD\n");
-	    break;
-	case HFSP_NODE_MAP  :
-	    printf("HFSP_NODE_MAP\n");
-	    break;
-	case HFSP_NODE_LEAF :
-	    printf("HFSP_NODE_LEAF\n");
-	    break;
-	default:
-	    printf("*** Unknown Node type ***\n");
-    }
-}
-
-#endif
diff --git a/fs/hfsplus/build.xml b/fs/hfsplus/build.xml
index d3d32cb..f6f5369 100644
--- a/fs/hfsplus/build.xml
+++ b/fs/hfsplus/build.xml
@@ -1,11 +1,11 @@
 <build>
  <library name="fs" type="static" target="target">
   <object source="blockiter.c" flags="-I$(SRCDIR)/fs/hfsplus/include
-I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
-  <object source="btree.c" flags="-I$(SRCDIR)/fs/hfsplus/include
-I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+  <object source="hfsp_btree.c" flags="-I$(SRCDIR)/fs/hfsplus/include
-I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
   <object source="libhfsp.c" flags="-I$(SRCDIR)/fs/hfsplus/include
-I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
-  <object source="record.c" flags="-I$(SRCDIR)/fs/hfsplus/include
-I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+  <object source="hfsp_record.c"
flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/
-fno-strict-aliasing" condition="HFSP"/>
   <object source="unicode.c" flags="-I$(SRCDIR)/fs/hfsplus/include
-I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
-  <object source="volume.c" flags="-I$(SRCDIR)/fs/hfsplus/include
-I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
+  <object source="hfsp_volume.c"
flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/
-fno-strict-aliasing" condition="HFSP"/>
   <object source="hfsp_fs.c" flags="-I$(SRCDIR)/fs/hfsplus/include
-I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/>
  </library>
 </build>
diff --git a/fs/hfsplus/hfsp_btree.c b/fs/hfsplus/hfsp_btree.c
new file mode 100644
index 0000000..24eca92
--- /dev/null
+++ b/fs/hfsplus/hfsp_btree.c
@@ -0,0 +1,372 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ * The fucntions are used to handle the various forms of btrees
+ * found on HFS+ volumes.
+ *
+ * The fucntions are used to handle the various forms of btrees
+ * found on HFS+ volumes.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann at libra.de>
+ * Original 1996-1998 Robert Leslie <rob at mars.org>
+ * Additional work by  Brad Boyer (flar at pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: btree.c,v 1.14 2000/10/25 05:43:04 hasi Exp $
+ */
+
+#include "config.h"
+#include "libhfsp.h"
+#include "volume.h"
+#include "btree.h"
+#include "record.h"
+#include "swab.h"
+
+/* Read the node from the given buffer and swap the bytes.
+ *
+ * return pointer after reading the structure
+ */
+static void* btree_readnode(btree_node_desc* node, void *p)
+{
+    node->next	    = bswabU32_inc(p);
+    node->prev	    = bswabU32_inc(p);
+    node->kind	    = bswabU8_inc(p);
+    node->height    = bswabU8_inc(p);
+    node->num_rec   = bswabU16_inc(p);
+    node->reserved  = bswabU16_inc(p);
+    return p;
+}
+
+/* read a btree header from the given buffer and swap the bytes.
+ *
+ * return pointer after reading the structure
+ */
+static void* btree_readhead(btree_head* head, void *p)
+{
+	UInt32 *q;
+        head->depth	    = bswabU16_inc(p);
+        head->root	    = bswabU32_inc(p);
+        head->leaf_count    = bswabU32_inc(p);
+        head->leaf_head	    = bswabU32_inc(p);
+        head->leaf_tail	    = bswabU32_inc(p);
+        head->node_size	    = bswabU16_inc(p);
+        head->max_key_len   = bswabU16_inc(p);
+        head->node_count    = bswabU32_inc(p);
+        head->free_nodes    = bswabU32_inc(p);
+        head->reserved1	    = bswabU16_inc(p);
+        head->clump_size    = bswabU32_inc(p);
+        head->btree_type    = bswabU8_inc(p);
+        head->reserved2	    = bswabU8_inc(p);
+        head->attributes    = bswabU32_inc(p);
+	    // skip reserved bytes
+	q=((UInt32*) p);
+	// ((UInt32*) p) += 16;
+	q+=16;
+	return q;
+}
+
+/* Priority of the depth of the node compared to LRU value.
+ * Should be the average number of keys per node but these vary. */
+#define DEPTH_FACTOR	1000
+
+/* Cache size is height of tree + this value
+ * Really big numbers wont help in case of ls -R
+ */
+#define EXTRA_CACHESIZE	3
+
+/* Not in use by now ... */
+#define CACHE_DIRTY 0x0001
+
+/* Intialize cache with default cache Size,
+ * must call node_cache_close to deallocate memory */
+static int node_cache_init(node_cache* cache, btree* tree, int size)
+{
+    int nodebufsize;
+    char * buf;
+
+    cache->size		= size;
+    cache->currindex	= 0;
+    nodebufsize = tree->head.node_size + sizeof(node_buf);
+    buf = malloc(size *(sizeof(node_entry) + nodebufsize));
+    if (!buf)
+	return -1;
+    cache -> nodebufsize = nodebufsize;
+    cache -> entries = (node_entry*) buf;
+    cache -> buffers = (char*) &cache->entries[size];
+    bzero(cache->entries, size*sizeof(node_entry));
+    return 0;
+}
+
+/* Like cache->buffers[i], since size of node_buf is variable */
+static inline node_buf* node_buf_get(node_cache* cache, int i)
+{
+    return (node_buf*) (cache->buffers + (i * cache->nodebufsize));
+}
+
+/* flush the node at index */
+static void node_cache_flush_node(node_cache* cache, int index)
+{
+    // NYI
+    cache -> entries[index].index = 0;	// invalidate entry
+}
+
+static void node_cache_close(node_cache* cache)
+{
+    if (!cache->entries) // not (fully) intialized ?
+	return;
+    free(cache->entries);
+}
+
+/* Load the cach node indentified by index with
+ * the node identified by node_index */
+
+static node_buf* node_cache_load_buf
+    (btree* bt, node_cache* cache, int index, UInt16 node_index)
+{
+    node_buf	*result	    = node_buf_get(cache ,index);
+    UInt32	blkpernode  = bt->blkpernode;
+    UInt32	block	    = node_index * blkpernode;
+    void*	p	    = volume_readfromfork(bt->vol, result->node, bt->fork,
+			     block, blkpernode, HFSP_EXTENT_DATA, bt->cnid);
+    node_entry	*e	    = &cache->entries[index];
+
+    if (!p)
+	return NULL;	// evil ...
+
+    result->index   = node_index;
+    btree_readnode(&result->desc, p);
+
+    e -> priority   = result->desc.height * DEPTH_FACTOR;
+    e -> index	    = node_index;
+    return result;
+}
+
+/* Read node at given index, using cache.
+ */
+node_buf* btree_node_by_index(btree* bt, UInt16 index)
+{
+    node_cache*	cache = &bt->cache;
+    int		oldindex, lruindex;
+    int		currindex = cache->currindex;
+    UInt32	prio;
+    node_entry	*e;
+
+    // Shortcut acces to current node, will not change priorities
+    if (cache->entries[currindex].index == index)
+	return node_buf_get(cache ,currindex);
+    oldindex = currindex;
+    if (currindex == 0)
+	currindex = cache->size;
+    currindex--;
+    lruindex = oldindex;	    // entry to be flushed when needed
+    prio     = 0;		    // current priority
+    while (currindex != oldindex)   // round robin
+    {
+	e = &cache->entries[currindex];
+	if (e->index == index)	    // got it
+	{
+	    if (e->priority != 0)   // already top, uuh
+		e->priority--;
+	    cache->currindex = currindex;
+	    return node_buf_get(cache ,currindex);
+	}
+	else
+	{
+	    if (!e->index)
+	    {
+		lruindex = currindex;
+		break;	// empty entry, load it
+	    }
+	    if (e->priority != UINT_MAX) // already least, uuh
+		e->priority++;
+	}
+	if (prio < e->priority)
+	{
+	    lruindex = currindex;
+	    prio = e->priority;
+	}
+	if (currindex == 0)
+	    currindex = cache->size;
+	currindex--;
+    }
+    e = &cache->entries[lruindex];
+    cache->currindex = lruindex;
+    if (e->flags & CACHE_DIRTY)
+           node_cache_flush_node(    cache, lruindex);
+    return node_cache_load_buf  (bt, cache, lruindex, index);
+}
+
+/** intialize the btree with the first entry in the fork */
+static int btree_init(btree* bt, volume* vol, hfsp_fork_raw* fork)
+{
+    void	    *p;
+    char	    buf[vol->blksize];
+    UInt16	    node_size;
+    btree_node_desc node;
+
+    bt->vol	= vol;
+    bt->fork	= fork;
+    p	= volume_readfromfork(vol, buf, fork, 0, 1,
+		 HFSP_EXTENT_DATA, bt->cnid);
+    if (!p)
+	return -1;
+    p = btree_readnode(&node, p);
+    if (node.kind != HFSP_NODE_HEAD)
+	return -1;   // should not happen ?
+    btree_readhead(&bt->head, p);
+
+    node_size = bt->head.node_size;
+    bt->blkpernode = node_size / vol->blksize;
+
+    if (bt->blkpernode == 0 || vol->blksize *
+	    bt->blkpernode != node_size)
+	return -1;  // should never happen ...
+
+    node_cache_init(&bt->cache, bt, bt->head.depth + EXTRA_CACHESIZE);
+
+    // Allocate buffer
+    // bt->buf = malloc(node_size);
+    // if (!bt->buf)
+    //	return ENOMEM;
+
+    return 0;
+}
+
+/** Intialize catalog btree, so that btree_close can safely be called. */
+void btree_reset(btree* bt)
+{
+    bt->cache.entries = NULL;
+}
+
+/** Intialize catalog btree */
+int btree_init_cat(btree* bt, volume* vol, hfsp_fork_raw* fork)
+{
+    int result = btree_init(bt,vol,fork);	// super (...)
+    bt->cnid  = HFSP_CAT_CNID;
+    bt->kcomp = record_key_compare;
+    bt->kread = record_readkey;
+    return result;
+}
+
+/** Intialize catalog btree */
+int btree_init_extent(btree* bt, volume* vol, hfsp_fork_raw* fork)
+{
+    int result = btree_init(bt,vol,fork);	// super (...)
+    bt->cnid  = HFSP_EXT_CNID;
+    bt->kcomp = record_extent_key_compare;
+    bt->kread = record_extent_readkey;
+    return result;
+}
+
+/** close the btree and free any resources */
+void btree_close(btree* bt)
+{
+    node_cache_close(&bt->cache);
+    // free(bt->buf);
+}
+
+/* returns pointer to key given by index in current node.
+ *
+ * Assumes that current node is not NODE_HEAD ...
+ */
+void* btree_key_by_index(btree* bt, node_buf* buf, UInt16 index)
+{
+    UInt16  node_size	    = bt->head.node_size;
+	// The offsets are found at the end of the node ...
+    UInt16  off_pos	    = node_size - (index +1) * sizeof(btree_record_offset);
+	// position of offset at end of node
+    btree_record_offset* offset =
+	(btree_record_offset*) (buf->node + off_pos);
+
+    // now we have the offset and can read the key ...
+#ifdef CONFIG_LITTLE_ENDIAN
+    return buf->node + bswabU16(*offset);
+#else
+    return buf->node + *offset;
+#endif
+}
+
+
+#ifdef DEBUG
+
+/* print btree header node information */
+void btree_printhead(btree_head* head)
+{
+    UInt32 attr;
+    printf("  depth       : %#X\n",  head->depth);
+    printf("  root        : %#lX\n", head->root);
+    printf("  leaf_count  : %#lX\n", head->leaf_count);
+    printf("  leaf_head   : %#lX\n", head->leaf_head);
+    printf("  leaf_tail   : %#lX\n", head->leaf_tail);
+    printf("  node_size   : %#X\n",  head->node_size);
+    printf("  max_key_len : %#X\n",  head->max_key_len);
+    printf("  node_count  : %#lX\n", head->node_count);
+    printf("  free_nodes  : %#lX\n", head->free_nodes);
+    printf("  reserved1   : %#X\n",  head->reserved1);
+    printf("  clump_size  : %#lX\n", head->clump_size);
+    printf("  btree_type  : %#X\n",  head->btree_type);
+    attr = head->attributes;
+    printf("  reserved2   : %#X\n",  head->reserved2);
+    if (attr & HFSPLUS_BAD_CLOSE)
+        printf(" HFSPLUS_BAD_CLOSE *** ");
+    else
+        printf(" !HFSPLUS_BAD_CLOSE");
+    if (attr & HFSPLUS_TREE_BIGKEYS)
+        printf(" HFSPLUS_TREE_BIGKEYS ");
+    else
+        printf("  !HFSPLUS_TREE_BIGKEYS");
+    if (attr & HFSPLUS_TREE_VAR_NDXKEY_SIZE)
+        printf(" HFSPLUS_TREE_VAR_NDXKEY_SIZE");
+    else
+        printf(" !HFSPLUS_TREE_VAR_NDXKEY_SIZE");
+    if (attr & HFSPLUS_TREE_UNUSED)
+        printf(" HFSPLUS_TREE_UNUSED ***\n");
+    printf("\n");
+}
+
+/* Dump all the node information to stdout */
+void btree_print(btree* bt)
+{
+    btree_node_desc* node;
+
+    btree_printhead(&bt->head);
+
+    node = &bt->node;
+    printf("next     : %#lX\n", node->next);
+    printf("prev     : %#lX\n", node->prev);
+    printf("height   : %#X\n",  node->height);
+    printf("num_rec  : %#X\n",  node->num_rec);
+    printf("reserved : %#X\n",  node->reserved);
+    printf("height   : %#X\n",  node->height);
              switch(node->kind)
+    {
+	case HFSP_NODE_NDX  :
+	    printf("HFSP_NODE_NDX\n");
+	    break;
+	case HFSP_NODE_HEAD :
+	    printf("HFSP_NODE_HEAD\n");
+	    break;
+	case HFSP_NODE_MAP  :
+	    printf("HFSP_NODE_MAP\n");
+	    break;
+	case HFSP_NODE_LEAF :
+	    printf("HFSP_NODE_LEAF\n");
+	    break;
+	default:
+	    printf("*** Unknown Node type ***\n");
+    }
+}
+
+#endif
diff --git a/fs/hfsplus/hfsp_record.c b/fs/hfsplus/hfsp_record.c
new file mode 100644
index 0000000..d4e7af1
--- /dev/null
+++ b/fs/hfsplus/hfsp_record.c
@@ -0,0 +1,759 @@
+/*
+ * libhfsp - library for reading and writing Macintosh HFS+ volumes.
+ *
+ * a record contains a key and a folder or file and is part
+ * of a btree.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann at libra.de>
+ * Original 1996-1998 Robert Leslie <rob at mars.org>
+ * Additional work by  Brad Boyer (flar at pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: record.c,v 1.24 2000/10/17 05:58:46 hasi Exp $
+ */
+
+#include "config.h"
+#include "libhfsp.h"
+#include "hfstime.h"
+#include "record.h"
+#include "volume.h"
+#include "btree.h"
+#include "unicode.h"
+#include "swab.h"
+
+/* read a hfsp_cat_key from memory */
+void* record_readkey(void* p, void* buf)
+{
+    hfsp_cat_key*   key = (hfsp_cat_key*) buf;
+    const void*	    check;
+    UInt16	    key_length, len,i;
+    UInt16*	    cp;
+
+    key->key_length = key_length    = bswabU16_inc(p);
+    check = p;
+    key->parent_cnid		    = bswabU32_inc(p);
+    key->name.strlen = len	    = bswabU16_inc(p);
+    cp = key->name.name;
+    for (i=0; i < len; i++, cp++)
+	*cp			    = bswabU16_inc(p);
+	/* check if keylenght was correct */
+    if (key_length != ((char*) p) - ((char*) check))
+	 HFSP_ERROR(EINVAL, "Invalid key length in record_readkey");
+    return p;
+  fail:
+    return NULL;
+}
+
+/* read a hfsp_extent_key from memory */
+void* record_extent_readkey(void* p, void* buf)
+{
+    hfsp_extent_key* key = (hfsp_extent_key*) buf;
+    UInt16  key_length;
+
+    key->key_length = key_length    = bswabU16_inc(p);
+    key->fork_type		    = bswabU8_inc(p);
+    key->filler			    = bswabU8_inc(p);
+    if (key_length != 10)
+	HFSP_ERROR(-1, "Invalid key length in record_extent_readkey");
+    key->file_id		    = bswabU32_inc(p);
+    key->start_block		    = bswabU32_inc(p);
+    return p;
+  fail:
+    return NULL;
+}
+
+
+/* read posix permission from memory */
+static inline void* record_readperm(void *p, hfsp_perm* perm)
+{
+    perm->owner= bswabU32_inc(p);
+    perm->group= bswabU32_inc(p);
+    perm->mode = bswabU32_inc(p);
+    perm->dev  = bswabU32_inc(p);
+    return p;
+}
+
+/* read directory info */
+static inline void* record_readDInfo(void *p, DInfo* info)
+{
+    info->frRect.top	= bswabU16_inc(p);
+    info->frRect.left	= bswabU16_inc(p);
+    info->frRect.bottom	= bswabU16_inc(p);
+    info->frRect.right	= bswabU16_inc(p);
+    info->frFlags	= bswabU16_inc(p);
+    info->frLocation.v	= bswabU16_inc(p);
+    info->frLocation.h	= bswabU16_inc(p);
+    info->frView	= bswabU16_inc(p);
+    return p;
+}
+
+/* read extra Directory info */
+static inline void* record_readDXInfo(void *p, DXInfo* xinfo)
+{
+    xinfo->frScroll.v  = bswabU16_inc(p);
+    xinfo->frScroll.h  = bswabU16_inc(p);
+    xinfo->frOpenChain = bswabU32_inc(p);
+    xinfo->frUnused    = bswabU16_inc(p);
+    xinfo->frComment   = bswabU16_inc(p);
+    xinfo->frPutAway   = bswabU32_inc(p);
+    return p;
+}
+
+/* read a hfsp_cat_folder from memory */
+static void* record_readfolder(void *p, hfsp_cat_folder* folder)
+{
+    folder->flags		= bswabU16_inc(p);
+    folder->valence		= bswabU32_inc(p);
+    folder->id			= bswabU32_inc(p);
+    folder->create_date		= bswabU32_inc(p);
+    folder->content_mod_date    = bswabU32_inc(p);
+    folder->attribute_mod_date	= bswabU32_inc(p);
+    folder->access_date		= bswabU32_inc(p);
+    folder->backup_date		= bswabU32_inc(p);
+    p = record_readperm	    (p, &folder->permissions);
+    p = record_readDInfo    (p, &folder->user_info);
+    p = record_readDXInfo   (p, &folder->finder_info);
+    folder->text_encoding	= bswabU32_inc(p);
+    folder->reserved		= bswabU32_inc(p);
+    return p;
+}
+
+/* read file info */
+static inline void* record_readFInfo(void *p, FInfo* info)
+{
+    info->fdType	= bswabU32_inc(p);
+    info->fdCreator	= bswabU32_inc(p);
+    info->fdFlags	= bswabU16_inc(p);
+    info->fdLocation.v	= bswabU16_inc(p);
+    info->fdLocation.h	= bswabU16_inc(p);
+    info->fdFldr	= bswabU16_inc(p);
+    return p;
+}
+
+/* read extra File info */
+static inline void* record_readFXInfo(void *p, FXInfo* xinfo)
+{
+    SInt16 *q;
+    xinfo->fdIconID	= bswabU16_inc(p);
+    q=(SInt16*) p;
+    q+=4; // skip unused
+    p=(void *)q;
+    xinfo->fdComment	= bswabU16_inc(p);
+    xinfo->fdPutAway	= bswabU32_inc(p);
+    return p;
+}
+
+/* read a hfsp_cat_file from memory */
+static void* record_readfile(void *p, hfsp_cat_file* file)
+{
+    file->flags			= bswabU16_inc(p);
+    file->reserved1		= bswabU32_inc(p);
+    file->id			= bswabU32_inc(p);
+    file->create_date		= bswabU32_inc(p);
+    file->content_mod_date	= bswabU32_inc(p);
+    file->attribute_mod_date	= bswabU32_inc(p);
+    file->access_date		= bswabU32_inc(p);
+    file->backup_date		= bswabU32_inc(p);
+    p = record_readperm	    (p, &file->permissions);
+    p = record_readFInfo    (p, &file->user_info);
+    p = record_readFXInfo   (p, &file->finder_info);
+    file->text_encoding		= bswabU32_inc(p);
+    file->reserved2		= bswabU32_inc(p);
+    p =	    volume_readfork (p, &file->data_fork);
+    return  volume_readfork (p, &file->res_fork);
+}
+
+/* read a hfsp_cat_thread from memory */
+static void* record_readthread(void *p, hfsp_cat_thread* entry)
+{
+    int	    i;
+    UInt16  len;
+    UInt16* cp;
+
+    entry->         reserved	= bswabU16_inc(p);
+    entry->	    parentID	= bswabU32_inc(p);
+    entry->nodeName.strlen = len= bswabU16_inc(p);
+    cp = entry->nodeName.name;
+    if (len > 255)
+        HFSP_ERROR(-1, "Invalid key length in record thread");
+    for (i=0; i < len; i++, cp++)
+	*cp			 = bswabU16_inc(p);
+    return p;
+ fail:
+    return NULL;
+}
+
+/* read a hfsp_cat_entry from memory */
+static void* record_readentry(void *p, hfsp_cat_entry* entry)
+{
+    UInt16 type = bswabU16_inc(p);
+    entry->type = type;
+    switch (type)
+    {
+	case HFSP_FOLDER:
+	    return record_readfolder(p, &entry->u.folder);
+	case HFSP_FILE:
+	    return record_readfile  (p, &entry->u.file);
+	case HFSP_FOLDER_THREAD:
+	case HFSP_FILE_THREAD:
+	    return record_readthread(p, &entry->u.thread);
+	default:
+	    HFSP_ERROR(-1, "Unexpected record type in record_readentry");
+    } ;
+  fail:
+    return NULL;
+}
+
+
+/* Most of the functions here will not change the node in the btree,
+   But this must be changed in the future ... */
+
+
+/* intialize the record with the given index entry in the btree. */
+static int record_init(record* r, btree* bt, node_buf* buf, UInt16 index)
+{
+    void *p;
+    r-> tree   = bt;
+    p = btree_key_by_index(bt,buf,index);
+    if (!p)
+	return -1;
+    p = record_readkey  (p, &r->key);
+    if (!p)
+	return -1;
+    p = record_readentry(p, &r->record);
+    if (!p)
+	return -1;
+    r->node_index = buf->index;
+    r-> keyind    = index;
+
+    return 0;
+}
+
+/* intialize the record with the given index entry in the btree. */
+static int record_init_extent(extent_record* r, btree* bt, node_buf*
buf, UInt16 index)
+{
+    void *p;
+    r-> tree   = bt;
+    p = btree_key_by_index(bt, buf,index);
+    if (!p)
+	return -1;
+    p = record_extent_readkey(p, &r->key);
+    if (!p)
+	return -1;
+    p = volume_readextent(p, r->extent);
+    if (!p)
+	return -1;
+    r->node_index = buf->index;
+    r-> keyind    = index;
+
+    return 0;
+}
+
+/* intialize the record to the first record of the tree
+ * which is (per design) the root node.
+ */
+int record_init_root(record* r, btree* tree)
+{
+    // Position to first leaf node ...
+    UInt32 leaf_head = tree->head.leaf_head;
+    node_buf* buf = btree_node_by_index(tree, leaf_head);
+    if (!buf)
+	return -1;
+    return record_init(r, tree, buf, 0);
+}
+
+/* Compare two cat_keys ... */
+int record_key_compare(void* k1, void* k2)
+{
+    hfsp_cat_key* key1 = (hfsp_cat_key*) k1;
+    hfsp_cat_key* key2 = (hfsp_cat_key*) k2;
+    int diff = key2->parent_cnid - key1->parent_cnid;
+    if (!diff) // same parent
+	diff = fast_unicode_compare(&key1->name, &key2->name);
+    return diff;
+}
+
+/* Compare two extent_keys ... */
+int record_extent_key_compare(void* k1, void* k2)
+{
+    hfsp_extent_key* key1 = (hfsp_extent_key*) k1;
+    hfsp_extent_key* key2 = (hfsp_extent_key*) k2;
+    int diff = key2->fork_type - key1->fork_type;
+    if (!diff) // same type
+    {
+	diff = key2->file_id - key1->file_id;
+	if (!diff) // same file
+	    diff = key2->start_block - key1->start_block;
+    }
+    return diff;
+}
+
+/* Position node in btree so that key might be inside */
+static node_buf* record_find_node(btree* tree, void *key)
+{
+    int			start, end, mid, comp;  // components of a binary search
+    void		*p = NULL;
+    char		curr_key[tree->head.max_key_len];
+		    // The current key under examination
+    hfsp_key_read	readkey	    = tree->kread;
+    hfsp_key_compare	key_compare = tree->kcomp;
+    UInt32		index;
+    node_buf*		node = btree_node_by_index(tree, tree->head.root);
+    if (!node)
+	HFSP_ERROR(-1, "record_find_node: Cant position to root node");
+    while (node->desc.kind == HFSP_NODE_NDX)
+    {
+	mid = start = 0;
+	end  = node->desc.num_rec;
+	comp = -1;
+	while (start < end)
+	{
+	    mid = (start + end) >> 1;
+	    p = btree_key_by_index(tree, node, mid);
+	    if (!p)
+		HFSP_ERROR(-1, "record_find_node: unexpected error");
+	    p = readkey  (p, curr_key);
+	    if (!p)
+		HFSP_ERROR(-1, "record_find_node: unexpected error");
+	    comp = key_compare(curr_key, key);
+	    if (comp > 0)
+		start = mid + 1;
+	    else if (comp < 0)
+		end = mid;
+	    else
+		break;
+	}
+	if (!p) // Empty tree, fascinating ...
+	    HFSP_ERROR(-1, "record_find_node: unexpected empty node");
+	if (comp < 0)	// mmh interesting key is before this key ...
+	{
+	    if (mid == 0)
+		return NULL;  // nothing before this key ..
+	    p = btree_key_by_index(tree, node, mid-1);
+	    if (!p)
+		HFSP_ERROR(-1, "record_find_node: unexpected error");
+	    p = readkey  (p, curr_key);
+	    if (!p)
+		HFSP_ERROR(-1, "record_find_node: unexpected error");
+	}
+
+	index = bswabU32_inc(p);
+	node = btree_node_by_index(tree, index);
+    }
+    return node;	// go on and use the found node
+  fail:
+    return NULL;
+}
+
+/* search for the given key in the btree.
+ *
+ * returns pointer to memory just after key or NULL
+ * In any case *keyind recives the index where the
+ * key was found (or could be inserted.)
+ */
+static void *
+record_find_key(btree* tree, void* key, int* keyind, UInt16* node_index)
+{
+    node_buf* buf = record_find_node(tree, key);
+    if (buf)
+    {
+	int		    comp  = -1;
+	int		    start = 0; // components of a binary search
+	int		    end   = buf->desc.num_rec;
+	int		    mid   = -1;
+	void		    *p    = NULL;
+	char		    curr_key[tree->head.max_key_len];
+	hfsp_key_read	    readkey	= tree->kread;
+	hfsp_key_compare    key_compare = tree->kcomp;
+	while (start < end)
+	{
+	    mid = (start + end) >> 1;
+	    p = btree_key_by_index(tree, buf, mid);
+	    if (!p)
+		HFSP_ERROR(-1, "record_init_key: unexpected error");
+	    p = readkey  (p, curr_key);
+	    if (!p)
+		HFSP_ERROR(-1, "record_init_cat_key: unexpected error");
+	    comp = key_compare(curr_key, key);
+	    if (comp > 0)
+		start = mid + 1;
+	    else if (comp < 0)
+		end = mid;
+	    else
+		break;
+	}
+	if (!p) // Empty tree, fascinating ...
+	    HFSP_ERROR(ENOENT, "record_init_key: unexpected empty node");
+	*keyind = mid;
+	*node_index = buf->index;
+	if (!comp)	// found something ...
+	    return p;
+    }
+    HFSP_ERROR(ENOENT, NULL);
+  fail:
+    return NULL;
+}
+
+/* intialize the record by searching for the given key in the btree.
+ *
+ * r is umodified on error.
+ */
+static int
+record_init_key(record* r, btree* tree, hfsp_cat_key* key)
+{
+    int	    keyind;
+    UInt16  node_index;
+    void    *p = record_find_key(tree, key, &keyind, &node_index);
+
+    if (p)
+    {
+	r -> tree      = tree;
+	r -> node_index= node_index;
+	r -> keyind    = keyind;
+	r -> key       = *key; // Better use a record_key_copy ...
+	p = record_readentry(p, &r->record);
+	if (!p)
+	    HFSP_ERROR(-1, "record_init_key: unexpected error");
+	return 0;
+    }
+  fail:
+    return -1;
+}
+
+/* intialize the extent_record to the extent identified by the
+ * (first) blockindex.
+ *
+ * forktype: either HFSP_EXTEND_DATA or HFSP_EXTEND_RSRC
+ */
+int record_init_file(extent_record* r, btree* tree,
+		    UInt8 forktype, UInt32 fileId, UInt32 blockindex)
+{
+    int		    keyind;
+    UInt16	    node_index;
+    hfsp_extent_key key = { 10, forktype, 0, fileId, blockindex };
+    void	    *p = record_find_key(tree, &key, &keyind, &node_index);
+
+    if (p)
+    {
+	r -> tree      = tree;
+	r -> node_index= node_index;
+	r -> keyind    = keyind;
+	r -> key       = key; // Better use a record_key_copy ...
+	p =  volume_readextent(p, r->extent);
+	if (!p)
+	    HFSP_ERROR(-1, "record_init_file: unexpected error");
+	return 0;
+    }
+  fail:
+    return -1;
+}
+
+/* intialize the record to the folder identified by cnid
+ */
+int record_init_cnid(record* r, btree* tree, UInt32 cnid)
+{
+    hfsp_cat_key    thread_key;	    // the thread is the first record
+
+    thread_key.key_length = 6;	    // null name (like '.' in unix )
+    thread_key.parent_cnid = cnid;
+    thread_key.name.strlen = 0;
+
+    return record_init_key(r, tree, &thread_key);
+}
+
+/* intialize the record to the first record of the parent.
+ */
+int record_init_parent(record* r, record* parent)
+{
+    if (parent->record.type == HFSP_FOLDER)
+	return record_init_cnid(r, parent->tree, parent->record.u.folder.id);
+    else if(parent->record.type == HFSP_FOLDER_THREAD)
+    {
+	if (r != parent)
+	    *r = *parent; // The folder thread is in fact the first entry, like '.'
+	return 0;
+    }
+    HFSP_ERROR(EINVAL,
+	"record_init_parent: parent is neither folder nor folder thread.");
+
+  fail:
+    return EINVAL;
+}
+
+
+/* find correct node record for given node and *pindex.
+ *
+ * index of record in this (or next) node
+ * */
+static node_buf* prepare_next(btree* tree, UInt16 node_index, UInt16* pindex)
+{
+    node_buf*	     buf    = btree_node_by_index(tree, node_index);
+    btree_node_desc* desc   = &buf->desc;
+    UInt32	     numrec = desc->num_rec;
+    if (*pindex >= numrec) // move on to next node
+    {
+	UInt16 next = desc->next;
+	*pindex = 0;
+	if (!next   /* is there a next node ? */
+	||  !( buf = btree_node_by_index(tree, next)))
+	    return NULL;
+    }
+    return buf;
+}
+/* move record foreward to next entry.
+ *
+ * In case of an error the value of *r is undefined !
+ */
+int record_next(record* r)
+{
+    btree*	tree	= r->tree;
+    UInt16	index	= r->keyind +1;
+    UInt32	parent;
+    node_buf*	buf	= prepare_next(tree, r->node_index, &index);
+
+    if (!buf)
+	return ENOENT;	// No (more) such file or directory
+
+    parent = r->key.parent_cnid;
+
+    if (record_init(r, tree, buf, index))
+	return -1;
+
+    if (r->key.parent_cnid != parent || // end of current directory
+	index != r->keyind)		// internal error ?
+	return ENOENT;	// No (more) such file or directory
+
+    return 0;
+}
+
+/* move record foreward to next extent record.
+ *
+ * In case of an error the value of *r is undefined !
+ */
+int record_next_extent(extent_record* r)
+{
+    btree*	tree   = r->tree;
+    UInt16	index  = r->keyind +1;
+    UInt32	file_id;
+    UInt8	fork_type;
+    node_buf*	buf	= prepare_next(tree, r->node_index, &index);
+
+    if (!buf)
+	return ENOENT;	// No (more) such file or directory
+
+    file_id	= r->key.file_id;
+    fork_type	= r->key.fork_type;
+
+    if (record_init_extent(r, tree, buf, index))
+	return -1;
+
+    if (r->key.file_id	 != file_id ||	    // end of current file
+	r->key.fork_type != fork_type ||    // end of current fork
+	index != r->keyind)		    // internal error ?
+	return ENOENT;	// No (more) such file or directory
+
+    return 0;
+}
+
+/* intialize the record by searching for the given string in the given folder.
+ *
+ * parent and r may be the same.
+ */
+int record_init_string_parent(record* r, record* parent, char* name)
+{
+    hfsp_cat_key key;
+
+    if (parent->record.type == HFSP_FOLDER)
+	key.parent_cnid = parent->record.u.folder.id;
+    else if(parent->record.type == HFSP_FOLDER_THREAD)
+	key.parent_cnid = parent->key.parent_cnid;
+    else
+	HFSP_ERROR(-1, "record_init_string_parent: parent is not a folder.");
+
+    key.key_length = 6 + unicode_asc2uni(&key.name,name); // 6 for minumum size
+    return record_init_key(r, parent->tree, &key);
+
+  fail:
+    return -1;
+}
+
+/* move record up in folder hierarchy (if possible) */
+int record_up(record* r)
+{
+    if (r->record.type == HFSP_FOLDER)
+    {
+	// locate folder thread
+	if (record_init_cnid(r, r->tree, r->record.u.folder.id))
+	    return -1;
+    }
+    else if(r->record.type == HFSP_FOLDER_THREAD)
+    {
+	// do nothing were are already where we want to be
+    }
+    else
+	HFSP_ERROR(-1, "record_up: record is neither folder nor folder thread.");
+
+    if(r->record.type != HFSP_FOLDER_THREAD)
+	HFSP_ERROR(-1, "record_up: unable to locate parent");
+    return record_init_cnid(r, r->tree, r->record.u.thread.parentID);
+
+  fail:
+    return -1;
+}
+
+#ifdef DEBUG
+
+/* print Quickdraw Point */
+static void record_print_Point(Point* p)
+{
+    printf("[ v=%d, h=%d ]", p->v, p->h);
+}
+
+/* print Quickdraw Rect */
+static void record_print_Rect(Rect* r)
+{
+    printf("[ top=%d, left=%d, bottom=%d, right=%d  ]",
+	     r->top, r->left, r->bottom, r->right);
+}
+
+/* print the key of a record */
+static void record_print_key(hfsp_cat_key* key)
+{
+    char buf[255]; // mh this _might_ overflow
+    unicode_uni2asc(buf, &key->name, 255);
+    printf("parent cnid :    %ld\n",   key->parent_cnid);
+    printf("name        :    %s\n", buf);
+}
+
+/* print permissions */
+static void record_print_perm(hfsp_perm* perm)
+{
+    printf("owner               :\t%ld\n",  perm->owner);
+    printf("group               :\t%ld\n",  perm->group);
+    printf("perm                :\t0x%lX\n",perm->mode);
+    printf("dev                 :\t%ld\n",  perm->dev);
+}
+
+/* print Directory info */
+static void record_print_DInfo(DInfo* dinfo)
+{
+    printf(  "frRect              :\t");    record_print_Rect(&dinfo->frRect);
+    printf("\nfrFlags             :\t0X%X\n",    dinfo->frFlags);
+    printf(  "frLocation          :\t");
record_print_Point(&dinfo->frLocation);
+    printf("\nfrView              :\t0X%X\n",    dinfo->frView);
+}
+
+/* print extended Directory info */
+static void record_print_DXInfo(DXInfo* xinfo)
+{
+    printf(  "frScroll            :\t");
record_print_Point(&xinfo->frScroll);
+    printf("\nfrOpenChain         :\t%ld\n",  xinfo->frOpenChain);
+    printf(  "frUnused            :\t%d\n",   xinfo->frUnused);
+    printf(  "frComment           :\t%d\n",   xinfo->frComment);
+    printf(  "frPutAway           :\t%ld\n",  xinfo->frPutAway);
+}
+
+static void record_print_folder(hfsp_cat_folder* folder)
+{
+    printf("flags               :\t0x%X\n",	folder->flags);
+    printf("valence             :\t0x%lX\n",	folder->valence);
+    printf("id                  :\t%ld\n",	folder->id);
+    record_print_perm	(&folder->permissions);
+    record_print_DInfo	(&folder->user_info);
+    record_print_DXInfo	(&folder->finder_info);
+    printf("text_encoding       :\t0x%lX\n",	folder->text_encoding);
+    printf("reserved            :\t0x%lX\n",	folder->reserved);
+}
+
+/* print File info */
+static void record_print_FInfo(FInfo* finfo)
+{
+    printf(  "fdType              :\t%4.4s\n", (char*) &finfo->fdType);
+    printf(  "fdCreator           :\t%4.4s\n", (char*) &finfo->fdCreator);
+    printf(  "fdFlags             :\t0X%X\n", finfo->fdFlags);
+    printf(  "fdLocation          :\t");
record_print_Point(&finfo->fdLocation);
+    printf("\nfdFldr              :\t%d\n",  finfo->fdFldr);
+}
+
+/* print extended File info */
+static void record_print_FXInfo(FXInfo* xinfo)
+{
+    printf(  "fdIconID            :\t%d\n",   xinfo->fdIconID);
+    // xinfo -> fdUnused;
+    printf(  "fdComment           :\t%d\n",   xinfo->fdComment);
+    printf(  "fdPutAway           :\t%ld\n",  xinfo->fdPutAway);
+}
+
+/* print folder entry */
+
+/* print file entry */
+static void record_print_file(hfsp_cat_file* file)
+{
+    printf("flags               :\t0x%X\n",	file->flags);
+    printf("reserved1           :\t0x%lX\n",	file->reserved1);
+    printf("id                  :\t%ld\n",	file->id);
+    record_print_perm	(&file->permissions);
+    record_print_FInfo	(&file->user_info);
+    record_print_FXInfo	(&file->finder_info);
+    printf("text_encoding       :\t0x%lX\n",	file->text_encoding);
+    printf("reserved            :\t0x%lX\n",	file->reserved2);
+    printf("Datafork:\n");
+    volume_print_fork (&file->data_fork);
+    printf("Rsrcfork:\n");
+    volume_print_fork (&file->res_fork);
+}
+
+/* print info for a file or folder thread */
+static void record_print_thread(hfsp_cat_thread* entry)
+{
+    char buf[255]; // mh this _might_ overflow
+    unicode_uni2asc(buf, &entry->nodeName, 255);
+    printf("parent cnid :\t%ld\n", entry->parentID);
+    printf("name        :\t%s\n" , buf);
+}
+
+/* print the information for a record */
+static void record_print_entry(hfsp_cat_entry* entry)
+{
+    switch (entry->type)
+    {
+	case HFSP_FOLDER:
+	    printf("=== Folder ===\n");
+	    return record_print_folder(&entry->u.folder);
+	case HFSP_FILE:
+	    printf("=== File ===\n");
+	    return record_print_file  (&entry->u.file);
+	case HFSP_FOLDER_THREAD:
+	    printf("=== Folder Thread ===\n");
+	    return record_print_thread(&entry->u.thread);
+	case HFSP_FILE_THREAD:
+	    printf("=== File Thread ==\n");
+	    return record_print_thread(&entry->u.thread);
+	default:
+	    printf("=== Unknown Record Type ===\n");
+    } ;
+}
+
+    /* Dump all the record information to stdout */
+void record_print(record* r)
+{
+    printf ("keyind      :    %u\n", r->keyind);
+    record_print_key  (&r->key);
+    record_print_entry(&r->record);
+}
+
+#endif
diff --git a/fs/hfsplus/hfsp_volume.c b/fs/hfsplus/hfsp_volume.c
new file mode 100644
index 0000000..802d700
--- /dev/null
+++ b/fs/hfsplus/hfsp_volume.c
@@ -0,0 +1,314 @@
+/*
+ * libhfs - library for reading and writing Macintosh HFS volumes
+ *
+ * Code to acces the basic volume information of a HFS+ volume.
+ *
+ * Copyright (C) 2000 Klaus Halfmann <khalfmann at libra.de>
+ * Original work by 1996-1998 Robert Leslie <rob at mars.org>
+ * other work 2000 from Brad Boyer (flar at pants.nu)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id: volume.c,v 1.21 2000/10/25 05:43:04 hasi Exp $
+ */
+
+#include "config.h"
+#include "libhfsp.h"
+#include "volume.h"
+#include "record.h"
+#include "btree.h"
+#include "blockiter.h"
+#include "os.h"
+#include "swab.h"
+#include "hfstime.h"
+
+
+/* Fill a given buffer with the given block in volume.
+ */
+int
+volume_readinbuf(volume * vol,void* buf, long block)
+{
+	UInt16 blksize_bits;
+	ASSERT( block < vol->maxblocks);
+
+	blksize_bits = vol->blksize_bits;
+	block	+= vol->startblock;
+	if( os_seek(vol->os_fd, block, blksize_bits) == block)
+		if( 1 == os_read(vol->os_fd, buf, 1, blksize_bits))
+			return 0;
+	return -1;
+}
+
+/* read multiple blocks into given memory.
+ *
+ * returns given pinter or NULL on failure.
+ */
+void*
+volume_readfromfork(volume* vol, void* buf,
+		hfsp_fork_raw* f, UInt32 block,
+		UInt32 count, UInt8 forktype, UInt32 fileId)
+{
+	blockiter iter;
+	char *cbuf = buf;
+
+	blockiter_init(&iter, vol, f, forktype, fileId);
+	if( blockiter_skip(&iter, block))
+		return NULL;
+
+	while( count > 0) {
+		--count;
+		if( volume_readinbuf(vol, cbuf, blockiter_curr(&iter)))
+			return NULL;
+		cbuf += vol->blksize;
+		if( count > 0 && blockiter_next(&iter))
+			return NULL;
+	}
+	return buf;
+}
+
+
+/* Read a raw hfsp_extent_rec from memory.
+ *
+ * return pointer right after the structure.
+ */
+void*
+volume_readextent(void *p, hfsp_extent_rec er)
+{
+	int 		i;
+	hfsp_extent	*e;
+
+	for( i=0; i < 8; i++) {
+		e = &er[i];
+		e->start_block = bswabU32_inc(p);
+		e->block_count = bswabU32_inc(p);
+	}
+	return p;
+}
+
+/* Read a raw hfsp_fork from memory.
+ *
+ * return pointer right after the structure.
+ */
+void*
+volume_readfork(void *p, hfsp_fork_raw* f)
+{
+	f->total_size   = bswabU64_inc(p);
+	f->clump_size   = bswabU32_inc(p);
+	f->total_blocks = bswabU32_inc(p);
+
+	return volume_readextent(p, f->extents);
+}
+
+/* Read the volume from the given buffer and swap the bytes.
+ *
+ * ToDo: add more consitency checks.
+ */
+static int
+volume_readbuf(hfsp_vh* vh, char * p)
+{
+	if(  (vh->signature = bswabU16_inc(p)) != HFSP_VOLHEAD_SIG)
+		HFSP_ERROR(-1, "This is not a HFS+ volume");
+
+	vh->version		= bswabU16_inc(p);
+	vh->attributes   	= bswabU32_inc(p);
+	vh->last_mount_vers	= bswabU32_inc(p);
+	vh->reserved		= bswabU32_inc(p);
+	vh->create_date		= bswabU32_inc(p);
+	vh->modify_date		= bswabU32_inc(p);
+	vh->backup_date		= bswabU32_inc(p);
+	vh->checked_date	= bswabU32_inc(p);
+	vh->file_count		= bswabU32_inc(p);
+	vh->folder_count	= bswabU32_inc(p);
+	vh->blocksize		= bswabU32_inc(p);
+	vh->total_blocks	= bswabU32_inc(p);
+	vh->free_blocks		= bswabU32_inc(p);
+	vh->next_alloc		= bswabU32_inc(p);
+	vh->rsrc_clump_sz	= bswabU32_inc(p);
+	vh->data_clump_sz	= bswabU32_inc(p);
+	vh->next_cnid		= bswabU32_inc(p);
+	vh->write_count		= bswabU32_inc(p);
+	vh->encodings_bmp	= bswabU64_inc(p);
+	memcpy(vh->finder_info, p, 32);
+	p += 32; // So finderinfo must be swapped later, ***
+	p = volume_readfork(p, &vh->alloc_file );
+	p = volume_readfork(p, &vh->ext_file   );
+	p = volume_readfork(p, &vh->cat_file   );
+	p = volume_readfork(p, &vh->attr_file  );
+        volume_readfork(p, &vh->start_file );
+	return 0;
+  fail:
+	return -1;
+}
+
+/* Read the volume from the given block */
+static int
+volume_read(volume * vol, hfsp_vh* vh, UInt32 block)
+{
+	char buf[vol->blksize];
+
+	if( volume_readinbuf(vol, buf, block))
+		return -1;
+        return volume_readbuf(vh, buf);
+}
+
+/* Find out wether the volume is wrapped and unwrap it eventually */
+static int
+volume_read_wrapper(volume * vol, hfsp_vh* vh)
+{
+	UInt16  signature;
+	char	buf[vol->blksize];
+        char    *p = buf;
+
+	if( volume_readinbuf(vol, buf, 2) ) // Wrapper or volume header starts here
+		return -1;
+
+	signature = bswabU16_inc(p);
+	if( signature == HFS_VOLHEAD_SIG) {		/* Wrapper */
+		UInt32  drAlBlkSiz;			/* size (in bytes) of allocation blocks */
+		UInt32	sect_per_block;			/* how may block build an hfs sector */
+		UInt16  drAlBlSt;			/* first allocation block in volume */
+		UInt16	embeds, embedl;			/* Start/lenght of embedded area in blocks */
+
+		p += 0x12;			/* skip unneded HFS vol fields */
+		drAlBlkSiz = bswabU32_inc(p);		/* offset 0x14 */
+		p += 0x4;			/* skip unneded HFS vol fields */
+		drAlBlSt = bswabU16_inc(p);		/* offset 0x1C */
+
+		p += 0x5E;			/* skip unneded HFS vol fields */
+		signature = bswabU16_inc(p);		/* offset 0x7C, drEmbedSigWord */
+		if( signature != HFSP_VOLHEAD_SIG)
+			HFSP_ERROR(-1, "This looks like a normal HFS volume");
+		embeds = bswabU16_inc(p);
+		embedl = bswabU16_inc(p);
+		sect_per_block =  (drAlBlkSiz / HFSP_BLOCKSZ);
+		// end is absolute (not relative to HFS+ start)
+		vol->maxblocks = embedl * sect_per_block;
+		vol->startblock = drAlBlSt + embeds * sect_per_block;
+		/* Now we can try to read the embedded HFS+ volume header */
+		return volume_read(vol,vh,2);
+	}
+	else if( signature == HFSP_VOLHEAD_SIG) { /* Native HFS+ volume */
+		p = buf; // Restore to begin of block
+                return volume_readbuf(vh, p);
+	} else
+		 HFSP_ERROR(-1, "Neither Wrapper nor native HFS+ volume header found");
+fail:
+	return -1;
+}
+
+
+/* Open the device, read and verify the volume header
+   (and its backup) */
+int
+volume_open( volume* vol, int os_fd )
+{
+	hfsp_vh backup;	/* backup volume found at second to last block */
+	long	sect_per_block;
+	int	shift;
+
+	vol->blksize_bits	= HFSP_BLOCKSZ_BITS;
+	vol->blksize		= HFSP_BLOCKSZ;
+	vol->startblock		= 0;
+	vol->maxblocks		= 3;
+		/* this should be enough until we find the volume descriptor */
+	vol->extents		= NULL; /* Thanks to Jeremias Sauceda */
+
+	btree_reset(&vol->catalog);
+	vol->os_fd = os_fd;
+
+	// vol->maxblocks = os_seek(vol->os_fd, -1, HFSP_BLOCKSZ_BITS);
+	// This wont work for /dev/... but we do not really need it
+
+	if( volume_read_wrapper(vol, &vol->vol))
+		return -1;
+	if( volume_read(vol, &backup, vol->maxblocks - 2))
+		return -1;
+
+	/* Now switch blksize from HFSP_BLOCKSZ (512) to value given in header
+	   and adjust depend values accordingly, after that a block always
+	   means a HFS+ allocation size */
+
+	/* Usually 4096 / 512  == 8 */
+	sect_per_block = vol->vol.blocksize / HFSP_BLOCKSZ;
+	shift = 0;
+	if( sect_per_block > 1) {
+		shift = 1;
+		while( sect_per_block > 2) {
+			sect_per_block >>=1;
+			shift++;
+		}		/* shift = 3 */
+	}
+	vol -> blksize_bits += shift;
+	vol -> blksize = 1 << vol->blksize_bits;
+	vol -> startblock >>= shift;
+	vol -> maxblocks = vol->vol.total_blocks;	/* cant calculate via shift ? */
+
+	if( btree_init_cat(&vol->catalog, vol, &vol->vol.cat_file))
+		return -1;
+
+	return 0;
+}
+
+/* Write back all data eventually cached and close the device */
+int
+volume_close(volume* vol)
+{
+	btree_close(&vol->catalog);
+	if( vol->extents) {
+		btree_close(vol->extents);
+		FREE(vol->extents);
+	}
+	return 0;
+}
+
+/* internal fucntion used to create the extents btree,
+   is called by inline function when needed */
+void
+volume_create_extents_tree(volume* vol)
+{
+	btree* result = (btree*) ALLOC(btree*, sizeof(btree));
+	if( !result)
+		HFSP_ERROR(ENOMEM, "No memory for extents btree");
+	if( !btree_init_extent(result, vol, &vol->vol.ext_file)) {
+		vol->extents = result;
+		return;
+	}
+  fail:
+	vol->extents = NULL;
+}
+
+/* Determine whether the volume is a HFS-plus volume */
+int
+volume_probe(int fd, long long offset)
+{
+	UInt16 *vol;
+	int ret = 0;
+
+	vol = (UInt16 *)malloc(2 * 1 << HFSP_BLOCKSZ_BITS);
+	os_seek_offset( fd, 2 * (1 << HFSP_BLOCKSZ_BITS) + offset );
+	os_read(fd, vol, 2, HFSP_BLOCKSZ_BITS);
+
+	if (__be16_to_cpu(vol[0]) == HFS_VOLHEAD_SIG &&
+		__be16_to_cpu(vol[0x7c]) == HFSP_VOLHEAD_SIG) {
+		ret = -1;
+	} else if (__be16_to_cpu(vol[0]) == HFSP_VOLHEAD_SIG) {
+		ret = -1;
+	}
+
+	free(vol);
+	return ret;
+}
+
diff --git a/fs/hfsplus/record.c b/fs/hfsplus/record.c
deleted file mode 100644
index d4e7af1..0000000
--- a/fs/hfsplus/record.c
+++ /dev/null
@@ -1,759 +0,0 @@
-/*
- * libhfsp - library for reading and writing Macintosh HFS+ volumes.
- *
- * a record contains a key and a folder or file and is part
- * of a btree.
- *
- * Copyright (C) 2000 Klaus Halfmann <khalfmann at libra.de>
- * Original 1996-1998 Robert Leslie <rob at mars.org>
- * Additional work by  Brad Boyer (flar at pants.nu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
- * MA 02110-1301, USA.
- *
- * $Id: record.c,v 1.24 2000/10/17 05:58:46 hasi Exp $
- */
-
-#include "config.h"
-#include "libhfsp.h"
-#include "hfstime.h"
-#include "record.h"
-#include "volume.h"
-#include "btree.h"
-#include "unicode.h"
-#include "swab.h"
-
-/* read a hfsp_cat_key from memory */
-void* record_readkey(void* p, void* buf)
-{
-    hfsp_cat_key*   key = (hfsp_cat_key*) buf;
-    const void*	    check;
-    UInt16	    key_length, len,i;
-    UInt16*	    cp;
-
-    key->key_length = key_length    = bswabU16_inc(p);
-    check = p;
-    key->parent_cnid		    = bswabU32_inc(p);
-    key->name.strlen = len	    = bswabU16_inc(p);
-    cp = key->name.name;
-    for (i=0; i < len; i++, cp++)
-	*cp			    = bswabU16_inc(p);
-	/* check if keylenght was correct */
-    if (key_length != ((char*) p) - ((char*) check))
-	 HFSP_ERROR(EINVAL, "Invalid key length in record_readkey");
-    return p;
-  fail:
-    return NULL;
-}
-
-/* read a hfsp_extent_key from memory */
-void* record_extent_readkey(void* p, void* buf)
-{
-    hfsp_extent_key* key = (hfsp_extent_key*) buf;
-    UInt16  key_length;
-
-    key->key_length = key_length    = bswabU16_inc(p);
-    key->fork_type		    = bswabU8_inc(p);
-    key->filler			    = bswabU8_inc(p);
-    if (key_length != 10)
-	HFSP_ERROR(-1, "Invalid key length in record_extent_readkey");
-    key->file_id		    = bswabU32_inc(p);
-    key->start_block		    = bswabU32_inc(p);
-    return p;
-  fail:
-    return NULL;
-}
-
-
-/* read posix permission from memory */
-static inline void* record_readperm(void *p, hfsp_perm* perm)
-{
-    perm->owner= bswabU32_inc(p);
-    perm->group= bswabU32_inc(p);
-    perm->mode = bswabU32_inc(p);
-    perm->dev  = bswabU32_inc(p);
-    return p;
-}
-
-/* read directory info */
-static inline void* record_readDInfo(void *p, DInfo* info)
-{
-    info->frRect.top	= bswabU16_inc(p);
-    info->frRect.left	= bswabU16_inc(p);
-    info->frRect.bottom	= bswabU16_inc(p);
-    info->frRect.right	= bswabU16_inc(p);
-    info->frFlags	= bswabU16_inc(p);
-    info->frLocation.v	= bswabU16_inc(p);
-    info->frLocation.h	= bswabU16_inc(p);
-    info->frView	= bswabU16_inc(p);
-    return p;
-}
-
-/* read extra Directory info */
-static inline void* record_readDXInfo(void *p, DXInfo* xinfo)
-{
-    xinfo->frScroll.v  = bswabU16_inc(p);
-    xinfo->frScroll.h  = bswabU16_inc(p);
-    xinfo->frOpenChain = bswabU32_inc(p);
-    xinfo->frUnused    = bswabU16_inc(p);
-    xinfo->frComment   = bswabU16_inc(p);
-    xinfo->frPutAway   = bswabU32_inc(p);
-    return p;
-}
-
-/* read a hfsp_cat_folder from memory */
-static void* record_readfolder(void *p, hfsp_cat_folder* folder)
-{
-    folder->flags		= bswabU16_inc(p);
-    folder->valence		= bswabU32_inc(p);
-    folder->id			= bswabU32_inc(p);
-    folder->create_date		= bswabU32_inc(p);
-    folder->content_mod_date    = bswabU32_inc(p);
-    folder->attribute_mod_date	= bswabU32_inc(p);
-    folder->access_date		= bswabU32_inc(p);
-    folder->backup_date		= bswabU32_inc(p);
-    p = record_readperm	    (p, &folder->permissions);
-    p = record_readDInfo    (p, &folder->user_info);
-    p = record_readDXInfo   (p, &folder->finder_info);
-    folder->text_encoding	= bswabU32_inc(p);
-    folder->reserved		= bswabU32_inc(p);
-    return p;
-}
-
-/* read file info */
-static inline void* record_readFInfo(void *p, FInfo* info)
-{
-    info->fdType	= bswabU32_inc(p);
-    info->fdCreator	= bswabU32_inc(p);
-    info->fdFlags	= bswabU16_inc(p);
-    info->fdLocation.v	= bswabU16_inc(p);
-    info->fdLocation.h	= bswabU16_inc(p);
-    info->fdFldr	= bswabU16_inc(p);
-    return p;
-}
-
-/* read extra File info */
-static inline void* record_readFXInfo(void *p, FXInfo* xinfo)
-{
-    SInt16 *q;
-    xinfo->fdIconID	= bswabU16_inc(p);
-    q=(SInt16*) p;
-    q+=4; // skip unused
-    p=(void *)q;
-    xinfo->fdComment	= bswabU16_inc(p);
-    xinfo->fdPutAway	= bswabU32_inc(p);
-    return p;
-}
-
-/* read a hfsp_cat_file from memory */
-static void* record_readfile(void *p, hfsp_cat_file* file)
-{
-    file->flags			= bswabU16_inc(p);
-    file->reserved1		= bswabU32_inc(p);
-    file->id			= bswabU32_inc(p);
-    file->create_date		= bswabU32_inc(p);
-    file->content_mod_date	= bswabU32_inc(p);
-    file->attribute_mod_date	= bswabU32_inc(p);
-    file->access_date		= bswabU32_inc(p);
-    file->backup_date		= bswabU32_inc(p);
-    p = record_readperm	    (p, &file->permissions);
-    p = record_readFInfo    (p, &file->user_info);
-    p = record_readFXInfo   (p, &file->finder_info);
-    file->text_encoding		= bswabU32_inc(p);
-    file->reserved2		= bswabU32_inc(p);
-    p =	    volume_readfork (p, &file->data_fork);
-    return  volume_readfork (p, &file->res_fork);
-}
-
-/* read a hfsp_cat_thread from memory */
-static void* record_readthread(void *p, hfsp_cat_thread* entry)
-{
-    int	    i;
-    UInt16  len;
-    UInt16* cp;
-
-    entry->         reserved	= bswabU16_inc(p);
-    entry->	    parentID	= bswabU32_inc(p);
-    entry->nodeName.strlen = len= bswabU16_inc(p);
-    cp = entry->nodeName.name;
-    if (len > 255)
-        HFSP_ERROR(-1, "Invalid key length in record thread");
-    for (i=0; i < len; i++, cp++)
-	*cp			 = bswabU16_inc(p);
-    return p;
- fail:
-    return NULL;
-}
-
-/* read a hfsp_cat_entry from memory */
-static void* record_readentry(void *p, hfsp_cat_entry* entry)
-{
-    UInt16 type = bswabU16_inc(p);
-    entry->type = type;
-    switch (type)
-    {
-	case HFSP_FOLDER:
-	    return record_readfolder(p, &entry->u.folder);
-	case HFSP_FILE:
-	    return record_readfile  (p, &entry->u.file);
-	case HFSP_FOLDER_THREAD:
-	case HFSP_FILE_THREAD:
-	    return record_readthread(p, &entry->u.thread);
-	default:
-	    HFSP_ERROR(-1, "Unexpected record type in record_readentry");
-    } ;
-  fail:
-    return NULL;
-}
-
-
-/* Most of the functions here will not change the node in the btree,
-   But this must be changed in the future ... */
-
-
-/* intialize the record with the given index entry in the btree. */
-static int record_init(record* r, btree* bt, node_buf* buf, UInt16 index)
-{
-    void *p;
-    r-> tree   = bt;
-    p = btree_key_by_index(bt,buf,index);
-    if (!p)
-	return -1;
-    p = record_readkey  (p, &r->key);
-    if (!p)
-	return -1;
-    p = record_readentry(p, &r->record);
-    if (!p)
-	return -1;
-    r->node_index = buf->index;
-    r-> keyind    = index;
-
-    return 0;
-}
-
-/* intialize the record with the given index entry in the btree. */
-static int record_init_extent(extent_record* r, btree* bt, node_buf*
buf, UInt16 index)
-{
-    void *p;
-    r-> tree   = bt;
-    p = btree_key_by_index(bt, buf,index);
-    if (!p)
-	return -1;
-    p = record_extent_readkey(p, &r->key);
-    if (!p)
-	return -1;
-    p = volume_readextent(p, r->extent);
-    if (!p)
-	return -1;
-    r->node_index = buf->index;
-    r-> keyind    = index;
-
-    return 0;
-}
-
-/* intialize the record to the first record of the tree
- * which is (per design) the root node.
- */
-int record_init_root(record* r, btree* tree)
-{
-    // Position to first leaf node ...
-    UInt32 leaf_head = tree->head.leaf_head;
-    node_buf* buf = btree_node_by_index(tree, leaf_head);
-    if (!buf)
-	return -1;
-    return record_init(r, tree, buf, 0);
-}
-
-/* Compare two cat_keys ... */
-int record_key_compare(void* k1, void* k2)
-{
-    hfsp_cat_key* key1 = (hfsp_cat_key*) k1;
-    hfsp_cat_key* key2 = (hfsp_cat_key*) k2;
-    int diff = key2->parent_cnid - key1->parent_cnid;
-    if (!diff) // same parent
-	diff = fast_unicode_compare(&key1->name, &key2->name);
-    return diff;
-}
-
-/* Compare two extent_keys ... */
-int record_extent_key_compare(void* k1, void* k2)
-{
-    hfsp_extent_key* key1 = (hfsp_extent_key*) k1;
-    hfsp_extent_key* key2 = (hfsp_extent_key*) k2;
-    int diff = key2->fork_type - key1->fork_type;
-    if (!diff) // same type
-    {
-	diff = key2->file_id - key1->file_id;
-	if (!diff) // same file
-	    diff = key2->start_block - key1->start_block;
-    }
-    return diff;
-}
-
-/* Position node in btree so that key might be inside */
-static node_buf* record_find_node(btree* tree, void *key)
-{
-    int			start, end, mid, comp;  // components of a binary search
-    void		*p = NULL;
-    char		curr_key[tree->head.max_key_len];
-		    // The current key under examination
-    hfsp_key_read	readkey	    = tree->kread;
-    hfsp_key_compare	key_compare = tree->kcomp;
-    UInt32		index;
-    node_buf*		node = btree_node_by_index(tree, tree->head.root);
-    if (!node)
-	HFSP_ERROR(-1, "record_find_node: Cant position to root node");
-    while (node->desc.kind == HFSP_NODE_NDX)
-    {
-	mid = start = 0;
-	end  = node->desc.num_rec;
-	comp = -1;
-	while (start < end)
-	{
-	    mid = (start + end) >> 1;
-	    p = btree_key_by_index(tree, node, mid);
-	    if (!p)
-		HFSP_ERROR(-1, "record_find_node: unexpected error");
-	    p = readkey  (p, curr_key);
-	    if (!p)
-		HFSP_ERROR(-1, "record_find_node: unexpected error");
-	    comp = key_compare(curr_key, key);
-	    if (comp > 0)
-		start = mid + 1;
-	    else if (comp < 0)
-		end = mid;
-	    else
-		break;
-	}
-	if (!p) // Empty tree, fascinating ...
-	    HFSP_ERROR(-1, "record_find_node: unexpected empty node");
-	if (comp < 0)	// mmh interesting key is before this key ...
-	{
-	    if (mid == 0)
-		return NULL;  // nothing before this key ..
-	    p = btree_key_by_index(tree, node, mid-1);
-	    if (!p)
-		HFSP_ERROR(-1, "record_find_node: unexpected error");
-	    p = readkey  (p, curr_key);
-	    if (!p)
-		HFSP_ERROR(-1, "record_find_node: unexpected error");
-	}
-
-	index = bswabU32_inc(p);
-	node = btree_node_by_index(tree, index);
-    }
-    return node;	// go on and use the found node
-  fail:
-    return NULL;
-}
-
-/* search for the given key in the btree.
- *
- * returns pointer to memory just after key or NULL
- * In any case *keyind recives the index where the
- * key was found (or could be inserted.)
- */
-static void *
-record_find_key(btree* tree, void* key, int* keyind, UInt16* node_index)
-{
-    node_buf* buf = record_find_node(tree, key);
-    if (buf)
-    {
-	int		    comp  = -1;
-	int		    start = 0; // components of a binary search
-	int		    end   = buf->desc.num_rec;
-	int		    mid   = -1;
-	void		    *p    = NULL;
-	char		    curr_key[tree->head.max_key_len];
-	hfsp_key_read	    readkey	= tree->kread;
-	hfsp_key_compare    key_compare = tree->kcomp;
-	while (start < end)
-	{
-	    mid = (start + end) >> 1;
-	    p = btree_key_by_index(tree, buf, mid);
-	    if (!p)
-		HFSP_ERROR(-1, "record_init_key: unexpected error");
-	    p = readkey  (p, curr_key);
-	    if (!p)
-		HFSP_ERROR(-1, "record_init_cat_key: unexpected error");
-	    comp = key_compare(curr_key, key);
-	    if (comp > 0)
-		start = mid + 1;
-	    else if (comp < 0)
-		end = mid;
-	    else
-		break;
-	}
-	if (!p) // Empty tree, fascinating ...
-	    HFSP_ERROR(ENOENT, "record_init_key: unexpected empty node");
-	*keyind = mid;
-	*node_index = buf->index;
-	if (!comp)	// found something ...
-	    return p;
-    }
-    HFSP_ERROR(ENOENT, NULL);
-  fail:
-    return NULL;
-}
-
-/* intialize the record by searching for the given key in the btree.
- *
- * r is umodified on error.
- */
-static int
-record_init_key(record* r, btree* tree, hfsp_cat_key* key)
-{
-    int	    keyind;
-    UInt16  node_index;
-    void    *p = record_find_key(tree, key, &keyind, &node_index);
-
-    if (p)
-    {
-	r -> tree      = tree;
-	r -> node_index= node_index;
-	r -> keyind    = keyind;
-	r -> key       = *key; // Better use a record_key_copy ...
-	p = record_readentry(p, &r->record);
-	if (!p)
-	    HFSP_ERROR(-1, "record_init_key: unexpected error");
-	return 0;
-    }
-  fail:
-    return -1;
-}
-
-/* intialize the extent_record to the extent identified by the
- * (first) blockindex.
- *
- * forktype: either HFSP_EXTEND_DATA or HFSP_EXTEND_RSRC
- */
-int record_init_file(extent_record* r, btree* tree,
-		    UInt8 forktype, UInt32 fileId, UInt32 blockindex)
-{
-    int		    keyind;
-    UInt16	    node_index;
-    hfsp_extent_key key = { 10, forktype, 0, fileId, blockindex };
-    void	    *p = record_find_key(tree, &key, &keyind, &node_index);
-
-    if (p)
-    {
-	r -> tree      = tree;
-	r -> node_index= node_index;
-	r -> keyind    = keyind;
-	r -> key       = key; // Better use a record_key_copy ...
-	p =  volume_readextent(p, r->extent);
-	if (!p)
-	    HFSP_ERROR(-1, "record_init_file: unexpected error");
-	return 0;
-    }
-  fail:
-    return -1;
-}
-
-/* intialize the record to the folder identified by cnid
- */
-int record_init_cnid(record* r, btree* tree, UInt32 cnid)
-{
-    hfsp_cat_key    thread_key;	    // the thread is the first record
-
-    thread_key.key_length = 6;	    // null name (like '.' in unix )
-    thread_key.parent_cnid = cnid;
-    thread_key.name.strlen = 0;
-
-    return record_init_key(r, tree, &thread_key);
-}
-
-/* intialize the record to the first record of the parent.
- */
-int record_init_parent(record* r, record* parent)
-{
-    if (parent->record.type == HFSP_FOLDER)
-	return record_init_cnid(r, parent->tree, parent->record.u.folder.id);
-    else if(parent->record.type == HFSP_FOLDER_THREAD)
-    {
-	if (r != parent)
-	    *r = *parent; // The folder thread is in fact the first entry, like '.'
-	return 0;
-    }
-    HFSP_ERROR(EINVAL,
-	"record_init_parent: parent is neither folder nor folder thread.");
-
-  fail:
-    return EINVAL;
-}
-
-
-/* find correct node record for given node and *pindex.
- *
- * index of record in this (or next) node
- * */
-static node_buf* prepare_next(btree* tree, UInt16 node_index, UInt16* pindex)
-{
-    node_buf*	     buf    = btree_node_by_index(tree, node_index);
-    btree_node_desc* desc   = &buf->desc;
-    UInt32	     numrec = desc->num_rec;
-    if (*pindex >= numrec) // move on to next node
-    {
-	UInt16 next = desc->next;
-	*pindex = 0;
-	if (!next   /* is there a next node ? */
-	||  !( buf = btree_node_by_index(tree, next)))
-	    return NULL;
-    }
-    return buf;
-}
-/* move record foreward to next entry.
- *
- * In case of an error the value of *r is undefined !
- */
-int record_next(record* r)
-{
-    btree*	tree	= r->tree;
-    UInt16	index	= r->keyind +1;
-    UInt32	parent;
-    node_buf*	buf	= prepare_next(tree, r->node_index, &index);
-
-    if (!buf)
-	return ENOENT;	// No (more) such file or directory
-
-    parent = r->key.parent_cnid;
-
-    if (record_init(r, tree, buf, index))
-	return -1;
-
-    if (r->key.parent_cnid != parent || // end of current directory
-	index != r->keyind)		// internal error ?
-	return ENOENT;	// No (more) such file or directory
-
-    return 0;
-}
-
-/* move record foreward to next extent record.
- *
- * In case of an error the value of *r is undefined !
- */
-int record_next_extent(extent_record* r)
-{
-    btree*	tree   = r->tree;
-    UInt16	index  = r->keyind +1;
-    UInt32	file_id;
-    UInt8	fork_type;
-    node_buf*	buf	= prepare_next(tree, r->node_index, &index);
-
-    if (!buf)
-	return ENOENT;	// No (more) such file or directory
-
-    file_id	= r->key.file_id;
-    fork_type	= r->key.fork_type;
-
-    if (record_init_extent(r, tree, buf, index))
-	return -1;
-
-    if (r->key.file_id	 != file_id ||	    // end of current file
-	r->key.fork_type != fork_type ||    // end of current fork
-	index != r->keyind)		    // internal error ?
-	return ENOENT;	// No (more) such file or directory
-
-    return 0;
-}
-
-/* intialize the record by searching for the given string in the given folder.
- *
- * parent and r may be the same.
- */
-int record_init_string_parent(record* r, record* parent, char* name)
-{
-    hfsp_cat_key key;
-
-    if (parent->record.type == HFSP_FOLDER)
-	key.parent_cnid = parent->record.u.folder.id;
-    else if(parent->record.type == HFSP_FOLDER_THREAD)
-	key.parent_cnid = parent->key.parent_cnid;
-    else
-	HFSP_ERROR(-1, "record_init_string_parent: parent is not a folder.");
-
-    key.key_length = 6 + unicode_asc2uni(&key.name,name); // 6 for minumum size
-    return record_init_key(r, parent->tree, &key);
-
-  fail:
-    return -1;
-}
-
-/* move record up in folder hierarchy (if possible) */
-int record_up(record* r)
-{
-    if (r->record.type == HFSP_FOLDER)
-    {
-	// locate folder thread
-	if (record_init_cnid(r, r->tree, r->record.u.folder.id))
-	    return -1;
-    }
-    else if(r->record.type == HFSP_FOLDER_THREAD)
-    {
-	// do nothing were are already where we want to be
-    }
-    else
-	HFSP_ERROR(-1, "record_up: record is neither folder nor folder thread.");
-
-    if(r->record.type != HFSP_FOLDER_THREAD)
-	HFSP_ERROR(-1, "record_up: unable to locate parent");
-    return record_init_cnid(r, r->tree, r->record.u.thread.parentID);
-
-  fail:
-    return -1;
-}
-
-#ifdef DEBUG
-
-/* print Quickdraw Point */
-static void record_print_Point(Point* p)
-{
-    printf("[ v=%d, h=%d ]", p->v, p->h);
-}
-
-/* print Quickdraw Rect */
-static void record_print_Rect(Rect* r)
-{
-    printf("[ top=%d, left=%d, bottom=%d, right=%d  ]",
-	     r->top, r->left, r->bottom, r->right);
-}
-
-/* print the key of a record */
-static void record_print_key(hfsp_cat_key* key)
-{
-    char buf[255]; // mh this _might_ overflow
-    unicode_uni2asc(buf, &key->name, 255);
-    printf("parent cnid :    %ld\n",   key->parent_cnid);
-    printf("name        :    %s\n", buf);
-}
-
-/* print permissions */
-static void record_print_perm(hfsp_perm* perm)
-{
-    printf("owner               :\t%ld\n",  perm->owner);
-    printf("group               :\t%ld\n",  perm->group);
-    printf("perm                :\t0x%lX\n",perm->mode);
-    printf("dev                 :\t%ld\n",  perm->dev);
-}
-
-/* print Directory info */
-static void record_print_DInfo(DInfo* dinfo)
-{
-    printf(  "frRect              :\t");    record_print_Rect(&dinfo->frRect);
-    printf("\nfrFlags             :\t0X%X\n",    dinfo->frFlags);
-    printf(  "frLocation          :\t");
record_print_Point(&dinfo->frLocation);
-    printf("\nfrView              :\t0X%X\n",    dinfo->frView);
-}
-
-/* print extended Directory info */
-static void record_print_DXInfo(DXInfo* xinfo)
-{
-    printf(  "frScroll            :\t");
record_print_Point(&xinfo->frScroll);
-    printf("\nfrOpenChain         :\t%ld\n",  xinfo->frOpenChain);
-    printf(  "frUnused            :\t%d\n",   xinfo->frUnused);
-    printf(  "frComment           :\t%d\n",   xinfo->frComment);
-    printf(  "frPutAway           :\t%ld\n",  xinfo->frPutAway);
-}
-
-static void record_print_folder(hfsp_cat_folder* folder)
-{
-    printf("flags               :\t0x%X\n",	folder->flags);
-    printf("valence             :\t0x%lX\n",	folder->valence);
-    printf("id                  :\t%ld\n",	folder->id);
-    record_print_perm	(&folder->permissions);
-    record_print_DInfo	(&folder->user_info);
-    record_print_DXInfo	(&folder->finder_info);
-    printf("text_encoding       :\t0x%lX\n",	folder->text_encoding);
-    printf("reserved            :\t0x%lX\n",	folder->reserved);
-}
-
-/* print File info */
-static void record_print_FInfo(FInfo* finfo)
-{
-    printf(  "fdType              :\t%4.4s\n", (char*) &finfo->fdType);
-    printf(  "fdCreator           :\t%4.4s\n", (char*) &finfo->fdCreator);
-    printf(  "fdFlags             :\t0X%X\n", finfo->fdFlags);
-    printf(  "fdLocation          :\t");
record_print_Point(&finfo->fdLocation);
-    printf("\nfdFldr              :\t%d\n",  finfo->fdFldr);
-}
-
-/* print extended File info */
-static void record_print_FXInfo(FXInfo* xinfo)
-{
-    printf(  "fdIconID            :\t%d\n",   xinfo->fdIconID);
-    // xinfo -> fdUnused;
-    printf(  "fdComment           :\t%d\n",   xinfo->fdComment);
-    printf(  "fdPutAway           :\t%ld\n",  xinfo->fdPutAway);
-}
-
-/* print folder entry */
-
-/* print file entry */
-static void record_print_file(hfsp_cat_file* file)
-{
-    printf("flags               :\t0x%X\n",	file->flags);
-    printf("reserved1           :\t0x%lX\n",	file->reserved1);
-    printf("id                  :\t%ld\n",	file->id);
-    record_print_perm	(&file->permissions);
-    record_print_FInfo	(&file->user_info);
-    record_print_FXInfo	(&file->finder_info);
-    printf("text_encoding       :\t0x%lX\n",	file->text_encoding);
-    printf("reserved            :\t0x%lX\n",	file->reserved2);
-    printf("Datafork:\n");
-    volume_print_fork (&file->data_fork);
-    printf("Rsrcfork:\n");
-    volume_print_fork (&file->res_fork);
-}
-
-/* print info for a file or folder thread */
-static void record_print_thread(hfsp_cat_thread* entry)
-{
-    char buf[255]; // mh this _might_ overflow
-    unicode_uni2asc(buf, &entry->nodeName, 255);
-    printf("parent cnid :\t%ld\n", entry->parentID);
-    printf("name        :\t%s\n" , buf);
-}
-
-/* print the information for a record */
-static void record_print_entry(hfsp_cat_entry* entry)
-{
-    switch (entry->type)
-    {
-	case HFSP_FOLDER:
-	    printf("=== Folder ===\n");
-	    return record_print_folder(&entry->u.folder);
-	case HFSP_FILE:
-	    printf("=== File ===\n");
-	    return record_print_file  (&entry->u.file);
-	case HFSP_FOLDER_THREAD:
-	    printf("=== Folder Thread ===\n");
-	    return record_print_thread(&entry->u.thread);
-	case HFSP_FILE_THREAD:
-	    printf("=== File Thread ==\n");
-	    return record_print_thread(&entry->u.thread);
-	default:
-	    printf("=== Unknown Record Type ===\n");
-    } ;
-}
-
-    /* Dump all the record information to stdout */
-void record_print(record* r)
-{
-    printf ("keyind      :    %u\n", r->keyind);
-    record_print_key  (&r->key);
-    record_print_entry(&r->record);
-}
-
-#endif
diff --git a/fs/hfsplus/volume.c b/fs/hfsplus/volume.c
deleted file mode 100644
index 40b3eac..0000000
--- a/fs/hfsplus/volume.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * libhfs - library for reading and writing Macintosh HFS volumes
- *
- * Code to acces the basic volume information of a HFS+ volume.
- *
- * Copyright (C) 2000 Klaus Halfmann <khalfmann at libra.de>
- * Original work by 1996-1998 Robert Leslie <rob at mars.org>
- * other work 2000 from Brad Boyer (flar at pants.nu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
- * MA 02110-1301, USA.
- *
- * $Id: volume.c,v 1.21 2000/10/25 05:43:04 hasi Exp $
- */
-
-#include "config.h"
-#include "libhfsp.h"
-#include "volume.h"
-#include "record.h"
-#include "btree.h"
-#include "blockiter.h"
-#include "os.h"
-#include "swab.h"
-#include "hfstime.h"
-
-
-/* Fill a given buffer with the given block in volume.
- */
-int
-volume_readinbuf(volume * vol,void* buf, long block)
-{
-	UInt16 blksize_bits;
-	ASSERT( block < vol->maxblocks);
-
-	blksize_bits = vol->blksize_bits;
-	block	+= vol->startblock;
-	if( os_seek(vol->os_fd, block, blksize_bits) == block)
-		if( 1 == os_read(vol->os_fd, buf, 1, blksize_bits))
-			return 0;
-	return -1;
-}
-
-/* read multiple blocks into given memory.
- *
- * returns given pinter or NULL on failure.
- */
-void*
-volume_readfromfork(volume* vol, void* buf,
-		hfsp_fork_raw* f, UInt32 block,
-		UInt32 count, UInt8 forktype, UInt32 fileId)
-{
-	blockiter iter;
-	char *cbuf = buf;
-
-	blockiter_init(&iter, vol, f, forktype, fileId);
-	if( blockiter_skip(&iter, block))
-		return NULL;
-
-	while( count > 0) {
-		--count;
-		if( volume_readinbuf(vol, cbuf, blockiter_curr(&iter)))
-			return NULL;
-		cbuf += vol->blksize;
-		if( count > 0 && blockiter_next(&iter))
-			return NULL;
-	}
-	return buf;
-}
-
-
-/* Read a raw hfsp_extent_rec from memory.
- *
- * return pointer right after the structure.
- */
-void*
-volume_readextent(void *p, hfsp_extent_rec er)
-{
-	int 		i;
-	hfsp_extent	*e;
-
-	for( i=0; i < 8; i++) {
-		e = &er[i];
-		e->start_block = bswabU32_inc(p);
-		e->block_count = bswabU32_inc(p);
-	}
-	return p;
-}
-
-/* Read a raw hfsp_fork from memory.
- *
- * return pointer right after the structure.
- */
-void*
-volume_readfork(void *p, hfsp_fork_raw* f)
-{
-	f->total_size   = bswabU64_inc(p);
-	f->clump_size   = bswabU32_inc(p);
-	f->total_blocks = bswabU32_inc(p);
-
-	return volume_readextent(p, f->extents);
-}
-
-/* Read the volume from the given buffer and swap the bytes.
- *
- * ToDo: add more consitency checks.
- */
-static int
-volume_readbuf(hfsp_vh* vh, char * p)
-{
-	if(  (vh->signature = bswabU16_inc(p)) != HFSP_VOLHEAD_SIG)
-		HFSP_ERROR(-1, "This is not a HFS+ volume");
-
-	vh->version		= bswabU16_inc(p);
-	vh->attributes   	= bswabU32_inc(p);
-	vh->last_mount_vers	= bswabU32_inc(p);
-	vh->reserved		= bswabU32_inc(p);
-	vh->create_date		= bswabU32_inc(p);
-	vh->modify_date		= bswabU32_inc(p);
-	vh->backup_date		= bswabU32_inc(p);
-	vh->checked_date	= bswabU32_inc(p);
-	vh->file_count		= bswabU32_inc(p);
-	vh->folder_count	= bswabU32_inc(p);
-	vh->blocksize		= bswabU32_inc(p);
-	vh->total_blocks	= bswabU32_inc(p);
-	vh->free_blocks		= bswabU32_inc(p);
-	vh->next_alloc		= bswabU32_inc(p);
-	vh->rsrc_clump_sz	= bswabU32_inc(p);
-	vh->data_clump_sz	= bswabU32_inc(p);
-	vh->next_cnid		= bswabU32_inc(p);
-	vh->write_count		= bswabU32_inc(p);
-	vh->encodings_bmp	= bswabU64_inc(p);
-	memcpy(vh->finder_info, p, 32);
-	p += 32; // So finderinfo must be swapped later, ***
-	p = volume_readfork(p, &vh->alloc_file );
-	p = volume_readfork(p, &vh->ext_file   );
-	p = volume_readfork(p, &vh->cat_file   );
-	p = volume_readfork(p, &vh->attr_file  );
-        volume_readfork(p, &vh->start_file );
-	return 0;
-  fail:
-	return -1;
-}
-
-/* Read the volume from the given block */
-static int
-volume_read(volume * vol, hfsp_vh* vh, UInt32 block)
-{
-	char buf[vol->blksize];
-
-	if( volume_readinbuf(vol, buf, block))
-		return -1;
-        return volume_readbuf(vh, buf);
-}
-
-/* Find out wether the volume is wrapped and unwrap it eventually */
-static int
-volume_read_wrapper(volume * vol, hfsp_vh* vh)
-{
-	UInt16  signature;
-	char	buf[vol->blksize];
-        char    *p = buf;
-
-	if( volume_readinbuf(vol, buf, 2) ) // Wrapper or volume header starts here
-		return -1;
-
-	signature = bswabU16_inc(p);
-	if( signature == HFS_VOLHEAD_SIG) {		/* Wrapper */
-		UInt32  drAlBlkSiz;			/* size (in bytes) of allocation blocks */
-		UInt32	sect_per_block;			/* how may block build an hfs sector */
-		UInt16  drAlBlSt;			/* first allocation block in volume */
-  		UInt16	embeds, embedl;			/* Start/lenght of embedded area in blocks */
-
-		p += 0x12;			/* skip unneded HFS vol fields */
-		drAlBlkSiz = bswabU32_inc(p);		/* offset 0x14 */
-		p += 0x4;			/* skip unneded HFS vol fields */
-		drAlBlSt = bswabU16_inc(p);		/* offset 0x1C */
-
-		p += 0x5E;			/* skip unneded HFS vol fields */
-		signature = bswabU16_inc(p);		/* offset 0x7C, drEmbedSigWord */
-		if( signature != HFSP_VOLHEAD_SIG)
-			HFSP_ERROR(-1, "This looks like a normal HFS volume");
-		embeds = bswabU16_inc(p);
-		embedl = bswabU16_inc(p);
-		sect_per_block =  (drAlBlkSiz / HFSP_BLOCKSZ);
-		// end is absolute (not relative to HFS+ start)
-		vol->maxblocks = embedl * sect_per_block;
-		vol->startblock = drAlBlSt + embeds * sect_per_block;
-		/* Now we can try to read the embedded HFS+ volume header */
-		return volume_read(vol,vh,2);
-	}
-	else if( signature == HFSP_VOLHEAD_SIG) { /* Native HFS+ volume */
-		p = buf; // Restore to begin of block
-                return volume_readbuf(vh, p);
-	} else
-		 HFSP_ERROR(-1, "Neither Wrapper nor native HFS+ volume header found");
-fail:
-	return -1;
-}
-
-
-/* Open the device, read and verify the volume header
-   (and its backup) */
-int
-volume_open( volume* vol, int os_fd )
-{
-	hfsp_vh backup;	/* backup volume found at second to last block */
-	long	sect_per_block;
-	int	shift;
-
-	vol->blksize_bits	= HFSP_BLOCKSZ_BITS;
-	vol->blksize		= HFSP_BLOCKSZ;
-	vol->startblock		= 0;
-	vol->maxblocks		= 3;
-		/* this should be enough until we find the volume descriptor */
-	vol->extents		= NULL; /* Thanks to Jeremias Sauceda */
-
-	btree_reset(&vol->catalog);
-	vol->os_fd = os_fd;
-
-	// vol->maxblocks = os_seek(vol->os_fd, -1, HFSP_BLOCKSZ_BITS);
-	// This wont work for /dev/... but we do not really need it
-
-	if( volume_read_wrapper(vol, &vol->vol))
-		return -1;
-	if( volume_read(vol, &backup, vol->maxblocks - 2))
-		return -1;
-
-	/* Now switch blksize from HFSP_BLOCKSZ (512) to value given in header
-	   and adjust depend values accordingly, after that a block always
-	   means a HFS+ allocation size */
-
-	/* Usually 4096 / 512  == 8 */
-	sect_per_block = vol->vol.blocksize / HFSP_BLOCKSZ;
-	shift = 0;
-	if( sect_per_block > 1) {
-		shift = 1;
-		while( sect_per_block > 2) {
-			sect_per_block >>=1;
-			shift++;
-		}		/* shift = 3 */
-	}
-	vol -> blksize_bits += shift;
-	vol -> blksize = 1 << vol->blksize_bits;
-	vol -> startblock >>= shift;
-	vol -> maxblocks = vol->vol.total_blocks;	/* cant calculate via shift ? */
-
-	if( btree_init_cat(&vol->catalog, vol, &vol->vol.cat_file))
-		return -1;
-
-	return 0;
-}
-
-/* Write back all data eventually cached and close the device */
-int
-volume_close(volume* vol)
-{
-	btree_close(&vol->catalog);
-	if( vol->extents) {
-		btree_close(vol->extents);
-		FREE(vol->extents);
-	}
-	return 0;
-}
-
-/* internal fucntion used to create the extents btree,
-   is called by inline function when needed */
-void
-volume_create_extents_tree(volume* vol)
-{
-	btree* result = (btree*) ALLOC(btree*, sizeof(btree));
-	if( !result)
-		HFSP_ERROR(ENOMEM, "No memory for extents btree");
-	if( !btree_init_extent(result, vol, &vol->vol.ext_file)) {
-		vol->extents = result;
-		return;
-	}
-  fail:
-	vol->extents = NULL;
-}
-
-/* Determine whether the volume is a HFS-plus volume */
-int
-volume_probe(int fd, long long offset)
-{
-	UInt16 *vol;
-	int ret = 0;
-
-	vol = (UInt16 *)malloc(2 * 1 << HFSP_BLOCKSZ_BITS);
-	os_seek_offset( fd, 2 * (1 << HFSP_BLOCKSZ_BITS) + offset );
-	os_read(fd, vol, 2, HFSP_BLOCKSZ_BITS);
-
-	if (__be16_to_cpu(vol[0]) == HFS_VOLHEAD_SIG &&
-		__be16_to_cpu(vol[0x7c]) == HFSP_VOLHEAD_SIG) {
-		ret = -1;	
-	} else if (__be16_to_cpu(vol[0]) == HFSP_VOLHEAD_SIG) {
-		ret = -1;
-	}
-
-	free(vol);
-	return ret;
-}
-
-- 
1.6.2.4



More information about the OpenBIOS mailing list