Tar

Tar.create函式
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) 為 true 時,path 才會包含在 tarball 中。如果 predicate(path) 對目錄傳回 false,目錄就會完全排除:目錄下的任何內容都不會包含在檔案中。

如果傳遞了 skeleton 關鍵字,則將給定的檔案或 IO 句柄用作產生 tarball 的「skeleton」。您可以透過將 skeleton 關鍵字傳遞給 extract 指令來建立 skeleton 檔案。如果使用該 skeleton 檔案呼叫 create,且提取的檔案沒有變更,則會重新建立一個相同的 tarball。skeletonpredicate 參數不能同時使用。

如果 portable 旗標為 true,則會在 Windows 上檢查路徑名稱的有效性,以確保它們不包含非法字元或保留名稱。請參閱 https://stackoverflow.com/a/31976060/659248 以取得詳細資訊。

Tar.extract函數
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 必須是現有的空目錄或可以建立為新目錄的不存在路徑。如果未指定 dir,則會將檔案解壓縮到暫時目錄中,而該目錄會由 extract 傳回。

如果傳遞了 predicate 函數,則會在解壓縮 tarball 時對遇到的每個 Header 物件呼叫該函數,並且只有在 predicate(hdr) 為 true 時才會解壓縮該項目。這可用於選擇性地僅解壓縮檔案的一部分,略過會導致 extract 擲回錯誤的項目,或記錄解壓縮過程中解壓縮的內容。

在傳遞給謂詞函數之前,Header 物件會從 tarball 中的原始標頭稍作修改:path 欄位會正規化,移除 . 項目,並將多個連續的斜線替換為單一斜線。如果項目類型為 :hardlink,連結目標路徑會以相同方式正規化,以便與目標項目的路徑相符;大小欄位會設定為目標路徑的大小(目標路徑必須是已見過的文件)。

如果傳遞了 skeleton 關鍵字,則會將解壓縮的 tarball 的「skeleton」寫入檔案或給定的 IO 處理常式。此 skeleton 檔案可透過將 skeleton 關鍵字傳遞給 create 函數來重新建立相同的 tarball。skeletonpredicate 參數無法同時使用。

如果 copy_symlinkstrue,則會將符號連結解壓縮為其連結到的內容的副本,而非解壓縮為符號連結本身,前提是這些連結在 tarball 內部,而且可以這麼做。非內部符號連結,例如連結到 /etc/passwd 的符號連結,將不會被複製。任何形式的循環符號連結也不會被複製,而是會被略過。預設情況下,extract 會偵測是否可以在 dir 中建立符號連結,如果無法建立,則會自動複製符號連結。

如果 set_permissionsfalse,則不會對解壓縮的文件設定任何權限。

Tar.list函數
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 呼叫 callback。如果 tarball 中的項目數量龐大,或是在 tarball 中發生錯誤之前想要檢查項目,這會很有用。如果 callback 函式可以接受第二個引數,型別為 Vector{UInt8}Vector{Pair{Symbol, String}},則會呼叫它,並將原始標頭資料表示為單一位元組向量,或將欄位名稱對應至該欄位原始資料的配對向量(如果將這些欄位串接在一起,結果就是標頭的原始資料)。

預設情況下,如果 list 遇到 extract 函式拒絕解壓縮的任何 tarball 內容,就會發生錯誤。使用 strict=false,它會略過這些檢查,並列出 tar 檔案的所有內容,無論 extract 是否會解壓縮它們。請注意,惡意的 tarball 可以執行各種狡猾且出乎意料的事情,試圖誘騙您執行惡意行為。

如果 tarball 引數是架構檔案(請參閱 extractcreate),則 list 會從檔案標頭中偵測到這一點,並適當地列出或反覆運算架構檔案的標頭。

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

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

old_tarball 改寫為 create 產生的標準格式,同時也檢查它不包含任何會導致 extract 引發錯誤的內容。這在功能上等同於執行

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

然而,它從不將任何內容解壓縮到磁碟,而是使用 seek 函數來瀏覽舊 tarball 的資料。如果沒有傳遞 new_tarball 參數,新的 tarball 會寫入一個臨時檔案,並傳回其路徑。

如果傳遞 predicate 函數,則會在解壓縮 old_tarball 時呼叫它,並在 predicate(hdr) 為 true 時略過該項目。這可以用於選擇性地僅重寫檔案庫的某些部分,略過會導致 extract 擲出錯誤的項目,或記錄在重寫過程中遇到的內容。

在傳遞給謂詞函數之前,Header 物件會從 tarball 中的原始標頭稍作修改:path 欄位會正規化,移除 . 項目,並將多個連續的斜線替換為單一斜線。如果項目類型為 :hardlink,連結目標路徑會以相同方式正規化,以便與目標項目的路徑相符;大小欄位會設定為目標路徑的大小(目標路徑必須是已見過的文件)。

如果 portable 旗標為 true,則會在 Windows 上檢查路徑名稱的有效性,以確保它們不包含非法字元或保留名稱。請參閱 https://stackoverflow.com/a/31976060/659248 以取得詳細資訊。

Tar.tree_hash函數
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 的檔案樹,也就是僅包含檔案、符號連結和非空目錄的檔案樹,此函數計算出的雜湊值會與 git 為該檔案樹計算出的雜湊值相同。請注意,tarball 可以表示包含空目錄的檔案樹,而 git 無法儲存這些檔案樹,此函數可以為這些檔案樹產生雜湊值,預設情況下(請參閱下方的 skip_empty,了解如何變更此行為),這些雜湊值會與略過這些空目錄的 tarball 的雜湊值不同。簡而言之,雜湊函數在 git 可以表示的所有樹狀結構上與 git 相符,但會以一致的方式將可雜湊樹狀結構的網域擴充到 git 無法表示的其他樹狀結構。

如果傳遞了 predicate 函數,則會在處理 tarball 時對遇到的每個 Header 物件呼叫該函數,並且僅當 predicate(hdr) 為 true 時才對項目進行雜湊。這可用於選擇性地僅對檔案庫的某些部分進行雜湊,以略過導致 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=true 計算的 tree_hash 雜湊值相符。換句話說,這個選項允許 tree_hash 模擬 git 如何對包含空目錄的樹狀結構進行雜湊。但是,如果您要雜湊可能包含空目錄的樹狀結構(即不是來自 git 儲存庫),建議您使用不會忽略空目錄的工具(例如這個工具)對它們進行雜湊。

Tar.Header類型

Header 類型是一個結構,表示 tar 檔案中單一記錄的基本元資料,其定義如下

struct Header
    path :: String # path relative to the root
    type :: Symbol # type indicator (see below)
    mode :: UInt16 # mode/permissions (best viewed in octal)
    size :: Int64  # size of record data in bytes
    link :: String # target path of a symlink
end

類型以下列符號表示:filehardlinksymlinkchardevblockdevdirectoryfifo,或對於未知類型,則以類型標記字元作為符號。請注意,extract 拒絕解壓縮類型為 filesymlinkdirectory 以外的記錄;list 僅會在以 strict=false 呼叫時列出其他類型的記錄。

tar 格式包含關於記錄的各種其他元資料,包括使用者和群組 ID、使用者和群組名稱,以及時間戳記。Tar 套件在設計上完全忽略這些。在建立 tar 檔案時,這些欄位總是設定為零/空。在讀取 tar 檔案時,這些欄位會被忽略,除了驗證每個標頭記錄的所有欄位的標頭檢查和之外。