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) )