| /* |
| Supports HFS Plus and HFSX file systems with or without an HFS |
| wrapper. |
| |
| Apple technical note 1150 documents the file system: |
| |
| http://developer.apple.com/technotes/tn/tn1150.html |
| |
| Briefly an hfs file system comprises a volume header, an |
| optional journal, and a set of forks. |
| |
| Most fs metadata resides in forks including a block allocation |
| bitmap, a tree storing extents (q.v.) for forks and bad disk |
| blocks, and a tree storing catalog (file and directory) |
| information. |
| |
| An extent comprises a starting block number and block count. |
| The fs maintains a list of k*NEXTENTS extents for each fork. |
| These are used to map fork block numbers to disk block |
| numbers. A fork's initial extents are in its catalog record |
| or (for fs forks) the volume header. The rest are in the |
| extents tree. |
| |
| Fs trees are layed out (in a fork) as an array of fixed-size |
| nodes. A node comprises a header, a sorted list of |
| variable-size records, and trailing record offsets. The |
| records in interior nodes map keys to (child) node numbers. |
| The records in leaf nodes map keys to data. The nodes at each |
| level in a tree are also sorted via (sibling) node numbers |
| stored in each node header. |
| */ |
| |
| typedef struct Extent Extent; |
| typedef struct Fork Fork; |
| typedef struct Inode Inode; |
| typedef struct Tree Tree; |
| typedef struct Node Node; |
| typedef struct Treeref Treeref; |
| typedef struct Key Key; |
| typedef struct Extentkey Extentkey; |
| typedef struct Name Name; |
| typedef struct Catalogkey Catalogkey; |
| typedef struct Hfs Hfs; |
| |
| enum |
| { |
| Hfssig = 0x4244, |
| Hfsplussig = 0x482B, |
| Hfsxsig = 0x4858, |
| Hfsplusmagic = (Hfsplussig<<16)|4, |
| Hfsxmagic = (Hfsxsig<<16)|5, |
| |
| NAMELEN = 255, |
| UTFNAMELEN = NAMELEN*UTFmax, |
| |
| NEXTENTS = 8, |
| |
| Dfork = 0, Rfork = 255, |
| |
| /* fixed cnids */ |
| RootpId = 1, RootId, ExtentsId, CatalogId, |
| BadblockId, AllocId, MinuserId = 16, |
| |
| /* size of a few structures on disk */ |
| Extentlen = 8, /* Extent */ |
| Ndlen = 14, /* Node */ |
| Folderlen = 88, Filelen = 248, /* Inode */ |
| Adlen = 82, /* Apple double header */ |
| Fioff = 50, |
| Filen = 32, /* Finder info */ |
| |
| /* values in Node.type */ |
| LeafNode = -1, IndexNode, HeaderNode, MapNode, |
| |
| /* catalog record types */ |
| Folder = 1, File, FolderThread, FileThread, |
| |
| /* permissions in Inode.mode */ |
| IEXEC = 00100, |
| IWRITE = 0200, |
| IREAD = 0400, |
| ISTXT = 01000, |
| ISGID = 02000, |
| ISUID = 04000, |
| |
| /* type in Inode.mode */ |
| IFMT = 0170000, |
| IFIFO = 0010000, |
| IFCHR = 0020000, |
| IFDIR = 0040000, |
| IFBLK = 0060000, |
| IFREG = 0100000, |
| IFLNK = 0120000, |
| IFSOCK = 0140000, |
| IFWHT = 0160000, |
| }; |
| |
| struct Extent |
| { |
| u32int start; /* first block in extent */ |
| u32int count; /* number of blocks in extent */ |
| }; |
| |
| struct Fork |
| { |
| u32int cnid; /* catalog node id (in memory only) */ |
| int type; /* Dfork or Rfork (in memory only) */ |
| u64int size; /* size in bytes */ |
| u32int nblocks; |
| Extent extent[NEXTENTS]; /* initial extents */ |
| }; |
| |
| /* |
| * In-core catalog record for a file or folder. |
| */ |
| struct Inode |
| { |
| u32int cnid; |
| u64int fileid; /* in memory only */ |
| u32int mtime; /* modification */ |
| u32int ctime; /* attribute modification */ |
| u32int atime; /* access */ |
| u32int nlink; /* in memory only */ |
| u32int uid; |
| u32int gid; |
| int mode; |
| u32int special; |
| union{ |
| u32int nentries; /* directories */ |
| struct{ /* files */ |
| Fork dfork; |
| Fork rfork; |
| uchar info[Filen]; |
| |
| /* in memory only */ |
| int nhdr; /* 0 or Adlen */ |
| Fork *fork; /* dfork or rfork */ |
| } f; |
| } u; |
| }; |
| |
| struct Tree |
| { |
| int nodesize; /* node size in bytes */ |
| u32int nnodes; /* number of nodes in tree */ |
| u32int root; /* node number of the tree's root */ |
| int height; |
| int maxkeylen; /* maximum key size in bytes */ |
| int indexkeylen; /* 0 or length of index node keys */ |
| int sensitive; /* are key strings case sensitive */ |
| Hfs *fs; |
| Fork *fork; |
| }; |
| |
| struct Node |
| { |
| int type; /* type of this node */ |
| u32int next; /* next related node or 0 */ |
| int nrec; /* number of records in this node */ |
| }; |
| |
| struct Treeref |
| { |
| Tree *tree; |
| u32int cnid; /* tree->fork->cnid, for debugging prints */ |
| |
| Block *block; /* a node in the tree */ |
| u32int nno; |
| Node node; |
| |
| int rno; /* a record in the node */ |
| int klen; |
| uchar *key; |
| int dlen; |
| uchar *data; |
| }; |
| |
| struct Key |
| { |
| int (*_cmp)(uchar *k, int len, int *order, Key *key); |
| void *priv; |
| }; |
| |
| struct Extentkey |
| { |
| u32int cnid; |
| int type; |
| u32int bno; |
| }; |
| |
| struct Name |
| { |
| int len; |
| Rune name[NAMELEN]; /* only len runes on disk */ |
| }; |
| |
| struct Catalogkey |
| { |
| u32int parent; |
| union{ |
| Name name; |
| uchar *b; /* not yet decoded */ |
| } u; |
| }; |
| |
| struct Hfs |
| { |
| u32int blocksize; |
| u32int nblock; |
| u32int nfree; /* for debugging */ |
| int hasbadblocks; |
| Fork alloc; /* block allocation bitmap */ |
| Fork extentsfork; |
| Fork catalogfork; |
| Tree extents; /* Extentkey -> Extent[NEXTENT] */ |
| Tree catalog; /* Catalogkey -> Catalogkey + Inode */ |
| u32int hlinkparent; /* 0 or cnid */ |
| Disk *disk; |
| Fsys *fsys; |
| }; |