// // hfs_misc.c - hfs routines // // Written by Eryk Vershen // /* * Copyright 2000 by Eryk Vershen */ // for *printf() #include // for malloc(), calloc() & free() #ifndef __linux__ #include #else #include #endif // for strncpy() & strcmp() #include // for O_RDONLY & O_RDWR #include // for errno #include #include #include "hfs_misc.h" #include "partition_map.h" #include "convert.h" #include "errors.h" // // Defines // #define MDB_OFFSET 2 #define HFS_SIG 0x4244 /* i.e 'BD' */ #define HFS_PLUS_SIG 0x482B /* i.e 'H+' */ #define get_align_long(x) (*(uint32_t*)(x)) // // Types // typedef long long u64; typedef struct ExtDescriptor { // extent descriptor uint16_t xdrStABN; // first allocation block uint16_t xdrNumABlks; // number of allocation blocks } ext_descriptor; typedef struct ExtDataRec { ext_descriptor ed[3]; // extent data record } ext_data_rec; /* * The crazy "uint16_t x[2]" stuff here is to get around the fact * that I can't convince the Mac compiler to align on 32 bit * quantities on 16 bit boundaries... */ struct mdb_record { // master directory block uint16_t drSigWord; // volume signature uint16_t drCrDate[2]; // date and time of volume creation uint16_t drLsMod[2]; // date and time of last modification uint16_t drAtrb; // volume attributes uint16_t drNmFls; // number of files in root directory uint16_t drVBMSt; // first block of volume bitmap uint16_t drAllocPtr; // start of next allocation search uint16_t drNmAlBlks; // number of allocation blocks in volume uint32_t drAlBlkSiz; // size (in bytes) of allocation blocks uint32_t drClpSiz; // default clump size uint16_t drAlBlSt; // first allocation block in volume uint16_t drNxtCNID[2]; // next unused catalog node ID uint16_t drFreeBks; // number of unused allocation blocks char drVN[28]; // volume name uint16_t drVolBkUp[2]; // date and time of last backup uint16_t drVSeqNum; // volume backup sequence number uint16_t drWrCnt[2]; // volume write count uint16_t drXTClpSiz[2]; // clump size for extents overflow file uint16_t drCTClpSiz[2]; // clump size for catalog file uint16_t drNmRtDirs; // number of directories in root directory uint32_t drFilCnt; // number of files in volume uint32_t drDirCnt; // number of directories in volume uint32_t drFndrInfo[8]; // information used by the Finder #ifdef notdef uint16_t drVCSize; // size (in blocks) of volume cache uint16_t drVBMCSize; // size (in blocks) of volume bitmap cache uint16_t drCtlCSize; // size (in blocks) of common volume cache #else uint16_t drEmbedSigWord; // type of embedded volume ext_descriptor drEmbedExtent; // embedded volume extent #endif uint16_t drXTFlSize[2]; // size of extents overflow file ext_data_rec drXTExtRec; // extent record for extents overflow file uint16_t drCTFlSize[2]; // size of catalog file ext_data_rec drCTExtRec; // extent record for catalog file }; typedef uint32_t HFSCatalogNodeID; typedef struct HFSPlusExtentDescriptor { uint32_t startBlock; uint32_t blockCount; } HFSPlusExtentDescriptor; typedef HFSPlusExtentDescriptor HFSPlusExtentRecord[ 8]; typedef struct HFSPlusForkData { u64 logicalSize; uint32_t clumpSize; uint32_t totalBlocks; HFSPlusExtentRecord extents; } HFSPlusForkData; struct HFSPlusVolumeHeader { uint16_t signature; uint16_t version; uint32_t attributes; uint32_t lastMountedVersion; uint32_t reserved; uint32_t createDate; uint32_t modifyDate; uint32_t backupDate; uint32_t checkedDate; uint32_t fileCount; uint32_t folderCount; uint32_t blockSize; uint32_t totalBlocks; uint32_t freeBlocks; uint32_t nextAllocation; uint32_t rsrcClumpSize; uint32_t dataClumpSize; HFSCatalogNodeID nextCatalogID; uint32_t writeCount; u64 encodingsBitmap; uint8_t finderInfo[ 32]; HFSPlusForkData allocationFile; HFSPlusForkData extentsFile; HFSPlusForkData catalogFile; HFSPlusForkData attributesFile; HFSPlusForkData startupFile; } HFSPlusVolumeHeader; // // Global Constants // // // Global Variables // // // Forward declarations // uint32_t embeded_offset(struct mdb_record *mdb, uint32_t sector); int read_partition_block(partition_map *entry, uint32_t num, char *buf); // // Routines // uint32_t embeded_offset(struct mdb_record *mdb, uint32_t sector) { uint32_t e_offset; e_offset = mdb->drAlBlSt + mdb->drEmbedExtent.xdrStABN * (mdb->drAlBlkSiz / 512); return e_offset + sector; } char * get_HFS_name(partition_map *entry, int *kind) { DPME *data; struct mdb_record *mdb; //struct HFSPlusVolumeHeader *mdb2; char *name = NULL; int len; *kind = kHFS_not; mdb = (struct mdb_record *) malloc(PBLOCK_SIZE); if (mdb == NULL) { error(errno, "can't allocate memory for MDB"); return NULL; } data = entry->data; if (strcmp(data->dpme_type, kHFSType) == 0) { if (read_partition_block(entry, 2, (char *)mdb) == 0) { error(-1, "Can't read block %d from partition %d", 2, entry->disk_address); goto not_hfs; } if (mdb->drSigWord == HFS_PLUS_SIG) { // pure HFS Plus // printf("%lu HFS Plus\n", entry->disk_address); *kind = kHFS_plus; } else if (mdb->drSigWord != HFS_SIG) { // not HFS !!! // printf("%"PRIu32" not HFS\n", entry->disk_address); *kind = kHFS_not; } else if (mdb->drEmbedSigWord != HFS_PLUS_SIG) { // HFS // printf("%lu HFS\n", entry->disk_address); *kind = kHFS_std; len = mdb->drVN[0]; name = (char *) malloc(len+1); strncpy(name, &mdb->drVN[1], len); name[len] = 0; } else { // embedded HFS plus // printf("%lu embedded HFS Plus\n", entry->disk_address); *kind = kHFS_embed; len = mdb->drVN[0]; name = (char *) malloc(len+1); strncpy(name, &mdb->drVN[1], len); name[len] = 0; } } not_hfs: free(mdb); return name; } // really need a function to read block n from partition m int read_partition_block(partition_map *entry, uint32_t num, char *buf) { DPME *data; partition_map_header * map; uint32_t base; u64 offset; map = entry->the_map; data = entry->data; base = data->dpme_pblock_start; if (num >= data->dpme_pblocks) { return 0; } offset = ((long long) base) * map->logical_block + num * 512; return read_media(map->m, offset, 512, (void *)buf); }