220 lines
4.8 KiB
C
220 lines
4.8 KiB
C
/*
|
|
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;
|
|
};
|