diff options
Diffstat (limited to 'src/copy.go')
-rw-r--r-- | src/copy.go | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/copy.go b/src/copy.go new file mode 100644 index 0000000..1076d41 --- /dev/null +++ b/src/copy.go @@ -0,0 +1,124 @@ + +// Package gorecurcopy provides recursive copying in Go (golang) with a +// minimum of extra packages. Original concept by Oleg Neumyvakin +// (https://stackoverflow.com/users/1592008/oleg-neumyvakin) and modified +// by Dirk Avery. +// Slightly modified by me. +package main + +import ( + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + // "syscall" +) + +// copyDir recursively copies a src directory to a destination. +func copyDir(src, dst string) error { + entries, err := ioutil.ReadDir(src) + if err != nil { + return err + } + for _, entry := range entries { + sourcePath := filepath.Join(src, entry.Name()) + destPath := filepath.Join(dst, entry.Name()) + + fileInfo, err := os.Lstat(sourcePath) + if err != nil { + return err + } + + switch fileInfo.Mode() & os.ModeType { + case os.ModeDir: + if err := _createDir(destPath, 0755); err != nil { + return err + } + if err := copyDir(sourcePath, destPath); err != nil { + return err + } + case os.ModeSymlink: + if err := copySymlink(sourcePath, destPath); err != nil { + return err + } + default: + if err := _copy(sourcePath, destPath); err != nil { + return err + } + } + + /* + stat, ok := fileInfo.Sys().(*syscall.Stat_t) + if !ok { + return fmt.Errorf("failed to get raw syscall.Stat_t data for '%s'", sourcePath) + } + if err := os.Lchown(destPath, int(stat.Uid), int(stat.Gid)); err != nil { + return err + } + */ + + isSymlink := entry.Mode()&os.ModeSymlink != 0 + if !isSymlink { + if err := os.Chmod(destPath, entry.Mode()); err != nil { + return err + } + } + } + return nil +} + +// Copy copies a src file to a dst file where src and dst are regular files. +func _copy(src, dst string) error { + sourceFileStat, err := os.Stat(src) + if err != nil { + return err + } + + if !sourceFileStat.Mode().IsRegular() { + return fmt.Errorf("%s is not a regular file", src) + } + + source, err := os.Open(src) + if err != nil { + return err + } + defer source.Close() + + destination, err := os.Create(dst) + if err != nil { + return err + } + defer destination.Close() + _, err = io.Copy(destination, source) + return err +} + +func _exists(path string) bool { + if _, err := os.Stat(path); os.IsNotExist(err) { + return false + } + + return true +} + +func _createDir(dir string, perm os.FileMode) error { + if _exists(dir) { + return nil + } + + if err := os.MkdirAll(dir, perm); err != nil { + return fmt.Errorf("failed to create directory: '%s', error: '%s'", dir, err.Error()) + } + + return nil +} + +// copySymlink copies a symbolic link from src to dst. +func copySymlink(src, dst string) error { + link, err := os.Readlink(src) + if err != nil { + return err + } + return os.Symlink(link, dst) +} |