Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / fs / hfsplus / hfsp_blockiter.c
1 /*
2  * libhfs - library for reading and writing Macintosh HFS volumes
3  *
4  * The iterator shown here iterates over the blocks of a fork.
5  *
6  * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
7  * Original work by 1996-1998 Robert Leslie <rob@mars.org>
8  * other work 2000 from Brad Boyer (flar@pants.nu)
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23  * MA 02110-1301, USA.
24  *
25  * $Id: blockiter.c,v 1.2 2000/10/17 05:58:46 hasi Exp $
26  */
27
28 #include "config.h"
29 #include "libhfsp.h"
30 #include "blockiter.h"
31 #include "volume.h"
32 #include "record.h"
33 #include "btree.h"
34 #include "os.h"
35 #include "swab.h"
36 #include "hfstime.h"
37
38 /* Initialize iterator for a given fork */
39 void
40 blockiter_init(blockiter* b, volume* vol, hfsp_fork_raw* f,
41                     UInt8 forktype, UInt32 fileId)
42 {
43     b->vol          = vol;
44     b->curr_block   = 0;
45     b->block        = 0;
46     b->max_block    = f->total_blocks;
47     b->fileId       = fileId;
48     b->index        = 0;
49     b->file         = f->extents;
50     b->e            = f->extents;
51     b->forktype     = forktype;
52     b->in_extent    = 0;
53 }
54
55 /* get next extent record when needed */
56 static int
57 blockiter_next_extent(blockiter *b)
58 {
59     btree*  extents_tree = volume_get_extents_tree(b->vol);
60     int     err;
61
62     b->index = 0;
63     if (b->in_extent) // already using extents record ?
64     {
65         err = record_next_extent(&b->er);
66         // Hope there is no need to check this ...
67         // if (b->er.key.start_block != b->curr_block)
68         //     HFSP_ERROR(ENOENT,
69         //      "Extents record inconistent");
70     }
71     else
72     {
73         err = record_init_file(&b->er, extents_tree, b->forktype,
74                 b->fileId, b->curr_block);
75         b->in_extent = -1;  // true
76     }
77     b->e = b->er.extent;
78     return err;
79 }
80
81 /* find next block of the fork iterating over */
82 int
83 blockiter_next(blockiter *b)
84 {
85     b->curr_block ++;
86     b->block ++;
87     if (b->curr_block >= b->max_block)
88         return -1; // end of Blocks, but no error
89     // in current part of extent ?
90     if (b->block >= b->e->block_count)
91     {
92         b->index++;
93         b->block = 0;           // reset relative position
94         b->e++;
95         if (b -> index >= 8)    // need to fetch another extent
96         {
97             if (blockiter_next_extent(b))
98                 HFSP_ERROR(ENOENT, "Extends record not found.");
99         }
100     }
101     return 0;
102
103   fail:
104     return -1;
105 }
106
107 /* skip the indicated number of blocks */
108 int
109 blockiter_skip(blockiter *b, UInt32 skip)
110 {
111     while (skip > 0)
112     {
113         // Skip to skip or end of current extent
114         UInt32 diff = b->e->block_count - b->block;
115         if (skip < diff)
116         {
117             diff = skip;
118             skip = 0;
119         }
120         else
121             skip -= diff;
122         b->curr_block += diff;
123         b->block      += diff;
124         if (b->curr_block >= b->max_block)
125             return -1;  // end of Blocks, but no error
126         if (b->block >= b->e->block_count)
127         {
128             b->index++;
129             b->block = 0;               // reset relative position
130             b->e++;
131             if (b -> index >= 8)        // need to fetch another extent
132             {
133                 if (blockiter_next_extent(b))
134                     HFSP_ERROR(ENOENT, "Extends record not found.");
135             }
136         }
137     } // we are here when skip was null, thats ok
138     return 0;
139   fail:
140     return -1;
141 }