diff options
author | Daniel J Walsh <dwalsh@redhat.com> | 2021-05-20 16:09:40 -0400 |
---|---|---|
committer | Daniel J Walsh <dwalsh@redhat.com> | 2021-05-22 05:27:03 -0400 |
commit | f22791aec7b4d942872ca21539a44d0375b73949 (patch) | |
tree | 6db26ccde1ea0defb78d21109be6b4d6997cf080 /pkg/bindings/images | |
parent | 490915c68e6fce48508d42d138ac1c92c877abe7 (diff) | |
download | podman-f22791aec7b4d942872ca21539a44d0375b73949.tar.gz podman-f22791aec7b4d942872ca21539a44d0375b73949.tar.bz2 podman-f22791aec7b4d942872ca21539a44d0375b73949.zip |
Handle hard links in remote builds
Fixes: https://github.com/containers/podman/issues/9893
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
Diffstat (limited to 'pkg/bindings/images')
-rw-r--r-- | pkg/bindings/images/build.go | 44 | ||||
-rw-r--r-- | pkg/bindings/images/build_unix.go | 16 | ||||
-rw-r--r-- | pkg/bindings/images/build_windows.go | 9 |
3 files changed, 57 insertions, 12 deletions
diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go index f5e7c0c98..b56afbceb 100644 --- a/pkg/bindings/images/build.go +++ b/pkg/bindings/images/build.go @@ -28,6 +28,11 @@ import ( "github.com/sirupsen/logrus" ) +type devino struct { + Dev uint64 + Ino uint64 +} + var ( iidRegex = regexp.MustCompile(`^[0-9a-f]{12}`) ) @@ -402,7 +407,7 @@ func nTar(excludes []string, sources ...string) (io.ReadCloser, error) { defer pw.Close() defer gw.Close() defer tw.Close() - + seen := make(map[devino]string) for _, src := range sources { s, err := filepath.Abs(src) if err != nil { @@ -431,25 +436,40 @@ func nTar(excludes []string, sources ...string) (io.ReadCloser, error) { } if info.Mode().IsRegular() { // add file item - f, lerr := os.Open(path) - if lerr != nil { - return lerr + di, isHardLink := checkHardLink(info) + if err != nil { + return err } - hdr, lerr := tar.FileInfoHeader(info, name) - if lerr != nil { - f.Close() - return lerr + hdr, err := tar.FileInfoHeader(info, "") + if err != nil { + return err + } + orig, ok := seen[di] + if ok { + hdr.Typeflag = tar.TypeLink + hdr.Linkname = orig + hdr.Size = 0 + + return tw.WriteHeader(hdr) + } + f, err := os.Open(path) + if err != nil { + return err } + hdr.Name = name - if lerr := tw.WriteHeader(hdr); lerr != nil { + if err := tw.WriteHeader(hdr); err != nil { f.Close() - return lerr + return err } - _, cerr := io.Copy(tw, f) + _, err = io.Copy(tw, f) f.Close() - return cerr + if err == nil && isHardLink { + seen[di] = name + } + return err } else if info.Mode().IsDir() { // add folders hdr, lerr := tar.FileInfoHeader(info, name) if lerr != nil { diff --git a/pkg/bindings/images/build_unix.go b/pkg/bindings/images/build_unix.go new file mode 100644 index 000000000..0afb1deb6 --- /dev/null +++ b/pkg/bindings/images/build_unix.go @@ -0,0 +1,16 @@ +// +build !windows + +package images + +import ( + "os" + "syscall" +) + +func checkHardLink(fi os.FileInfo) (devino, bool) { + st := fi.Sys().(*syscall.Stat_t) + return devino{ + Dev: uint64(st.Dev), + Ino: uint64(st.Ino), + }, st.Nlink > 1 +} diff --git a/pkg/bindings/images/build_windows.go b/pkg/bindings/images/build_windows.go new file mode 100644 index 000000000..bd71d1bf0 --- /dev/null +++ b/pkg/bindings/images/build_windows.go @@ -0,0 +1,9 @@ +package images + +import ( + "os" +) + +func checkHardLink(fi os.FileInfo) (devino, bool) { + return devino{}, false +} |