kubeform.dev/terraform-backend-sdk@v0.0.0-20220310143633-45f07fe731c5/configs/configload/copy_dir.go (about) 1 package configload 2 3 import ( 4 "io" 5 "os" 6 "path/filepath" 7 ) 8 9 // copyDir copies the src directory contents into dst. Both directories 10 // should already exist. 11 func copyDir(dst, src string) error { 12 src, err := filepath.EvalSymlinks(src) 13 if err != nil { 14 return err 15 } 16 17 walkFn := func(path string, info os.FileInfo, err error) error { 18 if err != nil { 19 return err 20 } 21 22 if path == src { 23 return nil 24 } 25 26 // The "path" has the src prefixed to it. We need to join our 27 // destination with the path without the src on it. 28 dstPath := filepath.Join(dst, path[len(src):]) 29 30 // we don't want to try and copy the same file over itself. 31 if eq, err := sameFile(path, dstPath); eq { 32 return nil 33 } else if err != nil { 34 return err 35 } 36 37 // If we have a directory, make that subdirectory, then continue 38 // the walk. 39 if info.IsDir() { 40 if path == filepath.Join(src, dst) { 41 // dst is in src; don't walk it. 42 return nil 43 } 44 45 if err := os.MkdirAll(dstPath, 0755); err != nil { 46 return err 47 } 48 49 return nil 50 } 51 52 // If the current path is a symlink, recreate the symlink relative to 53 // the dst directory 54 if info.Mode()&os.ModeSymlink == os.ModeSymlink { 55 target, err := os.Readlink(path) 56 if err != nil { 57 return err 58 } 59 60 return os.Symlink(target, dstPath) 61 } 62 63 // If we have a file, copy the contents. 64 srcF, err := os.Open(path) 65 if err != nil { 66 return err 67 } 68 defer srcF.Close() 69 70 dstF, err := os.Create(dstPath) 71 if err != nil { 72 return err 73 } 74 defer dstF.Close() 75 76 if _, err := io.Copy(dstF, srcF); err != nil { 77 return err 78 } 79 80 // Chmod it 81 return os.Chmod(dstPath, info.Mode()) 82 } 83 84 return filepath.Walk(src, walkFn) 85 } 86 87 // sameFile tried to determine if to paths are the same file. 88 // If the paths don't match, we lookup the inode on supported systems. 89 func sameFile(a, b string) (bool, error) { 90 if a == b { 91 return true, nil 92 } 93 94 aIno, err := inode(a) 95 if err != nil { 96 if os.IsNotExist(err) { 97 return false, nil 98 } 99 return false, err 100 } 101 102 bIno, err := inode(b) 103 if err != nil { 104 if os.IsNotExist(err) { 105 return false, nil 106 } 107 return false, err 108 } 109 110 if aIno > 0 && aIno == bIno { 111 return true, nil 112 } 113 114 return false, nil 115 }