GZip 在 macOS 和 Linux 上不会产生相同的压缩结果

Pol*_*Pol 32 linux gzip macos

我有几千个单独 GZip 压缩的文件(当然通过 -n标志,因此输出是确定性的)。然后他们进入一个 Git 存储库。我刚刚发现,对于其中 3 个文件,Gzip 在 macOS 和 Linux 上不会产生相同的输出。下面是一个例子:

苹果系统

$ cat Engine/Extras/ThirdPartyNotUE/NoRedist/EnsureIT/9.7.0/bin/finalizer | shasum -a 256
0ac378465b576991e1c7323008efcade253ce1ab08145899139f11733187e455  -

$ cat Engine/Extras/ThirdPartyNotUE/NoRedist/EnsureIT/9.7.0/bin/finalizer | gzip --fast -n | shasum -a 256
6e145c6239e64b7e28f61cbab49caacbe0dae846ce33d539bf5c7f2761053712  -

$ cat Engine/Extras/ThirdPartyNotUE/NoRedist/EnsureIT/9.7.0/bin/finalizer | gzip -n | shasum -a 256
3562fd9f1d18d52e500619b4a5d5dfa709f5da8601b9dd64088fb5da8de7b281  -

$ gzip --version
Apple gzip 272.250.1
Run Code Online (Sandbox Code Playgroud)

Linux

$ cat Engine/Extras/ThirdPartyNotUE/NoRedist/EnsureIT/9.7.0/bin/finalizer | shasum -a 256
0ac378465b576991e1c7323008efcade253ce1ab08145899139f11733187e455  -

$ cat Engine/Extras/ThirdPartyNotUE/NoRedist/EnsureIT/9.7.0/bin/finalizer | gzip --fast -n | shasum -a 256
10ac8b80af8d734ad3688aa6c7d9b582ab62cf7eda6bc1a0f08d6159cad96ddc  -

$ cat Engine/Extras/ThirdPartyNotUE/NoRedist/EnsureIT/9.7.0/bin/finalizer | gzip -n | shasum -a 256
cbf249e3a35f62a4f3b13e2c91fe0161af5d96a58727d17cf7a62e0ac3806393  -

$ gzip --version
gzip 1.6
Copyright (C) 2007, 2010, 2011 Free Software Foundation, Inc.
Copyright (C) 1993 Jean-loup Gailly.
This is free software.  You may redistribute copies of it under the terms of
the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
There is NO WARRANTY, to the extent permitted by law.

Written by Jean-loup Gailly.
Run Code Online (Sandbox Code Playgroud)

这怎么可能?我认为 GZip 实现是完全标准的?

更新:为了确认 macOS 和 Linux 版本在大多数情况下确实产生相同的输出,两个操作系统输出相同的哈希:

$ echo "Vive la France" | gzip --fast -n | shasum -a 256
af842c0cb2dbf94ae19f31c55e05fa0e403b249c8faead413ac2fa5e9b854768  -
Run Code Online (Sandbox Code Playgroud)

sch*_*der 57

请注意,GZip 中的压缩算法 (Deflate) 并非严格双射。详细说明:对于某些数据,根据算法实现和使用的参数,有不止一种可能的压缩输出。因此,根本无法保证 Apple GZip 和 gzip 1.6 会返回相同的压缩输出。这些输出都是有效的 GZip 流,标准只是保证这些可能的输出中的每一个都将被解压缩为相同的原始数据。

  • 变化不大。例如,不同的 deflate 实现可以决定将大数据拆分为不同大小的块或根据文件内容更改压缩策略。因此,Apple Gzip 和 gzip 1.6 可能非常相似,以至于它们在大多数情况下都会做出相同的决定,但也有一些例外。 (16认同)
  • 甚至两个不同版本的 gnu gzip 也可能产生不同的压缩结果,这取决于版本之间使用的算法的变化。而且,乍一看,我不确定这个特定版本的 Apple gzip 和这个特定版本的 GNU gzip 实际上_are_来自同一来源。同一个上游项目?当然。但是 Apple 实现的上游源可能来自该源的不同版本,而不是 gnu 实现。并且假设它们不是在 gzip 开发的不同时间开始的完全独立的分叉。 (7认同)
  • 好吧,要获得详细的明确答案,需要使用来自 OP 的文件进行测试(和/或两种实现中的代码潜水)。确实,没有它们,我们正在推测差异的来源。但事实上,可能存在的差异比人们预期的要多。另一个例子是匹配长度 258 有两种可能的编码(参见 /sf/ask/1900684061/ ) - 使用哪一种取决于实现,以及差异只会出现在重复数据上。 (5认同)
  • 这足以回答问题的主要部分:`这怎么可能` (4认同)

von*_*and 17

格式应该非常稳定,但请参阅其说明。它包含操作系统 ID 字段。显然,对于 MacOS 和 Linux 以及 FreeBSD 和...

  • 我相信两个操作系统都应该生成操作系统字节为“3 - Unix”的文件。此字段是原始 [PKZIP](https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-2.0.txt) 文件格式的遗留字段,任何类似 *nix 的操作系统都应获得“3”。也许差异与特定于操作系统的文件属性或 POSIX ACL 中的差异有关。或者很可能我认为@schnaader 的[下面的评论](https://unix.stackexchange.com/a/570554/398074) 可能就是这种情况。也许 OP 可以发布所创建文件的二进制转储,以便我们可以确定。 (6认同)
  • @640KB 但是,所有 MacOS、FreeBSD、Linux 都使用相同的操作系统 ID(3 = Unix)是绝对正确的——您可以在 [此处] 看到整个列表(https://tools.ietf.org/html/rfc1952 #page-6)。 (3认同)
  • `回声你好| gzip | hexdump -C -s ​​9 -n 1` 非常容易验证平台代码在任何地方(macOS 上的 Apple gzip 和其他类 Unix 平台上的 GNU gzip 下都是 03)。 (3认同)
  • 如果 Linux 和 macOS 的操作系统 ID 确实相同,那么这个答案(如所写)很遗憾是不正确的。 (2认同)
  • 链接的格式说明有 Unix =3 和 Macintosh =7。后者是否不适用于现代 macOS? (2认同)
  • @planetmaker 7 大概是为 OS X 之前的 Apple 原始 MacOS 设计的,它根本不像 Unix。 (2认同)
  • 至少其他答案纯粹是猜测,但这显然是错误的。保留它的目的是什么? (2认同)

fra*_*nus 10

Gzip 格式是标准的,实现 - 不一定。维基百科列出了至少 5 个独立于 free/oss 的实现,也有专有的。Apple 显然输出了不同的版本字符串。

格式和算法都允许有很大的自由度和很多设计选择,这些选择要么是品味问题,要么是在不同的用例中工作得更好。

查看Zip 文件:历史、解释和实现

我通常希望结果在不同实现之间只有一小部分小文件是相同的。

  • 而且我仍然不会得出结论,他们总是从中给出相同的压缩输出。查看 https://fossies.org/linux/gzip/ChangeLog 上的 gzip 更改日志,有很多更改。这些是否已在 Apple 的代码中采用?甚至无法找出 Apple 的 gzip 272.250.1 来自哪个日期。还找到了 gzip 1.4-1 ( https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=647522 ) 的这个 Debian 错误报告,其中压缩输出并不总是相同。已在 1.4-5 中修复,但演示了该问题并给出了另一个过去的示例。原因是未清零的内存污染了字典。 (2认同)