Пример #1
0
        /// <summary>
        /// Apply a patch to an existing file, and create a new file applies a single patch to one file; if the oldfile does not have the expected checksum:   if there is already a file with the additional extension .orig, then this is compared with
        /// the md5sum of the new file   also the old file is compared with the md5sum of the new file.   if the file is already there, it is copied to ANewFile generally: oldfile is not touched, and there is always a newfile created, either copied
        /// or patched. the orig file is left untouched
        /// </summary>
        public Boolean ApplyPatch(String AOldFile, String ANewFile, String APatchFile)
        {
            TPatchFileInfo   patchFileInfo = null;
            BZip2InputStream bzCtrl        = null;
            BZip2InputStream bzDiff        = null;
            BZip2InputStream bzExtra       = null;
            FileStream       fsCtrl;
            FileStream       fsDiff;
            FileStream       fsExtra;
            FileStream       fsOld;
            FileStream       fsNew;
            BinaryReader     brOld;
            BinaryWriter     bwNew;
            Int32            oldsize;
            FileVersionInfo  ver;
            Int32            i;
            Int32            oldpos;
            Int32            newpos;
            Int32            lenread;

            byte[] buf = new byte[9];

            if (AOldFile.Equals(ANewFile) == true)
            {
                throw new Exception("OldFileName name must be different from NewFileName");
            }

            ReadHeader(APatchFile, out patchFileInfo);

            if ((!CheckMd5Sum(AOldFile, patchFileInfo.OldMd5sum)))
            {
                // see if there is a file with extension .orig
                // we might have given the patched file already, and moved the original file to .orig
                if (System.IO.File.Exists(AOldFile + ".orig") && CheckMd5Sum(AOldFile + ".orig", patchFileInfo.OldMd5sum))
                {
                    System.IO.File.Copy(AOldFile + ".orig", AOldFile, true);
                }
                else if (System.IO.File.Exists(AOldFile + ".orig") && CheckMd5Sum(AOldFile + ".orig", patchFileInfo.NewMd5sum))
                {
                    System.IO.File.Copy(AOldFile + ".orig", ANewFile, true);
                }
                else if (CheckMd5Sum(AOldFile, patchFileInfo.NewMd5sum))
                {
                    // the new file is already there
                    System.IO.File.Copy(AOldFile, ANewFile, true);
                    return(true);
                }
                else
                {
                    throw new Exception("different base file, md5sum does not match. Expected: " + patchFileInfo.OldMd5sum);
                }
            }

            ver = FileVersionInfo.GetVersionInfo(AOldFile);

            if (patchFileInfo.StoredVersion.Compare(new TFileVersionInfo(ver)) != 0)
            {
                throw new Exception(
                          "the existing file has an unexpected version number, expected " + patchFileInfo.StoredVersion.ToString() + ", but was " +
                          ver.FileVersion);
            }

            fsCtrl  = bz2read(ref bzCtrl, HEADER_SIZE, APatchFile);
            fsDiff  = bz2read(ref bzDiff, HEADER_SIZE + patchFileInfo.bzctrllen, APatchFile);
            fsExtra = bz2read(ref bzExtra, HEADER_SIZE + patchFileInfo.bzctrllen + patchFileInfo.bzdatalen, APatchFile);
            try
            {
                fsOld = new FileStream(AOldFile, FileMode.Open);
                brOld = new BinaryReader(fsOld);
            }
            catch (Exception)
            {
                throw new Exception("Cannot read file " + AOldFile);
            }
            oldsize = (int)fsOld.Length;
            byte[] old = brOld.ReadBytes(oldsize);

            if (old.Length != oldsize)
            {
                throw new Exception("old file " + AOldFile + " has invalid size");
            }

            brOld.Close();
            fsOld.Close();
            byte[]  pNew = new byte[patchFileInfo.newsize + 1];
            Int32[] ctrl = new Int32[3];
            oldpos = 0;
            newpos = 0;

            while (newpos < patchFileInfo.newsize)
            {
                for (i = 0; i <= patchFileInfo.FormatVersion; i += 1)
                {
                    // we only support version 2
                    lenread = loopread(ref bzCtrl, ref buf, 0, 8);

                    if (lenread < 8)
                    {
                        throw new Exception("Corrupt patch (4)");
                    }

                    ctrl[i] = (Int32)offtin(buf, 0);
                }

                if (newpos + ctrl[0] > patchFileInfo.newsize)
                {
                    throw new Exception("Corrupt patch (5)");
                }

                lenread = loopread(ref bzDiff, ref pNew, newpos, ctrl[0]);

                if ((lenread < 0) || (lenread != ctrl[0]))
                {
                    throw new Exception("Corrupt patch (6)");
                }

                for (i = 0; i < ctrl[0]; i++)
                {
                    if ((oldpos + i >= 0) && (oldpos + i < oldsize))
                    {
                        pNew[newpos + i] = (byte)(((Int32)pNew[newpos + i] + (Int32)old[oldpos + i]) % 256);
                    }
                }

                newpos = newpos + ctrl[0];
                oldpos = oldpos + ctrl[0];

                if (patchFileInfo.FormatVersion == 2)
                {
                    if (newpos + ctrl[1] > patchFileInfo.newsize)
                    {
                        throw new Exception("Corrupt patch (7)");
                    }

                    lenread = loopread(ref bzExtra, ref pNew, newpos, ctrl[1]);

                    if ((lenread < 0) || (lenread != ctrl[1]))
                    {
                        throw new Exception("Corrupt patch (8)");
                    }

                    newpos = newpos + ctrl[1];
                    oldpos = oldpos + ctrl[2];
                }
            }

            // make sure there is nothing left to read
            if ((loopread(ref bzCtrl, ref buf, 0, 1) != 0) ||
                (loopread(ref bzDiff, ref buf, 0, 1) != 0) ||
                (loopread(ref bzExtra, ref buf, 0, 1) != 0))
            {
                throw new Exception("Corrupt patch (9)");
            }

            bzCtrl.Close();
            bzDiff.Close();
            bzExtra.Close();
            fsCtrl.Close();
            fsDiff.Close();
            fsExtra.Close();
            fsNew = new FileStream(ANewFile, FileMode.Create);
            bwNew = new BinaryWriter(fsNew);
            bwNew.Write(pNew, 0, patchFileInfo.newsize);
            bwNew.Close();
            fsNew.Close();
            System.IO.File.SetLastWriteTime(ANewFile, patchFileInfo.NewFileDateTime);

            if ((!CheckMd5Sum(ANewFile, patchFileInfo.NewMd5sum)))
            {
                return(false);
            }

            return(true);
        }
