void openDisk(const char* path) { int partIndex = -1; std::shared_ptr<HFSVolume> volume; g_fileReader.reset(new FileReader(path)); if (DMGDisk::isDMG(g_fileReader)) g_partitions.reset(new DMGDisk(g_fileReader)); else if (GPTDisk::isGPTDisk(g_fileReader)) g_partitions.reset(new GPTDisk(g_fileReader)); else if (AppleDisk::isAppleDisk(g_fileReader)) g_partitions.reset(new AppleDisk(g_fileReader)); else if (HFSVolume::isHFSPlus(g_fileReader)) volume.reset(new HFSVolume(g_fileReader)); else throw function_not_implemented_error("Unsupported file format"); if (g_partitions) { const std::vector<PartitionedDisk::Partition>& parts = g_partitions->partitions(); for (size_t i = 0; i < parts.size(); i++) { if (parts[i].type == "Apple_HFS" || parts[i].type == "Apple_HFSX") { std::cout << "Using partition #" << i << " of type " << parts[i].type << std::endl; partIndex = i; break; } else std::cerr << "Skipping partition of type " << parts[i].type << std::endl; } if (partIndex == -1) throw function_not_implemented_error("No suitable partition found in file"); volume.reset(new HFSVolume(g_partitions->readerForPartition(partIndex))); } g_volume.reset(new HFSHighLevelVolume(volume)); }
int32_t DMGPartition::readRun(void* buf, int32_t runIndex, uint64_t offsetInSector, int32_t count) { BLKXRun* run = &m_table->runs[runIndex]; RunType runType = RunType(be(run->type)); count = std::min<uint64_t>(count, uint64_t(be(run->sectorCount))*512 - offsetInSector); #ifdef DEBUG std::cout << "readRun(): runIndex = " << runIndex << ", offsetInSector = " << offsetInSector << ", count = " << count << std::endl; #endif switch (runType) { case RunType::Unknown: // My guess is that this value indicates a hole in the file (sparse file) case RunType::ZeroFill: //std::cout << "ZeroFill\n"; memset(buf, 0, count); return count; case RunType::Raw: //std::cout << "Raw\n"; return m_disk->read(buf, count, be(run->compOffset) + be(m_table->dataStart) + offsetInSector); case RunType::LZFSE: #ifndef COMPILE_WITH_LZFSE throw function_not_implemented_error("LZFSE is not yet supported"); #endif case RunType::Zlib: case RunType::Bzip2: case RunType::ADC: { std::unique_ptr<DMGDecompressor> decompressor; std::shared_ptr<Reader> subReader; subReader.reset(new SubReader(m_disk, be(run->compOffset) + be(m_table->dataStart), be(run->compLength))); decompressor.reset(DMGDecompressor::create(runType, subReader)); if (!decompressor) throw std::logic_error("DMGDecompressor::create() returned nullptr!"); unsigned long long int compLength = be(run->sectorCount)*512; if ( offsetInSector > compLength ) return 0; if ( offsetInSector + count > compLength ) count = compLength - offsetInSector; int32_t dec = decompressor->decompress((uint8_t*)buf, count, offsetInSector); if (dec < count) throw io_error("Error decompressing stream"); return count; } default: return 0; } }