Example #1
0
bool SectorReader::Read(u64 offset, u64 size, u8* out_ptr)
{
	u64 startingBlock = offset / m_blocksize;
	u64 remain = size;

	int positionInBlock = (int)(offset % m_blocksize);
	u64 block = startingBlock;

	while (remain > 0)
	{
		// Check if we are ready to do a large block read. > instead of >= so we don't bother if remain is only one block.
		if (positionInBlock == 0 && remain > (u64)m_blocksize)
		{
			u64 num_blocks = remain / m_blocksize;
			ReadMultipleAlignedBlocks(block, num_blocks, out_ptr);
			block += num_blocks;
			out_ptr += num_blocks * m_blocksize;
			remain -= num_blocks * m_blocksize;
			continue;
		}

		u32 toCopy = m_blocksize - positionInBlock;
		if (toCopy >= remain)
		{
			const u8* data = GetBlockData(block);
			if (!data)
				return false;

			// Yay, we are done!
			memcpy(out_ptr, data + positionInBlock, (size_t)remain);
			return true;
		}
		else
		{
			const u8* data = GetBlockData(block);
			if (!data)
				return false;

			memcpy(out_ptr, data + positionInBlock, toCopy);
			out_ptr += toCopy;
			remain -= toCopy;
			positionInBlock = 0;
			block++;
		}
	}

	return true;
}
Example #2
0
u32 SectorReader::ReadChunk(u8* buffer, u64 chunk_num)
{
  u64 block_num = chunk_num * m_chunk_blocks;
  u32 cnt_blocks = m_chunk_blocks;

  // If we are reading the end of a disk, there may not be enough blocks to
  // read a whole chunk. We need to clamp down in that case.
  u64 end_block = (GetDataSize() + m_block_size - 1) / m_block_size;
  if (end_block)
    cnt_blocks = static_cast<u32>(std::min<u64>(m_chunk_blocks, end_block - block_num));

  if (ReadMultipleAlignedBlocks(block_num, cnt_blocks, buffer))
  {
    if (cnt_blocks < m_chunk_blocks)
    {
      std::fill(buffer + cnt_blocks * m_block_size, buffer + m_chunk_blocks * m_block_size, 0u);
    }
    return cnt_blocks;
  }

  // end_block may be zero on real disks if we fail to get the media size.
  // We have to fallback to probing the disk instead.
  if (!end_block)
  {
    for (u32 i = 0; i < cnt_blocks; ++i)
    {
      if (!GetBlock(block_num + i, buffer))
      {
        std::fill(buffer, buffer + (cnt_blocks - i) * m_block_size, 0u);
        return i;
      }
      buffer += m_block_size;
    }
    return cnt_blocks;
  }
  return 0;
}