Tar

Tar.createFunction
create(
    [ predicate, ] dir, [ tarball ];
    [ skeleton, ] [ portable = false ]
) -> tarball

    predicate :: String --> Bool
    dir       :: AbstractString
    tarball   :: Union{AbstractString, AbstractCmd, IO}
    skeleton  :: Union{AbstractString, AbstractCmd, IO}
    portable  :: Bool

创建目录 dir 的 tar 归档 ("tarball")。生成的归档写入路径 tarball,如果未指定路径,则创建一个临时路径并由函数调用返回。如果 tarball 是一个 IO 对象,则 tarball 内容将写入该句柄(句柄保持打开状态)。

如果传递了 predicate 函数,则在递归搜索 dir 时会对每个遇到的系统路径调用该函数,只有当 predicate(path) 为真时,path 才会包含在 tarball 中。如果 predicate(path) 对某个目录返回假,则该目录将被完全排除:该目录下的内容将不会包含在归档中。

如果传递了 skeleton 关键字,则给定的文件或 IO 句柄将用作生成 tarball 的 "骨架"。通过将 skeleton 关键字传递给 extract 命令来创建骨架文件。如果使用该骨架文件调用 create,并且提取的文件没有更改,则会重新创建一个相同的 tarball。skeletonpredicate 参数不能一起使用。

如果 portable 标志为真,则会检查路径名称在 Windows 上的有效性,以确保它们不包含非法字符或具有保留的名称。有关详细信息,请参见 https://stackoverflow.com/a/31976060/659248。

source
Tar.extractFunction
extract(
    [ predicate, ] tarball, [ dir ];
    [ skeleton = <none>, ]
    [ copy_symlinks = <auto>, ]
    [ set_permissions = true, ]
) -> dir

    predicate       :: Header --> Bool
    tarball         :: Union{AbstractString, AbstractCmd, IO}
    dir             :: AbstractString
    skeleton        :: Union{AbstractString, AbstractCmd, IO}
    copy_symlinks   :: Bool
    set_permissions :: Bool

将位于路径 tarball 的 tar 归档(“tarball”)提取到目录 dir 中。如果 tarball 是一个 IO 对象而不是路径,则归档内容将从该 IO 流中读取。归档被提取到 dir,该目录必须是一个已存在的空目录或一个可以创建为新目录的不存在路径。如果未指定 dir,则归档将提取到一个临时目录中,该目录由 extract 返回。

如果传递了 predicate 函数,则在提取 tarball 时遇到的每个 Header 对象上调用该函数,只有当 predicate(hdr) 为真时,条目才会被提取。这可以用于选择性地提取归档的某些部分,跳过导致 extract 抛出错误的条目,或记录在提取过程中提取的内容。

在传递给谓词函数之前,Header 对象会从 tarball 的原始头部进行一些修改:path 字段被规范化以删除 . 条目,并将多个连续的斜杠替换为一个斜杠。如果条目的类型为 :hardlink,则链接目标路径以相同方式规范化,以便与目标条目的路径匹配;大小字段设置为目标路径的大小(该路径必须是已见过的文件)。

如果传递了 skeleton 关键字,则提取的 tarball 的“骨架”将写入给定的文件或 IO 句柄。此骨架文件可用于通过将 skeleton 关键字传递给 create 函数来重建一个相同的 tarball。skeletonpredicate 参数不能一起使用。

如果 copy_symlinkstrue,则不会将符号链接提取为符号链接,而是将其提取为它们链接到的内容的副本(如果它们在 tarball 内部并且可以这样做)。非内部符号链接,例如指向 /etc/passwd 的链接将不会被复制。以任何方式循环的符号链接也将不会被复制,而是会被跳过。默认情况下,extract 将检测是否可以在 dir 中创建符号链接,并在无法创建时自动复制符号链接。

如果 set_permissionsfalse,则不对提取的文件设置任何权限。

source
Tar.listFunction
list(tarball; [ strict = true ]) -> Vector{Header}
list(callback, tarball; [ strict = true ])

    callback  :: Header, [ <data> ] --> Any
    tarball   :: Union{AbstractString, AbstractCmd, IO}
    strict    :: Bool

列出位于路径 tarball 的 tar 归档(“tarball”)的内容。如果 tarball 是一个 IO 句柄,则从该流中读取 tar 内容。返回一个 Header 结构的向量。有关详细信息,请参见 Header

如果提供了 callback,则在每个 Header 上调用该回调,而不是返回一个头部的向量。如果 tarball 中的项目数量很大,或者您想在 tarball 中出现错误之前检查项目,这可能会很有用。如果 callback 函数可以接受第二个参数,类型为 Vector{UInt8}Vector{Pair{Symbol, String}},则它将被调用,并以单个字节向量或将字段名称映射到该字段的原始数据的对的向量的形式表示原始头部数据(如果这些字段连接在一起,结果就是头部的原始数据)。

默认情况下,如果 list 遇到 extract 函数拒绝提取的任何 tarball 内容,则会出错。使用 strict=false 时,它将跳过这些检查,并列出 tar 文件的所有内容,无论 extract 是否会提取它们。请注意,恶意的 tarball 可以做各种巧妙和意想不到的事情,试图欺骗您做一些不好的事情。

如果 tarball 参数是一个骨架文件(请参见 extractcreate),则 list 将从文件头检测到这一点,并适当地列出或迭代骨架文件的头部。

