Example #1
0
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;
}
Example #2
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;
}