github.com/cdoern/storage@v1.12.13/pkg/archive/changes_other.go (about) 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/containers/storage/pkg/idtools" 13 "github.com/containers/storage/pkg/system" 14 ) 15 16 func collectFileInfoForChanges(oldDir, newDir string, oldIDMap, newIDMap *idtools.IDMappings) (*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, oldIDMap) 24 errs <- err1 25 }() 26 go func() { 27 newRoot, err2 = collectFileInfo(newDir, newIDMap) 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, idMappings *idtools.IDMappings) (*FileInfo, error) { 42 root := newRootFileInfo(idMappings) 43 44 err := filepath.Walk(sourceDir, func(path string, f os.FileInfo, 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 idMappings: idMappings, 81 } 82 83 s, err := system.Lstat(path) 84 if err != nil { 85 return err 86 } 87 info.stat = s 88 89 info.capability, _ = system.Lgetxattr(path, "security.capability") 90 91 parent.children[info.name] = info 92 93 return nil 94 }) 95 if err != nil { 96 return nil, err 97 } 98 return root, nil 99 }