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;

本文出自达思数据恢复总工程师,转载请注明出处(达思数据恢复 http://www.bnuol.com)