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