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  }