예제 #1
0
 public static void WriteCommonHeader(Signature signature)
 {
     // Writing the initial header
     signature.Output.Write(RDiffBinary.SIGNATURE_MAGIC, 0, RDiffBinary.SIGNATURE_MAGIC.Length);
     signature.Output.Write(RDiffBinary.FixEndian(BitConverter.GetBytes(signature.BlockLength)), 0, 4);
     signature.Output.Write(RDiffBinary.FixEndian(BitConverter.GetBytes(signature.StrongLength)), 0, 4);
 }
예제 #2
0
        /// <summary>
        /// Adds a chunck of data to checksum list
        /// </summary>
        /// <param name="buffer">The data to add a checksum entry for</param>
        /// <param name="index">The index in the buffer to start reading from</param>
        /// <param name="count">The number of bytes to extract from the array</param>
        private static void AddChunk(Signature signature, byte[] buffer, int index, int count)
        {
            //Add weak checksum (Adler-32) to the chunk
            signature.Output.Write(RDiffBinary.FixEndian(BitConverter.GetBytes(Adler32Checksum.Calculate(buffer, index, count))), 0, 4);

            //Add strong checksum
            signature.Output.Write(Utility.Hash.ComputeHash(buffer, index, count), 0, signature.StrongLength);
        }
예제 #3
0
        /// <summary>
        /// Writes a literal command to a delta stream
        /// </summary>
        /// <param name="data">The literal data to write</param>
        /// <param name="output">The output delta stream</param>
        private static void WriteLiteral(byte[] data, DeltaBlock <int> block, Stream output)
        {
            byte[] lengthArray;

            output.WriteByte((byte)RDiffBinary.FindLiteralDeltaCommand(block.Size));
            lengthArray = RDiffBinary.EncodeLength(block.Size);
            output.Write(lengthArray, 0, lengthArray.Length);
            output.Write(data, block.Offset, block.Size);
        }
예제 #4
0
        /// <summary>
        /// Write a copy command to a delta stream
        /// </summary>
        /// <param name="offset">The offset in the basefile where the data is located</param>
        /// <param name="length">The length of the data to copy</param>
        /// <param name="output">The output delta stream</param>
        private static void WriteCopy(DeltaBlock <long> block, Stream output)
        {
            byte[] lengthArray;

            output.WriteByte((byte)RDiffBinary.FindCopyDeltaCommand(block));
            lengthArray = RDiffBinary.EncodeLength(block.Offset);
            output.Write(lengthArray, 0, lengthArray.Length);
            lengthArray = RDiffBinary.EncodeLength(block.Size);
            output.Write(lengthArray, 0, lengthArray.Length);
        }
예제 #5
0
        private int ReadStrongLength(Stream input, byte[] buffer)
        {
            int response;

            Utility.ReadChunk(input, buffer);

            response = BitConverter.ToInt32(RDiffBinary.FixEndian(buffer), 0);

            if (response < 1 || response > (Utility.Hash.HashSize / 8))
            {
                throw new Exception(string.Format(Strings.ChecksumFile.InvalidStrongsizeError, response));
            }

            return(response);
        }
예제 #6
0
        private int ReadBlockLength(Stream input, byte[] buffer)
        {
            int response;

            // Reading block lenght (stram must be in the right position
            Utility.ReadChunk(input, buffer);

            // Getting the block length
            response = BitConverter.ToInt32(RDiffBinary.FixEndian(buffer), 0);

            // Validating the block length
            if (response < 1 || response > int.MaxValue / 2)
            {
                throw new Exception(string.Format(Strings.ChecksumFile.InvalidBlocksizeError, response));
            }

            return(response);
        }
