void HFSGetDescription(CICell ih, char *str, long strMaxLen) { UInt16 nodeSize; UInt32 firstLeafNode; long dirIndex; char *name; long flags, time; if (HFSInitPartition(ih) == -1) { return; } /* Fill some crucial data structures by side effect. */ dirIndex = 0; HFSGetDirEntry(ih, "/", &dirIndex, &name, &flags, &time, 0, 0); /* Now we can loook up the volume name node. */ nodeSize = SWAP_BE16(gBTHeaders[kBTreeCatalog]->nodeSize); firstLeafNode = SWAP_BE32(gBTHeaders[kBTreeCatalog]->firstLeafNode); dirIndex = firstLeafNode * nodeSize; GetCatalogEntry(&dirIndex, &name, &flags, &time, 0, 0); strncpy(str, name, strMaxLen); str[strMaxLen] = '\0'; }
long HFSGetUUID(CICell ih, char *uuidStr) { if (HFSInitPartition(ih) == -1) return -1; if (gVolID == 0LL) return -1; return CreateUUIDString((uint8_t*)(&gVolID), sizeof(gVolID), uuidStr); }
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; }
long HFSGetDirEntry(CICell ih, char * dirPath, long * dirIndex, char ** name, long * flags, long * time, FinderInfo * finderInfo, long * infoValid) { char entry[512]; long dirID, dirFlags; if (HFSInitPartition(ih) == -1) return -1; if (*dirIndex == -1) return -1; dirID = kHFSRootFolderID; // Skip a lead '\'. Start in the system folder if there are two. if (dirPath[0] == '/') { if (dirPath[1] == '/') { if (gIsHFSPlus) dirID = SWAP_BE32(((long *)gHFSPlus->finderInfo)[5]); else dirID = SWAP_BE32(gHFSMDB->drFndrInfo[5]); if (dirID == 0) return -1; dirPath++; } dirPath++; } if (*dirIndex == 0) { ResolvePathToCatalogEntry(dirPath, &dirFlags, entry, dirID, dirIndex); if (*dirIndex == 0) *dirIndex = -1; if ((dirFlags & kFileTypeMask) != kFileTypeUnknown) return -1; } GetCatalogEntry(dirIndex, name, flags, time, finderInfo, infoValid); if (*dirIndex == 0) *dirIndex = -1; if ((*flags & kFileTypeMask) == kFileTypeUnknown) return -1; return 0; }
long HFSLoadFile(CICell ih, char *filePath) { char entry[512]; long dirID, result, length, flags; if (HFSInitPartition(ih) == -1) return -1; printf("Loading HFS%s file: [%s] from %x.\n", (gIsHFSPlus ? "+" : ""), filePath, ih); dirID = kHFSRootFolderID; // Skip a lead '\'. Start in the system folder if there are two. if (filePath[0] == '\\') { if (filePath[1] == '\\') { if (gIsHFSPlus) dirID = ((long *)gHFSPlus->finderInfo)[5]; else dirID = gHFSMDB->drFndrInfo[5]; if (dirID == 0) return -1; filePath++; } filePath++; } result = ResolvePathToCatalogEntry(filePath, &flags, entry, dirID, 0); if ((result == -1) || ((flags & kFileTypeMask) != kFileTypeFlat)) return -1; // Check file owner and permissions. if (flags & (kOwnerNotRoot | kPermGroupWrite | kPermOtherWrite)) return -1; result = ReadFile(entry, &length); if (result == -1) return -1; return length; }
long HFSReadFile(CICell ih, char * filePath, void *base, uint64_t offset, uint64_t length) { char entry[512]; char devStr[12]; long dirID, result, flags; 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)) { return -1; } #if UNUSED // Not yet for Intel. System.config/Default.table will fail this check. // Check file owner and permissions. if (flags & (kOwnerNotRoot | kPermGroupWrite | kPermOtherWrite)) return -1; #endif result = ReadFile(entry, &length, base, offset); if (result == -1) { return -1; } getDeviceDescription(ih, devStr); /*if (strstr(filePath, ".plist")) verbose("LoadConfig: [%s/%s] %d bytes.\n", devStr, filePath, (uint32_t)length);*/ if (strstr(filePath, "com.apple.Boot.plist")) verbose("Config: [%s/%s] %d bytes.\n", devStr, filePath, (uint32_t)length); if (strstr(filePath, "theme.plist")) { //valv: inspired from toitione's rtrim int t_len = strlen(filePath) - 12; char *themePath = strncpy(malloc(t_len + 1), filePath, t_len); themePath[t_len+1] = '\0'; verbose("Theme: [%s]/%s\n", devStr, themePath); } // if (strstr(filePath, "theme.plist")) verbose("Theme: [%s].\n", devStr); if (strstr(filePath, "smbios.plist")) verbose("SMBios: [%s/%s] %d bytes.\n", devStr, filePath, (uint32_t)length); if (strstr(filePath, ".aml")) verbose("ACPI: [%s/%s] %d bytes.\n", devStr, filePath, (uint32_t)length); return length; }
long HFSReadFile(CICell ih, char * filePath, void *base, uint64_t offset, uint64_t length) { char entry[512]; char devStr[12]; long dirID, result, flags = 0; 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)) { return -1; } #if UNUSED // Not yet for Intel. System.config/Default.table will fail this check. // Check file owner and permissions. if (flags & (kOwnerNotRoot | kPermGroupWrite | kPermOtherWrite)) return -1; #endif result = ReadFile(entry, &length, base, offset); if (result == -1) { return -1; } getDeviceDescription(ih, devStr, sizeof(devStr)); if (get_env(envHFSLoadVerbose)) { verbose("Read HFS%s file: [%s/%s] %d bytes.\n", (gIsHFSPlus ? "+" : ""), devStr, filePath, (uint32_t)length); } else if (get_env(envHFSLoadVerbose) == 0) { safe_set_env(envHFSLoadVerbose, 1); } return length; }
long HFSReadFile(CICell ih, char * filePath, void *base, unsigned long offset, unsigned long length) { char entry[512]; long dirID, result, flags; verbose("Loading HFS%s file: [%s] from %x.\n", (gIsHFSPlus ? "+" : ""), filePath, ih); 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)) { return -1; } #if UNUSED // Not yet for Intel. System.config/Default.table will fail this check. // Check file owner and permissions. if (flags & (kOwnerNotRoot | kPermGroupWrite | kPermOtherWrite)) return -1; #endif result = ReadFile(entry, &length, base, offset); if (result == -1) { return -1; } return length; }
long LookupPartition(char *devSpec) { CICell partIH; long partIndex, partType; long deviceType; // See if the devSpec has already been opened. for (partIndex = 0; partIndex < kNumPartInfos; partIndex++) { if (!strcmp(gParts[partIndex].partName, devSpec)) break; } // If it has not been opened, do so now. if (partIndex == kNumPartInfos) { // Find a free slot. for (partIndex = 0; partIndex < kNumPartInfos; partIndex++) { if (gParts[partIndex].partIH == 0) break; } // No free slots, so return error. if (partIndex == kNumPartInfos) return -1; deviceType = GetDeviceType(devSpec); switch (deviceType) { case kNetworkDeviceType : partIH = NetInitPartition(devSpec); if (partIH == 0) return -1; partType = kPartNet; break; case kBlockDeviceType : printf("Opening partition [%s]...\n", devSpec); partIH = Open(devSpec); if (partIH == 0) { printf("Failed to open partition [%s].\n", devSpec); return -1; } // Find out what kind of partition it is. if (HFSInitPartition(partIH) != -1) partType = kPartHFS; else if (UFSInitPartition(partIH) != -1) partType = kPartUFS; else if (Ext2InitPartition(partIH) != -1) partType = kPartExt2; else return -1; break; default : return -1; } gParts[partIndex].partIH = partIH; gParts[partIndex].partType = partType; strcpy(gParts[partIndex].partName, devSpec); switch (partType) { case kPartNet: gParts[partIndex].loadFile = NetLoadFile; gParts[partIndex].readFile = NULL; gParts[partIndex].getDirEntry = NetGetDirEntry; gParts[partIndex].getUUID = NULL; break; case kPartHFS: gParts[partIndex].loadFile = HFSLoadFile; gParts[partIndex].readFile = HFSReadFile; gParts[partIndex].getDirEntry = HFSGetDirEntry; gParts[partIndex].getUUID = HFSGetUUID; break; case kPartUFS: gParts[partIndex].loadFile = UFSLoadFile; gParts[partIndex].readFile = UFSReadFile; gParts[partIndex].getDirEntry = UFSGetDirEntry; gParts[partIndex].getUUID = UFSGetUUID; break; case kPartExt2: gParts[partIndex].loadFile = Ext2LoadFile; gParts[partIndex].readFile = NULL; gParts[partIndex].getDirEntry = Ext2GetDirEntry; gParts[partIndex].getUUID = NULL; // Ext2GetUUID exists, but there's no kernel support break; } } return partIndex; }