为什么 libarchive 的 bsdtar 解压缩在从 stdin 读取 ZIP 存档时会丢弃权限位,而不是直接读取?

为什么 libarchive 的 bsdtar 解压缩在从 stdin 读取 ZIP 存档时会丢弃权限位,而不是直接读取?

bsdtar我遇到过,包中的命令libarchive(至少在 Arch Linux 下).zip在读取时会丢弃 -archives中文件的可执行位stdin,但在直接处理文件时则不会。

.tar-archives 上,它在从标准输入读取时也保留可执行位。

测试用例:

创建档案:

创建文件:

touch a.txt
chmod 644 a.txt
touch a.out
chmod 755 a.out

文件权限:

ls -ln a.out a.txt

节目

-rwxr-xr-x 1 1001 1001 0 Dec 12 11:01 a.out
-rw-r--r-- 1 1001 1001 0 Dec 12 11:01 a.txt

将文件打包到存档中:

bsdtar --format=zip -cf a.zip a.out a.txt
bsdtar -cf a.tar a.out a.txt

zip(使用和tar而不是创建档案bsdtar会产生相同的结果。)

直接提取/显示存档内容:

bsdtar -tvf a.zip

或者

bsdtar -tvf - < a.zip

节目

-rwxr-xr-x  0 1001   1001        0 Dec 12 11:01 a.out
-rw-r--r--  0 1001   1001        0 Dec 12 11:01 a.txt

此处显示 的可执行位a.out。 的权限a.out为 755 和a.txt644。

阅读自stdin

cat a.zip | bsdtar -tvf -

节目

-rw-rw-r--  0 1001   1001        0 Dec 12 11:01 a.out
-rw-rw-r--  0 1001   1001        0 Dec 12 11:01 a.txt

此处的可执行位a.out被丢弃。此外,这两个文件都是可组写的,但它们不是以这种方式打包的。a.out和的权限a.txt都是664。

.tar-档案:

作为比较,对于.tar-archive,当从管道读取时,也会遵守存档中的权限stdin

bsdtar --numeric-owner -tvf a.tar

cat a.tar | bsdtar --numeric-owner -tvf -

都显示

-rwxr-xr-x  0 1001   1001        0 Dec 12 11:01 a.out
-rw-r--r--  0 1001   1001        0 Dec 12 11:01 a.txt

(请注意,显示 ZIP 存档的内容时,bsdtar默认显示数字所有者;对于 TAR 存档,它显示所有者的名称。)

问题是:

有何stdin特别之处bsdtar?为什么只在从管道中读取时而不是在时尚中读取bsdtar -tvf - < a.zip?为什么对.zip-archive 特殊,而不是 -archive .tar

答案1

在 bugtracker 上libarchive答案是:

Zip 档案包含两种不同的方式来描述内容:

  1. 每个条目的标头
  2. zip 文件末尾的中心目录。

如果可以在输入上查找,libarchive(以及扩展的 bsdtar)将使用中央目录,否则它将回退到仅流逻辑。正如您在测试用例中发现的那样,这些条目不一定一致。我们对此无能为力或不想做太多事情。请注意,您可以用普通的猫替换 wget,它仍然会显示相同的行为。

简而言之,这是 zip 文件流的固有问题,并且无法修复。

这条评论讲述如何使用以下命令创建一致的 ZIP 文件bsdtar

为了使bsdtar创建信息一致,--options zip:experimental需要在bsdtarzip文件创建命令中添加:

bsdtar --format=zip --options zip:experimental -cf a.zip a.out a.txt

进而

cat a.zip | bsdtar -tvf -

显示正确的权限:

-rwxr-xr-x  0 1001   1001        0 Feb 17 21:18 a.out
-rw-r--r--  0 1001   1001        0 Feb 17 21:18 a.txt

答案2

[这还不是真正的答案,但我会这样发布,因为不可能在评论中格式化任何内容]

zip不是从不可查找的文件中提取时产生问题的唯一格式。这是一个多会话 iso 映像的示例,但至少bsdtar有打印错误信息并以非零状态退出。它可能应该对 zip 文件做同样的事情;恕我直言,默默地搞乱权限是不可接受的。

$ echo a.out > a.out
$ genisoimage -quiet -R -o a.iso a.out
$ chmod 755 a.out
$ growisofs -M a.iso -R -quiet a.out
Executing 'genisoimage -C 16,176 -M /dev/fd/3 -R -quiet a.out | builtin_dd of=a.iso obs=32k seek=11'
Rock Ridge signatures found
builtin_dd: 176*2KB out @ average infx1352KBps
a.iso: copying volume descriptor(s)

$ cat a.iso | bsdtar xf -
bsdtar: Ignoring out-of-order file @19 (a.out) 51200 < 411648
bsdtar: Error exit delayed from previous errors.
$ ls -l a.out; hd a.out
-rwxr-xr-x 1 ahq ahq 6 Dec 11 19:15 a.out
00000000  00 00 00 00 00 00                                 |......|
00000006

$ bsdtar xf a.iso
$ ls -l a.out; hd a.out
-rwxr-xr-x 1 ahq ahq 6 Dec 11 19:15 a.out
00000000  61 2e 6f 75 74 0a                                 |a.out.|
00000006

相关内容