static long GetCatalogEntry(long long * dirIndex, char ** name, long * flags, long * time, FinderInfo * finderInfo, long * infoValid) { long extentSize, nodeSize, curNode, index; void *extent; char *nodeBuf, *testKey, *entry; BTNodeDescriptor *node; 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 = (long) (*dirIndex % nodeSize); curNode = (long) (*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; }
static long ResolvePathToCatalogEntry(char * filePath, long * flags, void * entry, long dirID, long long * dirIndex) { char *restPath; long result, cnt, subFolderID = 0; long long tmpDirIndex; HFSPlusCatalogFile *hfsPlusFile; // Copy the file name to gTempStr cnt = 0; while ((filePath[cnt] != '/') && (filePath[cnt] != '\0')) cnt++; strlcpy(gTempStr, filePath, cnt+1); // Move restPath to the right place. if (filePath[cnt] != '\0') cnt++; restPath = filePath + cnt; // gTempStr is a name in the current Dir. // restPath is the rest of the path if any. result = ReadCatalogEntry(gTempStr, dirID, entry, dirIndex); if (result == -1) { return -1; } GetCatalogEntryInfo(entry, flags, 0, 0, 0); if ((*flags & kFileTypeMask) == kFileTypeDirectory) { if (gIsHFSPlus) subFolderID = SWAP_BE32(((HFSPlusCatalogFolder *)entry)->folderID); else subFolderID = SWAP_BE32(((HFSCatalogFolder *)entry)->folderID); } if ((*flags & kFileTypeMask) == kFileTypeDirectory) result = ResolvePathToCatalogEntry(restPath, flags, entry, subFolderID, dirIndex); if (gIsHFSPlus && ((*flags & kFileTypeMask) == kFileTypeFlat)) { hfsPlusFile = (HFSPlusCatalogFile *)entry; if ((SWAP_BE32(hfsPlusFile->userInfo.fdType) == kHardLinkFileType) && (SWAP_BE32(hfsPlusFile->userInfo.fdCreator) == kHFSPlusCreator)) { #ifdef __i386__ snprintf(gLinkTemp, 64 ,"%s/%s%ld", HFSPLUSMETADATAFOLDER, HFS_INODE_PREFIX, SWAP_BE32(hfsPlusFile->bsdInfo.special.iNodeNum)); #else snprintf(gLinkTemp, sizeof(gLinkTemp),"%s/%s%ld", HFSPLUSMETADATAFOLDER, HFS_INODE_PREFIX, SWAP_BE32(hfsPlusFile->bsdInfo.special.iNodeNum)); #endif result = ResolvePathToCatalogEntry(gLinkTemp, flags, entry, kHFSRootFolderID, &tmpDirIndex); } } return result; }
static long GetCatalogEntry(unsigned long *dirIndex, char **name, long *flags, long *time) { long nodeSize, index; u_int32_t curNode; u_int64_t extentSize; void *extent; char *nodeBuf, *testKey, *entry; BTNodeDescriptor *node; if (gIsHFSPlus) { extent = &gHFSPlus->catalogFile.extents; extentSize = gHFSPlus->catalogFile.logicalSize; } else { extent = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec; extentSize = gHFSMDB->drCTFlSize; } nodeSize = gBTHeaders[kBTreeCatalog]->nodeSize; nodeBuf = (char *)malloc(nodeSize); node = (BTNodeDescriptor *)nodeBuf; index = *dirIndex % nodeSize; curNode = *dirIndex / nodeSize; // Read the BTree node and get the record for index. ReadExtent(extent, extentSize, kHFSCatalogFileID, curNode * (u_int32_t)nodeSize, nodeSize, nodeBuf, 1); GetBTreeRecord(index, nodeBuf, nodeSize, &testKey, &entry); GetCatalogEntryInfo(entry, flags, time); // Get the file name. if (gIsHFSPlus) { utf_encodestr(((HFSPlusCatalogKey *)testKey)->nodeName.unicode, ((HFSPlusCatalogKey *)testKey)->nodeName.length, gTempStr, 256); } else { strncpy(gTempStr, &((HFSCatalogKey *)testKey)->nodeName[1], ((HFSCatalogKey *)testKey)->nodeName[0]); } *name = gTempStr; // Update dirIndex. index++; if (index == node->numRecords) { index = 0; curNode = node->fLink; } *dirIndex = curNode * nodeSize + index; free(nodeBuf); return 0; }
static long ResolvePathToCatalogEntry(char *filePath, long *flags, void *entry, unsigned long dirID, unsigned long *dirIndex) { char *restPath; long result, cnt; unsigned long subFolderID = 0, tmpDirIndex; HFSPlusCatalogFile *hfsPlusFile; // Copy the file name to gTempStr cnt = 0; while ((filePath[cnt] != '\\') && (filePath[cnt] != '\0')) cnt++; strncpy(gTempStr, filePath, cnt); // Move restPath to the right place. if (filePath[cnt] != '\0') cnt++; restPath = filePath + cnt; // gTempStr is a name in the current Dir. // restPath is the rest of the path if any. result = ReadCatalogEntry(gTempStr, dirID, entry, dirIndex); if (result == -1) return -1; GetCatalogEntryInfo(entry, flags, 0); if ((*flags & kFileTypeMask) == kFileTypeDirectory) { if (gIsHFSPlus) subFolderID = ((HFSPlusCatalogFolder *)entry)->folderID; else subFolderID = ((HFSCatalogFolder *)entry)->folderID; } if ((*flags & kFileTypeMask) == kFileTypeDirectory) result = ResolvePathToCatalogEntry(restPath, flags, entry, subFolderID, dirIndex); if (gIsHFSPlus && ((*flags & kFileTypeMask) == kFileTypeFlat)) { hfsPlusFile = (HFSPlusCatalogFile *)entry; if ((hfsPlusFile->userInfo.fdType == kHardLinkFileType) && (hfsPlusFile->userInfo.fdCreator == kHFSPlusCreator)) { sprintf(gLinkTemp, "%s\\%s%d", HFSPLUSMETADATAFOLDER, HFS_INODE_PREFIX, hfsPlusFile->bsdInfo.special.iNodeNum); result = ResolvePathToCatalogEntry(gLinkTemp, flags, entry, kHFSRootFolderID, &tmpDirIndex); } } return result; }