]>
Commit | Line | Data |
---|---|---|
9b12e4fe JC |
1 | // +build !linux |
2 | ||
3 | package archive | |
4 | ||
5 | import ( | |
6 | "fmt" | |
7 | "os" | |
8 | "path/filepath" | |
9 | "runtime" | |
10 | "strings" | |
11 | ||
12 | "github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/system" | |
13 | ) | |
14 | ||
15 | func collectFileInfoForChanges(oldDir, newDir string) (*FileInfo, *FileInfo, error) { | |
16 | var ( | |
17 | oldRoot, newRoot *FileInfo | |
18 | err1, err2 error | |
19 | errs = make(chan error, 2) | |
20 | ) | |
21 | go func() { | |
22 | oldRoot, err1 = collectFileInfo(oldDir) | |
23 | errs <- err1 | |
24 | }() | |
25 | go func() { | |
26 | newRoot, err2 = collectFileInfo(newDir) | |
27 | errs <- err2 | |
28 | }() | |
29 | ||
30 | // block until both routines have returned | |
31 | for i := 0; i < 2; i++ { | |
32 | if err := <-errs; err != nil { | |
33 | return nil, nil, err | |
34 | } | |
35 | } | |
36 | ||
37 | return oldRoot, newRoot, nil | |
38 | } | |
39 | ||
40 | func collectFileInfo(sourceDir string) (*FileInfo, error) { | |
41 | root := newRootFileInfo() | |
42 | ||
43 | err := filepath.Walk(sourceDir, func(path string, f os.FileInfo, err error) error { | |
44 | if err != nil { | |
45 | return err | |
46 | } | |
47 | ||
48 | // Rebase path | |
49 | relPath, err := filepath.Rel(sourceDir, path) | |
50 | if err != nil { | |
51 | return err | |
52 | } | |
53 | ||
54 | // As this runs on the daemon side, file paths are OS specific. | |
55 | relPath = filepath.Join(string(os.PathSeparator), relPath) | |
56 | ||
57 | // See https://github.com/golang/go/issues/9168 - bug in filepath.Join. | |
58 | // Temporary workaround. If the returned path starts with two backslashes, | |
59 | // trim it down to a single backslash. Only relevant on Windows. | |
60 | if runtime.GOOS == "windows" { | |
61 | if strings.HasPrefix(relPath, `\\`) { | |
62 | relPath = relPath[1:] | |
63 | } | |
64 | } | |
65 | ||
66 | if relPath == string(os.PathSeparator) { | |
67 | return nil | |
68 | } | |
69 | ||
70 | parent := root.LookUp(filepath.Dir(relPath)) | |
71 | if parent == nil { | |
72 | return fmt.Errorf("collectFileInfo: Unexpectedly no parent for %s", relPath) | |
73 | } | |
74 | ||
75 | info := &FileInfo{ | |
76 | name: filepath.Base(relPath), | |
77 | children: make(map[string]*FileInfo), | |
78 | parent: parent, | |
79 | } | |
80 | ||
81 | s, err := system.Lstat(path) | |
82 | if err != nil { | |
83 | return err | |
84 | } | |
85 | info.stat = s | |
86 | ||
87 | info.capability, _ = system.Lgetxattr(path, "security.capability") | |
88 | ||
89 | parent.children[info.name] = info | |
90 | ||
91 | return nil | |
92 | }) | |
93 | if err != nil { | |
94 | return nil, err | |
95 | } | |
96 | return root, nil | |
97 | } |