1 |
/* |
2 |
* libhfs - library for reading and writing Macintosh HFS volumes |
3 |
* |
4 |
* Copyright (C) 2000 Klaus Halfmann (klaus.halfmann@feri.de) |
5 |
* Original work by 1996-1998 Robert Leslie (rob@mars.org) |
6 |
* |
7 |
* This file defines constants,structs etc needed for this library. |
8 |
* Everything found here is usually not related to Apple defintions. |
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., 675 Mass Ave, Cambridge, MA 02139, USA. |
23 |
* |
24 |
*/ |
25 |
|
26 |
#ifndef APPLE_H |
27 |
# include "apple.h" |
28 |
#endif |
29 |
|
30 |
# include "hfs.h" |
31 |
# include "hfsp.h" |
32 |
|
33 |
extern int errno; |
34 |
/* Last error is eventually found here */ |
35 |
extern const char *hfsp_error; |
36 |
|
37 |
# define HFSP_ERROR(code, str) \ |
38 |
do { hfsp_error = (str), errno = (code); goto fail; } while (0) |
39 |
|
40 |
# ifdef DEBUG |
41 |
# define ASSERT(cond) do { if (! (cond)) abort(); } while (0) |
42 |
# else |
43 |
# define ASSERT(cond) /* nothing */ |
44 |
# endif |
45 |
|
46 |
# define SIZE(type, n) ((size_t) (sizeof(type) * (n))) |
47 |
# define ALLOC(type, n) ((type *) malloc(SIZE(type, n))) |
48 |
# define ALLOCX(type, n) ((n) ? ALLOC(type, n) : (type *) 0) |
49 |
# define FREE(ptr) ((ptr) ? (void) free((void *) ptr) : (void) 0) |
50 |
|
51 |
# define REALLOC(ptr, type, n) \ |
52 |
((type *) ((ptr) ? realloc(ptr, SIZE(type, n)) : malloc(SIZE(type, n)))) |
53 |
# define REALLOCX(ptr, type, n) \ |
54 |
((n) ? REALLOC(ptr, type, n) : (FREE(ptr), (type *) 0)) |
55 |
|
56 |
# define STRINGIZE(x) #x |
57 |
# define STR(x) STRINGIZE(x) |
58 |
|
59 |
/* These macros will eventually be filled for a kernel-module or |
60 |
* a multithreaded environement */ |
61 |
#define HFSP_READLOCK 1 |
62 |
#define HFSP_WRITELOCK 2 |
63 |
|
64 |
#define HFSP_SYNC_START(mode, whatever) /* to be filled */ |
65 |
#define HFSP_SYNC_END(mode, whatever) /* to be filled */ |
66 |
|
67 |
/* Flags for volume header */ |
68 |
/* used by internal routines to specify the open modes */ |
69 |
# define HFSP_MODE_RDONLY 0x00 |
70 |
# define HFSP_MODE_RDWR 0x01 |
71 |
/** need to write backup volume header, due to significant change */ |
72 |
# define HFSP_BACKUP_DIRTY 0x02 |
73 |
|
74 |
/* Signatures registered with Apple to identify this driver */ |
75 |
/* Identifies the userland implementation */ |
76 |
# define HPLS_SIGNATURE 0x482B4C58 // 'H+LX' |
77 |
# define HFSPLUS_VERS 0x0004 // Current version of HFS+ Specification |
78 |
/* Identifies the kernel module by Brad Boyer (flar@pants.nu) */ |
79 |
# define HPLS_SIGRES1 0x482B4C78 // 'H+Lx' |
80 |
/* not jet in use ... */ |
81 |
# define HPLS_SIGRES2 0x482B6C78 // 'H+lx' |
82 |
/* Signature used by Apple */ |
83 |
# define HPAPPLE_SIGNATURE 0x382e3130 // '8.10' |
84 |
|
85 |
/* Version used for this implementation of HFS+. This is not related |
86 |
* to the VERSION file found at the top-level of this package, |
87 |
* but designates the version of the low level code */ |
88 |
#define HPLS_VERSION 1 /* must fit in a short */ |
89 |
|
90 |
|
91 |
/** helper function to create those Apple 4 byte Signatures */ |
92 |
static inline UInt32 sig(char c0, char c1, char c2, char c3) |
93 |
{ |
94 |
UInt32 sig; |
95 |
((char*)&sig)[0] = c0; |
96 |
((char*)&sig)[1] = c1; |
97 |
((char*)&sig)[2] = c2; |
98 |
((char*)&sig)[3] = c3; |
99 |
return sig; |
100 |
} |
101 |
|
102 |
|
103 |
|
104 |
/* Other Signatures may follow for informational purposes */ |
105 |
|
106 |
/* prototype for key comparing functions. */ |
107 |
typedef int (*hfsp_key_compare) (void* key1, void* key2); |
108 |
|
109 |
/* The read functions alaways retur the positiion right after |
110 |
* reading (and swapping) the variable amount of bytes needed |
111 |
* prototype for key reading (necessary for byte swapping) */ |
112 |
typedef char* (*hfsp_key_read) (char* p, void* key); |
113 |
|
114 |
/* prototype for record reading (including byte swapping) */ |
115 |
typedef char* (*hfsp_rec_read) (char* p, void* key); |
116 |
|
117 |
struct volume; /* foreward declaration for btree needed */ |
118 |
|
119 |
/* Structures for a node cache. The cache is an array |
120 |
* with linear search. (So making it to big may make |
121 |
* things slower). It is searched in a round robin |
122 |
* fashion. |
123 |
*/ |
124 |
|
125 |
typedef struct |
126 |
{ |
127 |
UInt32 priority; |
128 |
// as lower this number as higher the priority. |
129 |
// decremetned on any sucessfull usage |
130 |
// incremented else, intial value height*DEPTHFACTOR |
131 |
UInt16 index; // of node in fork |
132 |
// 0 means empty, since first node is node header |
133 |
UInt16 flags; // like DIRTY etc. |
134 |
} node_entry; |
135 |
|
136 |
/* an Entry is dirty and must be written back */ |
137 |
#define NODE_DIRTY 0x0001 |
138 |
/* opposite of dirty */ |
139 |
#define NODE_CLEAN 0x0000 |
140 |
|
141 |
typedef struct |
142 |
{ |
143 |
UInt32 index; // duplicate of above |
144 |
btree_node_desc desc; // header of node |
145 |
char node[0]; // size is actual node_size |
146 |
// contents of node in original byte order |
147 |
} node_buf; |
148 |
|
149 |
typedef struct |
150 |
{ |
151 |
int size; // number of nodes in the cache |
152 |
int currindex; // round robin index |
153 |
int nodebufsize; // size of complete node_buf, including node |
154 |
node_entry *entries; |
155 |
char *buffers; // actually *node_buf |
156 |
} node_cache; |
157 |
|
158 |
typedef struct |
159 |
{ // "virtual" member functions |
160 |
hfsp_key_compare kcomp; |
161 |
/* function used for key compare in _this_ btree */ |
162 |
hfsp_key_read kread; |
163 |
/* function used to read a key in _this_ btree */ |
164 |
hfsp_rec_read rread; |
165 |
/* function used to read a record in _this_ btree */ |
166 |
btree_node_desc head_node; |
167 |
/* Node descriptor for header node */ |
168 |
btree_head head; |
169 |
|
170 |
struct volume* vol; /* pointer to volume this tree is part of */ |
171 |
hfsp_fork_raw* fork; /* pointer to fork this tree is part of */ |
172 |
UInt32 cnid; /* (pseudo) file id for the fork */ |
173 |
UInt32 attributes; /* see bits below */ |
174 |
/* Header node (contains most important parts of btree) */ |
175 |
char* alloc_bits; |
176 |
/* All the rest of node 0 including the reserved area, |
177 |
* the first part of the allocation bit-map found in Map Nodes |
178 |
* and the two bakpointers needed for the header node, so this |
179 |
* memory + head represent the header node */ |
180 |
UInt16 blkpernode; |
181 |
/* Number of volume blocks per node (usually 0-4) |
182 |
0 indicates, that nodeperblk should be used */ |
183 |
UInt16 nodeperblk; |
184 |
/* Sometimes a block may contain more than one node */ |
185 |
UInt16 max_rec_size; |
186 |
/* Maximum Size of a leaf record */ |
187 |
UInt16 filler; |
188 |
node_cache cache; |
189 |
} btree; |
190 |
|
191 |
/* The Btree header is dirty and must be written back */ |
192 |
#define BTREE_HEADDIRTY 0x0001 |
193 |
|
194 |
/* The reserved Record starts at this offset in the header header node */ |
195 |
#define HEADER_RESERVEDOFFSET 120 |
196 |
|
197 |
/* The first map node eventually starts at this offset in the |
198 |
* header node */ |
199 |
#define HEADER_MAPOFFSET 248 |
200 |
|
201 |
/* Function on btrees are defined in btree.h */ |
202 |
|
203 |
/* A Wrapper around the raw hfs+ volume header for additional information |
204 |
* needed by this library. |
205 |
*/ |
206 |
|
207 |
typedef struct volume |
208 |
{ |
209 |
void *fd; /* OS dependend reference to device */ |
210 |
UInt16 blksize_bits; /* blocksize of device = 1 << blksize_bits */ |
211 |
UInt16 flags; /* as of now only HFSP_MODE_RDWR */ |
212 |
UInt32 blksize; /* always 1 << blksize_bits */ |
213 |
UInt32 maxblocks; /* maximum number of blocks in device */ |
214 |
hfsp_vh vol; /* raw volume data */ |
215 |
|
216 |
btree* extents; /* is NULL by default and intialized when needed */ |
217 |
btree catalog; /* This is always neeeded */ |
218 |
} volume; |
219 |
|
220 |
/* Functions on volumes are defined in volume.h */ |
221 |
|
222 |
typedef struct { // may not be used as found here |
223 |
btree* tree; // tree where this record is contained in. |
224 |
UInt16 node_index; /* index of node in btree */ |
225 |
UInt16 keyind; /* index of current key in node */ |
226 |
/* Warning node_index and keyind are private. They can become |
227 |
* invalid when the btree changes */ |
228 |
hfsp_cat_key key; /* current key */ |
229 |
UInt32 child; /* child node belonging to this key */ |
230 |
} index_record; |
231 |
|
232 |
typedef struct { |
233 |
btree* tree; // tree where this record is contained in. |
234 |
UInt16 node_index; /* index of node in btree */ |
235 |
UInt16 keyind; /* index of current key in node */ |
236 |
/* Warning node_index and keyind are private. They can become |
237 |
* invalid when the btree changes */ |
238 |
hfsp_extent_key key; /* current key */ |
239 |
hfsp_extent_rec extent; /* The payload carried around */ |
240 |
} extent_record; |
241 |
|
242 |
typedef struct { |
243 |
btree* tree; // tree where this record is contained in. |
244 |
UInt16 node_index; /* index of node in btree */ |
245 |
UInt16 keyind; /* index of current key in node */ |
246 |
/* Warning node_index and keyind are private. They can become |
247 |
* invalid when the btree changes */ |
248 |
hfsp_cat_key key; /* current key */ |
249 |
hfsp_cat_entry record; /* current record */ |
250 |
} record; |
251 |
|
252 |
/* Functions on records are defined in record.h */ |
253 |
|
254 |
|
255 |
|