Fix hardlinks in tar output

When we converted these to cpio we were not noticing that they
were invalid as they had incorrect paths as we converted the
path to a symlink anyway. Only the busybox images have hard links
in, the Alpine ones are symlinks anyway, which is why it was
less visible too.

Signed-off-by: Justin Cormack <justin.cormack@docker.com>
This commit is contained in:
Justin Cormack 2017-08-01 17:04:57 +01:00
parent 14a4d923ae
commit 48e42540d2
2 changed files with 15 additions and 1 deletions

View File

@ -7,6 +7,7 @@ import (
"errors" "errors"
"io" "io"
"io/ioutil" "io/ioutil"
"path/filepath"
"github.com/moby/tool/src/pad4" "github.com/moby/tool/src/pad4"
"github.com/surma/gocpio" "github.com/surma/gocpio"
@ -27,8 +28,17 @@ func typeconv(thdr *tar.Header) int64 {
case tar.TypeRegA: case tar.TypeRegA:
return cpio.TYPE_REG return cpio.TYPE_REG
// Currently hard links not supported very well :) // Currently hard links not supported very well :)
// Convert to relative symlink as absolute will not work in container
// cpio does support hardlinks but file contents still duplicated, so rely
// on compression to fix that which is fairly ugly. Symlink has not caused issues.
case tar.TypeLink: case tar.TypeLink:
thdr.Linkname = "/" + thdr.Linkname dir := filepath.Dir(thdr.Name)
rel, err := filepath.Rel(dir, thdr.Linkname)
if err != nil {
// should never happen, but leave as full abs path
rel = "/" + thdr.Linkname
}
thdr.Linkname = rel
return cpio.TYPE_SYMLINK return cpio.TYPE_SYMLINK
case tar.TypeSymlink: case tar.TypeSymlink:
return cpio.TYPE_SYMLINK return cpio.TYPE_SYMLINK

View File

@ -172,6 +172,10 @@ func ImageTar(image, prefix string, tw tarWriter, trust bool, pull bool, resolv
} else { } else {
log.Debugf("image tar: %s %s add %s", image, prefix, hdr.Name) log.Debugf("image tar: %s %s add %s", image, prefix, hdr.Name)
hdr.Name = prefix + hdr.Name hdr.Name = prefix + hdr.Name
if hdr.Typeflag == tar.TypeLink {
// hard links are referenced by full path so need to be adjusted
hdr.Linkname = prefix + hdr.Linkname
}
if err := tw.WriteHeader(hdr); err != nil { if err := tw.WriteHeader(hdr); err != nil {
return err return err
} }