From 2c13842451223261c5e585f527f1732e510db60d Mon Sep 17 00:00:00 2001 From: Cole Wippern Date: Tue, 12 Nov 2019 17:07:12 -0800 Subject: [PATCH] Resolve symlink paths --- pkg/commands/copy.go | 26 ++++++++++++++++++++++++++ pkg/util/fs_util.go | 8 +++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/pkg/commands/copy.go b/pkg/commands/copy.go index 15f778e8de..ad75f6f3f2 100644 --- a/pkg/commands/copy.go +++ b/pkg/commands/copy.go @@ -66,6 +66,14 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu if err != nil { return err } + + // If the destination dir is a symlink we need to resolve the path and use + // that instead of the symlink path + destPath, err = resolveIfSymlink(destPath) + if err != nil { + return err + } + if fi.IsDir() { if !filepath.IsAbs(dest) { // we need to add '/' to the end to indicate the destination is a directory @@ -178,3 +186,21 @@ func (cr *CachingCopyCommand) FilesToSnapshot() []string { func (cr *CachingCopyCommand) String() string { return cr.cmd.String() } + +func resolveIfSymlink(destPath string) (string, error) { + baseDir := filepath.Dir(destPath) + if info, err := os.Lstat(baseDir); err == nil { + switch mode := info.Mode(); { + case mode&os.ModeSymlink != 0: + linkPath, err := os.Readlink(baseDir) + if err != nil { + return "", errors.Wrap(err, "error reading symlink") + } + absLinkPath := filepath.Join(filepath.Dir(baseDir), linkPath) + newPath := filepath.Join(absLinkPath, filepath.Base(destPath)) + logrus.Tracef("Updating destination path from %v to %v due to symlink", destPath, newPath) + return newPath, nil + } + } + return destPath, nil +} diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index 00562e56f3..10fccb7f7b 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -424,11 +424,17 @@ func FilepathExists(path string) bool { func CreateFile(path string, reader io.Reader, perm os.FileMode, uid uint32, gid uint32) error { // Create directory path if it doesn't exist baseDir := filepath.Dir(path) - if _, err := os.Lstat(baseDir); os.IsNotExist(err) { + if info, err := os.Lstat(baseDir); os.IsNotExist(err) { logrus.Tracef("baseDir %s for file %s does not exist. Creating.", baseDir, path) if err := os.MkdirAll(baseDir, 0755); err != nil { return err } + } else { + switch mode := info.Mode(); { + case mode&os.ModeSymlink != 0: + logrus.Infof("destination cannot be a symlink %v", baseDir) + return errors.New("destination cannot be a symlink") + } } dest, err := os.Create(path) if err != nil {