Exemplo n.º 1
0
        private Record ReadFragments(Stream stream)
        {
            // Blocks may be padded if size left is less than the header
            int sizeLeft = (int)(BlockSize - stream.Position % BlockSize);

            if (sizeLeft < 7)
            {
                stream.Seek(sizeLeft, SeekOrigin.Current);
            }

            // Header is checksum (4 bytes), length (2 bytes), type (1 byte).
            byte[] header = new byte[4 + 2 + 1];
            if (stream.Read(header, 0, header.Length) != header.Length)
            {
                return(new Record(LogRecordType.BadRecord));
            }

            uint expectedCrc = BitConverter.ToUInt32(header, 0);

            ushort length = BitConverter.ToUInt16(header, 4);

            byte type = header[6];

            if (length > stream.Length - stream.Position)
            {
                throw new Exception("Not enough data in stream to read");
            }

            byte[] data = new byte[length];
            int    read = stream.Read(data, 0, data.Length);

            uint actualCrc = Crc32C.Compute(type);

            actualCrc = Crc32C.Mask(Crc32C.Append(actualCrc, data));

            Record rec = new Record()
            {
                Checksum      = expectedCrc,
                Length        = length,
                LogRecordType = (LogRecordType)type,
                Data          = data
            };

            if (rec.LogRecordType != LogRecordType.Zero && expectedCrc != actualCrc)
            {
                throw new InvalidDataException($"Corrupted data. Failed checksum test. Excpeted {expectedCrc}, but calculated actual {actualCrc}");
            }

            return(rec);
        }
Exemplo n.º 2
0
        private static BlockHandle WriteBlock(Stream stream, BlockCreator blockCreator, bool forceNoCompression = false)
        {
            byte[] dataBlock = blockCreator.Finish();
            if (dataBlock.Length == 0)
            {
                return(null);
            }

            // Compress here

            //byte compressionType = 0; // none

            //byte compressionType = 2; // zlib
            //memStream.WriteByte(0x87);
            //memStream.WriteByte(0x9C);
            byte compressionType = 0;             // none

            if (!forceNoCompression !)
            {
                compressionType      = 4;            // zlib raw
                using var memStream  = new MemoryStream();
                using var compStream = new DeflateStream(memStream, CompressionLevel.Fastest, true);
                compStream.Write(dataBlock);
                compStream.Flush();
                compStream.Close();
                dataBlock = memStream.ToArray();
            }

            uint checkCrc = Crc32C.Compute(dataBlock);

            checkCrc = Crc32C.Mask(Crc32C.Append(checkCrc, compressionType));

            long offset = stream.Position;

            stream.Write(dataBlock);
            stream.WriteByte(compressionType);
            stream.Write(BitConverter.GetBytes(checkCrc));

            stream.Flush();

            return(new BlockHandle((ulong)offset, (ulong)dataBlock.Length));
        }
Exemplo n.º 3
0
 internal static Crc32C Compute(byte[] buffer, int offset, int length) => Crc32C.Compute(buffer, offset, length);
Exemplo n.º 4
0
        private byte[] ReadBlock(Stream stream, ulong length, bool verifyChecksum)
        {
            // File format contains a sequence of blocks where each block has:
            //    block_data: uint8[n]
            //    type: uint8
            //    crc: uint32

            verifyChecksum = verifyChecksum || Database.ParanoidMode;

            var data = new byte[length];

            stream.Seek((long)0, SeekOrigin.Begin);
            stream.Read(data, 0, (int)length);

            byte compressionType = (byte)stream.ReadByte();

            byte[] checksum = new byte[4];
            stream.Read(checksum, 0, checksum.Length);
            uint crc = BitConverter.ToUInt32(checksum);

            if (verifyChecksum)
            {
                uint checkCrc = Crc32C.Compute(data);
                //checkCrc = Crc32C.Mask(Crc32C.Append(checkCrc, new[] { compressionType }));
                checkCrc = Crc32C.Mask(Crc32C.Append(checkCrc, compressionType));

                if (crc != checkCrc)
                {
                    throw new InvalidDataException($"Corrupted data. Failed checksum test. expected={crc}, actual={checkCrc}");
                }
            }

            if (compressionType == 0)
            {
                // uncompressed
            }
            else if (compressionType == 1)
            {
                // Snapp, i can't read that
                throw new NotSupportedException("Can't read snappy compressed data");
            }
            else if (compressionType >= 2)
            {
                using (var dataStream = new MemoryStream(data))
                {
                    if (compressionType == 2)
                    {
                        if (dataStream.ReadByte() != 0x78)
                        {
                            throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0xnn");
                        }
                        dataStream.ReadByte();
                    }

                    using (var defStream2 = new DeflateStream(dataStream, CompressionMode.Decompress))
                    {
                        // Get actual package out of bytes
                        using (var destination = new MemoryStream())
                        {
                            defStream2.CopyTo(destination);
                            data = destination.ToArray();
                        }
                    }
                }
            }

            return(data);
        }