github.com/dougneal/terraform@v0.6.15-0.20170330092735-b6a3840768a4/helper/copy/copy.go (about) 1 package copy 2 3 import ( 4 "fmt" 5 "io" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 ) 10 11 // From: https://gist.github.com/m4ng0squ4sh/92462b38df26839a3ca324697c8cba04 12 13 // CopyFile copies the contents of the file named src to the file named 14 // by dst. The file will be created if it does not already exist. If the 15 // destination file exists, all it's contents will be replaced by the contents 16 // of the source file. The file mode will be copied from the source and 17 // the copied data is synced/flushed to stable storage. 18 func CopyFile(src, dst string) (err error) { 19 in, err := os.Open(src) 20 if err != nil { 21 return 22 } 23 defer in.Close() 24 25 out, err := os.Create(dst) 26 if err != nil { 27 return 28 } 29 defer func() { 30 if e := out.Close(); e != nil { 31 err = e 32 } 33 }() 34 35 _, err = io.Copy(out, in) 36 if err != nil { 37 return 38 } 39 40 err = out.Sync() 41 if err != nil { 42 return 43 } 44 45 si, err := os.Stat(src) 46 if err != nil { 47 return 48 } 49 err = os.Chmod(dst, si.Mode()) 50 if err != nil { 51 return 52 } 53 54 return 55 } 56 57 // CopyDir recursively copies a directory tree, attempting to preserve permissions. 58 // Source directory must exist, destination directory must *not* exist. 59 // Symlinks are ignored and skipped. 60 func CopyDir(src string, dst string) (err error) { 61 src = filepath.Clean(src) 62 dst = filepath.Clean(dst) 63 64 si, err := os.Stat(src) 65 if err != nil { 66 return err 67 } 68 if !si.IsDir() { 69 return fmt.Errorf("source is not a directory") 70 } 71 72 _, err = os.Stat(dst) 73 if err != nil && !os.IsNotExist(err) { 74 return 75 } 76 if err == nil { 77 return fmt.Errorf("destination already exists") 78 } 79 80 err = os.MkdirAll(dst, si.Mode()) 81 if err != nil { 82 return 83 } 84 85 entries, err := ioutil.ReadDir(src) 86 if err != nil { 87 return 88 } 89 90 for _, entry := range entries { 91 srcPath := filepath.Join(src, entry.Name()) 92 dstPath := filepath.Join(dst, entry.Name()) 93 94 // If the entry is a symlink, we copy the contents 95 for entry.Mode()&os.ModeSymlink != 0 { 96 target, err := os.Readlink(srcPath) 97 if err != nil { 98 return err 99 } 100 101 entry, err = os.Stat(target) 102 if err != nil { 103 return err 104 } 105 } 106 107 if entry.IsDir() { 108 err = CopyDir(srcPath, dstPath) 109 if err != nil { 110 return 111 } 112 } else { 113 err = CopyFile(srcPath, dstPath) 114 if err != nil { 115 return 116 } 117 } 118 } 119 120 return 121 }