来源: http://199818.blog.51cto.com/189818/651792
MAC下常用的文件系统有:HFS,HFS+,HFSX。下面来分别介绍其结构
HFS文件系统大概结构:
HFS对地址分配块使用16位数值,分配块的最高限制数量是65536。
组成一个HFS卷需要下面的五个结构:
卷的逻辑块0和1是启动块,它包含了系统启动信息。例如,启动时载入的系统名称和壳(通常是Finder)文件。
逻辑块2包含主目录块(Master Directory Block,简称MDB)。
逻辑块3是卷位图(Volume Bitmap)的启动块,它追踪分配块使用状态。
总目录文件(Catalog File)是一个包含所有文件的记录和储存在卷中目录的B*-tree。
扩展溢出文件(Extent Overflow File)是当最初总目录文件中三个扩展占用后,另外一个包含额外扩展记录的分配块对应信息的B*-tree。
typedef struct HFS_MDB
{
UINT16 drSigWord; /* Signature word indicating fs type */
UINT32 drCrDate; /* fs creation date/time */
UINT32 drLsMod; /* fs modification date/time */
UINT16 drAtrb; /* fs attributes */
UINT16 drNmFls; /* number of files in root directory */
UINT16 drVBMSt; /* location (in 512-byte blocks)
00247 of the
volume bitmap */
UINT16 drAllocPtr; /* location (in allocation blocks)
00249 to begin
next allocation search */
UINT16 drNmAlBlks; /* number of allocation blocks */
UINT32 drAlBlkSiz; /* bytes in an allocation block *///本HFS分配块字节数
UINT32 drClpSiz; /* clumpsize, the number of bytes to
00253 allocate
when extending a file */
UINT16 drAlBlSt; /* location (in 512-byte blocks)第一个分配块起始扇区号
00255 of the
first allocation block */
UINT32 drNxtCNID; /* CNID to assign to the next
00257 file or
directory created */
UINT16 drFreeBks; /* number of free allocation blocks */
char drVN[28]; /* the volume label */
UINT32 drVolBkUp; /* fs backup date/time */
UINT16 drVSeqNum; /* backup sequence number */
UINT32 drWrCnt; /* fs write count */
UINT32 drXTClpSiz; /* clumpsize for the extents B-tree */
UINT32 drCTClpSiz; /* clumpsize for the catalog B-tree 目录文件大小*/
UINT16 drNmRtDirs; /* number of directories in
00266 the root
directory */
UINT32 drFilCnt; /* number of files in the fs */
UINT32 drDirCnt; /* number of directories in the fs */
char drFndrInfo[32]; /* data used by the Finder */
UINT16 drEmbedSigWord; /* embedded volume signature */
hfs_extent drEmbedExtent; /* starting block number (xdrStABN)
00272
and number of allocation blocks
00273
(xdrNumABlks) occupied by embedded
00274
volume */
UINT32 drXTFlSize; /* bytes in the extents B-tree */
hfs_extent_rec drXTExtRec; /* extents B-tree's first 3 extents */
UINT32 drCTFlSize; /* bytes in the catalog B-tree */
hfs_extent_rec drCTExtRec; /* catalog B-tree's first 3 extents */
}HFS_MDB,*PHFS_MDB;
HFS文件结构:
struct hfs_cat_file
{
//s8 type; /* The type of entry */
UINT8 reserved;
UINT8 Flags; /* Flags such as read-only */
signed char Typ; /* file version number = 0 */
struct hfs_finfo UsrWds; /* data used by the Finder */
UINT32 FlNum; /* The CNID */
UINT16 StBlk; /* obsolete */
UINT32 LgLen; /* The logical EOF of the data fork*/
UINT32 PyLen; /* The physical EOF of the data fork */
UINT16 RStBlk; /* obsolete */
UINT32 RLgLen; /* The logical EOF of the rsrc fork */
UINT32 RPyLen; /* The physical EOF of the rsrc fork */
UINT32 CrDat; /* The creation date */
UINT32 MdDat; /* The modified date */
UINT32 BkDat; /* The last backup date */
struct hfs_fxinfo FndrInfo; /* more data for the Finder */
UINT16 ClpSize; /* number of bytes to allocate 198 when extending files */
hfs_extent_rec ExtRec; /* first extent record
200 for the data fork */
hfs_extent_rec RExtRec; /* first extent record
202 for the resource fork */
UINT32 Resrv; /* reserved by Apple */
};
HFS目录结构:
struct hfs_cat_dir
{
//s8 type; /* The type of entry */
UINT8 reserved;
UINT16 Flags; /* flags */
UINT16 Val; /* Valence: number of files and
212 dirs in the directory */
UINT32 DirID; /* The CNID */
UINT32 CrDat; /* The creation date */
UINT32 MdDat; /* The modification date */
UINT32 BkDat; /* The last backup date */
// struct hfs_dinfo UsrInfo; /* data used by the Finder */
// struct hfs_dxinfo FndrInfo; /* more data used by Finder */
// UINT8 Resrv[16]; /* reserved by Apple */
};
HFS+/HFSX文件系统大概结构:
HFS+/HFSX文件系统用32-bit记录分配块的数量,因此,最多可以管理2的32次方个分配块。一般情况下,分配块的大小为4KB。所有的文件结构,包括卷头,都包含在一个或者几个分配块中。这点不同于HFS,HFS中的特殊结构(包括启动块、主目录块和位不属于任何分配块。为了减少文件碎片的产生,HFS+/HFSX在为文件分配存储空间的时候,会尽可能地为其分配一组连续的分配块或块组。块组的大小通常为分配块大小的整数倍,这个值在卷头中说明。
域文件(extend files)在实际存储过程中并不严格遵循这一算法,在卷头和目录记录中记录它的“块组”值并不是必需的,只需要有存储它们的值的空间就可以了。对于非连续存储的文件,Mac OS采用“下一可用分配策略”为其分配存储空间。即当Mac OS接收到文件空间分配请求时,如果首先找到的空闲空间无法满足请求的空间大小,则继续从下一个找到的空闲块开始继续分配,如果这次找到的连续空闲空间足够大,则根据
请求空间的大小分配“块组”大小的整倍数空间给这个文件。HFS+/HFSX文件系统中的卷头非常重要,它记录着索引文件的重要信息。它包括AllocationFile ExtentsOverflowFile CatalogFile AttributesFile StartupFile五个重要的文件信息。catalogfile中记载着文件的b-tree结构,如果我们如要提取其中的一个文件,我们首先得从此b-tree着手。b-tree中的重要结构就是树根和节点结构
卷头结构:
typedef struct HFSPlusVolumeHeader
{
UINT16 signature;//签名
UINT16 version;//版本
UINT32 attributes;
UINT32 lastMountedVersion;
UINT32 journalInfoBlock;//日志信息块
UINT32 createDate;
UINT32 modifyDate;//修改时间
UINT32 backupDate;//备份时间
UINT32 checkedDate;//最后检查时间
UINT32 fileCount;
UINT32 folderCount;
UINT32 blockSize;
UINT32 totalBlocks;//总块数
UINT32 freeBlocks;
UINT32 nextAllocation;//下一分配块号
UINT32 rsrcClumpSize;//资源叉块组大小
UINT32 dataClumpSize;//数据叉块组大小
UINT32 nextCatalogID;//下一目录ID
UINT32 writeCount;
UINT64 encodingsBitmap;//文档编码位图
UINT32 finderInfo[8];
HFSPlusAllocationExtents allocationFile;//分配文件信息(block bitmap)
HFSPlusExtentExtents extentsFile;//域溢出文件信息
HFSPlusCatalogExtents catalogFile;//目录文件信息
HFSPlusAttrExtents attributesFile;//属性文件信息
HFSPlusStartUpExtents startupFile;//启动文件信息
}HFSPlusVolumeHeader,*PHFSPlusVolumeHeader;
下图为卷头的内容:
HFS/HFS+/HFSX文件系统结构中最重要的元文件是目录文件(CatalogFile),我们来看下其结构:
树根结构:
typedef struct HFSPlusHead_Tree{
UINT16 depth;
// equal to height of btree_node_desc
UINT32 root;
// root node of the hierarchy
UINT32 leaf_count;
// number of leaf Records (not nodes)
UINT32 leaf_head;
// first leaf node
UINT32 leaf_tail;
// last leaf node
UINT16 node_size;
// node size of _all_ nodes in this fork
UINT16 max_key_len;
// maximum (or fixed) length of keys in this btree
UINT32 node_count;
// count of all (free and used) nodes in tree
UINT32 free_nodes;
UINT16 reserved1;
UINT32 clump_size;
// ignored my MacOS used by ?
UINT8 btree_type;
// always 0 for HFS+
UINT8 reserved2;
UINT32 attributes;
// see below
UINT32 reserved3[16];
} HFSPlusHead_Tree,*PHFSPlusHead_Tree;
从此结构中,我们可以得到节点的大小,节点的数目,第一个叶节点。我们可以根据节点大小和第一个节点位置来索引所有的节点,并解析出目录结构。
节点的结构如下图:
每个节点前14个字节描述:
typedef struct HFSPlus_Node_Desc{
UINT32 next;
UINT32 prev;
UINT8 kind;
UINT8 height; //tree高度
UINT16 num_rec; //记录数
UINT16 reserved;// 4字节对齐
} HFSPlus_Node_Desc,*PHFSPlus_Node_Desc;
目录结构:
typedef struct HFSPlusCatFolder {
//short int recordType;
UINT16 flags;
UINT32 valence;
UINT32 folderID;
UINT32 createDate;
UINT32 contentModDate;
UINT32 attributeModDate;
UINT32 accessDate;
UINT32 backupDate;
HFSPlus_Perm permissions;
DInfo userInfo;
DXInfo finderInfo;
UINT32 textEncoding;
UINT32 reserved;
}HFSPlusCatFolder,*PHFSPlusCatFolder;
文件结构:
typedef struct HFSPlusCatFile {
//UINT16 recordType;
UINT16 flags;
UINT32 reservedl;
UINT32 fileID;
UINT32 createDate;
UINT32 contentModDate;
UINT32 attributeModDate;
UINT32 accessDate;
UINT32 backupDate;
HFSPlus_Perm permissions;
FInfo userInfo;
FXInfo finderInfo;
UINT32 textEncoding;
UINT32 reserved;
HFSPlusAllocationExtents dataFork;
HFSPlusAllocationExtents resourceFork;
}HFSPlusCatFile,*PHFSPlusCatFile;