From 8cdb92e327a86ec4e9ccfdea04ee3d36819c4d40 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 25 Sep 2013 10:42:49 +0200 Subject: [PATCH] communicator/ssh: dir upload works when dir contains symlinks [Gh-449] --- CHANGELOG.md | 2 ++ communicator/ssh/communicator.go | 23 +++++++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 589492ae7..60b1780d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ BUG FIXES: * core: default user variable values don't need to be strings. [GH-456] * builder/amazon-chroot: Fix errors with waitin for state change. [GH-459] +* communicator/ssh: SCP uploads now work properly when directories + contain symlinks. [GH-449] ## 0.3.8 (September 22, 2013) diff --git a/communicator/ssh/communicator.go b/communicator/ssh/communicator.go index 96de20de0..e2eea4b21 100644 --- a/communicator/ssh/communicator.go +++ b/communicator/ssh/communicator.go @@ -408,8 +408,27 @@ func scpUploadDir(root string, fs []os.FileInfo, w io.Writer, r *bufio.Reader) e for _, fi := range fs { realPath := filepath.Join(root, fi.Name()) - if !fi.IsDir() { - // It is a regular file, just upload it + // Track if this is actually a symlink to a directory. If it is + // a symlink to a file we don't do any special behavior because uploading + // a file just works. If it is a directory, we need to know so we + // treat it as such. + isSymlinkToDir := false + if fi.Mode() & os.ModeSymlink == os.ModeSymlink { + symPath, err := filepath.EvalSymlinks(realPath) + if err != nil { + return err + } + + symFi, err := os.Lstat(symPath) + if err != nil { + return err + } + + isSymlinkToDir = symFi.IsDir() + } + + if !fi.IsDir() && !isSymlinkToDir { + // It is a regular file (or symlink to a file), just upload it f, err := os.Open(realPath) if err != nil { return err