1 package linux
2
3 import (
4 "fmt"
5 "io"
6 "io/ioutil"
7 "os"
8 "path/filepath"
9 "syscall"
10 )
11
12 func CopyDir(srcDir, dest string) error {
13 err := os.MkdirAll(dest, 0777)
14 if err != nil {
15 return err
16 }
17 c := copy{permIgnore: true}
18 err = c.copyDirInternal(srcDir, dest)
19 return err
20 }
21
22 type copy struct {
23 permIgnore bool
24 }
25
26 func (c *copy) copyDirInternal(srcDir, dest string) error {
27 entries, err := ioutil.ReadDir(srcDir)
28 if err != nil {
29 return err
30 }
31 for _, entry := range entries {
32 sourcePath := filepath.Join(srcDir, entry.Name())
33 destPath := filepath.Join(dest, entry.Name())
34
35 fileInfo, err := os.Stat(sourcePath)
36 if err != nil {
37 return fmt.Errorf("stat(%s) failed: %s", sourcePath, err)
38 }
39
40 stat, ok := fileInfo.Sys().(*syscall.Stat_t)
41 if !ok {
42 return fmt.Errorf("failed to get raw syscall.Stat_t data for '%s'", sourcePath)
43 }
44
45 switch fileInfo.Mode() & os.ModeType {
46 case os.ModeDir:
47 if err := CreateIfNotExists(destPath, 0755); err != nil {
48 return err
49 }
50 if err := c.copyDirInternal(sourcePath, destPath); err != nil {
51 return err
52 }
53 case os.ModeSymlink:
54 if err := CopySymLink(sourcePath, destPath); err != nil {
55 return err
56 }
57 default:
58 if err := Copy(sourcePath, destPath); err != nil {
59 return err
60 }
61 }
62
63
64 err = os.Lchown(destPath, int(stat.Uid), int(stat.Gid))
65 if !c.permIgnore && err != nil {
66 return fmt.Errorf("lchown(file=%s,uid=%d,gid=%d) failed: %s", destPath, stat.Uid, stat.Gid, err)
67 }
68 isSymlink := entry.Mode()&os.ModeSymlink != 0
69 if !isSymlink {
70 err := os.Chmod(destPath, entry.Mode())
71 if !c.permIgnore && err != nil {
72 return fmt.Errorf("chmod(%s) failed: %s", destPath, err)
73 }
74 }
75 }
76 return nil
77 }
78
79 func Copy(srcFile, dstFile string) error {
80 out, err := os.Create(dstFile)
81 if err != nil {
82 return fmt.Errorf("failed to create(%s): %s", dstFile, err)
83 }
84
85 defer out.Close()
86
87 in, err := os.Open(srcFile)
88 if err != nil {
89 return fmt.Errorf("failed to open(%s): %s", srcFile, err)
90 }
91 defer in.Close()
92
93 _, err = io.Copy(out, in)
94 if err != nil {
95 return err
96 }
97
98 return nil
99 }
100
101 func Exists(filePath string) bool {
102 if _, err := os.Stat(filePath); os.IsNotExist(err) {
103 return false
104 }
105
106 return true
107 }
108
109 func CreateIfNotExists(dir string, perm os.FileMode) error {
110 if Exists(dir) {
111 return nil
112 }
113
114 if err := os.MkdirAll(dir, perm); err != nil {
115 return fmt.Errorf("failed to create directory: '%s', error: '%s'", dir, err.Error())
116 }
117
118 return nil
119 }
120
121 func CopySymLink(source, dest string) error {
122 link, err := os.Readlink(source)
123 if err != nil {
124 return err
125 }
126 return os.Symlink(link, dest)
127 }
128
View as plain text