342 lines
8.4 KiB
Python
342 lines
8.4 KiB
Python
|
from construct import *
|
||
|
from construct.macros import UBInt64
|
||
|
"""
|
||
|
http://developer.apple.com/library/mac/#technotes/tn/tn1150.html
|
||
|
"""
|
||
|
|
||
|
def getString(obj):
|
||
|
return obj.HFSUniStr255.unicode
|
||
|
|
||
|
S_IFLNK = 0120000
|
||
|
kSymLinkFileType = 0x736C6E6B
|
||
|
kSymLinkCreator = 0x72686170
|
||
|
kHardLinkFileType = 0x686C6E6B
|
||
|
kHFSPlusCreator = 0x6866732B
|
||
|
|
||
|
kHFSCaseFolding = 0xCF
|
||
|
kHFSBinaryCompare = 0xBC
|
||
|
|
||
|
|
||
|
def is_symlink(rec):
|
||
|
return rec.FileInfo.fileCreator == kSymLinkCreator and rec.FileInfo.fileType == kSymLinkFileType
|
||
|
|
||
|
kHFSRootParentID = 1
|
||
|
kHFSRootFolderID = 2
|
||
|
kHFSExtentsFileID = 3
|
||
|
kHFSCatalogFileID = 4
|
||
|
kHFSBadBlockFileID = 5
|
||
|
kHFSAllocationFileID = 6
|
||
|
kHFSStartupFileID = 7
|
||
|
kHFSAttributesFileID = 8
|
||
|
kHFSRepairCatalogFileID = 14
|
||
|
kHFSBogusExtentFileID = 15
|
||
|
kHFSFirstUserCatalogNodeID = 16
|
||
|
|
||
|
kBTLeafNode = -1
|
||
|
kBTIndexNode = 0
|
||
|
kBTHeaderNode = 1
|
||
|
kBTMapNode = 2
|
||
|
|
||
|
kHFSPlusFolderRecord = 0x0001
|
||
|
kHFSPlusFileRecord = 0x0002
|
||
|
kHFSPlusFolderThreadRecord = 0x0003
|
||
|
kHFSPlusFileThreadRecord = 0x0004
|
||
|
|
||
|
kHFSPlusAttrInlineData = 0x10
|
||
|
kHFSPlusAttrForkData = 0x20
|
||
|
kHFSPlusAttrExtents = 0x30
|
||
|
|
||
|
kForkTypeData = 0
|
||
|
kForkTypeRsrc = 0xFF
|
||
|
|
||
|
kHFSVolumeHardwareLockBit = 7
|
||
|
kHFSVolumeUnmountedBit = 8
|
||
|
kHFSVolumeSparedBlocksBit = 9
|
||
|
kHFSVolumeNoCacheRequiredBit = 10
|
||
|
kHFSBootVolumeInconsistentBit = 11
|
||
|
kHFSCatalogNodeIDsReusedBit = 12
|
||
|
kHFSVolumeJournaledBit = 13
|
||
|
kHFSVolumeSoftwareLockBit = 15
|
||
|
|
||
|
DECMPFS_MAGIC = 0x636d7066 #cmpf
|
||
|
|
||
|
HFSPlusExtentDescriptor = Struct("HFSPlusExtentDescriptor",
|
||
|
UBInt32("startBlock"),
|
||
|
UBInt32("blockCount")
|
||
|
)
|
||
|
HFSPlusExtentRecord = Array(8,HFSPlusExtentDescriptor)
|
||
|
|
||
|
HFSPlusForkData = Struct("HFSPlusForkData",
|
||
|
UBInt64("logicalSize"),
|
||
|
UBInt32("clumpSize"),
|
||
|
UBInt32("totalBlocks"),
|
||
|
Array(8, HFSPlusExtentDescriptor)
|
||
|
)
|
||
|
|
||
|
HFSPlusVolumeHeader= Struct("HFSPlusVolumeHeader",
|
||
|
UBInt16("signature"),
|
||
|
UBInt16("version"),
|
||
|
UBInt32("attributes"),
|
||
|
UBInt32("lastMountedVersion"),
|
||
|
UBInt32("journalInfoBlock"),
|
||
|
UBInt32("createDate"),
|
||
|
UBInt32("modifyDate"),
|
||
|
UBInt32("backupDate"),
|
||
|
UBInt32("checkedDate"),
|
||
|
UBInt32("fileCount"),
|
||
|
UBInt32("folderCount"),
|
||
|
UBInt32("blockSize"),
|
||
|
UBInt32("totalBlocks"),
|
||
|
UBInt32("freeBlocks"),
|
||
|
UBInt32("nextAllocation"),
|
||
|
UBInt32("rsrcClumpSize"),
|
||
|
UBInt32("dataClumpSize"),
|
||
|
UBInt32("nextCatalogID"),
|
||
|
UBInt32("writeCount"),
|
||
|
UBInt64("encodingsBitmap"),
|
||
|
|
||
|
Array(8, UBInt32("finderInfo")),
|
||
|
|
||
|
Struct("allocationFile", Embed(HFSPlusForkData)),
|
||
|
Struct("extentsFile", Embed(HFSPlusForkData)),
|
||
|
Struct("catalogFile", Embed(HFSPlusForkData)),
|
||
|
Struct("attributesFile", Embed(HFSPlusForkData)),
|
||
|
Struct("startupFile", Embed(HFSPlusForkData)),
|
||
|
)
|
||
|
|
||
|
BTNodeDescriptor = Struct("BTNodeDescriptor",
|
||
|
UBInt32("fLink"),
|
||
|
UBInt32("bLink"),
|
||
|
SBInt8("kind"),
|
||
|
UBInt8("height"),
|
||
|
UBInt16("numRecords"),
|
||
|
UBInt16("reserved")
|
||
|
)
|
||
|
|
||
|
BTHeaderRec = Struct("BTHeaderRec",
|
||
|
UBInt16("treeDepth"),
|
||
|
UBInt32("rootNode"),
|
||
|
UBInt32("leafRecords"),
|
||
|
UBInt32("firstLeafNode"),
|
||
|
UBInt32("lastLeafNode"),
|
||
|
UBInt16("nodeSize"),
|
||
|
UBInt16("maxKeyLength"),
|
||
|
UBInt32("totalNodes"),
|
||
|
UBInt32("freeNodes"),
|
||
|
UBInt16("reserved1"),
|
||
|
UBInt32("clumpSize"),
|
||
|
UBInt8("btreeType"),
|
||
|
UBInt8("keyCompareType"),
|
||
|
UBInt32("attributes"),
|
||
|
Array(16, UBInt32("reserved3"))
|
||
|
)
|
||
|
|
||
|
HFSUniStr255 = Struct("HFSUniStr255",
|
||
|
UBInt16("length"),
|
||
|
String("unicode", lambda ctx: ctx["length"] * 2, encoding="utf-16-be")
|
||
|
)
|
||
|
|
||
|
HFSPlusAttrKey = Struct("HFSPlusAttrKey",
|
||
|
UBInt16("keyLength"),
|
||
|
UBInt16("pad"),
|
||
|
UBInt32("fileID"),
|
||
|
UBInt32("startBlock"),
|
||
|
HFSUniStr255,
|
||
|
#UBInt32("nodeNumber")
|
||
|
)
|
||
|
|
||
|
HFSPlusAttrData = Struct("HFSPlusAttrData",
|
||
|
UBInt32("recordType"),
|
||
|
Array(2, UBInt32("reserved")),
|
||
|
UBInt32("size"),
|
||
|
MetaField("data", lambda ctx: ctx["size"])
|
||
|
)
|
||
|
|
||
|
HFSPlusCatalogKey = Struct("HFSPlusCatalogKey",
|
||
|
UBInt16("keyLength"),
|
||
|
UBInt32("parentID"),
|
||
|
HFSUniStr255
|
||
|
)
|
||
|
|
||
|
HFSPlusBSDInfo = Struct("HFSPlusBSDInfo",
|
||
|
UBInt32("ownerID"),
|
||
|
UBInt32("groupID"),
|
||
|
UBInt8("adminFlags"),
|
||
|
UBInt8("ownerFlags"),
|
||
|
UBInt16("fileMode"),
|
||
|
UBInt32("union_special")
|
||
|
)
|
||
|
|
||
|
Point = Struct("Point",
|
||
|
SBInt16("v"),
|
||
|
SBInt16("h")
|
||
|
)
|
||
|
Rect = Struct("Rect",
|
||
|
SBInt16("top"),
|
||
|
SBInt16("left"),
|
||
|
SBInt16("bottom"),
|
||
|
SBInt16("right")
|
||
|
)
|
||
|
FileInfo = Struct("FileInfo",
|
||
|
UBInt32("fileType"),
|
||
|
UBInt32("fileCreator"),
|
||
|
UBInt16("finderFlags"),
|
||
|
Point,
|
||
|
UBInt16("reservedField")
|
||
|
)
|
||
|
ExtendedFileInfo = Struct("ExtendedFileInfo",
|
||
|
Array(4, SBInt16("reserved1")),
|
||
|
UBInt16("extendedFinderFlags"),
|
||
|
SBInt16("reserved2"),
|
||
|
SBInt32("putAwayFolderID")
|
||
|
)
|
||
|
|
||
|
FolderInfo = Struct("FolderInfo",
|
||
|
Rect,
|
||
|
UBInt16("finderFlags"),
|
||
|
Point,
|
||
|
UBInt16("reservedField")
|
||
|
)
|
||
|
|
||
|
ExtendedFolderInfo = Struct("ExtendedFolderInfo",
|
||
|
Point,
|
||
|
SBInt32("reserved1"),
|
||
|
UBInt16("extendedFinderFlags"),
|
||
|
SBInt16("reserved2"),
|
||
|
SBInt32("putAwayFolderID")
|
||
|
)
|
||
|
|
||
|
HFSPlusCatalogFolder = Struct("HFSPlusCatalogFolder",
|
||
|
UBInt16("flags"),
|
||
|
UBInt32("valence"),
|
||
|
UBInt32("folderID"),
|
||
|
UBInt32("createDate"),
|
||
|
UBInt32("contentModDate"),
|
||
|
UBInt32("attributeModDate"),
|
||
|
UBInt32("accessDate"),
|
||
|
UBInt32("backupDate"),
|
||
|
HFSPlusBSDInfo,
|
||
|
FolderInfo,
|
||
|
ExtendedFolderInfo,
|
||
|
UBInt32("textEncoding"),
|
||
|
UBInt32("reserved")
|
||
|
)
|
||
|
|
||
|
HFSPlusCatalogFile = Struct("HFSPlusCatalogFile",
|
||
|
UBInt16("flags"),
|
||
|
UBInt32("reserved1"),
|
||
|
UBInt32("fileID"),
|
||
|
UBInt32("createDate"),
|
||
|
UBInt32("contentModDate"),
|
||
|
UBInt32("attributeModDate"),
|
||
|
UBInt32("accessDate"),
|
||
|
UBInt32("backupDate"),
|
||
|
HFSPlusBSDInfo,
|
||
|
FileInfo,
|
||
|
ExtendedFileInfo,
|
||
|
UBInt32("textEncoding"),
|
||
|
UBInt32("reserved2"),
|
||
|
Struct("dataFork", Embed(HFSPlusForkData)),
|
||
|
Struct("resourceFork", Embed(HFSPlusForkData))
|
||
|
)
|
||
|
|
||
|
HFSPlusCatalogThread = Struct("HFSPlusCatalogThread",
|
||
|
SBInt16("reserved"),
|
||
|
UBInt32("parentID"),
|
||
|
HFSUniStr255,
|
||
|
)
|
||
|
|
||
|
HFSPlusCatalogData = Struct("HFSPlusCatalogData",
|
||
|
UBInt16("recordType"),
|
||
|
Switch("data", lambda ctx: ctx["recordType"],
|
||
|
{
|
||
|
kHFSPlusFolderRecord : HFSPlusCatalogFolder,
|
||
|
kHFSPlusFileRecord : HFSPlusCatalogFile,
|
||
|
kHFSPlusFolderThreadRecord: HFSPlusCatalogThread,
|
||
|
kHFSPlusFileThreadRecord: HFSPlusCatalogThread
|
||
|
},
|
||
|
default=HFSPlusCatalogFolder #XXX: should not reach
|
||
|
)
|
||
|
)
|
||
|
|
||
|
HFSPlusExtentKey = Struct("HFSPlusExtentKey",
|
||
|
UBInt16("keyLength"),
|
||
|
UBInt8("forkType"),
|
||
|
UBInt8("pad"),
|
||
|
UBInt32("fileID"),
|
||
|
UBInt32("startBlock")
|
||
|
)
|
||
|
|
||
|
HFSPlusDecmpfs = Struct("HFSPlusDecmpfs ",
|
||
|
ULInt32("compression_magic"),
|
||
|
ULInt32("compression_type"),
|
||
|
ULInt64("uncompressed_size"),
|
||
|
)
|
||
|
|
||
|
HFSPlusCmpfRsrcHead = Struct("HFSPlusCmpfRsrcHead",
|
||
|
UBInt32("headerSize"),
|
||
|
UBInt32("totalSize"),
|
||
|
UBInt32("dataSize"),
|
||
|
UBInt32("flags")
|
||
|
)
|
||
|
|
||
|
HFSPlusCmpfRsrcBlock = Struct("HFSPlusCmpfRsrcBlock",
|
||
|
ULInt32("offset"),
|
||
|
ULInt32("size")
|
||
|
)
|
||
|
|
||
|
HFSPlusCmpfRsrcBlockHead = Struct("HFSPlusCmpfRsrcBlockHead",
|
||
|
UBInt32("dataSize"),
|
||
|
ULInt32("numBlocks"),
|
||
|
Array(lambda ctx:ctx["numBlocks"], HFSPlusCmpfRsrcBlock)
|
||
|
)
|
||
|
|
||
|
HFSPlusCmpfEnd = Struct("HFSPlusCmpfEnd",
|
||
|
Array(6, UBInt32("pad")),
|
||
|
UBInt16("unk1"),
|
||
|
UBInt16("unk2"),
|
||
|
UBInt16("unk3"),
|
||
|
UBInt32("magic"),
|
||
|
UBInt32("flags"),
|
||
|
UBInt64("size"),
|
||
|
UBInt32("unk4")
|
||
|
)
|
||
|
|
||
|
|
||
|
"""
|
||
|
Journal stuff
|
||
|
"""
|
||
|
JournalInfoBlock = Struct("JournalInfoBlock",
|
||
|
UBInt32("flags"),
|
||
|
Array(8, UBInt32("device_signature")),
|
||
|
UBInt64("offset"),
|
||
|
UBInt64("size"),
|
||
|
Array(32, UBInt32("reserved"))
|
||
|
)
|
||
|
|
||
|
journal_header = Struct("journal_header",
|
||
|
ULInt32("magic"),
|
||
|
ULInt32("endian"),
|
||
|
ULInt64("start"),
|
||
|
ULInt64("end"),
|
||
|
ULInt64("size"),
|
||
|
ULInt32("blhdr_size"),
|
||
|
ULInt32("checksum"),
|
||
|
ULInt32("jhdr_size")
|
||
|
)
|
||
|
|
||
|
block_info = Struct("block_info",
|
||
|
ULInt64("bnum"),
|
||
|
ULInt32("bsize"),
|
||
|
ULInt32("next")
|
||
|
)
|
||
|
|
||
|
block_list_header = Struct("block_list_header",
|
||
|
ULInt16("max_blocks"),
|
||
|
ULInt16("num_blocks"),
|
||
|
ULInt32("bytes_used"),
|
||
|
SLInt32("checksum"),
|
||
|
UBInt32("pad"),
|
||
|
Array(lambda ctx:ctx["num_blocks"], block_info)
|
||
|
)
|