Update add to tar to correctly handle hard links

This commit is contained in:
Priya Wadhwa 2018-03-07 15:34:14 -08:00
parent 3195b84c25
commit 6668fa0d6f
No known key found for this signature in database
GPG Key ID: 0D0DAFD8F7AA73AE
1 changed files with 33 additions and 2 deletions

View File

@ -18,10 +18,14 @@ package util
import ( import (
"archive/tar" "archive/tar"
"github.com/sirupsen/logrus"
"io" "io"
"os" "os"
"syscall"
) )
var hardlinks = make(map[uint64]string)
// AddToTar adds the file i to tar w at path p // AddToTar adds the file i to tar w at path p
func AddToTar(p string, i os.FileInfo, w *tar.Writer) error { func AddToTar(p string, i os.FileInfo, w *tar.Writer) error {
linkDst := "" linkDst := ""
@ -32,19 +36,46 @@ func AddToTar(p string, i os.FileInfo, w *tar.Writer) error {
return err return err
} }
} }
hardlink := false
if sys := i.Sys(); sys != nil {
if stat, ok := sys.(*syscall.Stat_t); ok {
nlinks := stat.Nlink
if nlinks > 1 {
inode := stat.Ino
if original, exists := hardlinks[inode]; exists && original != p {
hardlink = true
logrus.Infof("%s inode exists in hardlinks map, linking to %s", p, original)
linkDst = original
} else {
hardlinks[inode] = p
}
}
}
}
hdr, err := tar.FileInfoHeader(i, linkDst) hdr, err := tar.FileInfoHeader(i, linkDst)
if err != nil { if err != nil {
return err return err
} }
hdr.Name = p hdr.Name = p
w.WriteHeader(hdr)
if !i.Mode().IsRegular() { if hardlink {
hdr.Linkname = linkDst
hdr.Typeflag = tar.TypeLink
hdr.Size = 0
}
if err := w.WriteHeader(hdr); err != nil {
return err
}
if !(i.Mode().IsRegular()) || hardlink {
return nil return nil
} }
r, err := os.Open(p) r, err := os.Open(p)
if err != nil { if err != nil {
return err return err
} }
defer r.Close()
if _, err := io.Copy(w, r); err != nil { if _, err := io.Copy(w, r); err != nil {
return err return err
} }