Пример #2
0
        /// <summary>
        /// called by ApplyPatch, can also be useful to analyse patch files
        /// </summary>
        public Boolean ReadHeader(String APatchFile, out TPatchFileInfo patchFileInfo)
        {
            FileStream fsHeader;
            BinaryReader brHeader;
            Int32 i;

            byte[] header = new byte[HEADER_SIZE];
            patchFileInfo = new TPatchFileInfo();
            fsHeader = new FileStream(APatchFile, FileMode.Open);
            brHeader = new BinaryReader(fsHeader);

            if ((int)fsHeader.Length < HEADER_SIZE)
            {
                throw new Exception("Corrupt patch (1)");
            }

            // see header format in unit description
            header = brHeader.ReadBytes(HEADER_SIZE);
            brHeader.Close();
            fsHeader.Close();

            if (header.Length != HEADER_SIZE)
            {
                throw new Exception("Corrupt patch (2)");
            }

            for (i = 0; i <= 7; i++)
            {
                if (header[i] != (byte)(FORMAT_DESCR)[i])
                {
                    throw new Exception("wrong version");
                }
            }

            patchFileInfo.FormatVersion = 2;
            patchFileInfo.bzctrllen = (int)offtin(header, 8);
            patchFileInfo.bzdatalen = (int)offtin(header, 16);
            patchFileInfo.newsize = (int)offtin(header, 24);

            if ((patchFileInfo.bzctrllen < 0) || (patchFileInfo.bzdatalen < 0) || (patchFileInfo.newsize < 0))
            {
                throw new Exception("Corrupt patch (3)");
            }

            patchFileInfo.NewFileDateTime = new DateTime(offtin(header, 32));
            patchFileInfo.OldMd5sum = "";

            for (i = 0; i <= 31; i += 1)
            {
                patchFileInfo.OldMd5sum = patchFileInfo.OldMd5sum + Convert.ToChar(header[40 + i]);
            }

            patchFileInfo.NewMd5sum = "";

            for (i = 0; i <= 31; i += 1)
            {
                patchFileInfo.NewMd5sum = patchFileInfo.NewMd5sum + Convert.ToChar(header[72 + i]);
            }

            patchFileInfo.StoredVersion = new TFileVersionInfo();
            patchFileInfo.StoredVersion.FileMajorPart = (UInt16)(((UInt16)(header[104]) * 256 + header[105]));
            patchFileInfo.StoredVersion.FileMinorPart = (UInt16)(header[106] * 256 + header[107]);
            patchFileInfo.StoredVersion.FileBuildPart = (UInt16)(header[108] * 256 + header[109]);
            patchFileInfo.StoredVersion.FilePrivatePart = (UInt16)(header[110] * 256 + header[111]);
            return true;
        }
