Example #1
0
static long ReadFile(void * file, unsigned long * length, void * base, long offset)
{
    void               *extents;
    long               fileID;
    long               fileLength;
    HFSCatalogFile     *hfsFile     = file;
    HFSPlusCatalogFile *hfsPlusFile = file;

    if (gIsHFSPlus) {
        fileID  = SWAP_BE32(hfsPlusFile->fileID);
        fileLength = (long)SWAP_BE64(hfsPlusFile->dataFork.logicalSize);
        extents = &hfsPlusFile->dataFork.extents;
    } else {
        fileID  = SWAP_BE32(hfsFile->fileID);
        fileLength = SWAP_BE32(hfsFile->dataLogicalSize);
        extents = &hfsFile->dataExtents;
    }

    if (offset > fileLength) {
        printf("Offset is too large.\n");
        return -1;
    }

    if ((*length == 0) || ((offset + *length) > fileLength)) {
        *length = fileLength - offset;
    }

    if (*length > kLoadSize) {
        printf("File is too large.\n");
        return -1;
    }

    *length = ReadExtent((char *)extents, fileLength, fileID,
                         offset, *length, (char *)base, 0);

    return 0;
}
Example #2
0
File: hfs.c Project: aosm/BootX
static long ReadFile(void *file, long *length, void *base, long offset)
{
  void               *extents;
  unsigned long      fileID;
  u_int64_t          fileLength;
  HFSCatalogFile     *hfsFile     = file;
  HFSPlusCatalogFile *hfsPlusFile = file;
  
  if (gIsHFSPlus) {
    fileID  = hfsPlusFile->fileID;
    fileLength = hfsPlusFile->dataFork.logicalSize;
    extents = &hfsPlusFile->dataFork.extents;
  } else {
    fileID  = hfsFile->fileID;
    fileLength = hfsFile->dataLogicalSize;
    extents = &hfsFile->dataExtents;
  }
  
  if (offset > fileLength) {
    printf("Offset is too large.\n");
    return -1;
  }
  
  if ((*length == 0) || ((offset + *length) > fileLength)) {
    *length = (long)(fileLength - offset);
  }
  
  if (*length > kLoadSize) {
    printf("File is too large.\n");
    return -1;
  }
  
  *length = ReadExtent(extents, fileLength, fileID,
		       offset, *length, base, 0);
  
  return 0;
}
Example #3
0
static long ReadBTreeEntry(long btree, void * key, char * entry, long * dirIndex)
{
    long             extentSize;
    void             *extent;
    short            extentFile;
    char             *nodeBuf;
    BTNodeDescriptor *node;
    long             nodeSize, result = 0, entrySize = 0;
    long             curNode, index = 0, lowerBound, upperBound;
    char             *testKey, *recordData;

    // Figure out which tree is being looked at.
    if (btree == kBTreeCatalog) {
        if (gIsHFSPlus) {
            extent     = &gHFSPlus->catalogFile.extents;
            extentSize = SWAP_BE64(gHFSPlus->catalogFile.logicalSize);
        } else {
            extent     = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec;
            extentSize = SWAP_BE32(gHFSMDB->drCTFlSize);
        }
        extentFile = kHFSCatalogFileID;
    } else {
        if (gIsHFSPlus) {
            extent     = &gHFSPlus->extentsFile.extents;
            extentSize = SWAP_BE64(gHFSPlus->extentsFile.logicalSize);
        } else {
            extent     = (HFSExtentDescriptor *)&gHFSMDB->drXTExtRec;
            extentSize = SWAP_BE32(gHFSMDB->drXTFlSize);
        }
        extentFile = kHFSExtentsFileID;
    }

    // Read the BTree Header if needed.
    if (gBTHeaders[btree] == 0) {
        ReadExtent(extent, extentSize, extentFile, 0, 256,
                   gBTreeHeaderBuffer + btree * 256, 0);
        gBTHeaders[btree] = (BTHeaderRec *)(gBTreeHeaderBuffer + btree * 256 +
                                            sizeof(BTNodeDescriptor));
        if ((gIsHFSPlus && btree == kBTreeCatalog) &&
            (gBTHeaders[btree]->keyCompareType == kHFSBinaryCompare)) {
          gCaseSensitive = 1;
        }
    }

    curNode  = SWAP_BE32(gBTHeaders[btree]->rootNode);
    nodeSize = SWAP_BE16(gBTHeaders[btree]->nodeSize);
    nodeBuf  = (char *)malloc(nodeSize);
    node     = (BTNodeDescriptor *)nodeBuf;

    while (1) {
        // Read the current node.
        ReadExtent(extent, extentSize, extentFile,
                   curNode * nodeSize, nodeSize, nodeBuf, 1);
    
        // Find the matching key.
        lowerBound = 0;
        upperBound = SWAP_BE16(node->numRecords) - 1;
        while (lowerBound <= upperBound) {
            index = (lowerBound + upperBound) / 2;

            GetBTreeRecord(index, nodeBuf, nodeSize, &testKey, &recordData);

            if (gIsHFSPlus) {
                if (btree == kBTreeCatalog) {
                    result = CompareHFSPlusCatalogKeys(key, testKey);
                } else {
                    result = CompareHFSPlusExtentsKeys(key, testKey);
                }
            } else {
                if (btree == kBTreeCatalog) {
                    result = CompareHFSCatalogKeys(key, testKey);
                } else {
                    result = CompareHFSExtentsKeys(key, testKey);
                }
            }
      
            if (result < 0) upperBound = index - 1;        // search < trial
            else if (result > 0) lowerBound = index + 1;   // search > trial
            else break;                                    // search = trial
        }
    
        if (result < 0) {
            index = upperBound;
            GetBTreeRecord(index, nodeBuf, nodeSize, &testKey, &recordData);
        }
    
        // Found the closest key... Recurse on it if this is an index node.
        if (node->kind == kBTIndexNode) {
            curNode = SWAP_BE32( *((long *)recordData) );
        } else break;
    }
  
    // Return error if the file was not found.
    if (result != 0) { free(nodeBuf); return -1; }

    if (btree == kBTreeCatalog) {
        switch (SWAP_BE16(*(short *)recordData)) {
            case kHFSFolderRecord           : entrySize = 70;  break;
            case kHFSFileRecord             : entrySize = 102; break;
            case kHFSFolderThreadRecord     : entrySize = 46;  break;
            case kHFSFileThreadRecord       : entrySize = 46;  break;
            case kHFSPlusFolderRecord       : entrySize = 88;  break;
            case kHFSPlusFileRecord         : entrySize = 248; break;
            case kHFSPlusFolderThreadRecord : entrySize = 264; break;
            case kHFSPlusFileThreadRecord   : entrySize = 264; break;
        }
    } else {
        if (gIsHFSPlus) entrySize = sizeof(HFSPlusExtentRecord);
        else entrySize = sizeof(HFSExtentRecord);
    }
  
    bcopy(recordData, entry, entrySize);

    // Update dirIndex.
    if (dirIndex != 0) {
        index++;
        if (index == SWAP_BE16(node->numRecords)) {
            index = 0;
            curNode = SWAP_BE32(node->fLink);
        }
        *dirIndex = curNode * nodeSize + index;
    }
  
    free(nodeBuf);
  
    return 0;
}
Example #4
0
long HFSInitPartition(CICell ih)
{
    long extentSize, extentFile, nodeSize;
    void *extent;

    if (ih == gCurrentIH) {
#ifdef __i386__
        CacheInit(ih, gCacheBlockSize);
#endif
        return 0;
    }

#ifdef __i386__
    if (!gTempStr) gTempStr = (char *)malloc(4096);
    if (!gLinkTemp) gLinkTemp = (char *)malloc(64);
    if (!gBTreeHeaderBuffer) gBTreeHeaderBuffer = (char *)malloc(512);
    if (!gHFSMdbVib) {
        gHFSMdbVib = (char *)malloc(kBlockSize);
        gHFSMDB = (HFSMasterDirectoryBlock *)gHFSMdbVib;
    }
    if (!gHFSPlusHeader) {
        gHFSPlusHeader = (char *)malloc(kBlockSize);
        gHFSPlus = (HFSPlusVolumeHeader *)gHFSPlusHeader;
    }
    if (!gTempStr || !gLinkTemp || !gBTreeHeaderBuffer ||
        !gHFSMdbVib || !gHFSPlusHeader) return -1;
#endif /* __i386__ */

    gAllocationOffset = 0;
    gIsHFSPlus = 0;
    gCaseSensitive = 0;
    gBTHeaders[0] = 0;
    gBTHeaders[1] = 0;

    // Look for the HFS MDB
    Seek(ih, kMDBBaseOffset);
    Read(ih, (long)gHFSMdbVib, kBlockSize);

    if ( SWAP_BE16(gHFSMDB->drSigWord) == kHFSSigWord ) {
        gAllocationOffset = SWAP_BE16(gHFSMDB->drAlBlSt) * kBlockSize;

        // See if it is HFSPlus
        if (SWAP_BE16(gHFSMDB->drEmbedSigWord) != kHFSPlusSigWord) {
            // Normal HFS;
            gCacheBlockSize = gBlockSize = SWAP_BE32(gHFSMDB->drAlBlkSiz);
            CacheInit(ih, gCacheBlockSize);
            gCurrentIH = ih;

            // grab the 64 bit volume ID
            bcopy(&gHFSMDB->drFndrInfo[6], &gVolID, 8);

            // Get the Catalog BTree node size.
            extent     = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec;
            extentSize = SWAP_BE32(gHFSMDB->drCTFlSize);
            extentFile = kHFSCatalogFileID;
            ReadExtent(extent, extentSize, extentFile, 0, 256,
                       gBTreeHeaderBuffer + kBTreeCatalog * 256, 0);

            nodeSize = SWAP_BE16(((BTHeaderRec *)(gBTreeHeaderBuffer + kBTreeCatalog * 256 + 
                                 sizeof(BTNodeDescriptor)))->nodeSize);

            // If the BTree node size is larger than the block size, reset the cache.
            if (nodeSize > gBlockSize) {
                gCacheBlockSize = nodeSize;
                CacheInit(ih, gCacheBlockSize);
            }

            return 0;
        }

        // Calculate the offset to the embeded HFSPlus volume.
        gAllocationOffset += (long long)SWAP_BE16(gHFSMDB->drEmbedExtent.startBlock) *
                                        SWAP_BE32(gHFSMDB->drAlBlkSiz);
    }

    // Look for the HFSPlus Header
    Seek(ih, gAllocationOffset + kMDBBaseOffset);
    Read(ih, (long)gHFSPlusHeader, kBlockSize);

    // Not a HFS+ or HFSX volume.
    if (SWAP_BE16(gHFSPlus->signature) != kHFSPlusSigWord &&
        SWAP_BE16(gHFSPlus->signature) != kHFSXSigWord) {
	verbose("HFS signature was not present.\n");
        gCurrentIH = 0;
	return -1;
    }

    gIsHFSPlus = 1;
    gCacheBlockSize = gBlockSize = SWAP_BE32(gHFSPlus->blockSize);
    CacheInit(ih, gCacheBlockSize);
    gCurrentIH = ih;

    // grab the 64 bit volume ID
    bcopy(&gHFSPlus->finderInfo[24], &gVolID, 8);

    // Get the Catalog BTree node size.
    extent     = &gHFSPlus->catalogFile.extents;
    extentSize = SWAP_BE64(gHFSPlus->catalogFile.logicalSize);
    extentFile = kHFSCatalogFileID;

    ReadExtent(extent, extentSize, extentFile, 0, 256,
               gBTreeHeaderBuffer + kBTreeCatalog * 256, 0);

    nodeSize = SWAP_BE16(((BTHeaderRec *)(gBTreeHeaderBuffer + kBTreeCatalog * 256 +
                         sizeof(BTNodeDescriptor)))->nodeSize);

    // If the BTree node size is larger than the block size, reset the cache.
    if (nodeSize > gBlockSize) {
        gCacheBlockSize = nodeSize;
        CacheInit(ih, gCacheBlockSize);
    }

    return 0;
}
Example #5
0
static long GetCatalogEntry(long long * dirIndex, char ** name, long * flags, u_int32_t * time, FinderInfo * finderInfo, long * infoValid)
{
	u_int64_t         extentSize;
	void              *extent;
	char              *nodeBuf, *testKey, *entry;
	BTNodeDescriptor  *node;
	u_int32_t         curNode;
	u_int16_t         nodeSize, index;

	if (gIsHFSPlus)
	{
		extent     = &gHFSPlus->catalogFile.extents;
		extentSize = SWAP_BE64(gHFSPlus->catalogFile.logicalSize);
	}
	else
	{
		extent     = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec;
		extentSize = SWAP_BE32(gHFSMDB->drCTFlSize);
	}

	nodeSize = SWAP_BE16(gBTHeaders[kBTreeCatalog]->nodeSize);
	nodeBuf  = (char *)malloc(nodeSize);
	node     = (BTNodeDescriptor *)nodeBuf;

	index   = (u_int16_t) (*dirIndex % nodeSize);
	curNode = (u_int32_t) (*dirIndex / nodeSize);

	// Read the BTree node and get the record for index.
	ReadExtent(extent, extentSize, kHFSCatalogFileID, (long long) curNode * nodeSize, nodeSize, nodeBuf, 1);

	GetBTreeRecord(index, nodeBuf, nodeSize, &testKey, &entry);

	GetCatalogEntryInfo(entry, flags, time, finderInfo, infoValid);

	// Get the file name.
	if (gIsHFSPlus)
	{
		utf_encodestr(((HFSPlusCatalogKey *)testKey)->nodeName.unicode,
                      SWAP_BE16(((HFSPlusCatalogKey *)testKey)->nodeName.length),
                      (u_int8_t *)gTempStr, 256, OSBigEndian);
	}
	else
	{
		strncpy(gTempStr, (const char *)&((HFSCatalogKey *)testKey)->nodeName[1], ((HFSCatalogKey *)testKey)->nodeName[0]);

		gTempStr[((HFSCatalogKey *)testKey)->nodeName[0]] = '\0';
	}

	*name = gTempStr;

	// Update dirIndex.
	index++;

	if (index == SWAP_BE16(node->numRecords))
	{
		index = 0;
		curNode = SWAP_BE32(node->fLink);
	}

	*dirIndex = (long long) curNode * nodeSize + index;

	free(nodeBuf);

	return 0;
}
Example #6
0
long HFSInitPartition(CICell ih)
{
  long extentSize, extentFile, nodeSize;
  void *extent;
  
  if (ih == gCurrentIH) return 0;
  
  printf("HFSInitPartition: %x\n", ih);
  
  gAllocationOffset = 0;
  gIsHFSPlus = 0;
  gCaseSensitive = 0;
  gBTHeaders[0] = 0;
  gBTHeaders[1] = 0;
  
  // Look for the HFS MDB
  Seek(ih, kMDBBaseOffset);
  Read(ih, (long)gHFSMdbVib, kBlockSize);
  
  if (gHFSMDB->drSigWord == kHFSSigWord) {
    gAllocationOffset = gHFSMDB->drAlBlSt * kBlockSize;
    
    // See if it is HFSPlus
    if (gHFSMDB->drEmbedSigWord != kHFSPlusSigWord) {
      // Normal HFS;
      gBlockSize = gHFSMDB->drAlBlkSiz;
      CacheInit(ih, gBlockSize);
      gCurrentIH = ih;
      
      // Get the Catalog BTree node size.
      extent     = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec;
      extentSize = gHFSMDB->drCTFlSize;
      extentFile = kHFSCatalogFileID;
      ReadExtent(extent, extentSize, extentFile, 0, 256,
		 gBTreeHeaderBuffer + kBTreeCatalog * 256, 0);
      nodeSize = ((BTHeaderRec *)(gBTreeHeaderBuffer + kBTreeCatalog * 256 + sizeof(BTNodeDescriptor)))->nodeSize;
      
      // If the BTree node size is larger than the block size, reset the cache.
      if (nodeSize > gBlockSize) CacheInit(ih, nodeSize);
      
      return 0;
    }
    
    // Calculate the offset to the embeded HFSPlus volume.
    gAllocationOffset += (long long)gHFSMDB->drEmbedExtent.startBlock * gHFSMDB->drAlBlkSiz;
  }
  
  // Look for the HFSPlus Header
  Seek(ih, gAllocationOffset + kMDBBaseOffset);
  Read(ih, (long)gHFSPlusHeader, kBlockSize);
  
  // Not a HFS[+] volume.
  if ((gHFSPlus->signature != kHFSPlusSigWord) &&
      (gHFSPlus->signature != kHFSXSigWord)) return -1;
  
  gIsHFSPlus = 1;
  gBlockSize = gHFSPlus->blockSize;
  CacheInit(ih, gBlockSize);
  gCurrentIH = ih;
  
  // Get the Catalog BTree node size.
  extent     = &gHFSPlus->catalogFile.extents;
  extentSize = gHFSPlus->catalogFile.logicalSize;
  extentFile = kHFSCatalogFileID;
  ReadExtent(extent, extentSize, extentFile, 0, 256,
	     gBTreeHeaderBuffer + kBTreeCatalog * 256, 0);
  nodeSize = ((BTHeaderRec *)(gBTreeHeaderBuffer + kBTreeCatalog * 256 + sizeof(BTNodeDescriptor)))->nodeSize;
  
  // If the BTree node size is larger than the block size, reset the cache.
  if (nodeSize > gBlockSize) CacheInit(ih, nodeSize);
  
  return 0;
}