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(a)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(a)libra.de>
- * Original 1996-1998 Robert Leslie <rob(a)mars.org>
- * Additional work by Brad Boyer (flar(a)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(a)libra.de>
+ * Original 1996-1998 Robert Leslie <rob(a)mars.org>
+ * Additional work by Brad Boyer (flar(a)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(a)libra.de>
+ * Original 1996-1998 Robert Leslie <rob(a)mars.org>
+ * Additional work by Brad Boyer (flar(a)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(a)libra.de>
+ * Original work by 1996-1998 Robert Leslie <rob(a)mars.org>
+ * other work 2000 from Brad Boyer (flar(a)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(a)libra.de>
- * Original 1996-1998 Robert Leslie <rob(a)mars.org>
- * Additional work by Brad Boyer (flar(a)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(a)libra.de>
- * Original work by 1996-1998 Robert Leslie <rob(a)mars.org>
- * other work 2000 from Brad Boyer (flar(a)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