summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/fs/hfsplus/hfsp_blockiter.c
blob: e910092291582e06caee66409e37d9f2fae3368f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
 * libhfs - library for reading and writing Macintosh HFS volumes
 *
 * The iterator shown here iterates over the blocks of a fork.
 *
 * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
 * Original work by 1996-1998 Robert Leslie <rob@mars.org>
 * other work 2000 from Brad Boyer (flar@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: blockiter.c,v 1.2 2000/10/17 05:58:46 hasi Exp $
 */

#include "config.h"
#include "libhfsp.h"
#include "blockiter.h"
#include "volume.h"
#include "record.h"
#include "btree.h"
#include "os.h"
#include "swab.h"
#include "hfstime.h"

/* Initialize iterator for a given fork */
void
blockiter_init(blockiter* b, volume* vol, hfsp_fork_raw* f,
		    UInt8 forktype, UInt32 fileId)
{
    b->vol	    = vol;
    b->curr_block   = 0;
    b->block	    = 0;
    b->max_block    = f->total_blocks;
    b->fileId	    = fileId;
    b->index	    = 0;
    b->file	    = f->extents;
    b->e	    = f->extents;
    b->forktype	    = forktype;
    b->in_extent    = 0;
}

/* get next extent record when needed */
static int
blockiter_next_extent(blockiter *b)
{
    btree*  extents_tree = volume_get_extents_tree(b->vol);
    int	    err;

    b->index = 0;
    if (b->in_extent) // already using extents record ?
    {
	err = record_next_extent(&b->er);
	// Hope there is no need to check this ...
	// if (b->er.key.start_block != b->curr_block)
	//     HFSP_ERROR(ENOENT,
	//	"Extents record inconistent");
    }
    else
    {
	err = record_init_file(&b->er, extents_tree, b->forktype,
		b->fileId, b->curr_block);
	b->in_extent = -1;  // true
    }
    b->e = b->er.extent;
    return err;
}

/* 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;
}

/* 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;
}