github.com/snyk/vervet/v4@v4.27.2/internal/files/copy.go (about) 1 package files 2 3 import ( 4 "io" 5 "io/fs" 6 "os" 7 "path/filepath" 8 ) 9 10 // CopyItem copies a file or directory from src to dst. 11 func CopyItem(dst, src string, force bool) error { 12 if st, err := os.Stat(src); err == nil && st.IsDir() { 13 return CopyDir(dst, src, force) 14 } else if err == nil { 15 return CopyFile(dst, src, force) 16 } else { 17 return err 18 } 19 } 20 21 // CopyDir recursively copies a directory from src to dst. 22 func CopyDir(dst, src string, force bool) error { 23 return filepath.WalkDir(src, func(path string, d fs.DirEntry, err error) error { 24 if err != nil { 25 return nil 26 } 27 name, err := filepath.Rel(src, path) 28 if err != nil { 29 return err 30 } 31 if d.IsDir() { 32 return nil 33 } 34 return CopyFile(filepath.Join(dst, name), path, force) 35 }) 36 } 37 38 // CopyFile copies a file from src to dst. If there are missing directories in 39 // dst, they are created. 40 func CopyFile(dst, src string, force bool) error { 41 srcf, err := os.Open(src) 42 if err != nil { 43 return err 44 } 45 defer srcf.Close() 46 flags := os.O_CREATE | os.O_WRONLY | os.O_TRUNC 47 if !force { 48 flags = flags | os.O_EXCL 49 } 50 51 dstDir := filepath.Dir(dst) 52 if dstDir != "." { 53 err = os.MkdirAll(dstDir, 0777) // leave it to umask 54 if err != nil { 55 return err 56 } 57 } 58 59 dstf, err := os.OpenFile(dst, flags, 0666) // leave it to umask 60 if err != nil { 61 return err 62 } 63 defer dstf.Close() 64 65 _, err = io.Copy(dstf, srcf) 66 if err != nil { 67 return err 68 } 69 return nil 70 }