github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/cmd/imagetool/scanFilteredFiles.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "runtime" 9 "syscall" 10 11 "github.com/Cloud-Foundations/Dominator/lib/filter" 12 "github.com/Cloud-Foundations/Dominator/lib/image" 13 "github.com/Cloud-Foundations/Dominator/lib/log" 14 "github.com/Cloud-Foundations/Dominator/lib/wsyscall" 15 proto "github.com/Cloud-Foundations/Dominator/proto/imageserver" 16 ) 17 18 func scanFilteredFilesSubcommand(args []string, logger log.DebugLogger) error { 19 if err := scanFilteredFiles(args[0], args[1], logger); err != nil { 20 return fmt.Errorf("Error scanning filtered files: %s", err) 21 } 22 return nil 23 } 24 25 func getImageMetadata(imageName string) (*image.Image, error) { 26 imageSClient, _ := getClients() 27 logger.Debugf(0, "getting image: %s\n", imageName) 28 request := proto.GetImageRequest{ 29 ImageName: imageName, 30 IgnoreFilesystem: true, 31 Timeout: *timeout, 32 } 33 var reply proto.GetImageResponse 34 err := imageSClient.RequestReply("ImageServer.GetImage", request, &reply) 35 if err != nil { 36 return nil, err 37 } 38 if reply.Image == nil { 39 return nil, fmt.Errorf("image: %s not found", imageName) 40 } 41 return reply.Image, nil 42 } 43 44 func scanFilteredFiles(imageName, dirName string, 45 logger log.DebugLogger) error { 46 scanFilter, err := filter.New(scanExcludeList) 47 if err != nil { 48 return err 49 } 50 img, err := getImageMetadata(imageName) 51 if err != nil { 52 return err 53 } 54 rootDir, err := ioutil.TempDir("", "") 55 if err != nil { 56 return err 57 } 58 defer os.Remove(rootDir) 59 errorChannel := make(chan error) 60 go func() { 61 errorChannel <- scanFilteredRoot(scanFilter, img.Filter, dirName, 62 rootDir, logger) 63 }() 64 return <-errorChannel 65 } 66 67 func scanFilteredRoot(scanFilter, imageFilter *filter.Filter, 68 dirName, rootDir string, logger log.DebugLogger) error { 69 return walkFilteredRoot(scanFilter, imageFilter, dirName, rootDir, 70 func(path string, fi os.FileInfo) error { 71 fmt.Println(path) 72 return nil 73 }, 74 logger) 75 } 76 77 func walkFilteredRoot(scanFilter, imageFilter *filter.Filter, 78 dirName, rootDir string, 79 walkFunc func(path string, fi os.FileInfo) error, 80 logger log.DebugLogger) error { 81 runtime.LockOSThread() 82 if err := wsyscall.UnshareMountNamespace(); err != nil { 83 return fmt.Errorf("unable to unshare mount namesace: %s", err) 84 } 85 syscall.Unmount(rootDir, 0) 86 err := wsyscall.Mount(dirName, rootDir, "", wsyscall.MS_BIND, "") 87 if err != nil { 88 return fmt.Errorf("unable to bind mount %s to %s: %s", 89 dirName, rootDir, err) 90 } 91 logger.Debugf(0, "scanning directory: %s\n", dirName) 92 startPos := len(rootDir) 93 return filepath.Walk(rootDir, 94 func(path string, fi os.FileInfo, err error) error { 95 if err != nil { 96 return err 97 } 98 path = path[startPos:] 99 if scanFilter.Match(path) { 100 return nil 101 } 102 if imageFilter.Match(path) { 103 if err := walkFunc(path, fi); err != nil { 104 return err 105 } 106 } 107 return nil 108 }) 109 }