コード例 #1
0
ファイル: blockiter.c プロジェクト: unrealord/pearpc
/* skip the indicated number of blocks */
int blockiter_skip(blockiter *b, UInt32 skip)
{
    while (skip > 0)
    {
        // Skip to skip or end of current extent
        UInt32 diff = b->e->block_count - b->block;
        if (skip < diff)
        {
            diff = skip;
            skip = 0;
        }
        else
            skip -= diff;
        b->curr_block += diff;
        b->block      += diff;
        if (b->curr_block >= b->max_block)
            return -1;	// end of Blocks, but no error
        if (b->block >= b->e->block_count)
        {
            b->index++;
            b->block = 0;		// reset relative position
            b->e++;
            if (b -> index >= 8)	// need to fetch another extent
            {
                if (blockiter_next_extent(b))
                    HFSP_ERROR(ENOENT, "Extends record not found.");
            }
        }
    } // we are here when skip was null, thats ok
    return 0;
fail:
    return -1;
}
コード例 #2
0
ファイル: volume.c プロジェクト: tycho/openbios
/* 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;
}
コード例 #3
0
/* 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;
}
コード例 #4
0
/* 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;
}
コード例 #5
0
/* 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;
}
コード例 #6
0
/* 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;
}
コード例 #7
0
/* 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;
}
コード例 #8
0
ファイル: record.c プロジェクト: Globalcherry/pearpc
/* write a hfsp_extent_key to memory */
char* record_extent_writekey(char* p, void* buf)
{
    hfsp_extent_key* key = (hfsp_extent_key*) buf;
    UInt16  key_length = key->key_length;
    if (key_length != 10)
	HFSP_ERROR(-1, "Invalid key length in record_extent_writekey");

    bstoreU16_inc (&p, key_length);
    bstoreU8_inc  (&p, key->fork_type);
    bstoreU8_inc  (&p, key->filler);
    bstoreU32_inc (&p, key->file_id);
    bstoreU32_inc (&p, key->start_block);
    return p;
  fail:
    return NULL;
}
コード例 #9
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;
}
コード例 #10
0
/* 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;
}
コード例 #11
0
/* 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;
}
コード例 #12
0
ファイル: record.c プロジェクト: Globalcherry/pearpc
/* write a hfsp_cat_entry to memory */
char* record_writeentry(char *p, hfsp_cat_entry* entry)
{
    UInt16 type = entry->type;
    bstoreU16_inc(&p, type);
    switch (type)
    {
	case HFSP_FOLDER:
	    return record_writefolder(p, &entry->u.folder);
	case HFSP_FILE:
	    return record_writefile  (p, &entry->u.file);
	case HFSP_FOLDER_THREAD:
	case HFSP_FILE_THREAD:
	    return record_writethread(p, &entry->u.thread);
	default:
	    HFSP_ERROR(-1, "Unexpected record type in record_writeentry");
    } ;
  fail:
    return NULL;
}
コード例 #13
0
ファイル: record.c プロジェクト: Globalcherry/pearpc
/* write a hfsp_cat_thread to memory */
static char* record_writethread(char *p, hfsp_cat_thread* entry)
{
    int	    i;
    UInt16  len;
    UInt16* cp;

    bstoreU16_inc(&p,	    entry->reserved);
    bstoreU32_inc(&p,	    entry->parentID);
    /* this is bad style, friends... (SW) */
/*    bstoreU16_inc(&p, len =  entry->nodeName.strlen);*/
    len =  entry->nodeName.strlen;
    bstoreU16_inc(&p, len);
    cp = entry->nodeName.name;
    if (len > 255)
	HFSP_ERROR(-1, "Invalid key length in record_thread");
    for (i=0; i < len; i++, cp++)
	bstoreU16_inc(&p, *cp);
    return p;
  fail:
    return NULL;
}
コード例 #14
0
/* 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;
}
コード例 #15
0
ファイル: record.c プロジェクト: Globalcherry/pearpc
/* write a hfsp_cat_key back to memory, check for correct length.
 *
 * @param p   buffer in memory to write to
 * @param buf memory containing the (swapped) key.
 *
 * @return pointer to byte after the structure or NULL on failure. 
 *
 */
char* record_writekey(char* p, void* buf)
{
    hfsp_cat_key*   key = (hfsp_cat_key*) buf;
    UInt16	    key_length, len,i;
    UInt16*	    cp;

    key_length = key->key_length;
    len	       = key->name.strlen;
    cp	       = key->name.name;
    if (key_length != (6 + len * 2))
	 HFSP_ERROR(EINVAL, "Invalid key length in record_writekey");

    bstoreU16_inc(&p, key_length);
    bstoreU32_inc(&p, key->parent_cnid);
    bstoreU16_inc(&p, len);
    for (i=0; i < len; i++, cp++)
	bstoreU16_inc(&p, *cp);
    return p;	
  fail:
    return NULL;
}
コード例 #16
0
/* 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;
}
コード例 #17
0
/* 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;
}
コード例 #18
0
ファイル: blockiter.c プロジェクト: unrealord/pearpc
/* find next block of the fork iterating over */
int blockiter_next(blockiter *b)
{
    b->curr_block ++;
    b->block ++;
    if (b->curr_block >= b->max_block)
        return -1; // end of Blocks, but no error
    // in current part of extent ?
    if (b->block >= b->e->block_count)
    {
        b->index++;
        b->block = 0;		// reset relative position
        b->e++;
        if (b -> index >= 8)	// need to fetch another extent
        {
            if (blockiter_next_extent(b))
                HFSP_ERROR(ENOENT, "Extends record not found.");
        }
    }
    return 0;

fail:
    return -1;
}
コード例 #19
0
ファイル: volume.c プロジェクト: tycho/openbios
/* 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  );
	p = volume_readfork(p, &vh->start_file );
	return 0;
  fail:
	return -1;
}