go archive/tar: Header.FileInfo.Mode.IsRegular reports true for non-regular files

a8jjtwal  于 3个月前  发布在  Go
关注(0)|答案(3)|浏览(93)

背景

tar文件是一种用于归档文件系统的格式,能够表示包括常规文件、目录、块设备和字符设备、符号链接和硬链接在内的任何内容。
多年来,许多与tar不兼容的扩展已经成为常见做法。具体来说,其中一个是使用伪文件来编码关于一个文件或一组文件的额外信息。伪文件以与普通文件相同的方式编码,但Header.Typeflag被设置为某个特殊值,文件的内容根据由typeflag确定的某种格式进行解析。GNU和PAX格式都是这种方法的重度用户。
Go实现的tar为描述其实际文件的伪文件提供自动解析元数据的功能。例如,Go1.1支持解析GNU格式的长文件名;Go1.3支持解析本地PAX头;Go1.3还支持解析GNU稀疏头。

问题

解析单个文件的元数据在API中很容易表示,因为我们只需在Header结构中表示附加信息即可。
然而,PAX格式添加了一个名为“全局PAX头”的功能,该功能编码了旨在修改所有后续文件的元数据(#22748表示实际上使用了此功能;例如,git archive --format=tgz生成它们)。
为了提供包含全局PAX头中的元数据,Reader.Next返回一个表示伪文件的单个Header(在go1.10中,我们实际上将PAX记录解析为Header.PAXRecords,但这与此问题无关)。
全局头(以及Go实现确实不识别的任何typeflag)的问题在于:

Header{Typeflag: TypeXGlobalHeader}.FileInfo().Mode().IsRegular() // true

这是迄今为止所有版本的Go的行为。
IsRegular报告为真的问题是:

  1. 它不真实。这不是一个常规文件。
  2. 仅依赖于Header.FileInfo的用户无法特别处理伪文件(例如,忽略它们)。
    然而,要使Header.FileInfo.Mode.IsRegular报告为假并非易事,因为os.FileMode.IsRegular的逻辑仅对非常狭窄的类型集报告为假,这些类型中没有一个是像元数据或未识别的typeflag这样的“特殊”文件的明显选择。
    因此,我们需要决定是否保留或更改当前针对像TypeXGlobalHeader这样的特殊文件的Header.FileInfo.Mode.IsRegular的行为。如果我们改变它,如何让它报告为假?我认为唯一的方法是在os包中定义一个新的常量(例如,ModeSpecial)。
    想法?
    \cc @rasky@bradfitz
xpszyzbs

xpszyzbs1#

嗯,挺糟糕的。
如果os.ModeSpecial定义得模糊一些,我也能接受。
我们也可以在archive/tar中记录这些头文件的存在。
实际上,我更倾向于默认跳过这样的东西,并让甚至遍历它们成为可选操作。现在可能太晚了才这样做。添加一个可选开关可能没什么用,因为即使他们知道tar格式(我之前不知道),人们也可以自己检查Header.Typeflagcontinue。但我假设大多数人不知道这些,也不想看到它们,所以我会尝试使用可选开关。我们需要在GitHub和谷歌上搜索,看看nobody-cares理论是否正确。

xesrikrc

xesrikrc2#

我投票给 os.ModeSpecial
我认为选择加入的方法也是一个好主意,但我认为它与 ModeSpecial 无关。我认为让用户使用 os.FileMode 进行文件处理仍然有价值,而不必强制他们切换到 Header.Typeflag ,除非严格要求。

kyvafyod

kyvafyod3#

https://golang.org/cl/94856提到了这个问题:os: add ModeUnknown flag

相关问题