1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12 
13 /* @(#)internal.h	1.2 01/11/01 joerg */
14 /*
15  * hfsutils - tools for reading and writing Macintosh HFS volumes
16  * Copyright (C) 1996, 1997 Robert Leslie
17  *
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 2 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31  */
32 
33 #include <timedefs.h>
34 #include <standard.h>
35 
36 # include "hfs.h"
37 
38 # define ERROR(code, str)	(hfs_error = (str), errno = (code))
39 
40 # define SIZE(type, n)		((size_t) (sizeof(type) * (n)))
41 # define ALLOC(type, n)		((type *) malloc(SIZE(type, n)))
42 # define ALLOCX(type, n)	((n) ? ALLOC(type, n) : (type *) 0)
43 # define FREE(ptr)		{if (ptr) free((void *) ptr) ;}
44 
45 # define REALLOC(ptr, type, n)  \
46     ((type *) ((ptr) ? realloc(ptr, SIZE(type, n)) : malloc(SIZE(type, n))))
47 # define REALLOCX(ptr, type, n)  \
48     ((n) ? REALLOC(type, n) : (FREE(ptr), (type *) 0))
49 
50 # define BMTST(bm, num)  \
51   (((char *) (bm))[(num) >> 3] & (0x80 >> ((num) & 0x07)))
52 # define BMSET(bm, num)  \
53   (((char *) (bm))[(num) >> 3] |= (0x80 >> ((num) & 0x07)))
54 # define BMCLR(bm, num)  \
55   (((char *) (bm))[(num) >> 3] &= ~(0x80 >> ((num) & 0x07)))
56 
57 typedef unsigned char block[HFS_BLOCKSZ];
58 
59 typedef signed char	Char;
60 typedef unsigned char	UChar;
61 typedef signed char	SignedByte;
62 typedef signed short	Integer;
63 typedef unsigned short	UInteger;
64 typedef signed long	LongInt;
65 typedef unsigned long	ULongInt;
66 typedef char		Str15[16];
67 typedef char		Str31[32];
68 typedef long		OSType;
69 
70 typedef struct {
71   UInteger	xdrStABN;	/* first allocation block */
72   UInteger	xdrNumABlks;	/* number of allocation blocks */
73 } ExtDescriptor;
74 
75 typedef ExtDescriptor ExtDataRec[3];
76 
77 typedef struct {
78   SignedByte	xkrKeyLen;	/* key length */
79   SignedByte	xkrFkType;	/* fork type (0x00/0xff == data/resource */
80   ULongInt	xkrFNum;	/* file number */
81   UInteger	xkrFABN;	/* starting file allocation block */
82 } ExtKeyRec;
83 
84 typedef struct {
85   SignedByte	ckrKeyLen;	/* key length */
86   SignedByte	ckrResrv1;	/* reserved */
87   ULongInt	ckrParID;	/* parent directory ID */
88   Str31		ckrCName;	/* catalog node name */
89 } CatKeyRec;
90 
91 # define HFS_MAP1SZ  256
92 # define HFS_MAPXSZ  492
93 
94 # define HFS_NODEREC(nd, rnum)	((nd).data + (nd).roff[rnum])
95 
96 # define HFS_RECKEYLEN(ptr)	(*(unsigned char *) (ptr))
97 # define HFS_RECKEYSKIP(ptr)	((1 + HFS_RECKEYLEN(ptr) + 1) & ~1)
98 # define HFS_RECDATA(ptr)	((ptr) + HFS_RECKEYSKIP(ptr))
99 
100 # define HFS_CATDATALEN		sizeof(CatDataRec)
101 # define HFS_EXTDATALEN		sizeof(ExtDataRec)
102 
103 # define HFS_CATKEYLEN		sizeof(CatKeyRec)
104 # define HFS_EXTKEYLEN		sizeof(ExtKeyRec)
105 
106 # define HFS_CATRECMAXLEN	(HFS_CATKEYLEN + HFS_CATDATALEN)
107 # define HFS_EXTRECMAXLEN	(HFS_EXTKEYLEN + HFS_EXTDATALEN)
108 
109 # define HFS_MAXRECLEN		HFS_CATRECMAXLEN
110 
111 typedef struct {
112   Integer	v;		/* vertical coordinate */
113   Integer	h;		/* horizontal coordinate */
114 } Point;
115 
116 typedef struct {
117   Integer	top;		/* top edge of rectangle */
118   Integer	left;		/* left edge */
119   Integer	bottom;		/* bottom edge */
120   Integer	right;		/* rightmost edge */
121 } Rect;
122 
123 typedef struct {
124   Rect		frRect;		/* folder's rectangle */
125   Integer	frFlags;	/* flags */
126   Point		frLocation;	/* folder's location */
127   Integer	frView;		/* folder's view */
128 } DInfo;
129 
130 typedef struct {
131   Point		frScroll;	/* scroll position */
132   LongInt	frOpenChain;	/* directory ID chain of open folders */
133   Integer	frUnused;	/* reserved */
134   Integer	frComment;	/* comment ID */
135   LongInt	frPutAway;	/* directory ID */
136 } DXInfo;
137 
138 typedef struct {
139   OSType	fdType;		/* file type */
140   OSType	fdCreator;	/* file's creator */
141   Integer	fdFlags;	/* flags */
142   Point		fdLocation;	/* file's location */
143   Integer	fdFldr;		/* file's window */
144 } FInfo;
145 
146 typedef struct {
147   Integer	fdIconID;	/* icon ID */
148   Integer	fdUnused[4];	/* reserved */
149   Integer	fdComment;	/* comment ID */
150   LongInt	fdPutAway;	/* home directory ID */
151 } FXInfo;
152 
153 typedef struct {
154   Integer	drSigWord;	/* volume signature (0x4244 for HFS) */
155   LongInt	drCrDate;	/* date and time of volume creation */
156   LongInt	drLsMod;	/* date and time of last modification */
157   Integer	drAtrb;		/* volume attributes */
158   UInteger	drNmFls;	/* number of files in root directory */
159   UInteger	drVBMSt;	/* first block of volume bit map (always 3) */
160   UInteger	drAllocPtr;	/* start of next allocation search */
161   UInteger	drNmAlBlks;	/* number of allocation blocks in volume */
162   ULongInt	drAlBlkSiz;	/* size (in bytes) of allocation blocks */
163   ULongInt	drClpSiz;	/* default clump size */
164   UInteger	drAlBlSt;	/* first allocation block in volume */
165   LongInt	drNxtCNID;	/* next unused catalog node ID (dir/file ID) */
166   UInteger	drFreeBks;	/* number of unused allocation blocks */
167   char		drVN[28];	/* volume name (1-27 chars) */
168   LongInt	drVolBkUp;	/* date and time of last backup */
169   Integer	drVSeqNum;	/* volume backup sequence number */
170   ULongInt	drWrCnt;	/* volume write count */
171   ULongInt	drXTClpSiz;	/* clump size for extents overflow file */
172   ULongInt	drCTClpSiz;	/* clump size for catalog file */
173   UInteger	drNmRtDirs;	/* number of directories in root directory */
174   ULongInt	drFilCnt;	/* number of files in volume */
175   ULongInt	drDirCnt;	/* number of directories in volume */
176   LongInt	drFndrInfo[8];	/* information used by the Finder */
177   UInteger	drVCSize;	/* size (in blocks) of volume cache */
178   UInteger	drVBMCSize;	/* size (in blocks) of volume bitmap cache */
179   UInteger	drCtlCSize;	/* size (in blocks) of common volume cache */
180   ULongInt	drXTFlSize;	/* size (in bytes) of extents overflow file */
181   ExtDataRec	drXTExtRec;	/* first extent record for extents file */
182   ULongInt	drCTFlSize;	/* size (in bytes) of catalog file */
183   ExtDataRec	drCTExtRec;	/* first extent record for catalog file */
184 } MDB;
185 
186 # define HFS_ATRB_BUSY		(1 <<  6)
187 # define HFS_ATRB_HLOCKED	(1 <<  7)
188 # define HFS_ATRB_UMOUNTED	(1 <<  8)
189 # define HFS_ATRB_BBSPARED	(1 <<  9)
190 # define HFS_ATRB_COPYPROT	(1 << 14)
191 # define HFS_ATRB_SLOCKED	(1 << 15)
192 
193 typedef enum {
194   cdrDirRec  = 1,
195   cdrFilRec  = 2,
196   cdrThdRec  = 3,
197   cdrFThdRec = 4
198 } CatDataType;
199 
200 typedef struct {
201   SignedByte	cdrType;	/* record type */
202   SignedByte	cdrResrv2;	/* reserved */
203   union {
204     struct {  /* cdrDirRec */
205       Integer	dirFlags;	/* directory flags */
206       UInteger	dirVal;		/* directory valence */
207       ULongInt	dirDirID;	/* directory ID */
208       LongInt	dirCrDat;	/* date and time of creation */
209       LongInt	dirMdDat;	/* date and time of last modification */
210       LongInt	dirBkDat;	/* date and time of last backup */
211       DInfo	dirUsrInfo;	/* Finder information */
212       DXInfo	dirFndrInfo;	/* additional Finder information */
213       LongInt	dirResrv[4];	/* reserved */
214     } dir;
215     struct {  /* cdrFilRec */
216       SignedByte
217 		filFlags;	/* file flags */
218       SignedByte
219 		filTyp;		/* file type */
220       FInfo	filUsrWds;	/* Finder information */
221       ULongInt	filFlNum;	/* file ID */
222       UInteger	filStBlk;	/* first alloc block of data fork */
223       ULongInt	filLgLen;	/* logical EOF of data fork */
224       ULongInt	filPyLen;	/* physical EOF of data fork */
225       UInteger	filRStBlk;	/* first alloc block of resource fork */
226       ULongInt	filRLgLen;	/* logical EOF of resource fork */
227       ULongInt	filRPyLen;	/* physical EOF of resource fork */
228       LongInt	filCrDat;	/* date and time of creation */
229       LongInt	filMdDat;	/* date and time of last modification */
230       LongInt	filBkDat;	/* date and time of last backup */
231       FXInfo	filFndrInfo;	/* additional Finder information */
232       UInteger	filClpSize;	/* file clump size */
233       ExtDataRec
234 		filExtRec;	/* first data fork extent record */
235       ExtDataRec
236 		filRExtRec;	/* first resource fork extent record */
237       LongInt	filResrv;	/* reserved */
238     } fil;
239     struct {  /* cdrThdRec */
240       LongInt	thdResrv[2];	/* reserved */
241       ULongInt	thdParID;	/* parent ID for this directory */
242       Str31	thdCName;	/* name of this directory */
243     } dthd;
244     struct {  /* cdrFThdRec */
245       LongInt	fthdResrv[2];	/* reserved */
246       ULongInt	fthdParID;	/* parent ID for this file */
247       Str31	fthdCName;	/* name of this file */
248     } fthd;
249   } u;
250 } CatDataRec;
251 
252 struct _hfsfile_ {
253   struct _hfsvol_ *vol;		/* pointer to volume descriptor */
254   long parid;			/* parent directory ID of this file */
255   char name[HFS_MAX_FLEN + 1];	/* catalog name of this file */
256   CatDataRec cat;		/* catalog information */
257   ExtDataRec ext;		/* current extent record */
258   unsigned int fabn;		/* starting file allocation block number */
259   int fork;			/* current selected fork for I/O */
260   unsigned long pos;		/* current file seek pointer */
261   unsigned long clump;		/* file's clump size, for allocation */
262   int flags;			/* bit flags */
263 
264   struct _hfsfile_ *prev;
265   struct _hfsfile_ *next;
266 };
267 
268 # define HFS_UPDATE_CATREC	0x01
269 
270 typedef struct {
271   ULongInt	ndFLink;	/* forward link */
272   ULongInt	ndBLink;	/* backward link */
273   SignedByte	ndType;		/* node type */
274   SignedByte	ndNHeight;	/* node level */
275   UInteger	ndNRecs;	/* number of records in node */
276   Integer	ndResv2;	/* reserved */
277 } NodeDescriptor;
278 
279 # define HFS_MAXRECS	35	/* maximum based on minimum record size */
280 
281 typedef struct _node_ {
282   struct _btree_ *bt;		/* btree to which this node belongs */
283   unsigned long nnum;		/* node index */
284   NodeDescriptor nd;		/* node descriptor */
285   int rnum;			/* current record index */
286   UInteger roff[HFS_MAXRECS + 1];	/* record offsets */
287   block data;			/* raw contents of node */
288 } node;
289 
290 enum {
291   ndIndxNode = 0x00,
292   ndHdrNode  = 0x01,
293   ndMapNode  = 0x02,
294   ndLeafNode = 0xff
295 };
296 
297 struct _hfsdir_ {
298   struct _hfsvol_ *vol;		/* associated volume */
299   long dirid;			/* directory ID of interest (or 0) */
300 
301   node n;			/* current B*-tree node */
302   struct _hfsvol_ *vptr;	/* current volume pointer */
303 
304   struct _hfsdir_ *prev;
305   struct _hfsdir_ *next;
306 };
307 
308 typedef struct {
309   UInteger	bthDepth;	/* current depth of tree */
310   ULongInt	bthRoot;	/* number of root node */
311   ULongInt	bthNRecs;	/* number of leaf records in tree */
312   ULongInt	bthFNode;	/* number of first leaf node */
313   ULongInt	bthLNode;	/* number of last leaf node */
314   UInteger	bthNodeSize;	/* size of a node */
315   UInteger	bthKeyLen;	/* maximum length of a key */
316   ULongInt	bthNNodes;	/* total number of nodes in tree */
317   ULongInt	bthFree;	/* number of free nodes */
318   SignedByte	bthResv[76];	/* reserved */
319 } BTHdrRec;
320 
321 typedef struct _btree_ {
322   hfsfile f;			/* subset file information */
323   node hdrnd;			/* header node */
324   BTHdrRec hdr;			/* header record */
325   char *map;			/* usage bitmap */
326   unsigned long mapsz;		/* number of bytes in bitmap */
327   int flags;			/* bit flags */
328 
329   int (*compare)(unsigned char *, unsigned char *);
330 				/* key comparison function */
331 } btree;
332 
333 # define HFS_UPDATE_BTHDR	0x01
334 
335 struct _hfsvol_ {
336   int fd;		/* volume's open file descriptor */
337   int flags;		/* bit flags */
338 
339 #ifdef APPLE_HYB
340   hce_mem *hce;		/* Extras needed by libhfs/mkisofs */
341 #endif /* APPLE_HYB */
342 
343   int pnum;		/* ordinal HFS partition number */
344   unsigned long vstart;	/* logical block offset to start of volume */
345   unsigned long vlen;	/* number of logical blocks in volume */
346   unsigned int lpa;	/* number of logical blocks per allocation block */
347 
348   MDB mdb;		/* master directory block */
349   block *vbm;		/* volume bit map */
350   btree ext;		/* B*-tree control block for extents overflow file */
351   btree cat;		/* B*-tree control block for catalog file */
352   long cwd;		/* directory id of current working directory */
353 
354   int refs;		/* number of external references to this volume */
355   hfsfile *files;	/* list of open files */
356   hfsdir *dirs;		/* list of open directories */
357 
358   struct _hfsvol_ *prev;
359   struct _hfsvol_ *next;
360 };
361 
362 # define HFS_READONLY		0x01
363 
364 # define HFS_UPDATE_MDB		0x10
365 # define HFS_UPDATE_ALTMDB	0x20
366 # define HFS_UPDATE_VBM		0x40
367 
368 extern hfsvol *hfs_mounts;
369 extern hfsvol *hfs_curvol;
370