【问题标题】:How do I create binary patches?如何创建二进制补丁?
【发布时间】:2010-12-29 00:58:10
【问题描述】:

为二进制文件制作补丁的最佳方法是什么?我希望用户可以简单地申请(一个简单的patch 应用程序会很好)。在文件上运行 diff 只会给出Binary files [...] differ

【问题讨论】:

    标签: binary patch


    【解决方案1】:

    查看bsdiffbspatchwebsitemanpagepaperGitHub fork)。

    要安装此工具:

    • Windows:下载并解压this package。您还需要在PATH 中提供bzip2.exe 的副本;从“二进制文件”链接here下载。
    • macOS:安装 Homebrew 并使用它来安装 bsdiff
    • Linux:使用包管理器安装 bsdiff

    【讨论】:

    • 相当古老的来源。使用现代 Visual Studio 进行编译并不容易——使用 VS 2009 可以正常工作,但我在使用较新版本时遇到了错误。此外,它只有 32 位,这是关于内存消耗的真正问题(请参阅其他答案)。我不确定,如果只是用 x64 编译可以解决这个问题-我切换到 .NET 端口,请参阅其他答案。
    • bsdiffcourgette 针对可执行二进制文件进行了优化;找到了一些unofficial Windows binaries,但它立即失败了
    【解决方案2】:

    Courgette,由 Google Chrome 团队开发,看起来是二进制修补可执行文件的最有效工具。

    引用他们的数据:

    以下是开发者频道最近 190.1 -> 190.4 更新的尺寸:

    • 完整更新: 10,385,920 字节
    • bsdiff 更新: 704,512 字节
    • 小胡瓜更新: 78,848 字节

    这里是instructions to build it。这是来自 2018 年的 a Windows binary,由 Mehrdad 提供。

    【讨论】:

    • 文档说,“我们编写了一个新的差异算法,它更了解我们正在推送的数据类型 - 包含已编译可执行文件的大文件”。这意味着它不会对其他二进制文件起作用(或者可能根本不起作用)。
    • 感谢您提供该链接。但在 Windows 下编译它是一个真实的故事。它首先安装一个完整的开发者系统,例如Git、Python 等。也许它可以工作,但在我的机器上,获取使用了一些安全且失败的端口。有人知道二进制下载链接吗?
    • @James Courgette 是bsdiff 的真正继承者。来自文档:西葫芦diff = bsdiff(concat(original, guess), update)。使用合理的bdiff 算法,您将拥有len(bdiff(concat(original,guess),update)) < len(bdiff(original,update))+C 和一个小的(常数)C。将C 设置为 10 是一个安全的选择。也许有人可以为bsdiff 计算C。请注意,如果给定的 bdiff 算法保证 len(bdiff(concat(original,random),update)) <= len(bdiff(original,update)) 对于原始、随机和更新的任何值,则 C==1。
    • 与 bsdiff 的输出不同,它已经被压缩(使用 bzip2),您可以通过使用 gzip 或 lzma 之类的东西来进一步减小 Courgette 输出的大小。
    【解决方案3】:

    xdelta (website, GitHub) 是另一种选择。它似乎是较新的,但除此之外,我不知道它与 bsdiff 等其他工具相比如何。

    用法:

    • 创建补丁:xdelta -e -s old_file new_file delta_file
    • 应用补丁:xdelta -d -s old_file delta_file decoded_new_file

    安装:

    • Windows:下载official binaries
    • 巧克力:choco install xdelta3
    • 自制:brew install xdelta
    • Linux:在您的包管理器中以xdeltaxdelta3 的形式提供。

    【讨论】:

    • Windows 二进制文件:official xdelta3unofficial xdelta
    • 这只是节省了我几个小时。需要测试某个版本的 1.1 GB 的 exe 自解压安装程序。通过 vpn 复制它需要 2.5 小时。我已经发布了与 3 个月前不同的版本...按照您的说明,生成的补丁(幸运的是)为 18MB - 猜测只有微小的变化。在远程系统上应用补丁。对新修补的 exe 执行了各种校验和,并且在两个系统上都匹配。有很多方法可能不起作用,但在我的情况下它工作得很好!
    【解决方案4】:

    现代端口:对于 bsdiff/bspatch 非常有用的 .NET 端口:

    https://github.com/LogosBible/bsdiff.net

    我个人的选择。 我对其进行了测试,它是所有链接中唯一的,我能够开箱即用地编译它(使用 Visual Studio,例如 2013)。 (其他地方的 C++ 源代码有点过时,至少需要一点抛光,并且只有 32 位,它设置了实际内存(差异源大小)限制。这是此 C++ 代码 bsdiff 的一个端口,甚至测试补丁结果是否相同到原始代码)。

    进一步的想法:使用 .NET 4.5,您甚至可以摆脱 #Zip lib,这是此处的依赖项。

    我没有测量它是否比 c++ 代码稍慢,但它对我来说很好,(bsdiff:90 MB 文件在 1-2 分钟内。),对我来说时间关键的只是 bspatch,不是 bsdiff。

    我不确定是否使用了 x64 机器的整个内存,但我假设它。支持 x64 的构建(“任何 CPU”)至少可以工作。尝试使用 100 MB 的文件。

    - 此外:如果您的主要目标是可执行文件,则引用的 Google 项目“Courgette”可能是最佳选择。但它是构建它的工作(至少对于 Windows 措施),并且对于二进制文件,它也使用纯 bsdiff/bspatch,据我了解文档。

    【讨论】:

      【解决方案5】:

      对于小而简单的补丁,最简单的方法是使用 -a(或 --text)选项告诉 diff 将文件视为文本。据我了解,更复杂的二进制差异仅对减小补丁大小有用。

      $ man diff | grep -B1 "as text"
             -a, --text
                    treat all files as text
      $ diff old new
      Binary files old and new differ
      $ diff -a old new > old.patch
      $ patch < old.patch old
      patching file old
      $ diff old new
      $
      

      如果文件大小相同,补丁只修改了几个字节,可以使用操作系统自带的xxd。下面将每个文件转换为每行一个字节的十六进制表示,然后对文件进行差异化以创建紧凑补丁,然后应用补丁。

      $ xxd -c1 old > old.hex
      $ xxd -c1 new > new.hex
      $ diff old.hex new.hex | grep "^+" | grep -v "^++" | sed "s/^+//" > old.hexpatch
      $ xxd -c1 -r old.hexpatch old
      $ diff old new
      $
      

      【讨论】:

        【解决方案6】:

        HDiffPatch:https://github.com/sisong/HDiffPatch
        可运行于:windows、macos、linux、android
        支持二进制文件或目录之间的差异;
        创建补丁:hdiffz [-m|-s-64] [-c-lzma2] old_path new_path out_delta_file
        应用补丁:hpatchz old_path delta_file out_new_path

        安装:
        Download from last release,或者下载下载源码&make;

        Jojos 二进制差异:https://sourceforge.net/projects/jojodiff/
        另一个很好的二进制差异算法;

        【讨论】:

          【解决方案7】:

          diff 和 git-diff 可以通过将二进制文件视为带有-a 的文本来处理它们。

          使用git-diff,您还可以使用--binary 生成二进制文件的ASCII 编码,例如适合粘贴到电子邮件中。

          【讨论】:

            【解决方案8】:

            https://github.com/reproteq/DiffPatchWpf DiffPatchWpf DiffPatchWpf 简单的二进制补丁制作工具。

            比较两个二进制文件并将它们之间的差异保存在新文件patch.txt中

            在另一个二进制文件中快速轻松地应用补丁。

            现在您可以快速轻松地将差异应用到另一个二进制文件中。

            示例:

            1- 加载文件Aori.bin

            2- 加载文件 Amod.bin

            3- 比较并保存 Aori-patch.txt

            4- 加载文件 Bori.bin

            5- 加载补丁Aori-patch.txt

            6- 应用补丁并保存文件 Bori-patched.bin

            alt标签

            https://youtu.be/EpyuF4t5MWk

            Microsoft Visual Studio 社区 2019

            版本 16.7.7

            .NETFramework,Version=v4.7.2

            在 windows 10x64bits 中测试

            【讨论】:

              【解决方案9】:

              假设您知道文件的结构,您可以使用 c / c++ 程序逐字节修改它:

              http://msdn.microsoft.com/en-us/library/c565h7xx(VS.71).aspx

              只需读入旧文件,然后根据需要写出修改后的新文件。

              不要忘记在文件中包含文件格式版本号,以便您知道如何读取文件格式的任何给定版本。

              【讨论】:

              • 这个解决方案太疯狂了。当sed 已经完成了您可能想要的一切时,使用 C/C++。或者,如果您更喜欢使用工业级的可移植编程语​​言,perl 是您的最佳选择。如果我正在编写路由器固件,我当然会使用 C 或 C++,但有区别......?
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2010-09-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多