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