github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/utils/fsutils/fs.go (about)

     1  package fsutils
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"io/fs"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	"go.uber.org/zap"
    11  	"golang.org/x/exp/slices"
    12  	"golang.org/x/xerrors"
    13  
    14  	"github.com/devseccon/trivy/pkg/log"
    15  )
    16  
    17  const (
    18  	xdgDataHome = "XDG_DATA_HOME"
    19  )
    20  
    21  var cacheDir string
    22  
    23  // defaultCacheDir returns/creates the cache-dir to be used for trivy operations
    24  func defaultCacheDir() string {
    25  	tmpDir, err := os.UserCacheDir()
    26  	if err != nil {
    27  		tmpDir = os.TempDir()
    28  	}
    29  	return filepath.Join(tmpDir, "trivy")
    30  }
    31  
    32  // CacheDir returns the directory used for caching
    33  func CacheDir() string {
    34  	if cacheDir == "" {
    35  		return defaultCacheDir()
    36  	}
    37  	return cacheDir
    38  }
    39  
    40  // SetCacheDir sets the trivy cacheDir
    41  func SetCacheDir(dir string) {
    42  	cacheDir = dir
    43  }
    44  
    45  func HomeDir() string {
    46  	dataHome := os.Getenv(xdgDataHome)
    47  	if dataHome != "" {
    48  		return dataHome
    49  	}
    50  
    51  	homeDir, _ := os.UserHomeDir()
    52  	return homeDir
    53  }
    54  
    55  // CopyFile copies the file content from scr to dst
    56  func CopyFile(src, dst string) (int64, error) {
    57  	sourceFileStat, err := os.Stat(src)
    58  	if err != nil {
    59  		return 0, xerrors.Errorf("file (%s) stat error: %w", src, err)
    60  	}
    61  
    62  	if !sourceFileStat.Mode().IsRegular() {
    63  		return 0, fmt.Errorf("%s is not a regular file", src)
    64  	}
    65  
    66  	source, err := os.Open(src)
    67  	if err != nil {
    68  		return 0, err
    69  	}
    70  	defer source.Close()
    71  
    72  	destination, err := os.Create(dst)
    73  	if err != nil {
    74  		return 0, err
    75  	}
    76  	defer destination.Close()
    77  	n, err := io.Copy(destination, source)
    78  	return n, err
    79  }
    80  
    81  func DirExists(path string) bool {
    82  	if f, err := os.Stat(path); os.IsNotExist(err) || !f.IsDir() {
    83  		return false
    84  	}
    85  	return true
    86  }
    87  
    88  type WalkDirRequiredFunc func(path string, d fs.DirEntry) bool
    89  
    90  type WalkDirFunc func(path string, d fs.DirEntry, r io.Reader) error
    91  
    92  func WalkDir(fsys fs.FS, root string, required WalkDirRequiredFunc, fn WalkDirFunc) error {
    93  	return fs.WalkDir(fsys, root, func(path string, d fs.DirEntry, err error) error {
    94  		if err != nil {
    95  			return err
    96  		} else if !d.Type().IsRegular() || !required(path, d) {
    97  			return nil
    98  		}
    99  
   100  		f, err := fsys.Open(path)
   101  		if err != nil {
   102  			return xerrors.Errorf("file open error: %w", err)
   103  		}
   104  		defer f.Close()
   105  
   106  		if err = fn(path, d, f); err != nil {
   107  			log.Logger.Debugw("Walk error", zap.String("file_path", path), zap.Error(err))
   108  		}
   109  		return nil
   110  	})
   111  }
   112  
   113  func RequiredExt(exts ...string) WalkDirRequiredFunc {
   114  	return func(filePath string, _ fs.DirEntry) bool {
   115  		return slices.Contains(exts, filepath.Ext(filePath))
   116  	}
   117  }
   118  
   119  func RequiredFile(fileNames ...string) WalkDirRequiredFunc {
   120  	return func(filePath string, _ fs.DirEntry) bool {
   121  		return slices.Contains(fileNames, filepath.Base(filePath))
   122  	}
   123  }