Пример #1
0
        /// <summary>
        /// Applies a BSDIFF-format patch to an original and produces the updated version
        /// </summary>
        /// <param name="input">Readable, seekable stream of the original (older) data</param>
        /// <param name="openPatchStream"><see cref="OpenPatchStream"/></param>
        /// <param name="output">Writable stream where the updated data will be written</param>
        public static void Apply(Stream input, OpenPatchStream openPatchStream, Stream output)
        {
            Stream controlStream, diffStream, extraStream;
            var    newSize = CreatePatchStreams(openPatchStream, out controlStream, out diffStream, out extraStream);

            // prepare to read three parts of the patch in parallel
            ApplyInternal(newSize, input, controlStream, diffStream, extraStream, output);
        }
Пример #2
0
        private static long CreatePatchStreams(OpenPatchStream openPatchStream, out Stream ctrl, out Stream diff, out Stream extra)
        {
            // read header
            long controlLength, diffLength, newSize;

            using (var patchStream = openPatchStream(0, BsDiff.HeaderSize))
            {
                // check patch stream capabilities
                if (!patchStream.CanRead)
                {
                    throw new ArgumentException("Patch stream must be readable", nameof(openPatchStream));
                }
                if (!patchStream.CanSeek)
                {
                    throw new ArgumentException("Patch stream must be seekable", nameof(openPatchStream));
                }

                var header = new byte[BsDiff.HeaderSize];
                patchStream.Read(header, 0, BsDiff.HeaderSize);

                // check for appropriate magic
                var signature = header.ReadLong();
                if (signature != BsDiff.Signature)
                {
                    throw new InvalidOperationException("Corrupt patch");
                }

                // read lengths from header
                controlLength = header.ReadLongAt(8);
                diffLength    = header.ReadLongAt(16);
                newSize       = header.ReadLongAt(24);

                if (controlLength < 0 || diffLength < 0 || newSize < 0)
                {
                    throw new InvalidOperationException("Corrupt patch");
                }
            }

            // prepare to read three parts of the patch in parallel
            Stream
                compressedControlStream = openPatchStream(BsDiff.HeaderSize, controlLength),
                compressedDiffStream    = openPatchStream(BsDiff.HeaderSize + controlLength, diffLength),
                compressedExtraStream   = openPatchStream(BsDiff.HeaderSize + controlLength + diffLength, 0);

            // decompress each part (to read it)
            ctrl  = BsDiff.GetEncodingStream(compressedControlStream, false);
            diff  = BsDiff.GetEncodingStream(compressedDiffStream, false);
            extra = BsDiff.GetEncodingStream(compressedExtraStream, false);

            return(newSize);
        }
Пример #3
0
        public static void Apply(Stream input, byte[] diff, Stream output)
        {
            OpenPatchStream openPatchStream = (uOffset, uLength) => {
                var offset = (int)uOffset;
                var length = (int)uLength;
                return(new MemoryStream(diff, offset,
                                        uLength > 0
                        ? length
                        : diff.Length - offset));
            };

            Stream controlStream, diffStream, extraStream;
            var    newSize = CreatePatchStreams(openPatchStream, out controlStream, out diffStream, out extraStream);

            // prepare to read three parts of the patch in parallel
            ApplyInternal(newSize, input, controlStream, diffStream, extraStream, output);
        }