1 |
dpavlin |
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 |
|
|
|