1 |
/* |
2 |
* libhfs - library for reading and writing Macintosh HFS volumes |
3 |
* Copyright (C) 1996-1998 Robert Leslie |
4 |
* |
5 |
* This program is free software; you can redistribute it and/or modify |
6 |
* it under the terms of the GNU General Public License as published by |
7 |
* the Free Software Foundation; either version 2 of the License, or |
8 |
* (at your option) any later version. |
9 |
* |
10 |
* This program is distributed in the hope that it will be useful, |
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 |
* GNU General Public License for more details. |
14 |
* |
15 |
* You should have received a copy of the GNU General Public License |
16 |
* along with this program; if not, write to the Free Software |
17 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
18 |
* |
19 |
*/ |
20 |
|
21 |
# ifdef HAVE_CONFIG_H |
22 |
# include "config.h" |
23 |
# endif |
24 |
|
25 |
# include <stdlib.h> |
26 |
# include <string.h> |
27 |
# include <errno.h> |
28 |
|
29 |
# include "libhfs.h" |
30 |
# include "low.h" |
31 |
# include "data.h" |
32 |
# include "block.h" |
33 |
# include "file.h" |
34 |
|
35 |
/* |
36 |
* NAME: low->getddr() |
37 |
* DESCRIPTION: read a driver descriptor record |
38 |
*/ |
39 |
int l_getddr(hfsvol *vol, Block0 *ddr) |
40 |
{ |
41 |
block b; |
42 |
const byte *ptr = b; |
43 |
int i; |
44 |
|
45 |
if (b_readpb(vol, 0, &b, 1) == -1) |
46 |
goto fail; |
47 |
|
48 |
d_fetchsw(&ptr, &ddr->sbSig); |
49 |
d_fetchsw(&ptr, &ddr->sbBlkSize); |
50 |
d_fetchsl(&ptr, &ddr->sbBlkCount); |
51 |
d_fetchsw(&ptr, &ddr->sbDevType); |
52 |
d_fetchsw(&ptr, &ddr->sbDevId); |
53 |
d_fetchsl(&ptr, &ddr->sbData); |
54 |
d_fetchsw(&ptr, &ddr->sbDrvrCount); |
55 |
d_fetchsl(&ptr, &ddr->ddBlock); |
56 |
d_fetchsw(&ptr, &ddr->ddSize); |
57 |
d_fetchsw(&ptr, &ddr->ddType); |
58 |
|
59 |
for (i = 0; i < 243; ++i) |
60 |
d_fetchsw(&ptr, &ddr->ddPad[i]); |
61 |
|
62 |
ASSERT(ptr - b == HFS_BLOCKSZ); |
63 |
|
64 |
return 0; |
65 |
|
66 |
fail: |
67 |
return -1; |
68 |
} |
69 |
|
70 |
/* |
71 |
* NAME: low->putddr() |
72 |
* DESCRIPTION: write a driver descriptor record |
73 |
*/ |
74 |
int l_putddr(hfsvol *vol, const Block0 *ddr) |
75 |
{ |
76 |
block b; |
77 |
byte *ptr = b; |
78 |
int i; |
79 |
|
80 |
d_storesw(&ptr, ddr->sbSig); |
81 |
d_storesw(&ptr, ddr->sbBlkSize); |
82 |
d_storesl(&ptr, ddr->sbBlkCount); |
83 |
d_storesw(&ptr, ddr->sbDevType); |
84 |
d_storesw(&ptr, ddr->sbDevId); |
85 |
d_storesl(&ptr, ddr->sbData); |
86 |
d_storesw(&ptr, ddr->sbDrvrCount); |
87 |
d_storesl(&ptr, ddr->ddBlock); |
88 |
d_storesw(&ptr, ddr->ddSize); |
89 |
d_storesw(&ptr, ddr->ddType); |
90 |
|
91 |
for (i = 0; i < 243; ++i) |
92 |
d_storesw(&ptr, ddr->ddPad[i]); |
93 |
|
94 |
ASSERT(ptr - b == HFS_BLOCKSZ); |
95 |
|
96 |
if (b_writepb(vol, 0, &b, 1) == -1) |
97 |
goto fail; |
98 |
|
99 |
return 0; |
100 |
|
101 |
fail: |
102 |
return -1; |
103 |
} |
104 |
|
105 |
/* |
106 |
* NAME: low->getpmentry() |
107 |
* DESCRIPTION: read a partition map entry |
108 |
*/ |
109 |
int l_getpmentry(hfsvol *vol, ApplePartition *map, unsigned long bnum) |
110 |
{ |
111 |
block b; |
112 |
const byte *ptr = b; |
113 |
int i; |
114 |
|
115 |
if (b_readpb(vol, bnum, &b, 1) == -1) |
116 |
goto fail; |
117 |
|
118 |
d_fetchsw(&ptr, &map->pmSig); |
119 |
d_fetchsw(&ptr, &map->pmSigPad); |
120 |
d_fetchsl(&ptr, &map->pmMapBlkCnt); |
121 |
d_fetchsl(&ptr, &map->pmPyPartStart); |
122 |
d_fetchsl(&ptr, &map->pmPartBlkCnt); |
123 |
|
124 |
strncpy((char *) map->pmPartName, (const char *) ptr, 32); |
125 |
map->pmPartName[32] = 0; |
126 |
ptr += 32; |
127 |
|
128 |
strncpy((char *) map->pmParType, (const char *) ptr, 32); |
129 |
map->pmParType[32] = 0; |
130 |
ptr += 32; |
131 |
|
132 |
d_fetchsl(&ptr, &map->pmLgDataStart); |
133 |
d_fetchsl(&ptr, &map->pmDataCnt); |
134 |
d_fetchsl(&ptr, &map->pmPartStatus); |
135 |
d_fetchsl(&ptr, &map->pmLgBootStart); |
136 |
d_fetchsl(&ptr, &map->pmBootSize); |
137 |
d_fetchsl(&ptr, &map->pmBootAddr); |
138 |
d_fetchsl(&ptr, &map->pmBootAddr2); |
139 |
d_fetchsl(&ptr, &map->pmBootEntry); |
140 |
d_fetchsl(&ptr, &map->pmBootEntry2); |
141 |
d_fetchsl(&ptr, &map->pmBootCksum); |
142 |
|
143 |
strncpy((char *) map->pmProcessor, (const char *) ptr, 16); |
144 |
map->pmProcessor[16] = 0; |
145 |
ptr += 16; |
146 |
|
147 |
for (i = 0; i < 188; ++i) |
148 |
d_fetchsw(&ptr, &map->pmPad[i]); |
149 |
|
150 |
ASSERT(ptr - b == HFS_BLOCKSZ); |
151 |
|
152 |
return 0; |
153 |
|
154 |
fail: |
155 |
return -1; |
156 |
} |
157 |
|
158 |
/* |
159 |
* NAME: low->putpmentry() |
160 |
* DESCRIPTION: write a partition map entry |
161 |
*/ |
162 |
int l_putpmentry(hfsvol *vol, const ApplePartition *map, unsigned long bnum) |
163 |
{ |
164 |
block b; |
165 |
byte *ptr = b; |
166 |
int i; |
167 |
|
168 |
d_storesw(&ptr, map->pmSig); |
169 |
d_storesw(&ptr, map->pmSigPad); |
170 |
d_storesl(&ptr, map->pmMapBlkCnt); |
171 |
d_storesl(&ptr, map->pmPyPartStart); |
172 |
d_storesl(&ptr, map->pmPartBlkCnt); |
173 |
|
174 |
memset(ptr, 0, 32); |
175 |
strncpy((char *) ptr, (const char *) map->pmPartName, 32); |
176 |
ptr += 32; |
177 |
|
178 |
memset(ptr, 0, 32); |
179 |
strncpy((char *) ptr, (const char *) map->pmParType, 32); |
180 |
ptr += 32; |
181 |
|
182 |
d_storesl(&ptr, map->pmLgDataStart); |
183 |
d_storesl(&ptr, map->pmDataCnt); |
184 |
d_storesl(&ptr, map->pmPartStatus); |
185 |
d_storesl(&ptr, map->pmLgBootStart); |
186 |
d_storesl(&ptr, map->pmBootSize); |
187 |
d_storesl(&ptr, map->pmBootAddr); |
188 |
d_storesl(&ptr, map->pmBootAddr2); |
189 |
d_storesl(&ptr, map->pmBootEntry); |
190 |
d_storesl(&ptr, map->pmBootEntry2); |
191 |
d_storesl(&ptr, map->pmBootCksum); |
192 |
|
193 |
memset(ptr, 0, 16); |
194 |
strncpy((char *) ptr, (const char *) map->pmProcessor, 16); |
195 |
ptr += 16; |
196 |
|
197 |
for (i = 0; i < 188; ++i) |
198 |
d_storesw(&ptr, map->pmPad[i]); |
199 |
|
200 |
ASSERT(ptr - b == HFS_BLOCKSZ); |
201 |
|
202 |
if (b_writepb(vol, bnum, &b, 1) == -1) |
203 |
goto fail; |
204 |
|
205 |
return 0; |
206 |
|
207 |
fail: |
208 |
return -1; |
209 |
} |
210 |
|
211 |
/* |
212 |
* NAME: low->getbb() |
213 |
* DESCRIPTION: read a volume's boot blocks |
214 |
*/ |
215 |
int l_getbb(hfsvol *vol, BootBlkHdr *bb, byte *bootcode) |
216 |
{ |
217 |
block b; |
218 |
const byte *ptr = b; |
219 |
|
220 |
if (b_readlb(vol, 0, &b) == -1) |
221 |
goto fail; |
222 |
|
223 |
d_fetchsw(&ptr, &bb->bbID); |
224 |
d_fetchsl(&ptr, &bb->bbEntry); |
225 |
d_fetchsw(&ptr, &bb->bbVersion); |
226 |
d_fetchsw(&ptr, &bb->bbPageFlags); |
227 |
|
228 |
d_fetchstr(&ptr, bb->bbSysName, sizeof(bb->bbSysName)); |
229 |
d_fetchstr(&ptr, bb->bbShellName, sizeof(bb->bbShellName)); |
230 |
d_fetchstr(&ptr, bb->bbDbg1Name, sizeof(bb->bbDbg1Name)); |
231 |
d_fetchstr(&ptr, bb->bbDbg2Name, sizeof(bb->bbDbg2Name)); |
232 |
d_fetchstr(&ptr, bb->bbScreenName, sizeof(bb->bbScreenName)); |
233 |
d_fetchstr(&ptr, bb->bbHelloName, sizeof(bb->bbHelloName)); |
234 |
d_fetchstr(&ptr, bb->bbScrapName, sizeof(bb->bbScrapName)); |
235 |
|
236 |
d_fetchsw(&ptr, &bb->bbCntFCBs); |
237 |
d_fetchsw(&ptr, &bb->bbCntEvts); |
238 |
d_fetchsl(&ptr, &bb->bb128KSHeap); |
239 |
d_fetchsl(&ptr, &bb->bb256KSHeap); |
240 |
d_fetchsl(&ptr, &bb->bbSysHeapSize); |
241 |
d_fetchsw(&ptr, &bb->filler); |
242 |
d_fetchsl(&ptr, &bb->bbSysHeapExtra); |
243 |
d_fetchsl(&ptr, &bb->bbSysHeapFract); |
244 |
|
245 |
ASSERT(ptr - b == 148); |
246 |
|
247 |
if (bootcode) |
248 |
{ |
249 |
memcpy(bootcode, ptr, HFS_BOOTCODE1LEN); |
250 |
|
251 |
if (b_readlb(vol, 1, &b) == -1) |
252 |
goto fail; |
253 |
|
254 |
memcpy(bootcode + HFS_BOOTCODE1LEN, b, HFS_BOOTCODE2LEN); |
255 |
} |
256 |
|
257 |
return 0; |
258 |
|
259 |
fail: |
260 |
return -1; |
261 |
} |
262 |
|
263 |
/* |
264 |
* NAME: low->putbb() |
265 |
* DESCRIPTION: write a volume's boot blocks |
266 |
*/ |
267 |
int l_putbb(hfsvol *vol, const BootBlkHdr *bb, const byte *bootcode) |
268 |
{ |
269 |
block b; |
270 |
byte *ptr = b; |
271 |
|
272 |
d_storesw(&ptr, bb->bbID); |
273 |
d_storesl(&ptr, bb->bbEntry); |
274 |
d_storesw(&ptr, bb->bbVersion); |
275 |
d_storesw(&ptr, bb->bbPageFlags); |
276 |
|
277 |
d_storestr(&ptr, bb->bbSysName, sizeof(bb->bbSysName)); |
278 |
d_storestr(&ptr, bb->bbShellName, sizeof(bb->bbShellName)); |
279 |
d_storestr(&ptr, bb->bbDbg1Name, sizeof(bb->bbDbg1Name)); |
280 |
d_storestr(&ptr, bb->bbDbg2Name, sizeof(bb->bbDbg2Name)); |
281 |
d_storestr(&ptr, bb->bbScreenName, sizeof(bb->bbScreenName)); |
282 |
d_storestr(&ptr, bb->bbHelloName, sizeof(bb->bbHelloName)); |
283 |
d_storestr(&ptr, bb->bbScrapName, sizeof(bb->bbScrapName)); |
284 |
|
285 |
d_storesw(&ptr, bb->bbCntFCBs); |
286 |
d_storesw(&ptr, bb->bbCntEvts); |
287 |
d_storesl(&ptr, bb->bb128KSHeap); |
288 |
d_storesl(&ptr, bb->bb256KSHeap); |
289 |
d_storesl(&ptr, bb->bbSysHeapSize); |
290 |
d_storesw(&ptr, bb->filler); |
291 |
d_storesl(&ptr, bb->bbSysHeapExtra); |
292 |
d_storesl(&ptr, bb->bbSysHeapFract); |
293 |
|
294 |
ASSERT(ptr - b == 148); |
295 |
|
296 |
if (bootcode) |
297 |
memcpy(ptr, bootcode, HFS_BOOTCODE1LEN); |
298 |
else |
299 |
memset(ptr, 0, HFS_BOOTCODE1LEN); |
300 |
|
301 |
if (b_writelb(vol, 0, &b) == -1) |
302 |
goto fail; |
303 |
|
304 |
if (bootcode) |
305 |
memcpy(&b, bootcode + HFS_BOOTCODE1LEN, HFS_BOOTCODE2LEN); |
306 |
else |
307 |
memset(&b, 0, HFS_BOOTCODE2LEN); |
308 |
|
309 |
if (b_writelb(vol, 1, &b) == -1) |
310 |
goto fail; |
311 |
|
312 |
return 0; |
313 |
|
314 |
fail: |
315 |
return -1; |
316 |
} |
317 |
|
318 |
/* |
319 |
* NAME: low->getmdb() |
320 |
* DESCRIPTION: read a master directory block |
321 |
*/ |
322 |
int l_getmdb(hfsvol *vol, MDB *mdb, int backup) |
323 |
{ |
324 |
block b; |
325 |
const byte *ptr = b; |
326 |
int i; |
327 |
|
328 |
if (b_readlb(vol, backup ? vol->vlen - 2 : 2, &b) == -1) |
329 |
goto fail; |
330 |
|
331 |
d_fetchsw(&ptr, &mdb->drSigWord); |
332 |
d_fetchsl(&ptr, &mdb->drCrDate); |
333 |
d_fetchsl(&ptr, &mdb->drLsMod); |
334 |
d_fetchsw(&ptr, &mdb->drAtrb); |
335 |
d_fetchuw(&ptr, &mdb->drNmFls); |
336 |
d_fetchuw(&ptr, &mdb->drVBMSt); |
337 |
d_fetchuw(&ptr, &mdb->drAllocPtr); |
338 |
d_fetchuw(&ptr, &mdb->drNmAlBlks); |
339 |
d_fetchul(&ptr, &mdb->drAlBlkSiz); |
340 |
d_fetchul(&ptr, &mdb->drClpSiz); |
341 |
d_fetchuw(&ptr, &mdb->drAlBlSt); |
342 |
d_fetchsl(&ptr, &mdb->drNxtCNID); |
343 |
d_fetchuw(&ptr, &mdb->drFreeBks); |
344 |
|
345 |
d_fetchstr(&ptr, mdb->drVN, sizeof(mdb->drVN)); |
346 |
|
347 |
ASSERT(ptr - b == 64); |
348 |
|
349 |
d_fetchsl(&ptr, &mdb->drVolBkUp); |
350 |
d_fetchsw(&ptr, &mdb->drVSeqNum); |
351 |
d_fetchul(&ptr, &mdb->drWrCnt); |
352 |
d_fetchul(&ptr, &mdb->drXTClpSiz); |
353 |
d_fetchul(&ptr, &mdb->drCTClpSiz); |
354 |
d_fetchuw(&ptr, &mdb->drNmRtDirs); |
355 |
d_fetchul(&ptr, &mdb->drFilCnt); |
356 |
d_fetchul(&ptr, &mdb->drDirCnt); |
357 |
|
358 |
for (i = 0; i < 8; ++i) |
359 |
d_fetchsl(&ptr, &mdb->drFndrInfo[i]); |
360 |
|
361 |
ASSERT(ptr - b == 124); |
362 |
|
363 |
d_fetchuw(&ptr, &mdb->drEmbedSigWord); |
364 |
d_fetchuw(&ptr, &mdb->drEmbedExtent.xdrStABN); |
365 |
d_fetchuw(&ptr, &mdb->drEmbedExtent.xdrNumABlks); |
366 |
|
367 |
d_fetchul(&ptr, &mdb->drXTFlSize); |
368 |
|
369 |
for (i = 0; i < 3; ++i) |
370 |
{ |
371 |
d_fetchuw(&ptr, &mdb->drXTExtRec[i].xdrStABN); |
372 |
d_fetchuw(&ptr, &mdb->drXTExtRec[i].xdrNumABlks); |
373 |
} |
374 |
|
375 |
ASSERT(ptr - b == 146); |
376 |
|
377 |
d_fetchul(&ptr, &mdb->drCTFlSize); |
378 |
|
379 |
for (i = 0; i < 3; ++i) |
380 |
{ |
381 |
d_fetchuw(&ptr, &mdb->drCTExtRec[i].xdrStABN); |
382 |
d_fetchuw(&ptr, &mdb->drCTExtRec[i].xdrNumABlks); |
383 |
} |
384 |
|
385 |
ASSERT(ptr - b == 162); |
386 |
|
387 |
return 0; |
388 |
|
389 |
fail: |
390 |
return -1; |
391 |
} |
392 |
|
393 |
/* |
394 |
* NAME: low->putmdb() |
395 |
* DESCRIPTION: write master directory block(s) |
396 |
*/ |
397 |
int l_putmdb(hfsvol *vol, const MDB *mdb, int backup) |
398 |
{ |
399 |
block b; |
400 |
byte *ptr = b; |
401 |
int i; |
402 |
|
403 |
d_storesw(&ptr, mdb->drSigWord); |
404 |
d_storesl(&ptr, mdb->drCrDate); |
405 |
d_storesl(&ptr, mdb->drLsMod); |
406 |
d_storesw(&ptr, mdb->drAtrb); |
407 |
d_storeuw(&ptr, mdb->drNmFls); |
408 |
d_storeuw(&ptr, mdb->drVBMSt); |
409 |
d_storeuw(&ptr, mdb->drAllocPtr); |
410 |
d_storeuw(&ptr, mdb->drNmAlBlks); |
411 |
d_storeul(&ptr, mdb->drAlBlkSiz); |
412 |
d_storeul(&ptr, mdb->drClpSiz); |
413 |
d_storeuw(&ptr, mdb->drAlBlSt); |
414 |
d_storesl(&ptr, mdb->drNxtCNID); |
415 |
d_storeuw(&ptr, mdb->drFreeBks); |
416 |
|
417 |
d_storestr(&ptr, mdb->drVN, sizeof(mdb->drVN)); |
418 |
|
419 |
ASSERT(ptr - b == 64); |
420 |
|
421 |
d_storesl(&ptr, mdb->drVolBkUp); |
422 |
d_storesw(&ptr, mdb->drVSeqNum); |
423 |
d_storeul(&ptr, mdb->drWrCnt); |
424 |
d_storeul(&ptr, mdb->drXTClpSiz); |
425 |
d_storeul(&ptr, mdb->drCTClpSiz); |
426 |
d_storeuw(&ptr, mdb->drNmRtDirs); |
427 |
d_storeul(&ptr, mdb->drFilCnt); |
428 |
d_storeul(&ptr, mdb->drDirCnt); |
429 |
|
430 |
for (i = 0; i < 8; ++i) |
431 |
d_storesl(&ptr, mdb->drFndrInfo[i]); |
432 |
|
433 |
ASSERT(ptr - b == 124); |
434 |
|
435 |
d_storeuw(&ptr, mdb->drEmbedSigWord); |
436 |
d_storeuw(&ptr, mdb->drEmbedExtent.xdrStABN); |
437 |
d_storeuw(&ptr, mdb->drEmbedExtent.xdrNumABlks); |
438 |
|
439 |
d_storeul(&ptr, mdb->drXTFlSize); |
440 |
|
441 |
for (i = 0; i < 3; ++i) |
442 |
{ |
443 |
d_storeuw(&ptr, mdb->drXTExtRec[i].xdrStABN); |
444 |
d_storeuw(&ptr, mdb->drXTExtRec[i].xdrNumABlks); |
445 |
} |
446 |
|
447 |
ASSERT(ptr - b == 146); |
448 |
|
449 |
d_storeul(&ptr, mdb->drCTFlSize); |
450 |
|
451 |
for (i = 0; i < 3; ++i) |
452 |
{ |
453 |
d_storeuw(&ptr, mdb->drCTExtRec[i].xdrStABN); |
454 |
d_storeuw(&ptr, mdb->drCTExtRec[i].xdrNumABlks); |
455 |
} |
456 |
|
457 |
ASSERT(ptr - b == 162); |
458 |
|
459 |
memset(ptr, 0, HFS_BLOCKSZ - (ptr - b)); |
460 |
|
461 |
if (b_writelb(vol, 2, &b) == -1 || |
462 |
(backup && b_writelb(vol, vol->vlen - 2, &b) == -1)) |
463 |
goto fail; |
464 |
|
465 |
return 0; |
466 |
|
467 |
fail: |
468 |
return -1; |
469 |
} |