private hdErr read_block_into_cache(hard_disk_info info, int block) { bool checkCrc = true; mapentry mapEntry = info.map[block]; switch (mapEntry.flags & mapFlags.MAP_ENTRY_FLAG_TYPE_MASK) { case mapFlags.MAP_ENTRY_TYPE_COMPRESSED: { if (mapEntry.BlockCache != null) { Buffer.BlockCopy(mapEntry.BlockCache, 0, cache, 0, (int)info.blocksize); //already checked CRC for this block when the cache was made checkCrc = false; break; } info.file.Seek((long)info.map[block].offset, SeekOrigin.Begin); switch (info.compression) { case HDCOMPRESSION_ZLIB: case HDCOMPRESSION_ZLIB_PLUS: { using (var st = new System.IO.Compression.DeflateStream(info.file, System.IO.Compression.CompressionMode.Decompress, true)) { int bytes = st.Read(cache, 0, (int)info.blocksize); if (bytes != (int)info.blocksize) return hdErr.HDERR_READ_ERROR; if (mapEntry.UseCount > 0) { mapEntry.BlockCache = new byte[bytes]; Buffer.BlockCopy(cache, 0, mapEntry.BlockCache, 0, bytes); } } break; } default: { Console.WriteLine("Unknown compression"); return hdErr.HDERR_DECOMPRESSION_ERROR; } } break; } case mapFlags.MAP_ENTRY_TYPE_UNCOMPRESSED: { info.file.Seek((long)info.map[block].offset, SeekOrigin.Begin); int bytes = info.file.Read(cache, 0, (int)info.blocksize); if (bytes != (int)info.blocksize) return hdErr.HDERR_READ_ERROR; break; } case mapFlags.MAP_ENTRY_TYPE_MINI: { byte[] tmp = BitConverter.GetBytes(info.map[block].offset); for (int i = 0; i < 8; i++) { cache[i] = tmp[7 - i]; } for (int i = 8; i < info.blocksize; i++) { cache[i] = cache[i - 8]; } break; } case mapFlags.MAP_ENTRY_TYPE_SELF_HUNK: { hdErr ret = read_block_into_cache(info, (int)mapEntry.offset); if (ret != hdErr.HDERR_NONE) return ret; // check CRC in the read_block_into_cache call checkCrc = false; break; } default: return hdErr.HDERR_DECOMPRESSION_ERROR; } if (checkCrc && (mapEntry.flags & mapFlags.MAP_ENTRY_FLAG_NO_CRC) == 0) { if (!CRC.VerifyDigest(mapEntry.crc, cache, 0, info.blocksize)) return hdErr.HDERR_DECOMPRESSION_ERROR; } return hdErr.HDERR_NONE; }
private static hdErr read_sector_map(hard_disk_info info) { info.map = new mapentry[info.totalblocks]; info.file.Seek(info.length, SeekOrigin.Begin); using (BinaryReader br = new BinaryReader(info.file, Encoding.UTF8, true)) { if (info.version <= 2) { for (int i = 0; i < info.totalblocks; i++) { UInt64 tmpu = br.ReadUInt64BE(); mapentry me = new mapentry() { offset = (tmpu << 20) >> 20, crc = 0, length = (tmpu >> 44), UseCount = 0 }; me.flags = mapFlags.MAP_ENTRY_FLAG_NO_CRC | ((me.length == info.blocksize) ? mapFlags.MAP_ENTRY_TYPE_UNCOMPRESSED : mapFlags.MAP_ENTRY_TYPE_COMPRESSED); info.map[i] = me; } Dictionary<ulong, int> selfhunkMap = new Dictionary<ulong, int>(); for (int i = 0; i < info.totalblocks; i++) { if (selfhunkMap.TryGetValue(info.map[i].offset, out int index)) { info.map[i].offset = (ulong)index; info.map[i].flags = mapFlags.MAP_ENTRY_FLAG_NO_CRC | mapFlags.MAP_ENTRY_TYPE_SELF_HUNK; } else selfhunkMap.Add(info.map[i].offset, i); } } else { for (int i = 0; i < info.totalblocks; i++) { mapentry me = new mapentry() { offset = br.ReadUInt64BE(), crc = br.ReadUInt32BE(), length = br.ReadUInt16BE(), flags = (mapFlags)br.ReadUInt16BE(), UseCount = 0 }; info.map[i] = me; } } for (int i = 0; i < info.totalblocks; i++) { if ((info.map[i].flags & mapFlags.MAP_ENTRY_FLAG_TYPE_MASK) == mapFlags.MAP_ENTRY_TYPE_SELF_HUNK) { info.map[info.map[i].offset].UseCount += 1; } } } return hdErr.HDERR_NONE; }
public hdErr read_block_into_cache(int block, byte[] cache, ref byte[] crc) { crc = null; mapentry mapEntry = _hd.map[block]; switch (mapEntry.flags & mapFlags.MAP_ENTRY_FLAG_TYPE_MASK) { case mapFlags.MAP_ENTRY_TYPE_COMPRESSED: { if (mapEntry.BlockCache != null) { Buffer.BlockCopy(mapEntry.BlockCache, 0, cache, 0, (int)_hd.blocksize); //already checked CRC for this block when the cache was made break; } _hd.file.Seek((long)_hd.map[block].offset, SeekOrigin.Begin); switch (_hd.compression) { case HDCOMPRESSION_ZLIB: case HDCOMPRESSION_ZLIB_PLUS: { using (var st = new System.IO.Compression.DeflateStream(_hd.file, System.IO.Compression.CompressionMode.Decompress, true)) { int bytes = st.Read(cache, 0, (int)_hd.blocksize); if (bytes != (int)_hd.blocksize) { return(hdErr.HDERR_READ_ERROR); } if (mapEntry.UseCount > 0) { mapEntry.BlockCache = new byte[bytes]; Buffer.BlockCopy(cache, 0, mapEntry.BlockCache, 0, bytes); } } if ((mapEntry.flags & mapFlags.MAP_ENTRY_FLAG_NO_CRC) == 0) { _crc = BitConverter.GetBytes(mapEntry.crc); } break; } default: { Console.WriteLine("Unknown compression"); return(hdErr.HDERR_DECOMPRESSION_ERROR); } } break; } case mapFlags.MAP_ENTRY_TYPE_UNCOMPRESSED: { _hd.file.Seek((long)_hd.map[block].offset, SeekOrigin.Begin); int bytes = _hd.file.Read(cache, 0, (int)_hd.blocksize); if (bytes != (int)_hd.blocksize) { return(hdErr.HDERR_READ_ERROR); } if ((mapEntry.flags & mapFlags.MAP_ENTRY_FLAG_NO_CRC) == 0) { _crc = BitConverter.GetBytes(mapEntry.crc); } break; } case mapFlags.MAP_ENTRY_TYPE_MINI: { byte[] tmp = BitConverter.GetBytes(_hd.map[block].offset); for (int i = 0; i < 8; i++) { cache[i] = tmp[7 - i]; } for (int i = 8; i < _hd.blocksize; i++) { cache[i] = cache[i - 8]; } if ((mapEntry.flags & mapFlags.MAP_ENTRY_FLAG_NO_CRC) == 0) { _crc = BitConverter.GetBytes(mapEntry.crc); } break; } case mapFlags.MAP_ENTRY_TYPE_SELF_HUNK: { hdErr ret = read_block_into_cache((int)mapEntry.offset, cache, ref crc); if (ret != hdErr.HDERR_NONE) { return(ret); } break; } default: return(hdErr.HDERR_DECOMPRESSION_ERROR); } return(hdErr.HDERR_NONE); }