1// 2// hfs_misc.c - hfs routines 3// 4// Written by Eryk Vershen 5// 6 7/* 8 * Copyright 2000 by Eryk Vershen 9 */ 10 11// for *printf() 12#include <stdio.h> 13 14// for malloc(), calloc() & free() 15#ifndef __linux__ 16#include <stdlib.h> 17#else 18#include <malloc.h> 19#endif 20 21// for strncpy() & strcmp() 22#include <string.h> 23// for O_RDONLY & O_RDWR 24#include <fcntl.h> 25// for errno 26#include <errno.h> 27 28#include "hfs_misc.h" 29#include "partition_map.h" 30#include "convert.h" 31#include "errors.h" 32 33 34// 35// Defines 36// 37#define MDB_OFFSET 2 38#define HFS_SIG 0x4244 /* i.e 'BD' */ 39#define HFS_PLUS_SIG 0x482B /* i.e 'H+' */ 40 41#define get_align_long(x) (*(u32*)(x)) 42 43 44// 45// Types 46// 47typedef long long u64; 48 49typedef struct ExtDescriptor { // extent descriptor 50 u16 xdrStABN; // first allocation block 51 u16 xdrNumABlks; // number of allocation blocks 52} ext_descriptor; 53 54typedef struct ExtDataRec { 55 ext_descriptor ed[3]; // extent data record 56} ext_data_rec; 57 58/* 59 * The crazy "u16 x[2]" stuff here is to get around the fact 60 * that I can't convince the Mac compiler to align on 32 bit 61 * quantities on 16 bit boundaries... 62 */ 63struct mdb_record { // master directory block 64 u16 drSigWord; // volume signature 65 u16 drCrDate[2]; // date and time of volume creation 66 u16 drLsMod[2]; // date and time of last modification 67 u16 drAtrb; // volume attributes 68 u16 drNmFls; // number of files in root directory 69 u16 drVBMSt; // first block of volume bitmap 70 u16 drAllocPtr; // start of next allocation search 71 u16 drNmAlBlks; // number of allocation blocks in volume 72 u32 drAlBlkSiz; // size (in bytes) of allocation blocks 73 u32 drClpSiz; // default clump size 74 u16 drAlBlSt; // first allocation block in volume 75 u16 drNxtCNID[2]; // next unused catalog node ID 76 u16 drFreeBks; // number of unused allocation blocks 77 char drVN[28]; // volume name 78 u16 drVolBkUp[2]; // date and time of last backup 79 u16 drVSeqNum; // volume backup sequence number 80 u16 drWrCnt[2]; // volume write count 81 u16 drXTClpSiz[2]; // clump size for extents overflow file 82 u16 drCTClpSiz[2]; // clump size for catalog file 83 u16 drNmRtDirs; // number of directories in root directory 84 u32 drFilCnt; // number of files in volume 85 u32 drDirCnt; // number of directories in volume 86 u32 drFndrInfo[8]; // information used by the Finder 87#ifdef notdef 88 u16 drVCSize; // size (in blocks) of volume cache 89 u16 drVBMCSize; // size (in blocks) of volume bitmap cache 90 u16 drCtlCSize; // size (in blocks) of common volume cache 91#else 92 u16 drEmbedSigWord; // type of embedded volume 93 ext_descriptor drEmbedExtent; // embedded volume extent 94#endif 95 u16 drXTFlSize[2]; // size of extents overflow file 96 ext_data_rec drXTExtRec; // extent record for extents overflow file 97 u16 drCTFlSize[2]; // size of catalog file 98 ext_data_rec drCTExtRec; // extent record for catalog file 99}; 100 101 102typedef u32 HFSCatalogNodeID; 103 104typedef struct HFSPlusExtentDescriptor { 105 u32 startBlock; 106 u32 blockCount; 107} HFSPlusExtentDescriptor; 108 109typedef HFSPlusExtentDescriptor HFSPlusExtentRecord[ 8]; 110 111typedef struct HFSPlusForkData { 112 u64 logicalSize; 113 u32 clumpSize; 114 u32 totalBlocks; 115 HFSPlusExtentRecord extents; 116} HFSPlusForkData; 117 118struct HFSPlusVolumeHeader { 119 u16 signature; 120 u16 version; 121 u32 attributes; 122 u32 lastMountedVersion; 123 u32 reserved; 124 u32 createDate; 125 u32 modifyDate; 126 u32 backupDate; 127 u32 checkedDate; 128 u32 fileCount; 129 u32 folderCount; 130 u32 blockSize; 131 u32 totalBlocks; 132 u32 freeBlocks; 133 u32 nextAllocation; 134 u32 rsrcClumpSize; 135 u32 dataClumpSize; 136 HFSCatalogNodeID nextCatalogID; 137 u32 writeCount; 138 u64 encodingsBitmap; 139 u8 finderInfo[ 32]; 140 HFSPlusForkData allocationFile; 141 HFSPlusForkData extentsFile; 142 HFSPlusForkData catalogFile; 143 HFSPlusForkData attributesFile; 144 HFSPlusForkData startupFile; 145} HFSPlusVolumeHeader; 146 147 148// 149// Global Constants 150// 151 152 153// 154// Global Variables 155// 156 157 158// 159// Forward declarations 160// 161u32 embeded_offset(struct mdb_record *mdb, u32 sector); 162int read_partition_block(partition_map *entry, unsigned long num, char *buf); 163 164 165// 166// Routines 167// 168u32 169embeded_offset(struct mdb_record *mdb, u32 sector) 170{ 171 u32 e_offset; 172 173 e_offset = mdb->drAlBlSt + mdb->drEmbedExtent.xdrStABN * (mdb->drAlBlkSiz / 512); 174 175 return e_offset + sector; 176} 177 178 179char * 180get_HFS_name(partition_map *entry, int *kind) 181{ 182 DPME *data; 183 struct mdb_record *mdb; 184 //struct HFSPlusVolumeHeader *mdb2; 185 char *name = NULL; 186 int len; 187 188 *kind = kHFS_not; 189 190 mdb = (struct mdb_record *) malloc(PBLOCK_SIZE); 191 if (mdb == NULL) { 192 error(errno, "can't allocate memory for MDB"); 193 return NULL; 194 } 195 196 data = entry->data; 197 if (strcmp(data->dpme_type, kHFSType) == 0) { 198 if (read_partition_block(entry, 2, (char *)mdb) == 0) { 199 error(-1, "Can't read block %d from partition %d", 2, entry->disk_address); 200 goto not_hfs; 201 } 202 if (mdb->drSigWord == HFS_PLUS_SIG) { 203 // pure HFS Plus 204 // printf("%lu HFS Plus\n", entry->disk_address); 205 *kind = kHFS_plus; 206 } else if (mdb->drSigWord != HFS_SIG) { 207 // not HFS !!! 208 // printf("%lu not HFS\n", entry->disk_address); 209 *kind = kHFS_not; 210 } else if (mdb->drEmbedSigWord != HFS_PLUS_SIG) { 211 // HFS 212 // printf("%lu HFS\n", entry->disk_address); 213 *kind = kHFS_std; 214 len = mdb->drVN[0]; 215 name = (char *) malloc(len+1); 216 strncpy(name, &mdb->drVN[1], len); 217 name[len] = 0; 218 } else { 219 // embedded HFS plus 220 // printf("%lu embedded HFS Plus\n", entry->disk_address); 221 *kind = kHFS_embed; 222 len = mdb->drVN[0]; 223 name = (char *) malloc(len+1); 224 strncpy(name, &mdb->drVN[1], len); 225 name[len] = 0; 226 } 227 } 228not_hfs: 229 free(mdb); 230 return name; 231} 232 233// really need a function to read block n from partition m 234 235int 236read_partition_block(partition_map *entry, unsigned long num, char *buf) 237{ 238 DPME *data; 239 partition_map_header * map; 240 u32 base; 241 u64 offset; 242 243 map = entry->the_map; 244 data = entry->data; 245 base = data->dpme_pblock_start; 246 247 if (num >= data->dpme_pblocks) { 248 return 0; 249 } 250 offset = ((long long) base) * map->logical_block + num * 512; 251 252 return read_media(map->m, offset, 512, (void *)buf); 253} 254