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