Blob


1 /*
2 Supports HFS Plus and HFSX file systems with or without an HFS
3 wrapper.
5 Apple technical note 1150 documents the file system:
7 http://developer.apple.com/technotes/tn/tn1150.html
9 Briefly an hfs file system comprises a volume header, an
10 optional journal, and a set of forks.
12 Most fs metadata resides in forks including a block allocation
13 bitmap, a tree storing extents (q.v.) for forks and bad disk
14 blocks, and a tree storing catalog (file and directory)
15 information.
17 An extent comprises a starting block number and block count.
18 The fs maintains a list of k*NEXTENTS extents for each fork.
19 These are used to map fork block numbers to disk block
20 numbers. A fork's initial extents are in its catalog record
21 or (for fs forks) the volume header. The rest are in the
22 extents tree.
24 Fs trees are layed out (in a fork) as an array of fixed-size
25 nodes. A node comprises a header, a sorted list of
26 variable-size records, and trailing record offsets. The
27 records in interior nodes map keys to (child) node numbers.
28 The records in leaf nodes map keys to data. The nodes at each
29 level in a tree are also sorted via (sibling) node numbers
30 stored in each node header.
31 */
33 typedef struct Extent Extent;
34 typedef struct Fork Fork;
35 typedef struct Inode Inode;
36 typedef struct Tree Tree;
37 typedef struct Node Node;
38 typedef struct Treeref Treeref;
39 typedef struct Key Key;
40 typedef struct Extentkey Extentkey;
41 typedef struct Name Name;
42 typedef struct Catalogkey Catalogkey;
43 typedef struct Hfs Hfs;
45 enum
46 {
47 Hfssig = 0x4244,
48 Hfsplussig = 0x482B,
49 Hfsxsig = 0x4858,
50 Hfsplusmagic = (Hfsplussig<<16)|4,
51 Hfsxmagic = (Hfsxsig<<16)|5,
53 NAMELEN = 255,
54 UTFNAMELEN = NAMELEN*UTFmax,
56 NEXTENTS = 8,
58 Dfork = 0, Rfork = 255,
60 /* fixed cnids */
61 RootpId = 1, RootId, ExtentsId, CatalogId,
62 BadblockId, AllocId, MinuserId = 16,
64 /* size of a few structures on disk */
65 Extentlen = 8, /* Extent */
66 Ndlen = 14, /* Node */
67 Folderlen = 88, Filelen = 248, /* Inode */
68 Adlen = 82, /* Apple double header */
69 Fioff = 50,
70 Filen = 32, /* Finder info */
72 /* values in Node.type */
73 LeafNode = -1, IndexNode, HeaderNode, MapNode,
75 /* catalog record types */
76 Folder = 1, File, FolderThread, FileThread,
78 /* some systems have these defined */
79 #undef IEXEC
80 #undef IWRITE
81 #undef IREAD
82 #undef ISVTX
83 #undef ISGID
84 #undef ISUID
85 #undef IFMT
86 #undef IFIFO
87 #undef IFCHR
88 #undef IFDIR
89 #undef IFBLK
90 #undef IFREG
91 #undef IFLNK
92 #undef IFSOCK
93 #undef IFWHT
95 #define IEXEC HFS_IEXEC
96 #define IWRITE HFS_IWRITE
97 #define IREAD HFS_IREAD
98 #define ISVTX HFS_ISVTX
99 #define ISGID HFS_ISGID
100 #define ISUID HFS_ISUID
101 #define IFMT HFS_IFMT
102 #define IFIFO HFS_IFIFO
103 #define IFCHR HFS_IFCHR
104 #define IFDIR HFS_IFDIR
105 #define IFBLK HFS_IFBLK
106 #define IFREG HFS_IFREG
107 #define IFLNK HFS_IFLNK
108 #define IFSOCK HFS_IFSOCK
109 #define IFWHT HFS_IFWHT
111 /* permissions in Inode.mode */
112 IEXEC = 00100,
113 IWRITE = 0200,
114 IREAD = 0400,
115 ISTXT = 01000,
116 ISGID = 02000,
117 ISUID = 04000,
119 /* type in Inode.mode */
120 IFMT = 0170000,
121 IFIFO = 0010000,
122 IFCHR = 0020000,
123 IFDIR = 0040000,
124 IFBLK = 0060000,
125 IFREG = 0100000,
126 IFLNK = 0120000,
127 IFSOCK = 0140000,
128 IFWHT = 0160000,
129 };
131 struct Extent
133 u32int start; /* first block in extent */
134 u32int count; /* number of blocks in extent */
135 };
137 struct Fork
139 u32int cnid; /* catalog node id (in memory only) */
140 int type; /* Dfork or Rfork (in memory only) */
141 u64int size; /* size in bytes */
142 u32int nblocks;
143 Extent extent[NEXTENTS]; /* initial extents */
144 };
146 /*
147 * In-core catalog record for a file or folder.
148 */
149 struct Inode
151 u32int cnid;
152 u64int fileid; /* in memory only */
153 u32int mtime; /* modification */
154 u32int ctime; /* attribute modification */
155 u32int atime; /* access */
156 u32int nlink; /* in memory only */
157 u32int uid;
158 u32int gid;
159 int mode;
160 u32int special;
161 union{
162 u32int nentries; /* directories */
163 struct{ /* files */
164 Fork dfork;
165 Fork rfork;
166 uchar info[Filen];
168 /* in memory only */
169 int nhdr; /* 0 or Adlen */
170 Fork *fork; /* dfork or rfork */
171 } f;
172 } u;
173 };
175 struct Tree
177 int nodesize; /* node size in bytes */
178 u32int nnodes; /* number of nodes in tree */
179 u32int root; /* node number of the tree's root */
180 int height;
181 int maxkeylen; /* maximum key size in bytes */
182 int indexkeylen; /* 0 or length of index node keys */
183 int sensitive; /* are key strings case sensitive */
184 Hfs *fs;
185 Fork *fork;
186 };
188 struct Node
190 int type; /* type of this node */
191 u32int next; /* next related node or 0 */
192 int nrec; /* number of records in this node */
193 };
195 struct Treeref
197 Tree *tree;
198 u32int cnid; /* tree->fork->cnid, for debugging prints */
200 Block *block; /* a node in the tree */
201 u32int nno;
202 Node node;
204 int rno; /* a record in the node */
205 int klen;
206 uchar *key;
207 int dlen;
208 uchar *data;
209 };
211 struct Key
213 int (*_cmp)(uchar *k, int len, int *order, Key *key);
214 void *priv;
215 };
217 struct Extentkey
219 u32int cnid;
220 int type;
221 u32int bno;
222 };
224 struct Name
226 int len;
227 Rune name[NAMELEN]; /* only len runes on disk */
228 };
230 struct Catalogkey
232 u32int parent;
233 union{
234 Name name;
235 uchar *b; /* not yet decoded */
236 } u;
237 };
239 struct Hfs
241 u32int blocksize;
242 u32int nblock;
243 u32int nfree; /* for debugging */
244 int hasbadblocks;
245 Fork alloc; /* block allocation bitmap */
246 Fork extentsfork;
247 Fork catalogfork;
248 Tree extents; /* Extentkey -> Extent[NEXTENT] */
249 Tree catalog; /* Catalogkey -> Catalogkey + Inode */
250 u32int hlinkparent; /* 0 or cnid */
251 Disk *disk;
252 Fsys *fsys;
253 };