source
Tar.rewriteFunction
rewrite(
    [ predicate, ] old_tarball, [ new_tarball ];
    [ portable = false, ]
) -> new_tarball

    predicate   :: Header --> Bool
    old_tarball :: Union{AbstractString, AbstractCmd, IO}
    new_tarball :: Union{AbstractString, AbstractCmd, IO}
    portable    :: Bool

old_tarball 重写为 create 生成的标准格式,同时检查它是否包含任何会导致 extract 引发错误的内容。这在功能上等同于执行

Tar.create(Tar.extract(predicate, old_tarball), new_tarball)

然而,它从不将任何内容提取到磁盘,而是使用 seek 函数来导航旧 tarball 的数据。如果没有传递 new_tarball 参数,则新 tarball 将写入一个临时文件,并返回其路径。

如果传递了 predicate 函数,则在提取 old_tarball 时会对每个遇到的 Header 对象调用该函数,除非 predicate(hdr) 为真,否则该条目将被跳过。这可以用于选择性地重写存档的某些部分,跳过会导致 extract 抛出错误的条目,或记录在重写过程中遇到的内容。

在传递给谓词函数之前,Header 对象会从 tarball 的原始头部进行一些修改:path 字段被规范化以删除 . 条目,并将多个连续的斜杠替换为一个斜杠。如果条目的类型为 :hardlink,则链接目标路径也以相同方式规范化,以便与目标条目的路径匹配;大小字段设置为目标路径的大小(该路径必须是已见过的文件)。

如果 portable 标志为真,则会检查路径名称在 Windows 上的有效性,以确保它们不包含非法字符或具有保留的名称。有关详细信息,请参见 https://stackoverflow.com/a/31976060/659248。

source
Tar.tree_hashFunction
tree_hash([ predicate, ] tarball;
          [ algorithm = "git-sha1", ]
          [ skip_empty = false ]) -> hash::String

    predicate  :: Header --> Bool
    tarball    :: Union{AbstractString, AbstractCmd, IO}
    algorithm  :: AbstractString
    skip_empty :: Bool

计算 tarball 中包含的文件树的树哈希值。默认情况下,这使用 git 的树哈希算法和 SHA1 安全哈希函数(如当前版本的 git)。这意味着对于任何 git 可以表示的 tarball 的文件树——即仅包含文件、符号链接和非空目录的 tarball——此函数计算的哈希值将与 git 为该文件树计算的哈希值相同。请注意,tarball 可以表示包含空目录的文件树,而 git 无法存储这些空目录,此函数可以为这些空目录生成哈希,默认情况下(请参见 skip_empty 下面如何更改此行为)与省略这些空目录的 tarball 的哈希不同。简而言之,哈希函数在 git 可以表示的所有树上与 git 一致,但以一致的方式扩展了可哈希树的域到 git 无法表示的其他树。

如果传递了 predicate 函数,则在处理 tarball 时会对每个遇到的 Header 对象调用该函数,只有当 predicate(hdr) 为真时,条目才会被哈希。这可以用于选择性地仅哈希归档的某些部分,跳过导致 extract 抛出错误的条目,或记录在哈希过程中提取的内容。

在传递给谓词函数之前,Header 对象会从 tarball 的原始头部进行一些修改:path 字段被规范化以删除 . 条目,并将多个连续的斜杠替换为一个斜杠。如果条目的类型为 :hardlink,则链接目标路径以相同方式规范化,以便与目标条目的路径匹配;大小字段设置为目标路径的大小(该路径必须是已见过的文件)。

当前支持的 algorithm 值为 git-sha1(默认)和 git-sha256,后者使用与 git-sha1 相同的基本算法,但将 SHA1 哈希函数替换为 SHA2-256,这是 git 将在未来过渡使用的哈希函数(由于对 SHA1 的已知攻击)。未来可能会添加对其他文件树哈希算法的支持。

skip_empty 选项控制是否将递归不包含文件或符号链接的 tarball 中的目录包含在哈希中或忽略。一般来说,如果您正在哈希 tarball 或文件树的内容,您关心的是所有目录,而不仅仅是非空目录,因此将这些目录包含在计算的哈希中是默认行为。那么,为什么这个函数甚至提供跳过空目录的选项呢?因为 git 拒绝存储空目录,如果您尝试将它们添加到仓库中,它将忽略它们。因此,如果您通过将文件添加到 git 仓库来计算参考树哈希,然后请求 git 获取树哈希,您获得的哈希值将与 skip_empty=truetree_hash 计算的哈希值匹配。换句话说,此选项允许 tree_hash 模拟 git 如何哈希包含空目录的树。然而,如果您正在哈希可能包含空目录的树(即不来自 git 仓库),建议您使用不忽略空目录的工具(例如此工具)进行哈希。

source
Tar.HeaderType

Header 类型是一个结构体,表示 tar 文件中单个记录的基本元数据,其定义如下:

struct Header
    path :: String # 相对于根的路径
    type :: Symbol # 类型指示符(见下文)
    mode :: UInt16 # 模式/权限(最好以八进制查看)
    size :: Int64  # 记录数据的字节大小
    link :: String # 符号链接的目标路径
end

类型用以下符号表示:filehardlinksymlinkchardevblockdevdirectoryfifo,或者对于未知类型,使用类型标志字符作为符号。请注意,extract 拒绝提取类型为 filesymlinkdirectory 以外的记录;list 仅在 strict=false 的情况下列出其他类型的记录。

tar 格式包含有关记录的各种其他元数据,包括用户和组 ID、用户和组名称以及时间戳。Tar 包故意完全忽略这些。在创建 tar 文件时,这些字段始终设置为零/空。在读取 tar 文件时,除了验证每个头记录的头部校验和外,这些字段会被忽略。

source