Merge pull request #852 from tonistiigi/contenthash-symlink-parent

contenthash: fix symlink parent reference
docker-19.03
Akihiro Suda 2019-03-05 12:31:47 +09:00 committed by GitHub
commit 038973d423
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 15 deletions

View File

@ -736,26 +736,33 @@ func getFollowLinksWalk(root *iradix.Node, k []byte, follow bool, linksWalked *i
dir, file := splitKey(k)
_, parent, err := getFollowLinksWalk(root, dir, follow, linksWalked)
k, parent, err := getFollowLinksWalk(root, dir, follow, linksWalked)
if err != nil {
return nil, nil, err
}
if parent != nil && parent.Type == CacheRecordTypeSymlink {
*linksWalked++
if *linksWalked > 255 {
return nil, nil, errors.Errorf("too many links")
if parent != nil {
if parent.Type == CacheRecordTypeSymlink {
*linksWalked++
if *linksWalked > 255 {
return nil, nil, errors.Errorf("too many links")
}
dirPath := path.Clean(string(convertKeyToPath(dir)))
if dirPath == "." || dirPath == "/" {
dirPath = ""
}
link := path.Clean(parent.Linkname)
if !path.IsAbs(link) {
link = path.Join("/", path.Join(path.Dir(dirPath), link))
}
return getFollowLinksWalk(root, append(convertPathToKey([]byte(link)), file...), follow, linksWalked)
}
dirPath := path.Clean(string(convertKeyToPath(dir)))
if dirPath == "." || dirPath == "/" {
dirPath = ""
}
link := path.Clean(parent.Linkname)
if !path.IsAbs(link) {
link = path.Join("/", path.Join(path.Dir(dirPath), link))
}
return getFollowLinksWalk(root, append(convertPathToKey([]byte(link)), file...), follow, linksWalked)
}
k = append(k, file...)
v, ok = root.Get(k)
if ok {
return k, v.(*CacheRecord), nil
}
}
return nil, nil, nil
}

View File

@ -564,6 +564,61 @@ func TestSymlinkAbsDirSuffix(t *testing.T) {
require.NoError(t, err)
}
func TestSymlinkThroughParent(t *testing.T) {
t.Parallel()
tmpdir, err := ioutil.TempDir("", "buildkit-state")
require.NoError(t, err)
defer os.RemoveAll(tmpdir)
snapshotter, err := native.NewSnapshotter(filepath.Join(tmpdir, "snapshots"))
require.NoError(t, err)
cm := setupCacheManager(t, tmpdir, snapshotter)
defer cm.Close()
ch := []string{
"ADD lib dir",
"ADD lib/sub dir",
"ADD lib/sub/foo file data0",
"ADD lib/sub/link symlink ../../lib2",
"ADD lib2 dir",
"ADD lib2/sub dir",
"ADD lib2/sub/foo file data0",
"ADD link1 symlink /lib",
"ADD link2 symlink /lib/",
"ADD link3 symlink /lib/.",
"ADD link4 symlink /lib/../lib",
"ADD link5 symlink ../lib",
}
ref := createRef(t, cm, ch)
dgst, err := Checksum(context.TODO(), ref, "link1/sub/foo", true)
require.NoError(t, err)
require.Equal(t, dgstFileData0, dgst)
dgst, err = Checksum(context.TODO(), ref, "link2/sub/foo", true)
require.NoError(t, err)
require.Equal(t, dgstFileData0, dgst)
dgst, err = Checksum(context.TODO(), ref, "link3/sub/foo", true)
require.NoError(t, err)
require.Equal(t, dgstFileData0, dgst)
dgst, err = Checksum(context.TODO(), ref, "link4/sub/foo", true)
require.NoError(t, err)
require.Equal(t, dgstFileData0, dgst)
dgst, err = Checksum(context.TODO(), ref, "link5/sub/foo", true)
require.NoError(t, err)
require.Equal(t, dgstFileData0, dgst)
dgst, err = Checksum(context.TODO(), ref, "link1/sub/link/sub/foo", true)
require.NoError(t, err)
require.Equal(t, dgstFileData0, dgst)
err = ref.Release(context.TODO())
require.NoError(t, err)
}
func TestSymlinkInPathHandleChange(t *testing.T) {
t.Parallel()
tmpdir, err := ioutil.TempDir("", "buildkit-state")