Merge pull request #222 from jonboulle/hardlinks

actool: properly deal with hardlinks when building images
This commit is contained in:
Jonathan Boulle
2014-12-07 17:49:37 -08:00
5 changed files with 22 additions and 7 deletions
+8 -1
View File
@@ -37,6 +37,8 @@ func init() {
}
func buildWalker(root string, aw aci.ArchiveWriter, rootfs bool) filepath.WalkFunc {
// cache of inode -> filepath, used to leverage hard links in the archive
inos := map[uint64]string{}
return func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
@@ -81,7 +83,12 @@ func buildWalker(root string, aw aci.ArchiveWriter, rootfs bool) filepath.WalkFu
// modify the Name field of the returned header to provide the
// full path name of the file.
hdr.Name = relpath
tarheader.Populate(hdr, info)
tarheader.Populate(hdr, info, inos)
// If the file is a hard link we don't need the contents
if hdr.Typeflag == tar.TypeLink {
hdr.Size = 0
file = nil
}
aw.AddFile(relpath, hdr, file)
return nil
+1 -1
View File
@@ -13,7 +13,7 @@ func init() {
populateHeaderStat = append(populateHeaderStat, populateHeaderCtime)
}
func populateHeaderCtime(h *tar.Header, fi os.FileInfo) {
func populateHeaderCtime(h *tar.Header, fi os.FileInfo, _ map[uint64]string) {
st, ok := fi.Sys().(*syscall.Stat_t)
if !ok {
return
+1 -1
View File
@@ -11,7 +11,7 @@ func init() {
populateHeaderStat = append(populateHeaderStat, populateHeaderCtime)
}
func populateHeaderCtime(h *tar.Header, fi os.FileInfo) {
func populateHeaderCtime(h *tar.Header, fi os.FileInfo, _ map[uint64]string) {
st, ok := fi.Sys().(*syscall.Stat_t)
if !ok {
return
+9 -1
View File
@@ -10,11 +10,19 @@ func init() {
populateHeaderStat = append(populateHeaderStat, populateHeaderUnix)
}
func populateHeaderUnix(h *tar.Header, fi os.FileInfo) {
func populateHeaderUnix(h *tar.Header, fi os.FileInfo, seen map[uint64]string) {
st, ok := fi.Sys().(*syscall.Stat_t)
if !ok {
return
}
h.Uid = int(st.Uid)
h.Gid = int(st.Gid)
// If we have already seen this inode, generate a hardlink
p, ok := seen[uint64(st.Ino)]
if ok {
h.Linkname = p
h.Typeflag = tar.TypeLink
} else {
seen[uint64(st.Ino)] = h.Name
}
}
+3 -3
View File
@@ -5,10 +5,10 @@ import (
"os"
)
var populateHeaderStat []func(h *tar.Header, fi os.FileInfo)
var populateHeaderStat []func(h *tar.Header, fi os.FileInfo, seen map[uint64]string)
func Populate(h *tar.Header, fi os.FileInfo) {
func Populate(h *tar.Header, fi os.FileInfo, seen map[uint64]string) {
for _, pop := range populateHeaderStat {
pop(h, fi)
pop(h, fi, seen)
}
}