mirror of
https://github.com/containers/podman.git
synced 2025-05-17 23:26:08 +08:00
Handle hard links in remote builds
Fixes: https://github.com/containers/podman/issues/9893 Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:

committed by
Matthew Heon

parent
c53638e9f6
commit
ba884865c5
3
Makefile
3
Makefile
@ -382,6 +382,9 @@ bin/podman.cross.%: .gopathok
|
||||
.PHONY: local-cross
|
||||
local-cross: $(CROSS_BUILD_TARGETS) ## Cross compile podman binary for multiple architectures
|
||||
|
||||
.PHONY: cross
|
||||
cross: local-cross
|
||||
|
||||
# Update nix/nixpkgs.json its latest stable commit
|
||||
.PHONY: nixpkgs
|
||||
nixpkgs:
|
||||
|
@ -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 {
|
||||
|
16
pkg/bindings/images/build_unix.go
Normal file
16
pkg/bindings/images/build_unix.go
Normal file
@ -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
|
||||
}
|
9
pkg/bindings/images/build_windows.go
Normal file
9
pkg/bindings/images/build_windows.go
Normal file
@ -0,0 +1,9 @@
|
||||
package images
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
func checkHardLink(fi os.FileInfo) (devino, bool) {
|
||||
return devino{}, false
|
||||
}
|
@ -766,6 +766,26 @@ EOF
|
||||
is "$output" ".*/tmp/bogus: no such file or directory"
|
||||
}
|
||||
|
||||
@test "podman build COPY hardlinks " {
|
||||
tmpdir=$PODMAN_TMPDIR/build-test
|
||||
mkdir -p $tmpdir
|
||||
|
||||
dockerfile=$tmpdir/Dockerfile
|
||||
cat >$dockerfile <<EOF
|
||||
FROM $IMAGE
|
||||
COPY . /test
|
||||
EOF
|
||||
ln $dockerfile $tmpdir/hardlink
|
||||
|
||||
run_podman build -t build_test $tmpdir
|
||||
run_podman run --rm build_test stat -c '%i' /test/Dockerfile
|
||||
dinode=$output
|
||||
run_podman run --rm build_test stat -c '%i' /test/hardlink
|
||||
is "$output" "$dinode" "COPY hardlinks work"
|
||||
|
||||
run_podman rmi -f build_test
|
||||
}
|
||||
|
||||
function teardown() {
|
||||
# A timeout or other error in 'build' can leave behind stale images
|
||||
# that podman can't even see and which will cascade into subsequent
|
||||
|
Reference in New Issue
Block a user