#include <stdio.h>
#ifndef __linux__
#include <stdlib.h>
#else
#include <malloc.h>
#endif
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include "hfs_misc.h"
#include "partition_map.h"
#include "convert.h"
#include "errors.h"
#define MDB_OFFSET 2
#define HFS_SIG 0x4244
#define HFS_PLUS_SIG 0x482B
#define get_align_long(x) (*(u32*)(x))
typedef long long u64;
typedef struct ExtDescriptor { u16 xdrStABN; u16 xdrNumABlks; } ext_descriptor;
typedef struct ExtDataRec {
ext_descriptor ed[3]; } ext_data_rec;
struct mdb_record { u16 drSigWord; u16 drCrDate[2]; u16 drLsMod[2]; u16 drAtrb; u16 drNmFls; u16 drVBMSt; u16 drAllocPtr; u16 drNmAlBlks; u32 drAlBlkSiz; u32 drClpSiz; u16 drAlBlSt; u16 drNxtCNID[2]; u16 drFreeBks; char drVN[28]; u16 drVolBkUp[2]; u16 drVSeqNum; u16 drWrCnt[2]; u16 drXTClpSiz[2]; u16 drCTClpSiz[2]; u16 drNmRtDirs; u32 drFilCnt; u32 drDirCnt; u32 drFndrInfo[8]; #ifdef notdef
u16 drVCSize; u16 drVBMCSize; u16 drCtlCSize; #else
u16 drEmbedSigWord; ext_descriptor drEmbedExtent; #endif
u16 drXTFlSize[2]; ext_data_rec drXTExtRec; u16 drCTFlSize[2]; ext_data_rec drCTExtRec; };
typedef u32 HFSCatalogNodeID;
typedef struct HFSPlusExtentDescriptor {
u32 startBlock;
u32 blockCount;
} HFSPlusExtentDescriptor;
typedef HFSPlusExtentDescriptor HFSPlusExtentRecord[ 8];
typedef struct HFSPlusForkData {
u64 logicalSize;
u32 clumpSize;
u32 totalBlocks;
HFSPlusExtentRecord extents;
} HFSPlusForkData;
struct HFSPlusVolumeHeader {
u16 signature;
u16 version;
u32 attributes;
u32 lastMountedVersion;
u32 reserved;
u32 createDate;
u32 modifyDate;
u32 backupDate;
u32 checkedDate;
u32 fileCount;
u32 folderCount;
u32 blockSize;
u32 totalBlocks;
u32 freeBlocks;
u32 nextAllocation;
u32 rsrcClumpSize;
u32 dataClumpSize;
HFSCatalogNodeID nextCatalogID;
u32 writeCount;
u64 encodingsBitmap;
u8 finderInfo[ 32];
HFSPlusForkData allocationFile;
HFSPlusForkData extentsFile;
HFSPlusForkData catalogFile;
HFSPlusForkData attributesFile;
HFSPlusForkData startupFile;
} HFSPlusVolumeHeader;
u32 embeded_offset(struct mdb_record *mdb, u32 sector);
int read_partition_block(partition_map *entry, unsigned long num, char *buf);
u32
embeded_offset(struct mdb_record *mdb, u32 sector)
{
u32 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;
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) {
*kind = kHFS_plus;
} else if (mdb->drSigWord != HFS_SIG) {
*kind = kHFS_not;
} else if (mdb->drEmbedSigWord != HFS_PLUS_SIG) {
*kind = kHFS_std;
len = mdb->drVN[0];
name = (char *) malloc(len+1);
strncpy(name, &mdb->drVN[1], len);
name[len] = 0;
} else {
*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;
}
int
read_partition_block(partition_map *entry, unsigned long num, char *buf)
{
DPME *data;
partition_map_header * map;
u32 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);
}