1
2
3
4
5 package cgotest
6
7 import (
8 "io"
9 "os"
10 "path/filepath"
11 "strings"
12 )
13
14
15 func OverlayDir(dstRoot, srcRoot string) error {
16 dstRoot = filepath.Clean(dstRoot)
17 if err := os.MkdirAll(dstRoot, 0777); err != nil {
18 return err
19 }
20
21 srcRoot, err := filepath.Abs(srcRoot)
22 if err != nil {
23 return err
24 }
25
26 return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
27 if err != nil || srcPath == srcRoot {
28 return err
29 }
30
31 suffix := strings.TrimPrefix(srcPath, srcRoot)
32 for len(suffix) > 0 && suffix[0] == filepath.Separator {
33 suffix = suffix[1:]
34 }
35 dstPath := filepath.Join(dstRoot, suffix)
36
37 perm := info.Mode() & os.ModePerm
38 if info.Mode()&os.ModeSymlink != 0 {
39 info, err = os.Stat(srcPath)
40 if err != nil {
41 return err
42 }
43 perm = info.Mode() & os.ModePerm
44 }
45
46
47
48 if info.IsDir() {
49 return os.MkdirAll(dstPath, perm|0200)
50 }
51
52
53 if err := os.Symlink(srcPath, dstPath); err == nil {
54 return nil
55 }
56
57
58 src, err := os.Open(srcPath)
59 if err != nil {
60 return err
61 }
62 defer src.Close()
63
64 dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)
65 if err != nil {
66 return err
67 }
68
69 _, err = io.Copy(dst, src)
70 if closeErr := dst.Close(); err == nil {
71 err = closeErr
72 }
73 return err
74 })
75 }
76
View as plain text