Пример #1
0
        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();
        }
Пример #2
0
        /// <param name="sparseIndex">one-based index</param>
        /// <returns>True if the write was complete (i.e. this was the last sparse)</returns>
        public static bool WriteCompressedSparse(Stream input, Stream output, long maxSparseSize)
        {
            // We will write the header later
            output.Seek(SparseHeader.Length, SeekOrigin.Begin);
            long currentSparseSize = SparseHeader.Length;

            uint chunkCount = 0;

            if (input.Position != 0)
            {
                WriteDontCareChunk(output, (uint)(input.Position / BlockSize));
                chunkCount++;
            }

            MemoryStream rawChunk = new MemoryStream();

            byte[] fill      = null;
            int    fillCount = 0;

            // We keep reading as long as we have a room for an additional chunk
            // (the largest chunk is a raw chunk)
            while (currentSparseSize + ChunkHeader.Length + BlockSize <= maxSparseSize &&
                   input.Position < input.Length)
            {
                byte[] block = new byte[BlockSize];
                input.Read(block, 0, BlockSize);
                byte[] currentFill = SparseCompressionHelper.TryToCompressBlock(block);

                if (fill != null)
                {
                    if (currentFill != null)
                    {
                        if (ByteUtils.AreByteArraysEqual(fill, currentFill))
                        {
                            fillCount++;
                        }
                        else
                        {
                            WriteFillChunk(output, fill, (uint)fillCount);
                            chunkCount++;

                            fillCount          = 1;
                            fill               = currentFill;
                            currentSparseSize += ChunkHeader.Length + 4;
                        }
                    }
                    else
                    {
                        WriteFillChunk(output, fill, (uint)fillCount);
                        chunkCount++;

                        ByteWriter.WriteBytes(rawChunk, block);
                        fill               = null;
                        fillCount          = 0;
                        currentSparseSize += ChunkHeader.Length + BlockSize;
                    }
                }
                else // fill == null
                {
                    if (currentFill != null)
                    {
                        WriteRawChunk(output, rawChunk);
                        chunkCount++;

                        rawChunk           = new MemoryStream();
                        fillCount          = 1;
                        fill               = currentFill;
                        currentSparseSize += ChunkHeader.Length + 4;
                    }
                    else
                    {
                        ByteWriter.WriteBytes(rawChunk, block);
                        currentSparseSize += BlockSize;
                    }
                }
            }

            if (rawChunk.Length > 0)
            {
                WriteRawChunk(output, rawChunk);
                chunkCount++;
            }
            else
            {
                WriteFillChunk(output, fill, (uint)fillCount);
                chunkCount++;
            }

            bool complete = (input.Position == input.Length);

            if (!complete)
            {
                WriteDontCareChunk(output, (uint)((input.Length - input.Position) / BlockSize));
                chunkCount++;
            }

            output.Seek(0, SeekOrigin.Begin);
            SparseHeader sparseHeader = new SparseHeader();

            sparseHeader.BlockSize   = BlockSize;
            sparseHeader.TotalBlocks = (uint)(input.Length / BlockSize);
            sparseHeader.TotalChunks = chunkCount;
            sparseHeader.WriteBytes(output);
            output.Close();

            return(complete);
        }
Пример #3
0
        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);
        }