diff --git a/internal/fs/fs.go b/internal/fs/fs.go index a79032017b..f72d0832dd 100644 --- a/internal/fs/fs.go +++ b/internal/fs/fs.go @@ -9,6 +9,7 @@ import ( "io/ioutil" "os" "path/filepath" + "runtime" "strings" "unicode" @@ -269,12 +270,15 @@ func CopyDir(src, dst string) error { // of the source file. The file mode will be copied from the source and // the copied data is synced/flushed to stable storage. func copyFile(src, dst string) (err error) { - if sym, err := IsSymlink(src); err != nil { - return err - } else if sym { - err := copySymlink(src, dst) + sym, err := IsSymlink(src) + if err != nil { return err } + // Skip cloning the symlink on Windows and fallback to copying the file content + // since creating a symlink on Windows requires admin permissions. + if sym && runtime.GOOS != "windows" { + return cloneSymlink(src, dst) + } in, err := os.Open(src) if err != nil { @@ -314,17 +318,17 @@ func copyFile(src, dst string) (err error) { return } -// copySymlink will resolve the src symlink and create a new symlink in dst. -// If src is a relative symlink, dst will also be a relative symlink. -func copySymlink(src, dst string) error { - resolved, err := os.Readlink(src) +// cloneSymlink will resolve sl and create a new symlink in dst. +// If sl is a relative symlink, dst will also be a relative symlink. +func cloneSymlink(sl, dst string) error { + resolved, err := os.Readlink(sl) if err != nil { return errors.Wrap(err, "failed to resolve symlink") } err = os.Symlink(resolved, dst) if err != nil { - return errors.Wrapf(err, "failed to create symlink %s to %s", src, resolved) + return errors.Wrapf(err, "failed to create symlink %s to %s", dst, resolved) } return nil