예제 #7
0
        public ChecksumGenerator(Stream inputFileStream)
        {
            byte[] tempBuffer;
            int    byteCounter;

            _signatureByteList = new List <byte>();
            _signatureByteList.AddRange(RDiffBinary.SIGNATURE_MAGIC);
            _signatureByteList.AddRange(RDiffBinary.FixEndian(BitConverter.GetBytes(DEFAULT_BLOCK_SIZE)));
            _signatureByteList.AddRange(RDiffBinary.FixEndian(BitConverter.GetBytes(DEFAULT_STRONG_LEN)));

            tempBuffer = new byte[DEFAULT_BLOCK_SIZE];

            while ((byteCounter = inputFileStream.Read(tempBuffer, 0, tempBuffer.Length)) != 0)
            {
                AddSignatureChunk(tempBuffer, 0, byteCounter);
            }

            _signature = _signatureByteList.ToArray();
        }
예제 #8
0
        /// <summary>
        /// Adds a chunck of data to checksum list
        /// </summary>
        /// <param name="buffer">The data to add a checksum entry for</param>
        /// <param name="index">The index in the buffer to start reading from</param>
        /// <param name="count">The number of bytes to extract from the array</param>
        private void AddSignatureChunk(byte[] buffer, int index, int count)
        {
            byte[] tempBuffer;

            //if (!hashAlgorithm.CanReuseTransform)
            //{
            //    hashAlgorithm = MD5.Create();
            //}

            _signatureByteList.AddRange(
                RDiffBinary.FixEndian(
                    BitConverter.GetBytes(
                        Adler32Checksum.Calculate(buffer, index, count))));

            //Add first half of the computed hash
            tempBuffer = Utility.Hash.ComputeHash(buffer, index, count);

            for (int i = 0; i < DEFAULT_STRONG_LEN; i++)
            {
                _signatureByteList.Add(tempBuffer[i]);
            }
        }
예제 #9
0
        /// <summary>
        /// Reads a ChecksumFile from a stream
        /// </summary>
        /// <param name="input">The stream to read from</param>
        public ChecksumFileReader(Stream input)
        {
            #region Variables

            byte[]       readBuffer;
            int          strongLength;
            long         chunkCount;
            uint         weak;
            byte[]       strongBuffer;
            List <ulong> tempStrongIndex;

            #endregion


            readBuffer = new byte[4];

            Utility.ValidateSignature(input, readBuffer, RDiffBinary.SIGNATURE_MAGIC);

            // Saving the block length for future reference
            _checksumBlockLenght = ReadBlockLength(input, readBuffer);

            /// The number of bytes used for storing a single strong signature
            strongLength = ReadBlockLength(input, readBuffer);

            //Prepare the data structures
            _weakLookup     = new HashSet <uint>(); //new bool[ushort.MaxValue + 1]; //bool[0x10000];
            _longsPerStrong = (strongLength + (BYTES_PER_LONG - 1)) / BYTES_PER_LONG;
            strongBuffer    = new byte[_longsPerStrong * BYTES_PER_LONG];

            //We would like to use static allocation for these lists, but unfortunately
            // the zip stream does not report the correct length
            _weakKeysIndex  = new Dictionary <uint, List <long> >();
            tempStrongIndex = new List <ulong>();

            chunkCount = 0;

            //Repeat until the stream is exhausted
            while (Utility.ForceStreamRead(input, readBuffer, 4) == 4)
            {
                weak = BitConverter.ToUInt32(RDiffBinary.FixEndian(readBuffer), 0);

                if (Utility.ForceStreamRead(input, strongBuffer, strongLength) != strongLength)
                {
                    throw new Exception(Strings.ChecksumFile.EndofstreamInStrongSignatureError);
                }

                // Ensure key existance
                if (!_weakKeysIndex.ContainsKey(weak))
                {
                    _weakKeysIndex.Add(weak, new List <long>());
                }

                //Record the entries
                _weakKeysIndex[weak].Add(chunkCount);

                for (int i = 0; i < _longsPerStrong; i++)
                {
                    tempStrongIndex.Add(BitConverter.ToUInt64(strongBuffer, i * BYTES_PER_LONG));
                }

                chunkCount++;
            }

            // Storing the indexes in permanent arrays
            _strongIndex = tempStrongIndex.ToArray();
        }
