Skip to content
This repository was archived by the owner on Sep 9, 2020. It is now read-only.

Commit d4803f7

Browse files
committed
internal/fs: clone symlinks on Windows and fall back to file copying
Signed-off-by: Ibrahim AshShohail <[email protected]>
1 parent 80ad660 commit d4803f7

File tree

1 file changed

+18
-20
lines changed

1 file changed

+18
-20
lines changed

internal/fs/fs.go

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"io/ioutil"
1010
"os"
1111
"path/filepath"
12+
"runtime"
1213
"strings"
1314
"unicode"
1415

@@ -270,9 +271,17 @@ func CopyDir(src, dst string) error {
270271
// the copied data is synced/flushed to stable storage.
271272
func copyFile(src, dst string) (err error) {
272273
if sym, err := IsSymlink(src); err != nil {
273-
return err
274+
return errors.Wrap(err, "symlink check failed")
274275
} else if sym {
275-
return cloneSymlink(src, dst)
276+
if err := cloneSymlink(src, dst); err != nil {
277+
if runtime.GOOS == "windows" && strings.HasSuffix(err.Error(), "A required privilege is not held by the client.") {
278+
// If cloning the symlink fails on Windows because the user
279+
// does not have the required privileges, ignore the error and
280+
// fall back to copying the file contents instead of cloning.
281+
} else {
282+
return err
283+
}
284+
}
276285
}
277286

278287
in, err := os.Open(src)
@@ -285,28 +294,22 @@ func copyFile(src, dst string) (err error) {
285294
if err != nil {
286295
return
287296
}
288-
defer func() {
289-
if e := out.Close(); e != nil {
290-
err = e
291-
}
292-
}()
297+
defer out.Close()
293298

294-
_, err = io.Copy(out, in)
295-
if err != nil {
299+
if _, err = io.Copy(out, in); err != nil {
296300
return
297301
}
298302

299-
err = out.Sync()
300-
if err != nil {
303+
if err = out.Sync(); err != nil {
301304
return
302305
}
303306

304307
si, err := os.Stat(src)
305308
if err != nil {
306309
return
307310
}
308-
err = os.Chmod(dst, si.Mode())
309-
if err != nil {
311+
312+
if err = os.Chmod(dst, si.Mode()); err != nil {
310313
return
311314
}
312315

@@ -318,15 +321,10 @@ func copyFile(src, dst string) (err error) {
318321
func cloneSymlink(sl, dst string) error {
319322
resolved, err := os.Readlink(sl)
320323
if err != nil {
321-
return errors.Wrap(err, "failed to resolve symlink")
322-
}
323-
324-
err = os.Symlink(resolved, dst)
325-
if err != nil {
326-
return errors.Wrapf(err, "failed to create symlink %s to %s", dst, resolved)
324+
return err
327325
}
328326

329-
return nil
327+
return os.Symlink(resolved, dst)
330328
}
331329

332330
// IsDir determines is the path given is a directory or not.

0 commit comments

Comments
 (0)