回答
tar
會保留硬鏈接。
這裏的三個硬鏈接的文件,一個文件,一個環節一個樣品目錄:
foo% vdir .
total 16
-rw-r--r-- 3 kostix kostix 5 Jul 12 19:37 bar.txt
-rw-r--r-- 3 kostix kostix 5 Jul 12 19:37 foo.txt
-rw-r--r-- 3 kostix kostix 5 Jul 12 19:37 test.txt
-rw-r--r-- 1 kostix kostix 9 Jul 12 19:49 xyzzy.txt
現在我們將其歸檔使用GNU tar
並驗證它確實增加了鏈接 (因爲我們沒有傳遞給它--hard-dereferece
命令行選項):
foo% tar -cf ../foo.tar .
foo% tar -tvf ../foo.tar
drwxr-xr-x kostix/kostix 0 2016-07-12 19:49 ./
-rw-r--r-- kostix/kostix 9 2016-07-12 19:49 ./xyzzy.txt
-rw-r--r-- kostix/kostix 5 2016-07-12 19:37 ./bar.txt
hrw-r--r-- kostix/kostix 0 2016-07-12 19:37 ./test.txt link to ./bar.txt
hrw-r--r-- kostix/kostix 0 2016-07-12 19:37 ./foo.txt link to ./bar.txt
的archive/tar
文檔是指一束限定在tar
ARCHI標準文獻(不幸的是,沒有一個標準:例如,GNU tar不支持POSIX擴展屬性,而BSD tar(依賴於libarchive
),而pax
也是如此。 舉的硬鏈接其位:
LNKTYPE
此標誌表示鏈接到另一個文件的文件任何類型的, 先前存檔。這些文件在Unix中由每個具有相同設備和inode編號的文件標識。鏈接名稱在 鏈接名稱字段中指定,其後綴爲空。
因此,一個hadrlink是指一些 前述(已歸檔)通過其名稱的文件的特殊類型(「1」)的enrty。
所以我們來創建一個遊樂場的例子。
我們的base64編碼我們的檔案:
foo% base64 <../foo.tar | xclip -selection clipboard
&hellip;而寫the code。 檔案包含一個單一目錄,一個文件(類型'0'),另一個文件(類型'0'),後面跟着兩個硬鏈接(類型'1')。
從操場示例的輸出:
Archive entry '5': ./
Archive entry '0': ./xyzzy.txt
Archive entry '0': ./bar.txt
Archive entry '1': ./test.txt link to ./bar.txt
Archive entry '1': ./foo.txt link to ./bar.txt
所以你的鏈接計數代碼應該:
掃描整個檔案記錄,通過記錄。
記住任何常規文件(類型
archive/tar.TypeReg
或鍵入archive/tar.TypeRegA
)已經處理過的,並具有與其相關聯的計數器,從1開始。那麼,在現實中,你最好是獨家和記錄條目各類 除了符號鏈接和目錄—因爲焦油 檔案文件可以包含字符和塊設備節點和FIFO(命名管道)。
當你遇到一個硬鏈接(類型
archive/tar.TypeReg
),- 閱讀它的頭的
Linkname
領域。 - 查看「已見」文件的列表,並增加與該名稱匹配的條目的計數器 。在2016年7月13日
- 閱讀它的頭的
更新作爲OP其實是想知道如何在 源文件系統管理的硬鏈接,這裏的更新。
的主要想法是,與POSIX語義文件系統:
目錄項指定一個文件實際上指向稱爲「索引節點」的特殊 文件系統元數據塊。 inode包含指向它的目錄條目數 。
創建硬鏈接實際上只是:
- 創建新目錄條目指向的inode原始(源)的 在
ln
條款文件—「鏈接目標」。 - 遞增該inode中的鏈接計數器。
- 創建新目錄條目指向的inode原始(源)的 在
因此,任何文件被唯一地標識由兩個整數: 「設備號」標識主機文件系統 在其上的文件的位置,並且節點號碼識別該文件的數據的物理設備。
接下來,如果兩個文件具有相同的(設備,inode)對,則它們表示相同的內容。或者,如果我們換一種說法,其中一個 是另一個的硬鏈接。
因此,將文件添加至tar
存檔,同時保留硬鏈接的工作原理是這樣的:
已經添加了一個文件,它的(設備,索引節點)對保存一些查找表。
當添加另一個文件時,找出它的(設備,inode)對,然後在該表中查找它。
如果找到匹配項,則表明文件的數據已經傳輸,我們應該添加一個硬鏈接。
否則,表現如步驟(1)。
所以這裏的代碼:
package main
import (
"archive/tar"
"io"
"log"
"os"
"path/filepath"
"syscall"
)
type devino struct {
Dev uint64
Ino uint64
}
func main() {
log.SetFlags(0)
if len(os.Args) != 2 {
log.Fatalf("Usage: %s DIR\n", os.Args[0])
}
seen := make(map[devino]string)
tw := tar.NewWriter(os.Stdout)
err := filepath.Walk(os.Args[1],
func(fn string, fi os.FileInfo, we error) (err error) {
if we != nil {
log.Fatal("Error processing directory", we)
}
hdr, err := tar.FileInfoHeader(fi, "")
if err != nil {
return
}
if fi.IsDir() {
err = tw.WriteHeader(hdr)
return
}
st := fi.Sys().(*syscall.Stat_t)
di := devino{
Dev: st.Dev,
Ino: st.Ino,
}
orig, ok := seen[di]
if ok {
hdr.Typeflag = tar.TypeLink
hdr.Linkname = orig
hdr.Size = 0
err = tw.WriteHeader(hdr)
return
}
fd, err := os.Open(fn)
if err != nil {
return
}
err = tw.WriteHeader(hdr)
if err != nil {
return
}
_, err = io.Copy(tw, fd)
fd.Close() // Ignoring error for a file opened R/O
if err == nil {
seen[di] = fi.Name()
}
return err
})
if err != nil {
log.Fatal(err)
}
err = tw.Close()
if err != nil {
log.Fatal(err)
}
return
}
請注意,這是相當跛:
它不適當地文件和目錄名的交易。
它並不試圖用正確的符號鏈接和FIFO, 工作,並跳過Unix域套接字等
它假定它工作在一個POSIX環境。
在非POSIX系統中,
Sys()
方法呼籲os.FileInfo
類型的值可能會返回別的東西,而不是POSIX'ysyscall.Stat_t
。假設在Windows上有多個由不同的 「磁盤」或「驅動器」託管的文件系統。我不知道Go如何處理它。 也許在這種情況下,必須以某種方式模擬「設備號」。
在另一方面,它顯示瞭如何處理硬鏈接:
- 將頭結構的「鏈接名稱」字段。
- 將標題的「大小」字段重置爲0(因爲沒有數據會跟隨)。
您可能還需要使用其他方法來維持查找表:如果你的大多數文件都預計將位於同一個物理文件系統,每個條目爲每個條目的設備編號浪費的uint64
。因此,地圖層次結構可能是一個明智的做法:首先將設備編號映射到將inode編號映射到文件名的另一個映射。
希望這會有所幫助。
哇我不期待這麼多的反饋!這些是一些真正有用的觀點,謝謝分享:) – steve
- 1. tar文件歸檔不
- 2. 保存歸檔的文檔文件夾
- 3. 測試文件中tar歸檔
- 4. 遞歸硬鏈接
- 5. Autotools - tar這看起來不像一個tar歸檔文件
- 6. 提取鏈接描述歸檔文件
- 7. 如何使用Perl的Archive :: Tar保存tar檔案文件中的setuid位?
- 8. 列表的多個.tar歸檔文件的文件
- 9. 提取存儲在tar歸檔文件中的以前版本的文件
- 10. Golang:將文件追加到現有的tar歸檔文件
- 11. 刪除從tar歸檔文件中提取的文件
- 12. 排除從tar歸檔文件目錄中有.tarignore文件
- 13. 如何使用compress/gzip和archive/tar創建壓縮的tar歸檔文件?
- 14. 使用php提取空目錄的tar歸檔文件PharData
- 15. 將tar文件歸檔到Perl中的其他位置
- 16. 鏈接到文檔附件的鏈接
- 17. GCC鏈接 - 指定存檔文件
- 18. 截斷的tar歸檔錯誤
- 19. 碼頭加載和保存:歸檔/ tar:無效的焦點標題
- 20. tar僅列出歸檔文件而不是目錄
- 21. tar命令無法找到文件歸檔
- 22. Ruby:創建一個Gzipped Tar歸檔文件
- 23. 擦除文件後保持硬鏈接連接
- 24. 「歸檔」 CSV到存檔文件夾
- 25. 在Ruby中,如何將tar歸檔流直接提取到文件系統?
- 26. 鏈接硬件庫
- 27. 使用python遞歸創建硬鏈接
- 28. 隱藏符號鏈接文件夾到硬鏈接文件夾
- 29. 如何將文件追加到Java中的.tar歸檔文件中?
- 30. 如何創建不會展開到子文件夾的tar歸檔文件?
其實我已經重新閱讀你的問題好幾次,現在扶着想到你居然要問如何找到硬鏈接的文件*在源文件系統*當它們被添加到壓縮文件,而不是怎麼算的在tar檔案中的硬連接文件的數量(我回答的問題)。你能否詳細說明你想問什麼? – kostix
嘿kostix, 我其實的意思是問如何計算硬鏈接的數量,同時流式存檔。儘管感謝您的輸入! – steve
好的,用PoC實現更新我的代碼。適用於我的硬鏈接的測試目錄(對文件/目錄名的模數處理不完整);我沒有時間調整它,像股票'焦油'工作,對不起。 – kostix