예제 #10
0
        /// <summary>
        /// Creates a new file based on the basefile and the delta information.
        /// The basefile and output stream cannot point to the same resource (ea. file).
        /// The base file MUST be seekable.
        /// </summary>
        /// <param name="basefile">A seekable stream with the baseinformation</param>
        /// <param name="output">The stream to write the patched data to. Must not point to the same resource as the basefile.</param>
        public static void PatchFile(Stream basefile, Stream output, Stream deltaFile)
        {
            #region Variables

            byte[] readBuffer;
            int    command;
            int    commandLength;
            byte[] commandBuffer;
            long   chunkSize;
            long   baseFileOffset;

            #endregion

            readBuffer = new byte[4];

            Utility.ValidateSignature(deltaFile, readBuffer, RDiffBinary.DELTA_MAGIC);

            // Reading the first command
            command = deltaFile.ReadByte();

            //Keep reading until we hit the end command
            while (command != RDiffBinary.EndCommand)
            {
                // It is an error to omit the end command
                if (command < 0)
                {
                    throw new Exception(Strings.DeltaFile.EndofstreamWithoutMarkerError);
                }

                if (Enum.IsDefined(typeof(LiteralDeltaCommand), (LiteralDeltaCommand)command))
                {
                    // Find out how many bytes of literal data there is
                    commandLength = RDiffBinary.GetLiteralLength((LiteralDeltaCommand)command);
                    commandBuffer = new byte[commandLength];

                    if (Utility.ForceStreamRead(deltaFile, commandBuffer, commandBuffer.Length) != commandBuffer.Length)
                    {
                        throw new Exception(Strings.DeltaFile.UnexpectedEndofstreamError);
                    }

                    chunkSize = RDiffBinary.DecodeLength(commandBuffer);

                    if (chunkSize < 0)
                    {
                        throw new Exception(Strings.DeltaFile.InvalidLitteralSizeError);
                    }

                    // Copy the literal data from the patch to the output
                    Utility.StreamCopy(deltaFile, output, chunkSize);
                }
                else if (Enum.IsDefined(typeof(CopyDeltaCommand), (CopyDeltaCommand)command))
                {
                    // Find the offset of the data in the base file
                    commandLength = RDiffBinary.GetCopyOffsetSize((CopyDeltaCommand)command);
                    commandBuffer = new byte[commandLength];

                    if (Utility.ForceStreamRead(deltaFile, commandBuffer, commandBuffer.Length) != commandBuffer.Length)
                    {
                        throw new Exception(Strings.DeltaFile.UnexpectedEndofstreamError);
                    }

                    baseFileOffset = RDiffBinary.DecodeLength(commandBuffer);
                    if (baseFileOffset < 0)
                    {
                        throw new Exception(Strings.DeltaFile.InvalidCopyOffsetError);
                    }

                    //Find the length of the data to copy from the basefile
                    commandLength = RDiffBinary.GetCopyLengthSize((CopyDeltaCommand)command);
                    commandBuffer = new byte[commandLength];
                    if (Utility.ForceStreamRead(deltaFile, commandBuffer, commandBuffer.Length) != commandBuffer.Length)
                    {
                        throw new Exception(Strings.DeltaFile.UnexpectedEndofstreamError);
                    }

                    chunkSize = RDiffBinary.DecodeLength(commandBuffer);
                    if (chunkSize < 0)
                    {
                        throw new Exception(Strings.DeltaFile.InvalidCopyLengthError);
                    }

                    //Seek to the begining, and copy
                    basefile.Position = baseFileOffset;
                    Utility.StreamCopy(basefile, output, chunkSize);
                }
                else if (command <= RDiffBinary.LiteralLimit)
                {
                    //Literal data less than 64 bytes are found, copy it
                    Utility.StreamCopy(deltaFile, output, command);
                }
                else
                {
                    throw new Exception(Strings.DeltaFile.UnknownCommandError);
                }

                // Read the next command
                command = deltaFile.ReadByte();
            }

            output.Flush();
        }