1/*
2 * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28#ifndef __HFS_FORMAT__
29#define __HFS_FORMAT__
30
31#include <sys/types.h>
32#include <sys/appleapiopts.h>
33#include <hfs/hfs_unistr.h>
34
35/*
36 * hfs_format.h
37 *
38 * This file describes the on-disk format for HFS and HFS Plus volumes.
39 * The HFS Plus volume format is desciibed in detail in Apple Technote 1150.
40 *
41 * http://developer.apple.com/technotes/tn/tn1150.html
42 *
43 * Note: Starting 10.9, definition of struct HFSUniStr255 exists in hfs_unitstr.h
44 *
45 */
46
47#ifdef __cplusplus
48extern "C" {
49#endif
50
51/* some on-disk hfs structures have 68K alignment (misaligned) */
52
53/* Signatures used to differentiate between HFS and HFS Plus volumes */
54enum {
55	kHFSSigWord		= 0x4244,	/* 'BD' in ASCII */
56	kHFSPlusSigWord		= 0x482B,	/* 'H+' in ASCII */
57	kHFSXSigWord		= 0x4858,	/* 'HX' in ASCII */
58
59	kHFSPlusVersion		= 0x0004,	/* 'H+' volumes are version 4 only */
60	kHFSXVersion		= 0x0005,	/* 'HX' volumes start with version 5 */
61
62	kHFSPlusMountVersion	= 0x31302E30,	/* '10.0' for Mac OS X */
63	kHFSJMountVersion	= 0x4846534a,	/* 'HFSJ' for journaled HFS+ on OS X */
64	kFSKMountVersion	= 0x46534b21	/* 'FSK!' for failed journal replay */
65};
66
67
68#ifdef __APPLE_API_PRIVATE
69/*
70 * Mac OS X has two special directories on HFS+ volumes for hardlinked files
71 * and hardlinked directories as well as for open-unlinked files.
72 *
73 * These directories and their contents are not exported from the filesystem
74 * under Mac OS X.
75 */
76#define HFSPLUSMETADATAFOLDER       "\xE2\x90\x80\xE2\x90\x80\xE2\x90\x80\xE2\x90\x80HFS+ Private Data"
77#define HFSPLUS_DIR_METADATA_FOLDER ".HFS+ Private Directory Data\xd"
78
79/*
80 * Files in the "HFS+ Private Data" folder have one of the following prefixes
81 * followed by a decimal number (no leading zeros) for the file ID.
82 *
83 * Note: Earlier version of Mac OS X used a 32 bit random number for the link
84 * ref number instead of the file id.
85 *
86 * e.g.  iNode7182000 and temp3296
87 */
88#define HFS_INODE_PREFIX	"iNode"
89#define HFS_DELETE_PREFIX	"temp"
90
91/*
92 * Files in the ".HFS+ Private Directory Data" folder have the following
93 * prefix followed by a decimal number (no leading zeros) for the file ID.
94 *
95 * e.g. dir_555
96 */
97#define HFS_DIRINODE_PREFIX	"dir_"
98
99/*
100 * Hardlink inodes save the head of the link chain in
101 * an extended attribute named FIRST_LINK_XATTR_NAME.
102 * The attribute data is the decimal value in ASCII
103 * of the cnid for the first link in the chain.
104 *
105 * This extended attribute is private (i.e. its not
106 * exported in the getxattr/listxattr POSIX APIs).
107 */
108#define FIRST_LINK_XATTR_NAME	"com.apple.system.hfs.firstlink"
109#define FIRST_LINK_XATTR_REC_SIZE (sizeof(HFSPlusAttrData) - 2 + 12)
110
111/*
112 * The name space ID for generating an HFS volume UUID
113 *
114 * B3E20F39-F292-11D6-97A4-00306543ECAC
115 */
116#define HFS_UUID_NAMESPACE_ID  "\xB3\xE2\x0F\x39\xF2\x92\x11\xD6\x97\xA4\x00\x30\x65\x43\xEC\xAC"
117
118#endif /* __APPLE_API_PRIVATE */
119
120/*
121 * Indirect link files (hard links) have the following type/creator.
122 */
123enum {
124	kHardLinkFileType = 0x686C6E6B,  /* 'hlnk' */
125	kHFSPlusCreator   = 0x6866732B   /* 'hfs+' */
126};
127
128
129/*
130 *	File type and creator for symbolic links
131 */
132enum {
133      kSymLinkFileType  = 0x736C6E6B, /* 'slnk' */
134      kSymLinkCreator   = 0x72686170  /* 'rhap' */
135};
136
137
138enum {
139	kHFSMaxVolumeNameChars		= 27,
140	kHFSMaxFileNameChars		= 31,
141	kHFSPlusMaxFileNameChars	= 255
142};
143
144
145/* Extent overflow file data structures */
146
147/* HFS Extent key */
148struct HFSExtentKey {
149	u_int8_t 	keyLength;	/* length of key, excluding this field */
150	u_int8_t 	forkType;	/* 0 = data fork, FF = resource fork */
151	u_int32_t 	fileID;		/* file ID */
152	u_int16_t 	startBlock;	/* first file allocation block number in this extent */
153} __attribute__((aligned(2), packed));
154typedef struct HFSExtentKey HFSExtentKey;
155
156/* HFS Plus Extent key */
157struct HFSPlusExtentKey {
158	u_int16_t 	keyLength;		/* length of key, excluding this field */
159	u_int8_t 	forkType;		/* 0 = data fork, FF = resource fork */
160	u_int8_t 	pad;			/* make the other fields align on 32-bit boundary */
161	u_int32_t 	fileID;			/* file ID */
162	u_int32_t 	startBlock;		/* first file allocation block number in this extent */
163} __attribute__((aligned(2), packed));
164typedef struct HFSPlusExtentKey HFSPlusExtentKey;
165
166/* Number of extent descriptors per extent record */
167enum {
168	kHFSExtentDensity	= 3,
169	kHFSPlusExtentDensity	= 8
170};
171
172/* HFS extent descriptor */
173struct HFSExtentDescriptor {
174	u_int16_t 	startBlock;		/* first allocation block */
175	u_int16_t 	blockCount;		/* number of allocation blocks */
176} __attribute__((aligned(2), packed));
177typedef struct HFSExtentDescriptor HFSExtentDescriptor;
178
179/* HFS Plus extent descriptor */
180struct HFSPlusExtentDescriptor {
181	u_int32_t 	startBlock;		/* first allocation block */
182	u_int32_t 	blockCount;		/* number of allocation blocks */
183} __attribute__((aligned(2), packed));
184typedef struct HFSPlusExtentDescriptor HFSPlusExtentDescriptor;
185
186/* HFS extent record */
187typedef HFSExtentDescriptor HFSExtentRecord[3];
188
189/* HFS Plus extent record */
190typedef HFSPlusExtentDescriptor HFSPlusExtentRecord[8];
191
192
193/* Finder information */
194struct FndrFileInfo {
195	u_int32_t 	fdType;		/* file type */
196	u_int32_t 	fdCreator;	/* file creator */
197	u_int16_t 	fdFlags;	/* Finder flags */
198	struct {
199	    int16_t	v;		/* file's location */
200	    int16_t	h;
201	} fdLocation;
202	int16_t 	opaque;
203} __attribute__((aligned(2), packed));
204typedef struct FndrFileInfo FndrFileInfo;
205
206struct FndrDirInfo {
207	struct {			/* folder's window rectangle */
208	    int16_t	top;
209	    int16_t	left;
210	    int16_t	bottom;
211	    int16_t	right;
212	} frRect;
213	unsigned short 	frFlags;	/* Finder flags */
214	struct {
215	    u_int16_t	v;		/* folder's location */
216	    u_int16_t	h;
217	} frLocation;
218	int16_t 	opaque;
219} __attribute__((aligned(2), packed));
220typedef struct FndrDirInfo FndrDirInfo;
221
222struct FndrOpaqueInfo {
223	int8_t opaque[16];
224} __attribute__((aligned(2), packed));
225typedef struct FndrOpaqueInfo FndrOpaqueInfo;
226
227struct FndrExtendedDirInfo {
228	u_int32_t document_id;
229	u_int32_t date_added;
230	u_int16_t extended_flags;
231	u_int16_t reserved3;
232	u_int32_t write_gen_counter;
233} __attribute__((aligned(2), packed));
234
235struct FndrExtendedFileInfo {
236	u_int32_t document_id;
237	u_int32_t date_added;
238	u_int16_t extended_flags;
239	u_int16_t reserved2;
240	u_int32_t write_gen_counter;
241} __attribute__((aligned(2), packed));
242
243/* HFS Plus Fork data info - 80 bytes */
244struct HFSPlusForkData {
245	u_int64_t 		logicalSize;	/* fork's logical size in bytes */
246	u_int32_t 		clumpSize;	/* fork's clump size in bytes */
247	u_int32_t 		totalBlocks;	/* total blocks used by this fork */
248	HFSPlusExtentRecord 	extents;	/* initial set of extents */
249} __attribute__((aligned(2), packed));
250typedef struct HFSPlusForkData HFSPlusForkData;
251
252
253/* Mac OS X has 16 bytes worth of "BSD" info.
254 *
255 * Note:  Mac OS 9 implementations and applications
256 * should preserve, but not change, this information.
257 */
258struct HFSPlusBSDInfo {
259	u_int32_t 	ownerID;	/* user-id of owner or hard link chain previous link */
260	u_int32_t 	groupID;	/* group-id of owner or hard link chain next link */
261	u_int8_t 	adminFlags;	/* super-user changeable flags */
262	u_int8_t 	ownerFlags;	/* owner changeable flags */
263	u_int16_t 	fileMode;	/* file type and permission bits */
264	union {
265	    u_int32_t	iNodeNum;	/* indirect node number (hard links only) */
266	    u_int32_t	linkCount;	/* links that refer to this indirect node */
267	    u_int32_t	rawDevice;	/* special file device (FBLK and FCHR only) */
268	} special;
269} __attribute__((aligned(2), packed));
270typedef struct HFSPlusBSDInfo HFSPlusBSDInfo;
271
272/*
273 * Hardlink "links" resolve to an inode
274 * and the actual uid/gid comes from that
275 * inode.
276 *
277 * We repurpose the links's uid/gid fields
278 * for the hardlink link chain. The chain
279 * consists of a doubly linked list of file
280 * ids.
281 */
282
283#define hl_firstLinkID     reserved1         /* Valid only if HasLinkChain flag is set (indirect nodes only) */
284
285#define hl_prevLinkID      bsdInfo.ownerID   /* Valid only if HasLinkChain flag is set */
286#define hl_nextLinkID      bsdInfo.groupID   /* Valid only if HasLinkChain flag is set */
287
288#define hl_linkReference   bsdInfo.special.iNodeNum
289#define hl_linkCount       bsdInfo.special.linkCount
290
291
292/* Catalog file data structures */
293
294enum {
295	kHFSRootParentID		= 1,	/* Parent ID of the root folder */
296	kHFSRootFolderID		= 2,	/* Folder ID of the root folder */
297	kHFSExtentsFileID		= 3,	/* File ID of the extents file */
298	kHFSCatalogFileID		= 4,	/* File ID of the catalog file */
299	kHFSBadBlockFileID		= 5,	/* File ID of the bad allocation block file */
300	kHFSAllocationFileID		= 6,	/* File ID of the allocation file (HFS Plus only) */
301	kHFSStartupFileID		= 7,	/* File ID of the startup file (HFS Plus only) */
302	kHFSAttributesFileID		= 8,	/* File ID of the attribute file (HFS Plus only) */
303	kHFSAttributeDataFileID         = 13,	/* Used in Mac OS X runtime for extent based attributes */
304	                                        /* kHFSAttributeDataFileID is never stored on disk. */
305	kHFSRepairCatalogFileID		= 14,	/* Used when rebuilding Catalog B-tree */
306	kHFSBogusExtentFileID		= 15,	/* Used for exchanging extents in extents file */
307	kHFSFirstUserCatalogNodeID	= 16
308};
309
310/* HFS catalog key */
311struct HFSCatalogKey {
312	u_int8_t 	keyLength;		/* key length (in bytes) */
313	u_int8_t 	reserved;		/* reserved (set to zero) */
314	u_int32_t 	parentID;		/* parent folder ID */
315	u_int8_t 	nodeName[kHFSMaxFileNameChars + 1]; /* catalog node name */
316} __attribute__((aligned(2), packed));
317typedef struct HFSCatalogKey HFSCatalogKey;
318
319/* HFS Plus catalog key */
320struct HFSPlusCatalogKey {
321	u_int16_t 		keyLength;	/* key length (in bytes) */
322	u_int32_t 		parentID;	/* parent folder ID */
323	HFSUniStr255 		nodeName;	/* catalog node name */
324} __attribute__((aligned(2), packed));
325typedef struct HFSPlusCatalogKey HFSPlusCatalogKey;
326
327/* Catalog record types */
328enum {
329	/* HFS Catalog Records */
330	kHFSFolderRecord		= 0x0100,	/* Folder record */
331	kHFSFileRecord			= 0x0200,	/* File record */
332	kHFSFolderThreadRecord		= 0x0300,	/* Folder thread record */
333	kHFSFileThreadRecord		= 0x0400,	/* File thread record */
334
335	/* HFS Plus Catalog Records */
336	kHFSPlusFolderRecord		= 1,		/* Folder record */
337	kHFSPlusFileRecord		= 2,		/* File record */
338	kHFSPlusFolderThreadRecord	= 3,		/* Folder thread record */
339	kHFSPlusFileThreadRecord	= 4		/* File thread record */
340};
341
342
343/* Catalog file record flags */
344enum {
345	kHFSFileLockedBit	= 0x0000,	/* file is locked and cannot be written to */
346	kHFSFileLockedMask	= 0x0001,
347
348	kHFSThreadExistsBit	= 0x0001,	/* a file thread record exists for this file */
349	kHFSThreadExistsMask	= 0x0002,
350
351	kHFSHasAttributesBit	= 0x0002,	/* object has extended attributes */
352	kHFSHasAttributesMask	= 0x0004,
353
354	kHFSHasSecurityBit	= 0x0003,	/* object has security data (ACLs) */
355	kHFSHasSecurityMask	= 0x0008,
356
357	kHFSHasFolderCountBit	= 0x0004,	/* only for HFSX, folder maintains a separate sub-folder count */
358	kHFSHasFolderCountMask	= 0x0010,	/* (sum of folder records and directory hard links) */
359
360	kHFSHasLinkChainBit	= 0x0005,	/* has hardlink chain (inode or link) */
361	kHFSHasLinkChainMask	= 0x0020,
362
363	kHFSHasChildLinkBit	= 0x0006,	/* folder has a child that's a dir link */
364	kHFSHasChildLinkMask	= 0x0040,
365
366	kHFSHasDateAddedBit = 0x0007,	/* File/Folder has the date-added stored in the finder info. */
367	kHFSHasDateAddedMask = 0x0080
368};
369
370
371/* HFS catalog folder record - 70 bytes */
372struct HFSCatalogFolder {
373	int16_t 		recordType;		/* == kHFSFolderRecord */
374	u_int16_t 		flags;			/* folder flags */
375	u_int16_t 		valence;		/* folder valence */
376	u_int32_t		folderID;		/* folder ID */
377	u_int32_t 		createDate;		/* date and time of creation */
378	u_int32_t 		modifyDate;		/* date and time of last modification */
379	u_int32_t 		backupDate;		/* date and time of last backup */
380	FndrDirInfo 		userInfo;		/* Finder information */
381	FndrOpaqueInfo		finderInfo;		/* additional Finder information */
382	u_int32_t 		reserved[4];		/* reserved - initialized as zero */
383} __attribute__((aligned(2), packed));
384typedef struct HFSCatalogFolder HFSCatalogFolder;
385
386/* HFS Plus catalog folder record - 88 bytes */
387struct HFSPlusCatalogFolder {
388	int16_t 		recordType;		/* == kHFSPlusFolderRecord */
389	u_int16_t 		flags;			/* file flags */
390	u_int32_t 		valence;		/* folder's item count */
391	u_int32_t 		folderID;		/* folder ID */
392	u_int32_t 		createDate;		/* date and time of creation */
393	u_int32_t 		contentModDate;		/* date and time of last content modification */
394	u_int32_t 		attributeModDate;	/* date and time of last attribute modification */
395	u_int32_t 		accessDate;		/* date and time of last access (MacOS X only) */
396	u_int32_t 		backupDate;		/* date and time of last backup */
397	HFSPlusBSDInfo		bsdInfo;		/* permissions (for MacOS X) */
398	FndrDirInfo 		userInfo;		/* Finder information */
399	FndrOpaqueInfo	 	finderInfo;		/* additional Finder information */
400	u_int32_t 		textEncoding;		/* hint for name conversions */
401	u_int32_t 		folderCount;		/* number of enclosed folders, active when HasFolderCount is set */
402} __attribute__((aligned(2), packed));
403typedef struct HFSPlusCatalogFolder HFSPlusCatalogFolder;
404
405/* HFS catalog file record - 102 bytes */
406struct HFSCatalogFile {
407	int16_t 		recordType;		/* == kHFSFileRecord */
408	u_int8_t 		flags;			/* file flags */
409	int8_t 			fileType;		/* file type (unused ?) */
410	FndrFileInfo 		userInfo;		/* Finder information */
411	u_int32_t 		fileID;			/* file ID */
412	u_int16_t 		dataStartBlock;		/* not used - set to zero */
413	int32_t 		dataLogicalSize;	/* logical EOF of data fork */
414	int32_t 		dataPhysicalSize;	/* physical EOF of data fork */
415	u_int16_t		rsrcStartBlock;		/* not used - set to zero */
416	int32_t			rsrcLogicalSize;	/* logical EOF of resource fork */
417	int32_t			rsrcPhysicalSize;	/* physical EOF of resource fork */
418	u_int32_t		createDate;		/* date and time of creation */
419	u_int32_t		modifyDate;		/* date and time of last modification */
420	u_int32_t		backupDate;		/* date and time of last backup */
421	FndrOpaqueInfo		finderInfo;		/* additional Finder information */
422	u_int16_t		clumpSize;		/* file clump size (not used) */
423	HFSExtentRecord		dataExtents;		/* first data fork extent record */
424	HFSExtentRecord		rsrcExtents;		/* first resource fork extent record */
425	u_int32_t		reserved;		/* reserved - initialized as zero */
426} __attribute__((aligned(2), packed));
427typedef struct HFSCatalogFile HFSCatalogFile;
428
429/* HFS Plus catalog file record - 248 bytes */
430struct HFSPlusCatalogFile {
431	int16_t 		recordType;		/* == kHFSPlusFileRecord */
432	u_int16_t 		flags;			/* file flags */
433	u_int32_t 		reserved1;		/* reserved - initialized as zero */
434	u_int32_t 		fileID;			/* file ID */
435	u_int32_t 		createDate;		/* date and time of creation */
436	u_int32_t 		contentModDate;		/* date and time of last content modification */
437	u_int32_t 		attributeModDate;	/* date and time of last attribute modification */
438	u_int32_t 		accessDate;		/* date and time of last access (MacOS X only) */
439	u_int32_t 		backupDate;		/* date and time of last backup */
440	HFSPlusBSDInfo 		bsdInfo;		/* permissions (for MacOS X) */
441	FndrFileInfo 		userInfo;		/* Finder information */
442	FndrOpaqueInfo	 	finderInfo;		/* additional Finder information */
443	u_int32_t 		textEncoding;		/* hint for name conversions */
444	u_int32_t 		reserved2;		/* reserved - initialized as zero */
445
446	/* Note: these start on double long (64 bit) boundary */
447	HFSPlusForkData 	dataFork;		/* size and block data for data fork */
448	HFSPlusForkData 	resourceFork;		/* size and block data for resource fork */
449} __attribute__((aligned(2), packed));
450typedef struct HFSPlusCatalogFile HFSPlusCatalogFile;
451
452/* HFS catalog thread record - 46 bytes */
453struct HFSCatalogThread {
454	int16_t 	recordType;		/* == kHFSFolderThreadRecord or kHFSFileThreadRecord */
455	int32_t 	reserved[2];		/* reserved - initialized as zero */
456	u_int32_t 	parentID;		/* parent ID for this catalog node */
457	u_int8_t 	nodeName[kHFSMaxFileNameChars + 1]; /* name of this catalog node */
458} __attribute__((aligned(2), packed));
459typedef struct HFSCatalogThread HFSCatalogThread;
460
461/* HFS Plus catalog thread record -- 264 bytes */
462struct HFSPlusCatalogThread {
463	int16_t 	recordType;		/* == kHFSPlusFolderThreadRecord or kHFSPlusFileThreadRecord */
464	int16_t 	reserved;		/* reserved - initialized as zero */
465	u_int32_t 	parentID;		/* parent ID for this catalog node */
466	HFSUniStr255 	nodeName;		/* name of this catalog node (variable length) */
467} __attribute__((aligned(2), packed));
468typedef struct HFSPlusCatalogThread HFSPlusCatalogThread;
469
470#ifdef __APPLE_API_UNSTABLE
471/*
472 * 	These are the types of records in the attribute B-tree.  The values were
473 * 	chosen so that they wouldn't conflict with the catalog record types.
474 */
475enum {
476	kHFSPlusAttrInlineData	= 0x10,   /* attributes whose data fits in a b-tree node */
477	kHFSPlusAttrForkData	= 0x20,   /* extent based attributes (data lives in extents) */
478	kHFSPlusAttrExtents	= 0x30    /* overflow extents for large attributes */
479};
480
481
482/*
483 *  	HFSPlusAttrForkData
484 * 	For larger attributes, whose value is stored in allocation blocks.
485 * 	If the attribute has more than 8 extents, there will be additional
486 * 	records (of type HFSPlusAttrExtents) for this attribute.
487 */
488struct HFSPlusAttrForkData {
489	u_int32_t 	recordType;		/* == kHFSPlusAttrForkData*/
490	u_int32_t 	reserved;
491	HFSPlusForkData theFork;		/* size and first extents of value*/
492} __attribute__((aligned(2), packed));
493typedef struct HFSPlusAttrForkData HFSPlusAttrForkData;
494
495/*
496 * 	HFSPlusAttrExtents
497 * 	This record contains information about overflow extents for large,
498 * 	fragmented attributes.
499 */
500struct HFSPlusAttrExtents {
501	u_int32_t 		recordType;	/* == kHFSPlusAttrExtents*/
502	u_int32_t 		reserved;
503	HFSPlusExtentRecord	extents;	/* additional extents*/
504} __attribute__((aligned(2), packed));
505typedef struct HFSPlusAttrExtents HFSPlusAttrExtents;
506
507/*
508 * Atrributes B-tree Data Record
509 *
510 * For small attributes, whose entire value is stored
511 * within a single B-tree record.
512 */
513struct HFSPlusAttrData {
514	u_int32_t    recordType;   /* == kHFSPlusAttrInlineData */
515	u_int32_t    reserved[2];
516	u_int32_t    attrSize;     /* size of attribute data in bytes */
517	u_int8_t     attrData[2];  /* variable length */
518} __attribute__((aligned(2), packed));
519typedef struct HFSPlusAttrData HFSPlusAttrData;
520
521
522/* HFSPlusAttrInlineData is obsolete use HFSPlusAttrData instead */
523struct HFSPlusAttrInlineData {
524	u_int32_t 	recordType;
525	u_int32_t 	reserved;
526	u_int32_t 	logicalSize;
527	u_int8_t 	userData[2];
528} __attribute__((aligned(2), packed));
529typedef struct HFSPlusAttrInlineData HFSPlusAttrInlineData;
530
531
532/* A generic Attribute Record */
533union HFSPlusAttrRecord {
534	u_int32_t 		recordType;
535	HFSPlusAttrInlineData 	inlineData;   /* NOT USED */
536	HFSPlusAttrData 	attrData;
537	HFSPlusAttrForkData 	forkData;
538	HFSPlusAttrExtents 	overflowExtents;
539};
540typedef union HFSPlusAttrRecord HFSPlusAttrRecord;
541
542/* Attribute key */
543enum { kHFSMaxAttrNameLen = 127 };
544struct HFSPlusAttrKey {
545	u_int16_t     keyLength;       /* key length (in bytes) */
546	u_int16_t     pad;	       /* set to zero */
547	u_int32_t     fileID;          /* file associated with attribute */
548	u_int32_t     startBlock;      /* first allocation block number for extents */
549	u_int16_t     attrNameLen;     /* number of unicode characters */
550	u_int16_t     attrName[kHFSMaxAttrNameLen];   /* attribute name (Unicode) */
551} __attribute__((aligned(2), packed));
552typedef struct HFSPlusAttrKey HFSPlusAttrKey;
553
554#define kHFSPlusAttrKeyMaximumLength   (sizeof(HFSPlusAttrKey) - sizeof(u_int16_t))
555#define kHFSPlusAttrKeyMinimumLength   (kHFSPlusAttrKeyMaximumLength - kHFSMaxAttrNameLen*sizeof(u_int16_t))
556
557#endif /* __APPLE_API_UNSTABLE */
558
559
560/* Key and node lengths */
561enum {
562	kHFSPlusExtentKeyMaximumLength = sizeof(HFSPlusExtentKey) - sizeof(u_int16_t),
563	kHFSExtentKeyMaximumLength	= sizeof(HFSExtentKey) - sizeof(u_int8_t),
564	kHFSPlusCatalogKeyMaximumLength = sizeof(HFSPlusCatalogKey) - sizeof(u_int16_t),
565	kHFSPlusCatalogKeyMinimumLength = kHFSPlusCatalogKeyMaximumLength - sizeof(HFSUniStr255) + sizeof(u_int16_t),
566	kHFSCatalogKeyMaximumLength	= sizeof(HFSCatalogKey) - sizeof(u_int8_t),
567	kHFSCatalogKeyMinimumLength	= kHFSCatalogKeyMaximumLength - (kHFSMaxFileNameChars + 1) + sizeof(u_int8_t),
568	kHFSPlusCatalogMinNodeSize	= 4096,
569	kHFSPlusExtentMinNodeSize	= 512,
570	kHFSPlusAttrMinNodeSize		= 4096
571};
572
573/* HFS and HFS Plus volume attribute bits */
574enum {
575	/* Bits 0-6 are reserved (always cleared by MountVol call) */
576	kHFSVolumeHardwareLockBit	= 7,		/* volume is locked by hardware */
577	kHFSVolumeUnmountedBit		= 8,		/* volume was successfully unmounted */
578	kHFSVolumeSparedBlocksBit	= 9,		/* volume has bad blocks spared */
579	kHFSVolumeNoCacheRequiredBit = 10,		/* don't cache volume blocks (i.e. RAM or ROM disk) */
580	kHFSBootVolumeInconsistentBit = 11,		/* boot volume is inconsistent (System 7.6 and later) */
581	kHFSCatalogNodeIDsReusedBit = 12,
582	kHFSVolumeJournaledBit = 13,			/* this volume has a journal on it */
583	kHFSVolumeInconsistentBit = 14,			/* serious inconsistencies detected at runtime */
584	kHFSVolumeSoftwareLockBit	= 15,		/* volume is locked by software */
585	/*
586	 * HFS only has 16 bits of attributes in the MDB, but HFS Plus has 32 bits.
587	 * Therefore, bits 16-31 can only be used on HFS Plus.
588	 */
589	kHFSUnusedNodeFixBit = 31,				/* Unused nodes in the Catalog B-tree have been zero-filled.  See Radar #6947811. */
590	kHFSContentProtectionBit = 30,			/* Volume has per-file content protection */
591
592	/***  Keep these in sync with the bits above ! ****/
593	kHFSVolumeHardwareLockMask		= 0x00000080,
594	kHFSVolumeUnmountedMask			= 0x00000100,
595	kHFSVolumeSparedBlocksMask		= 0x00000200,
596	kHFSVolumeNoCacheRequiredMask 	= 0x00000400,
597	kHFSBootVolumeInconsistentMask	= 0x00000800,
598	kHFSCatalogNodeIDsReusedMask 	= 0x00001000,
599	kHFSVolumeJournaledMask			= 0x00002000,
600	kHFSVolumeInconsistentMask 		= 0x00004000,
601	kHFSVolumeSoftwareLockMask		= 0x00008000,
602
603	/* Bits 16-31 are allocated from high to low */
604
605	kHFSContentProtectionMask 		= 0x40000000,
606	kHFSUnusedNodeFixMask 			= 0x80000000,
607
608	kHFSMDBAttributesMask			= 0x8380
609};
610
611enum {
612	kHFSUnusedNodesFixDate = 0xc5ef2480		/* March 25, 2009 */
613};
614
615/* HFS Master Directory Block - 162 bytes */
616/* Stored at sector #2 (3rd sector) and second-to-last sector. */
617struct HFSMasterDirectoryBlock {
618	u_int16_t 		drSigWord;	/* == kHFSSigWord */
619	u_int32_t 		drCrDate;	/* date and time of volume creation */
620	u_int32_t 		drLsMod;	/* date and time of last modification */
621	u_int16_t 		drAtrb;		/* volume attributes */
622	u_int16_t 		drNmFls;	/* number of files in root folder */
623	u_int16_t 		drVBMSt;	/* first block of volume bitmap */
624	u_int16_t 		drAllocPtr;	/* start of next allocation search */
625	u_int16_t 		drNmAlBlks;	/* number of allocation blocks in volume */
626	u_int32_t 		drAlBlkSiz;	/* size (in bytes) of allocation blocks */
627	u_int32_t 		drClpSiz;	/* default clump size */
628	u_int16_t 		drAlBlSt;	/* first allocation block in volume */
629	u_int32_t 		drNxtCNID;	/* next unused catalog node ID */
630	u_int16_t 		drFreeBks;	/* number of unused allocation blocks */
631	u_int8_t 		drVN[kHFSMaxVolumeNameChars + 1];  /* volume name */
632	u_int32_t 		drVolBkUp;	/* date and time of last backup */
633	u_int16_t 		drVSeqNum;	/* volume backup sequence number */
634	u_int32_t 		drWrCnt;	/* volume write count */
635	u_int32_t 		drXTClpSiz;	/* clump size for extents overflow file */
636	u_int32_t 		drCTClpSiz;	/* clump size for catalog file */
637	u_int16_t 		drNmRtDirs;	/* number of directories in root folder */
638	u_int32_t 		drFilCnt;	/* number of files in volume */
639	u_int32_t 		drDirCnt;	/* number of directories in volume */
640	u_int32_t 		drFndrInfo[8];	/* information used by the Finder */
641	u_int16_t 		drEmbedSigWord;	/* embedded volume signature (formerly drVCSize) */
642	HFSExtentDescriptor	drEmbedExtent;	/* embedded volume location and size (formerly drVBMCSize and drCtlCSize) */
643	u_int32_t		drXTFlSize;	/* size of extents overflow file */
644	HFSExtentRecord		drXTExtRec;	/* extent record for extents overflow file */
645	u_int32_t 		drCTFlSize;	/* size of catalog file */
646	HFSExtentRecord 	drCTExtRec;	/* extent record for catalog file */
647} __attribute__((aligned(2), packed));
648typedef struct HFSMasterDirectoryBlock	HFSMasterDirectoryBlock;
649
650
651#ifdef __APPLE_API_UNSTABLE
652#define SET_HFS_TEXT_ENCODING(hint)  \
653	(0x656e6300 | ((hint) & 0xff))
654#define GET_HFS_TEXT_ENCODING(hint)  \
655	(((hint) & 0xffffff00) == 0x656e6300 ? (hint) & 0x000000ff : 0xffffffffU)
656#endif /* __APPLE_API_UNSTABLE */
657
658
659/* HFS Plus Volume Header - 512 bytes */
660/* Stored at sector #2 (3rd sector) and second-to-last sector. */
661struct HFSPlusVolumeHeader {
662	u_int16_t 	signature;		/* == kHFSPlusSigWord */
663	u_int16_t 	version;		/* == kHFSPlusVersion */
664	u_int32_t 	attributes;		/* volume attributes */
665	u_int32_t 	lastMountedVersion;	/* implementation version which last mounted volume */
666	u_int32_t 	journalInfoBlock;	/* block addr of journal info (if volume is journaled, zero otherwise) */
667
668	u_int32_t 	createDate;		/* date and time of volume creation */
669	u_int32_t 	modifyDate;		/* date and time of last modification */
670	u_int32_t 	backupDate;		/* date and time of last backup */
671	u_int32_t 	checkedDate;		/* date and time of last disk check */
672
673	u_int32_t 	fileCount;		/* number of files in volume */
674	u_int32_t 	folderCount;		/* number of directories in volume */
675
676	u_int32_t 	blockSize;		/* size (in bytes) of allocation blocks */
677	u_int32_t 	totalBlocks;		/* number of allocation blocks in volume (includes this header and VBM*/
678	u_int32_t 	freeBlocks;		/* number of unused allocation blocks */
679
680	u_int32_t 	nextAllocation;		/* start of next allocation search */
681	u_int32_t 	rsrcClumpSize;		/* default resource fork clump size */
682	u_int32_t 	dataClumpSize;		/* default data fork clump size */
683	u_int32_t 	nextCatalogID;		/* next unused catalog node ID */
684
685	u_int32_t 	writeCount;		/* volume write count */
686	u_int64_t 	encodingsBitmap;	/* which encodings have been use  on this volume */
687
688	u_int8_t 	finderInfo[32];		/* information used by the Finder */
689
690	HFSPlusForkData	 allocationFile;	/* allocation bitmap file */
691	HFSPlusForkData  extentsFile;		/* extents B-tree file */
692	HFSPlusForkData  catalogFile;		/* catalog B-tree file */
693	HFSPlusForkData  attributesFile;	/* extended attributes B-tree file */
694	HFSPlusForkData	 startupFile;		/* boot file (secondary loader) */
695} __attribute__((aligned(2), packed));
696typedef struct HFSPlusVolumeHeader HFSPlusVolumeHeader;
697
698
699/* B-tree structures */
700
701enum BTreeKeyLimits{
702	kMaxKeyLength	= 520
703};
704
705union BTreeKey{
706	u_int8_t	length8;
707	u_int16_t	length16;
708	u_int8_t	rawData [kMaxKeyLength+2];
709};
710typedef union BTreeKey BTreeKey;
711
712/* BTNodeDescriptor -- Every B-tree node starts with these fields. */
713struct BTNodeDescriptor {
714	u_int32_t	fLink;			/* next node at this level*/
715	u_int32_t 	bLink;			/* previous node at this level*/
716	int8_t 		kind;			/* kind of node (leaf, index, header, map)*/
717	u_int8_t 	height;			/* zero for header, map; child is one more than parent*/
718	u_int16_t 	numRecords;		/* number of records in this node*/
719	u_int16_t 	reserved;		/* reserved - initialized as zero */
720} __attribute__((aligned(2), packed));
721typedef struct BTNodeDescriptor BTNodeDescriptor;
722
723/* Constants for BTNodeDescriptor kind */
724enum {
725	kBTLeafNode	= -1,
726	kBTIndexNode	= 0,
727	kBTHeaderNode	= 1,
728	kBTMapNode	= 2
729};
730
731/* BTHeaderRec -- The first record of a B-tree header node */
732struct BTHeaderRec {
733	u_int16_t	treeDepth;		/* maximum height (usually leaf nodes) */
734	u_int32_t 	rootNode;		/* node number of root node */
735	u_int32_t 	leafRecords;		/* number of leaf records in all leaf nodes */
736	u_int32_t 	firstLeafNode;		/* node number of first leaf node */
737	u_int32_t 	lastLeafNode;		/* node number of last leaf node */
738	u_int16_t 	nodeSize;		/* size of a node, in bytes */
739	u_int16_t 	maxKeyLength;		/* reserved */
740	u_int32_t 	totalNodes;		/* total number of nodes in tree */
741	u_int32_t 	freeNodes;		/* number of unused (free) nodes in tree */
742	u_int16_t 	reserved1;		/* unused */
743	u_int32_t 	clumpSize;		/* reserved */
744	u_int8_t 	btreeType;		/* reserved */
745	u_int8_t 	keyCompareType;		/* Key string Comparison Type */
746	u_int32_t 	attributes;		/* persistent attributes about the tree */
747	u_int32_t 	reserved3[16];		/* reserved */
748} __attribute__((aligned(2), packed));
749typedef struct BTHeaderRec BTHeaderRec;
750
751/* Constants for BTHeaderRec attributes */
752enum {
753	kBTBadCloseMask		 = 0x00000001,	/* reserved */
754	kBTBigKeysMask		 = 0x00000002,	/* key length field is 16 bits */
755	kBTVariableIndexKeysMask = 0x00000004	/* keys in index nodes are variable length */
756};
757
758
759/* Catalog Key Name Comparison Type */
760enum {
761	kHFSCaseFolding   = 0xCF,  /* case folding (case-insensitive) */
762	kHFSBinaryCompare = 0xBC  /* binary compare (case-sensitive) */
763};
764
765#include <uuid/uuid.h>
766
767/* JournalInfoBlock - Structure that describes where our journal lives */
768
769// the original size of the reserved field in the JournalInfoBlock was
770// 32*sizeof(u_int32_t).  To keep the total size of the structure the
771// same we subtract the size of new fields (currently: ext_jnl_uuid and
772// machine_uuid).  If you add additional fields, place them before the
773// reserved field and subtract their size in this macro.
774//
775#define JIB_RESERVED_SIZE  ((32*sizeof(u_int32_t)) - sizeof(uuid_string_t) - 48)
776
777struct JournalInfoBlock {
778	u_int32_t	flags;
779    	u_int32_t       device_signature[8];  // signature used to locate our device.
780	u_int64_t       offset;               // byte offset to the journal on the device
781	u_int64_t       size;                 // size in bytes of the journal
782	uuid_string_t   ext_jnl_uuid;
783	char            machine_serial_num[48];
784	char    	reserved[JIB_RESERVED_SIZE];
785} __attribute__((aligned(2), packed));
786typedef struct JournalInfoBlock JournalInfoBlock;
787
788enum {
789    kJIJournalInFSMask          = 0x00000001,
790    kJIJournalOnOtherDeviceMask = 0x00000002,
791    kJIJournalNeedInitMask      = 0x00000004
792};
793
794//
795// This the content type uuid for "external journal" GPT
796// partitions.  Each instance of a partition also has a
797// uuid that uniquely identifies that instance.
798//
799#define EXTJNL_CONTENT_TYPE_UUID "4A6F7572-6E61-11AA-AA11-00306543ECAC"
800
801
802#ifdef __cplusplus
803}
804#endif
805
806#endif /* __HFS_FORMAT__ */
807