1*f0d9efc0Sbeck /*
2*f0d9efc0Sbeck * hfsutils - tools for reading and writing Macintosh HFS volumes
3*f0d9efc0Sbeck * Copyright (C) 1996, 1997 Robert Leslie
4*f0d9efc0Sbeck *
5*f0d9efc0Sbeck * This program is free software; you can redistribute it and/or modify
6*f0d9efc0Sbeck * it under the terms of the GNU General Public License as published by
7*f0d9efc0Sbeck * the Free Software Foundation; either version 2 of the License, or
8*f0d9efc0Sbeck * (at your option) any later version.
9*f0d9efc0Sbeck *
10*f0d9efc0Sbeck * This program is distributed in the hope that it will be useful,
11*f0d9efc0Sbeck * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*f0d9efc0Sbeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*f0d9efc0Sbeck * GNU General Public License for more details.
14*f0d9efc0Sbeck *
15*f0d9efc0Sbeck * You should have received a copy of the GNU General Public License
16*f0d9efc0Sbeck * along with this program; if not, write to the Free Software
17*f0d9efc0Sbeck * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*f0d9efc0Sbeck */
19*f0d9efc0Sbeck
20*f0d9efc0Sbeck # include <string.h>
21*f0d9efc0Sbeck # include <stdlib.h>
22*f0d9efc0Sbeck # include <errno.h>
23*f0d9efc0Sbeck # include <unistd.h>
24*f0d9efc0Sbeck # include <fcntl.h>
25*f0d9efc0Sbeck
26*f0d9efc0Sbeck # include "internal.h"
27*f0d9efc0Sbeck # include "data.h"
28*f0d9efc0Sbeck # include "block.h"
29*f0d9efc0Sbeck # include "low.h"
30*f0d9efc0Sbeck # include "file.h"
31*f0d9efc0Sbeck
32*f0d9efc0Sbeck /*
33*f0d9efc0Sbeck * NAME: low->lockvol()
34*f0d9efc0Sbeck * DESCRIPTION: prevent destructive simultaneous access
35*f0d9efc0Sbeck */
l_lockvol(hfsvol * vol)36*f0d9efc0Sbeck int l_lockvol(hfsvol *vol)
37*f0d9efc0Sbeck {
38*f0d9efc0Sbeck # ifndef NODEVLOCKS
39*f0d9efc0Sbeck
40*f0d9efc0Sbeck struct flock lock;
41*f0d9efc0Sbeck
42*f0d9efc0Sbeck lock.l_type = (vol->flags & HFS_READONLY) ? F_RDLCK : F_WRLCK;
43*f0d9efc0Sbeck lock.l_start = 0;
44*f0d9efc0Sbeck lock.l_whence = SEEK_SET;
45*f0d9efc0Sbeck lock.l_len = 0;
46*f0d9efc0Sbeck
47*f0d9efc0Sbeck if (fcntl(vol->fd, F_SETLK, &lock) < 0)
48*f0d9efc0Sbeck {
49*f0d9efc0Sbeck ERROR(errno, "unable to obtain lock for device");
50*f0d9efc0Sbeck return -1;
51*f0d9efc0Sbeck }
52*f0d9efc0Sbeck
53*f0d9efc0Sbeck # endif
54*f0d9efc0Sbeck
55*f0d9efc0Sbeck return 0;
56*f0d9efc0Sbeck }
57*f0d9efc0Sbeck
58*f0d9efc0Sbeck /*
59*f0d9efc0Sbeck * NAME: low->readblock0()
60*f0d9efc0Sbeck * DESCRIPTION: read the first sector and get bearings
61*f0d9efc0Sbeck */
l_readblock0(hfsvol * vol)62*f0d9efc0Sbeck int l_readblock0(hfsvol *vol)
63*f0d9efc0Sbeck {
64*f0d9efc0Sbeck block b;
65*f0d9efc0Sbeck unsigned char *ptr = b;
66*f0d9efc0Sbeck Block0 rec;
67*f0d9efc0Sbeck
68*f0d9efc0Sbeck if (b_readlb(vol, 0, &b) < 0)
69*f0d9efc0Sbeck return -1;
70*f0d9efc0Sbeck
71*f0d9efc0Sbeck d_fetchw(&ptr, &rec.sbSig);
72*f0d9efc0Sbeck d_fetchw(&ptr, &rec.sbBlkSize);
73*f0d9efc0Sbeck d_fetchl(&ptr, &rec.sbBlkCount);
74*f0d9efc0Sbeck d_fetchw(&ptr, &rec.sbDevType);
75*f0d9efc0Sbeck d_fetchw(&ptr, &rec.sbDevId);
76*f0d9efc0Sbeck d_fetchl(&ptr, &rec.sbData);
77*f0d9efc0Sbeck d_fetchw(&ptr, &rec.sbDrvrCount);
78*f0d9efc0Sbeck d_fetchl(&ptr, &rec.ddBlock);
79*f0d9efc0Sbeck d_fetchw(&ptr, &rec.ddSize);
80*f0d9efc0Sbeck d_fetchw(&ptr, &rec.ddType);
81*f0d9efc0Sbeck
82*f0d9efc0Sbeck switch (rec.sbSig)
83*f0d9efc0Sbeck {
84*f0d9efc0Sbeck case 0x4552: /* block device with a partition table */
85*f0d9efc0Sbeck {
86*f0d9efc0Sbeck if (rec.sbBlkSize != HFS_BLOCKSZ)
87*f0d9efc0Sbeck {
88*f0d9efc0Sbeck ERROR(EINVAL, "unsupported block size");
89*f0d9efc0Sbeck return -1;
90*f0d9efc0Sbeck }
91*f0d9efc0Sbeck
92*f0d9efc0Sbeck vol->vlen = rec.sbBlkCount;
93*f0d9efc0Sbeck
94*f0d9efc0Sbeck if (l_readpm(vol) < 0)
95*f0d9efc0Sbeck return -1;
96*f0d9efc0Sbeck }
97*f0d9efc0Sbeck break;
98*f0d9efc0Sbeck
99*f0d9efc0Sbeck case 0x4c4b: /* bootable floppy */
100*f0d9efc0Sbeck vol->pnum = 0;
101*f0d9efc0Sbeck break;
102*f0d9efc0Sbeck
103*f0d9efc0Sbeck default: /* non-bootable floppy or something else */
104*f0d9efc0Sbeck
105*f0d9efc0Sbeck /* some miscreant media may also be partitioned;
106*f0d9efc0Sbeck we attempt to read a partition map, but ignore any failure */
107*f0d9efc0Sbeck
108*f0d9efc0Sbeck if (l_readpm(vol) < 0)
109*f0d9efc0Sbeck vol->pnum = 0;
110*f0d9efc0Sbeck }
111*f0d9efc0Sbeck
112*f0d9efc0Sbeck return 0;
113*f0d9efc0Sbeck }
114*f0d9efc0Sbeck
115*f0d9efc0Sbeck /*
116*f0d9efc0Sbeck * NAME: low->readpm()
117*f0d9efc0Sbeck * DESCRIPTION: read the partition map and locate an HFS volume
118*f0d9efc0Sbeck */
l_readpm(hfsvol * vol)119*f0d9efc0Sbeck int l_readpm(hfsvol *vol)
120*f0d9efc0Sbeck {
121*f0d9efc0Sbeck block b;
122*f0d9efc0Sbeck unsigned char *ptr;
123*f0d9efc0Sbeck Partition map;
124*f0d9efc0Sbeck unsigned long bnum;
125*f0d9efc0Sbeck int pnum;
126*f0d9efc0Sbeck
127*f0d9efc0Sbeck bnum = 1;
128*f0d9efc0Sbeck pnum = vol->pnum;
129*f0d9efc0Sbeck
130*f0d9efc0Sbeck while (1)
131*f0d9efc0Sbeck {
132*f0d9efc0Sbeck if (b_readlb(vol, bnum, &b) < 0)
133*f0d9efc0Sbeck return -1;
134*f0d9efc0Sbeck
135*f0d9efc0Sbeck ptr = b;
136*f0d9efc0Sbeck
137*f0d9efc0Sbeck d_fetchw(&ptr, &map.pmSig);
138*f0d9efc0Sbeck d_fetchw(&ptr, &map.pmSigPad);
139*f0d9efc0Sbeck d_fetchl(&ptr, &map.pmMapBlkCnt);
140*f0d9efc0Sbeck d_fetchl(&ptr, &map.pmPyPartStart);
141*f0d9efc0Sbeck d_fetchl(&ptr, &map.pmPartBlkCnt);
142*f0d9efc0Sbeck
143*f0d9efc0Sbeck memcpy(map.pmPartName, ptr, 32);
144*f0d9efc0Sbeck map.pmPartName[32] = 0;
145*f0d9efc0Sbeck ptr += 32;
146*f0d9efc0Sbeck
147*f0d9efc0Sbeck memcpy(map.pmParType, ptr, 32);
148*f0d9efc0Sbeck map.pmParType[32] = 0;
149*f0d9efc0Sbeck ptr += 32;
150*f0d9efc0Sbeck
151*f0d9efc0Sbeck d_fetchl(&ptr, &map.pmLgDataStart);
152*f0d9efc0Sbeck d_fetchl(&ptr, &map.pmDataCnt);
153*f0d9efc0Sbeck d_fetchl(&ptr, &map.pmPartStatus);
154*f0d9efc0Sbeck d_fetchl(&ptr, &map.pmLgBootStart);
155*f0d9efc0Sbeck d_fetchl(&ptr, &map.pmBootSize);
156*f0d9efc0Sbeck d_fetchl(&ptr, &map.pmBootAddr);
157*f0d9efc0Sbeck d_fetchl(&ptr, &map.pmBootAddr2);
158*f0d9efc0Sbeck d_fetchl(&ptr, &map.pmBootEntry);
159*f0d9efc0Sbeck d_fetchl(&ptr, &map.pmBootEntry2);
160*f0d9efc0Sbeck d_fetchl(&ptr, &map.pmBootCksum);
161*f0d9efc0Sbeck
162*f0d9efc0Sbeck memcpy(map.pmProcessor, ptr, 16);
163*f0d9efc0Sbeck map.pmProcessor[16] = 0;
164*f0d9efc0Sbeck ptr += 16;
165*f0d9efc0Sbeck
166*f0d9efc0Sbeck if (map.pmSig == 0x5453)
167*f0d9efc0Sbeck {
168*f0d9efc0Sbeck /* old partition map sig */
169*f0d9efc0Sbeck
170*f0d9efc0Sbeck ERROR(EINVAL, "unsupported partition map signature");
171*f0d9efc0Sbeck return -1;
172*f0d9efc0Sbeck }
173*f0d9efc0Sbeck
174*f0d9efc0Sbeck if (map.pmSig != 0x504d)
175*f0d9efc0Sbeck {
176*f0d9efc0Sbeck ERROR(EINVAL, "bad partition map");
177*f0d9efc0Sbeck return -1;
178*f0d9efc0Sbeck }
179*f0d9efc0Sbeck
180*f0d9efc0Sbeck if (strcmp((char *) map.pmParType, "Apple_HFS") == 0 && --pnum == 0)
181*f0d9efc0Sbeck {
182*f0d9efc0Sbeck if (map.pmLgDataStart != 0)
183*f0d9efc0Sbeck {
184*f0d9efc0Sbeck ERROR(EINVAL, "unsupported start of partition logical data");
185*f0d9efc0Sbeck return -1;
186*f0d9efc0Sbeck }
187*f0d9efc0Sbeck
188*f0d9efc0Sbeck vol->vstart = map.pmPyPartStart;
189*f0d9efc0Sbeck vol->vlen = map.pmPartBlkCnt;
190*f0d9efc0Sbeck
191*f0d9efc0Sbeck return 0;
192*f0d9efc0Sbeck }
193*f0d9efc0Sbeck
194*f0d9efc0Sbeck if (bnum >= map.pmMapBlkCnt)
195*f0d9efc0Sbeck {
196*f0d9efc0Sbeck ERROR(EINVAL, "can't find HFS partition");
197*f0d9efc0Sbeck return -1;
198*f0d9efc0Sbeck }
199*f0d9efc0Sbeck
200*f0d9efc0Sbeck ++bnum;
201*f0d9efc0Sbeck }
202*f0d9efc0Sbeck }
203*f0d9efc0Sbeck
204*f0d9efc0Sbeck /*
205*f0d9efc0Sbeck * NAME: low->readmdb()
206*f0d9efc0Sbeck * DESCRIPTION: read the master directory block into memory
207*f0d9efc0Sbeck */
l_readmdb(hfsvol * vol)208*f0d9efc0Sbeck int l_readmdb(hfsvol *vol)
209*f0d9efc0Sbeck {
210*f0d9efc0Sbeck block b;
211*f0d9efc0Sbeck unsigned char *ptr = b;
212*f0d9efc0Sbeck MDB *mdb = &vol->mdb;
213*f0d9efc0Sbeck hfsfile *ext = &vol->ext.f;
214*f0d9efc0Sbeck hfsfile *cat = &vol->cat.f;
215*f0d9efc0Sbeck int i;
216*f0d9efc0Sbeck
217*f0d9efc0Sbeck if (b_readlb(vol, 2, &b) < 0)
218*f0d9efc0Sbeck return -1;
219*f0d9efc0Sbeck
220*f0d9efc0Sbeck d_fetchw(&ptr, &mdb->drSigWord);
221*f0d9efc0Sbeck d_fetchl(&ptr, &mdb->drCrDate);
222*f0d9efc0Sbeck d_fetchl(&ptr, &mdb->drLsMod);
223*f0d9efc0Sbeck d_fetchw(&ptr, &mdb->drAtrb);
224*f0d9efc0Sbeck d_fetchw(&ptr, (short *) &mdb->drNmFls);
225*f0d9efc0Sbeck d_fetchw(&ptr, (short *) &mdb->drVBMSt);
226*f0d9efc0Sbeck d_fetchw(&ptr, (short *) &mdb->drAllocPtr);
227*f0d9efc0Sbeck d_fetchw(&ptr, (short *) &mdb->drNmAlBlks);
228*f0d9efc0Sbeck d_fetchl(&ptr, (long *) &mdb->drAlBlkSiz);
229*f0d9efc0Sbeck d_fetchl(&ptr, (long *) &mdb->drClpSiz);
230*f0d9efc0Sbeck d_fetchw(&ptr, (short *) &mdb->drAlBlSt);
231*f0d9efc0Sbeck d_fetchl(&ptr, &mdb->drNxtCNID);
232*f0d9efc0Sbeck d_fetchw(&ptr, (short *) &mdb->drFreeBks);
233*f0d9efc0Sbeck
234*f0d9efc0Sbeck d_fetchs(&ptr, mdb->drVN, sizeof(mdb->drVN));
235*f0d9efc0Sbeck
236*f0d9efc0Sbeck if (ptr - b != 64)
237*f0d9efc0Sbeck abort();
238*f0d9efc0Sbeck
239*f0d9efc0Sbeck d_fetchl(&ptr, &mdb->drVolBkUp);
240*f0d9efc0Sbeck d_fetchw(&ptr, &mdb->drVSeqNum);
241*f0d9efc0Sbeck d_fetchl(&ptr, (long *) &mdb->drWrCnt);
242*f0d9efc0Sbeck d_fetchl(&ptr, (long *) &mdb->drXTClpSiz);
243*f0d9efc0Sbeck d_fetchl(&ptr, (long *) &mdb->drCTClpSiz);
244*f0d9efc0Sbeck d_fetchw(&ptr, (short *) &mdb->drNmRtDirs);
245*f0d9efc0Sbeck d_fetchl(&ptr, (long *) &mdb->drFilCnt);
246*f0d9efc0Sbeck d_fetchl(&ptr, (long *) &mdb->drDirCnt);
247*f0d9efc0Sbeck
248*f0d9efc0Sbeck for (i = 0; i < 8; ++i)
249*f0d9efc0Sbeck d_fetchl(&ptr, &mdb->drFndrInfo[i]);
250*f0d9efc0Sbeck
251*f0d9efc0Sbeck if (ptr - b != 124)
252*f0d9efc0Sbeck abort();
253*f0d9efc0Sbeck
254*f0d9efc0Sbeck d_fetchw(&ptr, (short *) &mdb->drVCSize);
255*f0d9efc0Sbeck d_fetchw(&ptr, (short *) &mdb->drVBMCSize);
256*f0d9efc0Sbeck d_fetchw(&ptr, (short *) &mdb->drCtlCSize);
257*f0d9efc0Sbeck
258*f0d9efc0Sbeck d_fetchl(&ptr, (long *) &mdb->drXTFlSize);
259*f0d9efc0Sbeck
260*f0d9efc0Sbeck for (i = 0; i < 3; ++i)
261*f0d9efc0Sbeck {
262*f0d9efc0Sbeck d_fetchw(&ptr, (short *) &mdb->drXTExtRec[i].xdrStABN);
263*f0d9efc0Sbeck d_fetchw(&ptr, (short *) &mdb->drXTExtRec[i].xdrNumABlks);
264*f0d9efc0Sbeck }
265*f0d9efc0Sbeck
266*f0d9efc0Sbeck if (ptr - b != 146)
267*f0d9efc0Sbeck abort();
268*f0d9efc0Sbeck
269*f0d9efc0Sbeck d_fetchl(&ptr, (long *) &mdb->drCTFlSize);
270*f0d9efc0Sbeck
271*f0d9efc0Sbeck for (i = 0; i < 3; ++i)
272*f0d9efc0Sbeck {
273*f0d9efc0Sbeck d_fetchw(&ptr, (short *) &mdb->drCTExtRec[i].xdrStABN);
274*f0d9efc0Sbeck d_fetchw(&ptr, (short *) &mdb->drCTExtRec[i].xdrNumABlks);
275*f0d9efc0Sbeck }
276*f0d9efc0Sbeck
277*f0d9efc0Sbeck if (ptr - b != 162)
278*f0d9efc0Sbeck abort();
279*f0d9efc0Sbeck
280*f0d9efc0Sbeck vol->lpa = mdb->drAlBlkSiz / HFS_BLOCKSZ;
281*f0d9efc0Sbeck
282*f0d9efc0Sbeck /* extents pseudo-file structs */
283*f0d9efc0Sbeck
284*f0d9efc0Sbeck ext->vol = vol;
285*f0d9efc0Sbeck ext->parid = 0;
286*f0d9efc0Sbeck strcpy(ext->name, "extents overflow");
287*f0d9efc0Sbeck
288*f0d9efc0Sbeck ext->cat.cdrType = cdrFilRec;
289*f0d9efc0Sbeck /* ext->cat.cdrResrv2 */
290*f0d9efc0Sbeck ext->cat.u.fil.filFlags = 0;
291*f0d9efc0Sbeck ext->cat.u.fil.filTyp = 0;
292*f0d9efc0Sbeck /* ext->cat.u.fil.filUsrWds */
293*f0d9efc0Sbeck ext->cat.u.fil.filFlNum = HFS_CNID_EXT;
294*f0d9efc0Sbeck ext->cat.u.fil.filStBlk = mdb->drXTExtRec[0].xdrStABN;
295*f0d9efc0Sbeck ext->cat.u.fil.filLgLen = mdb->drXTFlSize;
296*f0d9efc0Sbeck ext->cat.u.fil.filPyLen = mdb->drXTFlSize;
297*f0d9efc0Sbeck ext->cat.u.fil.filRStBlk = 0;
298*f0d9efc0Sbeck ext->cat.u.fil.filRLgLen = 0;
299*f0d9efc0Sbeck ext->cat.u.fil.filRPyLen = 0;
300*f0d9efc0Sbeck ext->cat.u.fil.filCrDat = mdb->drCrDate;
301*f0d9efc0Sbeck ext->cat.u.fil.filMdDat = mdb->drLsMod;
302*f0d9efc0Sbeck ext->cat.u.fil.filBkDat = 0;
303*f0d9efc0Sbeck /* ext->cat.u.fil.filFndrInfo */
304*f0d9efc0Sbeck ext->cat.u.fil.filClpSize = 0;
305*f0d9efc0Sbeck
306*f0d9efc0Sbeck memcpy(ext->cat.u.fil.filExtRec, mdb->drXTExtRec, sizeof(ExtDataRec));
307*f0d9efc0Sbeck for (i = 0; i < 3; ++i)
308*f0d9efc0Sbeck {
309*f0d9efc0Sbeck ext->cat.u.fil.filRExtRec[i].xdrStABN = 0;
310*f0d9efc0Sbeck ext->cat.u.fil.filRExtRec[i].xdrNumABlks = 0;
311*f0d9efc0Sbeck }
312*f0d9efc0Sbeck f_selectfork(ext, 0);
313*f0d9efc0Sbeck
314*f0d9efc0Sbeck ext->clump = mdb->drXTClpSiz;
315*f0d9efc0Sbeck ext->flags = 0;
316*f0d9efc0Sbeck
317*f0d9efc0Sbeck ext->prev = ext->next = 0;
318*f0d9efc0Sbeck
319*f0d9efc0Sbeck /* catalog pseudo-file structs */
320*f0d9efc0Sbeck
321*f0d9efc0Sbeck cat->vol = vol;
322*f0d9efc0Sbeck cat->parid = 0;
323*f0d9efc0Sbeck strcpy(cat->name, "catalog");
324*f0d9efc0Sbeck
325*f0d9efc0Sbeck cat->cat.cdrType = cdrFilRec;
326*f0d9efc0Sbeck /* cat->cat.cdrResrv2 */
327*f0d9efc0Sbeck cat->cat.u.fil.filFlags = 0;
328*f0d9efc0Sbeck cat->cat.u.fil.filTyp = 0;
329*f0d9efc0Sbeck /* cat->cat.u.fil.filUsrWds */
330*f0d9efc0Sbeck cat->cat.u.fil.filFlNum = HFS_CNID_CAT;
331*f0d9efc0Sbeck cat->cat.u.fil.filStBlk = mdb->drCTExtRec[0].xdrStABN;
332*f0d9efc0Sbeck cat->cat.u.fil.filLgLen = mdb->drCTFlSize;
333*f0d9efc0Sbeck cat->cat.u.fil.filPyLen = mdb->drCTFlSize;
334*f0d9efc0Sbeck cat->cat.u.fil.filRStBlk = 0;
335*f0d9efc0Sbeck cat->cat.u.fil.filRLgLen = 0;
336*f0d9efc0Sbeck cat->cat.u.fil.filRPyLen = 0;
337*f0d9efc0Sbeck cat->cat.u.fil.filCrDat = mdb->drCrDate;
338*f0d9efc0Sbeck cat->cat.u.fil.filMdDat = mdb->drLsMod;
339*f0d9efc0Sbeck cat->cat.u.fil.filBkDat = 0;
340*f0d9efc0Sbeck /* cat->cat.u.fil.filFndrInfo */
341*f0d9efc0Sbeck cat->cat.u.fil.filClpSize = 0;
342*f0d9efc0Sbeck
343*f0d9efc0Sbeck memcpy(cat->cat.u.fil.filExtRec, mdb->drCTExtRec, sizeof(ExtDataRec));
344*f0d9efc0Sbeck for (i = 0; i < 3; ++i)
345*f0d9efc0Sbeck {
346*f0d9efc0Sbeck cat->cat.u.fil.filRExtRec[i].xdrStABN = 0;
347*f0d9efc0Sbeck cat->cat.u.fil.filRExtRec[i].xdrNumABlks = 0;
348*f0d9efc0Sbeck }
349*f0d9efc0Sbeck f_selectfork(cat, 0);
350*f0d9efc0Sbeck
351*f0d9efc0Sbeck cat->clump = mdb->drCTClpSiz;
352*f0d9efc0Sbeck cat->flags = 0;
353*f0d9efc0Sbeck
354*f0d9efc0Sbeck cat->prev = cat->next = 0;
355*f0d9efc0Sbeck
356*f0d9efc0Sbeck return 0;
357*f0d9efc0Sbeck }
358*f0d9efc0Sbeck
359*f0d9efc0Sbeck /*
360*f0d9efc0Sbeck * NAME: low->writemdb()
361*f0d9efc0Sbeck * DESCRIPTION: write the master directory block to disk
362*f0d9efc0Sbeck */
l_writemdb(hfsvol * vol)363*f0d9efc0Sbeck int l_writemdb(hfsvol *vol)
364*f0d9efc0Sbeck {
365*f0d9efc0Sbeck block b;
366*f0d9efc0Sbeck unsigned char *ptr = b;
367*f0d9efc0Sbeck MDB *mdb = &vol->mdb;
368*f0d9efc0Sbeck hfsfile *ext = &vol->ext.f;
369*f0d9efc0Sbeck hfsfile *cat = &vol->cat.f;
370*f0d9efc0Sbeck int i;
371*f0d9efc0Sbeck
372*f0d9efc0Sbeck memset(&b, 0, sizeof(b));
373*f0d9efc0Sbeck
374*f0d9efc0Sbeck mdb->drXTFlSize = ext->cat.u.fil.filPyLen;
375*f0d9efc0Sbeck mdb->drXTClpSiz = ext->clump;
376*f0d9efc0Sbeck memcpy(mdb->drXTExtRec, ext->cat.u.fil.filExtRec, sizeof(ExtDataRec));
377*f0d9efc0Sbeck
378*f0d9efc0Sbeck mdb->drCTFlSize = cat->cat.u.fil.filPyLen;
379*f0d9efc0Sbeck mdb->drCTClpSiz = cat->clump;
380*f0d9efc0Sbeck memcpy(mdb->drCTExtRec, cat->cat.u.fil.filExtRec, sizeof(ExtDataRec));
381*f0d9efc0Sbeck
382*f0d9efc0Sbeck d_storew(&ptr, mdb->drSigWord);
383*f0d9efc0Sbeck d_storel(&ptr, mdb->drCrDate);
384*f0d9efc0Sbeck d_storel(&ptr, mdb->drLsMod);
385*f0d9efc0Sbeck d_storew(&ptr, mdb->drAtrb);
386*f0d9efc0Sbeck d_storew(&ptr, mdb->drNmFls);
387*f0d9efc0Sbeck d_storew(&ptr, mdb->drVBMSt);
388*f0d9efc0Sbeck d_storew(&ptr, mdb->drAllocPtr);
389*f0d9efc0Sbeck d_storew(&ptr, mdb->drNmAlBlks);
390*f0d9efc0Sbeck d_storel(&ptr, mdb->drAlBlkSiz);
391*f0d9efc0Sbeck d_storel(&ptr, mdb->drClpSiz);
392*f0d9efc0Sbeck d_storew(&ptr, mdb->drAlBlSt);
393*f0d9efc0Sbeck d_storel(&ptr, mdb->drNxtCNID);
394*f0d9efc0Sbeck d_storew(&ptr, mdb->drFreeBks);
395*f0d9efc0Sbeck d_stores(&ptr, mdb->drVN, sizeof(mdb->drVN));
396*f0d9efc0Sbeck
397*f0d9efc0Sbeck if (ptr - b != 64)
398*f0d9efc0Sbeck abort();
399*f0d9efc0Sbeck
400*f0d9efc0Sbeck d_storel(&ptr, mdb->drVolBkUp);
401*f0d9efc0Sbeck d_storew(&ptr, mdb->drVSeqNum);
402*f0d9efc0Sbeck d_storel(&ptr, mdb->drWrCnt);
403*f0d9efc0Sbeck d_storel(&ptr, mdb->drXTClpSiz);
404*f0d9efc0Sbeck d_storel(&ptr, mdb->drCTClpSiz);
405*f0d9efc0Sbeck d_storew(&ptr, mdb->drNmRtDirs);
406*f0d9efc0Sbeck d_storel(&ptr, mdb->drFilCnt);
407*f0d9efc0Sbeck d_storel(&ptr, mdb->drDirCnt);
408*f0d9efc0Sbeck
409*f0d9efc0Sbeck for (i = 0; i < 8; ++i)
410*f0d9efc0Sbeck d_storel(&ptr, mdb->drFndrInfo[i]);
411*f0d9efc0Sbeck
412*f0d9efc0Sbeck if (ptr - b != 124)
413*f0d9efc0Sbeck abort();
414*f0d9efc0Sbeck
415*f0d9efc0Sbeck d_storew(&ptr, mdb->drVCSize);
416*f0d9efc0Sbeck d_storew(&ptr, mdb->drVBMCSize);
417*f0d9efc0Sbeck d_storew(&ptr, mdb->drCtlCSize);
418*f0d9efc0Sbeck d_storel(&ptr, mdb->drXTFlSize);
419*f0d9efc0Sbeck
420*f0d9efc0Sbeck for (i = 0; i < 3; ++i)
421*f0d9efc0Sbeck {
422*f0d9efc0Sbeck d_storew(&ptr, mdb->drXTExtRec[i].xdrStABN);
423*f0d9efc0Sbeck d_storew(&ptr, mdb->drXTExtRec[i].xdrNumABlks);
424*f0d9efc0Sbeck }
425*f0d9efc0Sbeck
426*f0d9efc0Sbeck if (ptr - b != 146)
427*f0d9efc0Sbeck abort();
428*f0d9efc0Sbeck
429*f0d9efc0Sbeck d_storel(&ptr, mdb->drCTFlSize);
430*f0d9efc0Sbeck
431*f0d9efc0Sbeck for (i = 0; i < 3; ++i)
432*f0d9efc0Sbeck {
433*f0d9efc0Sbeck d_storew(&ptr, mdb->drCTExtRec[i].xdrStABN);
434*f0d9efc0Sbeck d_storew(&ptr, mdb->drCTExtRec[i].xdrNumABlks);
435*f0d9efc0Sbeck }
436*f0d9efc0Sbeck
437*f0d9efc0Sbeck if (ptr - b != 162)
438*f0d9efc0Sbeck abort();
439*f0d9efc0Sbeck
440*f0d9efc0Sbeck if (b_writelb(vol, 2, &b) < 0)
441*f0d9efc0Sbeck return -1;
442*f0d9efc0Sbeck if (vol->flags & HFS_UPDATE_ALTMDB)
443*f0d9efc0Sbeck {
444*f0d9efc0Sbeck #ifdef APPLE_HYB
445*f0d9efc0Sbeck /* "write" alternative MDB to memory copy */
446*f0d9efc0Sbeck memcpy(vol->hce->hfs_alt_mdb, &b, sizeof(b));
447*f0d9efc0Sbeck #else
448*f0d9efc0Sbeck if (b_writelb(vol, vol->vlen - 2, &b) < 0)
449*f0d9efc0Sbeck return -1;
450*f0d9efc0Sbeck #endif /* APPLE_HYB */
451*f0d9efc0Sbeck }
452*f0d9efc0Sbeck vol->flags &= ~(HFS_UPDATE_MDB | HFS_UPDATE_ALTMDB);
453*f0d9efc0Sbeck
454*f0d9efc0Sbeck return 0;
455*f0d9efc0Sbeck }
456*f0d9efc0Sbeck
457*f0d9efc0Sbeck /*
458*f0d9efc0Sbeck * NAME: low->readvbm()
459*f0d9efc0Sbeck * DESCRIPTION: read the volume bit map into memory
460*f0d9efc0Sbeck */
l_readvbm(hfsvol * vol)461*f0d9efc0Sbeck int l_readvbm(hfsvol *vol)
462*f0d9efc0Sbeck {
463*f0d9efc0Sbeck int vbmst = vol->mdb.drVBMSt;
464*f0d9efc0Sbeck int vbmsz = (vol->mdb.drNmAlBlks + 4095) / 4096;
465*f0d9efc0Sbeck block *bp;
466*f0d9efc0Sbeck
467*f0d9efc0Sbeck if (vol->mdb.drAlBlSt - vbmst < vbmsz)
468*f0d9efc0Sbeck {
469*f0d9efc0Sbeck ERROR(EIO, "volume bitmap collides with volume data");
470*f0d9efc0Sbeck return -1;
471*f0d9efc0Sbeck }
472*f0d9efc0Sbeck
473*f0d9efc0Sbeck bp = ALLOC(block, vbmsz);
474*f0d9efc0Sbeck if (bp == 0)
475*f0d9efc0Sbeck {
476*f0d9efc0Sbeck ERROR(ENOMEM, 0);
477*f0d9efc0Sbeck return -1;
478*f0d9efc0Sbeck }
479*f0d9efc0Sbeck
480*f0d9efc0Sbeck vol->vbm = bp;
481*f0d9efc0Sbeck
482*f0d9efc0Sbeck while (vbmsz--)
483*f0d9efc0Sbeck {
484*f0d9efc0Sbeck if (b_readlb(vol, vbmst++, bp++) < 0)
485*f0d9efc0Sbeck {
486*f0d9efc0Sbeck FREE(vol->vbm);
487*f0d9efc0Sbeck vol->vbm = 0;
488*f0d9efc0Sbeck
489*f0d9efc0Sbeck return -1;
490*f0d9efc0Sbeck }
491*f0d9efc0Sbeck }
492*f0d9efc0Sbeck
493*f0d9efc0Sbeck return 0;
494*f0d9efc0Sbeck }
495*f0d9efc0Sbeck
496*f0d9efc0Sbeck /*
497*f0d9efc0Sbeck * NAME: low->writevbm()
498*f0d9efc0Sbeck * DESCRIPTION: write the volume bit map to disk
499*f0d9efc0Sbeck */
l_writevbm(hfsvol * vol)500*f0d9efc0Sbeck int l_writevbm(hfsvol *vol)
501*f0d9efc0Sbeck {
502*f0d9efc0Sbeck int vbmst = vol->mdb.drVBMSt;
503*f0d9efc0Sbeck int vbmsz = (vol->mdb.drNmAlBlks + 4095) / 4096;
504*f0d9efc0Sbeck block *bp = vol->vbm;
505*f0d9efc0Sbeck
506*f0d9efc0Sbeck while (vbmsz--)
507*f0d9efc0Sbeck {
508*f0d9efc0Sbeck if (b_writelb(vol, vbmst++, bp++) < 0)
509*f0d9efc0Sbeck return -1;
510*f0d9efc0Sbeck }
511*f0d9efc0Sbeck
512*f0d9efc0Sbeck vol->flags &= ~HFS_UPDATE_VBM;
513*f0d9efc0Sbeck
514*f0d9efc0Sbeck return 0;
515*f0d9efc0Sbeck }
516