public static void DecompressSparse(Stream input, Stream output) { SparseHeader sparseHeader = SparseHeader.Read(input); if (sparseHeader == null) { throw new ArgumentException("Invalid Sparse Image Format"); } output.Seek(0, SeekOrigin.Begin); for (uint index = 0; index < sparseHeader.TotalChunks; index++) { ChunkHeader chunkHeader = ChunkHeader.Read(input); long dataLength = (long)chunkHeader.ChunkSize * sparseHeader.BlockSize; switch (chunkHeader.ChunkType) { case ChunkType.Raw: { byte[] data = ReadBytes(input, (int)dataLength); ByteWriter.WriteBytes(output, data); break; } case ChunkType.Fill: { byte[] fillBytes = ReadBytes(input, 4); byte[] data = new byte[dataLength]; for (int offset = 0; offset < data.Length; offset += 4) { ByteWriter.WriteBytes(data, offset, fillBytes); } ByteWriter.WriteBytes(output, data); break; } case ChunkType.DontCare: { output.Seek(dataLength, SeekOrigin.Current); break; } case ChunkType.CRC: { byte[] crcBytes = ReadBytes(input, 4); break; } default: { throw new ArgumentException("Error: Invalid Chunk Type"); } } } input.Close(); }
private static void PrintSparseImageStatistics(string path) { FileStream stream; try { stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); } catch (IOException) { Console.WriteLine("Cannot open " + path); return; } catch (UnauthorizedAccessException) { Console.WriteLine("Cannot open {0} - Access Denied", path); return; } SparseHeader sparseHeader = SparseHeader.Read(stream); if (sparseHeader == null) { Console.WriteLine("Invalid Sparse Image Format"); return; } Console.WriteLine("Total Blocks: " + sparseHeader.TotalBlocks); Console.WriteLine("Total Chunks: " + sparseHeader.TotalChunks); long outputSize = 0; for (uint index = 0; index < sparseHeader.TotalChunks; index++) { ChunkHeader chunkHeader = ChunkHeader.Read(stream); Console.Write("Chunk type: {0}, size: {1}, total size: {2}", chunkHeader.ChunkType.ToString(), chunkHeader.ChunkSize, chunkHeader.TotalSize); int dataLength = (int)(chunkHeader.ChunkSize * sparseHeader.BlockSize); switch (chunkHeader.ChunkType) { case ChunkType.Raw: { SparseDecompressionHelper.ReadBytes(stream, dataLength); Console.WriteLine(); outputSize += dataLength; break; } case ChunkType.Fill: { byte[] fillBytes = SparseDecompressionHelper.ReadBytes(stream, 4); uint fill = LittleEndianConverter.ToUInt32(fillBytes, 0); Console.WriteLine(", value: 0x{0}", fill.ToString("X8")); outputSize += dataLength; break; } case ChunkType.DontCare: { Console.WriteLine(); break; } case ChunkType.CRC: { byte[] crcBytes = SparseDecompressionHelper.ReadBytes(stream, 4); uint crc = LittleEndianConverter.ToUInt32(crcBytes, 0); Console.WriteLine(", value: 0x{0}", crc.ToString("X8")); break; } default: { Console.WriteLine(); Console.WriteLine("Error: Invalid Chunk Type"); return; } } } stream.Close(); Console.WriteLine("Output size: {0}", outputSize); }