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