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