1
// Copyright 2014 Canonical Ltd.
2
// Licensed under the LGPLv3, see LICENCE file for details.
13
// Copy recursively copies the file, directory or symbolic link at src
14
// to dst. The destination must not exist. Symbolic links are not
17
// If the copy fails half way through, the destination might be left
19
func Copy(src, dst string) error {
20
srcInfo, srcErr := os.Lstat(src)
24
_, dstErr := os.Lstat(dst)
26
// TODO(rog) add a flag to permit overwriting?
27
return fmt.Errorf("will not overwrite %q", dst)
29
if !os.IsNotExist(dstErr) {
32
switch mode := srcInfo.Mode(); mode & os.ModeType {
34
return copySymLink(src, dst)
36
return copyDir(src, dst, mode)
38
return copyFile(src, dst, mode)
40
return fmt.Errorf("cannot copy file with mode %v", mode)
44
func copySymLink(src, dst string) error {
45
target, err := os.Readlink(src)
49
return os.Symlink(target, dst)
52
func copyFile(src, dst string, mode os.FileMode) error {
53
srcf, err := os.Open(src)
58
dstf, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode.Perm())
63
// Make the actual permissions match the source permissions
64
// even in the presence of umask.
65
if err := os.Chmod(dstf.Name(), mode.Perm()); err != nil {
68
if _, err := io.Copy(dstf, srcf); err != nil {
69
return fmt.Errorf("cannot copy %q to %q: %v", src, dst, err)
74
func copyDir(src, dst string, mode os.FileMode) error {
75
srcf, err := os.Open(src)
81
// The source directory doesn't have write permission,
82
// so give the new directory write permission anyway
83
// so that we have permission to create its contents.
84
// We'll make the permissions match at the end.
87
if err := os.Mkdir(dst, mode.Perm()); err != nil {
91
names, err := srcf.Readdirnames(100)
92
for _, name := range names {
93
if err := Copy(filepath.Join(src, name), filepath.Join(dst, name)); err != nil {
101
return fmt.Errorf("error reading directory %q: %v", src, err)
104
if err := os.Chmod(dst, mode.Perm()); err != nil {