Пример #3
0
        /// <summary>
        /// called by ApplyPatch, can also be useful to analyse patch files
        /// </summary>
        public Boolean ReadHeader(String APatchFile, out TPatchFileInfo patchFileInfo)
        {
            FileStream   fsHeader;
            BinaryReader brHeader;
            Int32        i;

            byte[] header = new byte[HEADER_SIZE];
            patchFileInfo = new TPatchFileInfo();
            fsHeader      = new FileStream(APatchFile, FileMode.Open);
            brHeader      = new BinaryReader(fsHeader);

            if ((int)fsHeader.Length < HEADER_SIZE)
            {
                throw new Exception("Corrupt patch (1)");
            }

            // see header format in unit description
            header = brHeader.ReadBytes(HEADER_SIZE);
            brHeader.Close();
            fsHeader.Close();

            if (header.Length != HEADER_SIZE)
            {
                throw new Exception("Corrupt patch (2)");
            }

            for (i = 0; i <= 7; i++)
            {
                if (header[i] != (byte)(FORMAT_DESCR)[i])
                {
                    throw new Exception("wrong version");
                }
            }

            patchFileInfo.FormatVersion = 2;
            patchFileInfo.bzctrllen     = (int)offtin(header, 8);
            patchFileInfo.bzdatalen     = (int)offtin(header, 16);
            patchFileInfo.newsize       = (int)offtin(header, 24);

            if ((patchFileInfo.bzctrllen < 0) || (patchFileInfo.bzdatalen < 0) || (patchFileInfo.newsize < 0))
            {
                throw new Exception("Corrupt patch (3)");
            }

            patchFileInfo.NewFileDateTime = new DateTime(offtin(header, 32));
            patchFileInfo.OldMd5sum       = "";

            for (i = 0; i <= 31; i += 1)
            {
                patchFileInfo.OldMd5sum = patchFileInfo.OldMd5sum + Convert.ToChar(header[40 + i]);
            }

            patchFileInfo.NewMd5sum = "";

            for (i = 0; i <= 31; i += 1)
            {
                patchFileInfo.NewMd5sum = patchFileInfo.NewMd5sum + Convert.ToChar(header[72 + i]);
            }

            patchFileInfo.StoredVersion = new TFileVersionInfo();
            patchFileInfo.StoredVersion.FileMajorPart   = (UInt16)(((UInt16)(header[104]) * 256 + header[105]));
            patchFileInfo.StoredVersion.FileMinorPart   = (UInt16)(header[106] * 256 + header[107]);
            patchFileInfo.StoredVersion.FileBuildPart   = (UInt16)(header[108] * 256 + header[109]);
            patchFileInfo.StoredVersion.FilePrivatePart = (UInt16)(header[110] * 256 + header[111]);
            return(true);
        }