long HFSGetFileBlock(CICell ih, char *filePath, u_int64_t *firstBlock) { char entry[512]; long result, flags; u_int32_t dirID; void *extents; HFSCatalogFile *hfsFile = (void *)entry; HFSPlusCatalogFile *hfsPlusFile = (void *)entry; if (HFSInitPartition(ih) == -1) { return -1; } dirID = kHFSRootFolderID; // Skip a lead '/'. Start in the system folder if there are two. if (filePath[0] == '/') { if (filePath[1] == '/') { if (gIsHFSPlus) { dirID = SWAP_BE32(((long *) gHFSPlus->finderInfo)[5]); } else { dirID = SWAP_BE32(gHFSMDB->drFndrInfo[5]); } if (dirID == 0) { return -1; } filePath++; } filePath++; } result = ResolvePathToCatalogEntry(filePath, &flags, entry, dirID, 0); if ((result == -1) || ((flags & kFileTypeMask) != kFileTypeFlat)) { printf("HFS: Resolve path %s failed\n", filePath); return -1; } if (gIsHFSPlus) { extents = &hfsPlusFile->dataFork.extents; } else { extents = &hfsFile->dataExtents; } #if DEBUG printf("extent start 0x%x\n", GetExtentStart(extents, 0)); printf("block size 0x%x\n", gBlockSize); printf("Allocation offset 0x%x\n", (unsigned long)gAllocationOffset); #endif *firstBlock = ((u_int64_t) GetExtentStart(extents, 0) * (u_int64_t) gBlockSize + gAllocationOffset) / 512ULL; return 0; }
static long ReadExtent(char * extent, long extentSize, long extentFile, long offset, long size, void * buffer, long cache) { long lastOffset, blockNumber, countedBlocks = 0; long nextExtent = 0, sizeRead = 0, readSize; long nextExtentBlock, currentExtentBlock = 0; long long readOffset; long extentDensity, sizeofExtent, currentExtentSize; char *currentExtent, *extentBuffer = 0, *bufferPos = buffer; if (offset >= extentSize) return 0; if (gIsHFSPlus) { extentDensity = kHFSPlusExtentDensity; sizeofExtent = sizeof(HFSPlusExtentDescriptor); } else { extentDensity = kHFSExtentDensity; sizeofExtent = sizeof(HFSExtentDescriptor); } lastOffset = offset + size; while (offset < lastOffset) { blockNumber = offset / gBlockSize; // Find the extent for the offset. for (; ; nextExtent++) { if (nextExtent < extentDensity) { if ((countedBlocks+GetExtentSize(extent, nextExtent)-1)<blockNumber) { countedBlocks += GetExtentSize(extent, nextExtent); continue; } currentExtent = extent + nextExtent * sizeofExtent; break; } if (extentBuffer == 0) { extentBuffer = malloc(sizeofExtent * extentDensity); if (extentBuffer == 0) return -1; } nextExtentBlock = nextExtent / extentDensity; if (currentExtentBlock != nextExtentBlock) { ReadExtentsEntry(extentFile, countedBlocks, extentBuffer); currentExtentBlock = nextExtentBlock; } currentExtentSize = GetExtentSize(extentBuffer, nextExtent % extentDensity); if ((countedBlocks + currentExtentSize - 1) >= blockNumber) { currentExtent = extentBuffer + sizeofExtent * (nextExtent % extentDensity); break; } countedBlocks += currentExtentSize; } readOffset = ((blockNumber - countedBlocks) * gBlockSize) + (offset % gBlockSize); readSize = GetExtentSize(currentExtent, 0) * gBlockSize - readOffset; if (readSize > (size - sizeRead)) readSize = size - sizeRead; readOffset += (long long)GetExtentStart(currentExtent, 0) * gBlockSize; CacheRead(gCurrentIH, bufferPos, gAllocationOffset + readOffset, readSize, cache); sizeRead += readSize; offset += readSize; bufferPos += readSize; } if (extentBuffer) free(extentBuffer); return sizeRead; }