go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/fsutil/tar.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package fsutil 5 6 import ( 7 "archive/tar" 8 "errors" 9 "io" 10 "os" 11 12 "github.com/rs/zerolog/log" 13 "github.com/spf13/afero" 14 ) 15 16 func Tar(fs afero.Fs, f afero.File) (io.ReadCloser, error) { 17 stat, err := f.Stat() 18 if err != nil { 19 return nil, errors.New("could not retrieve file stats") 20 } 21 22 afutil := afero.Afero{Fs: fs} 23 24 // determine all files that we need to transfer 25 fileList := map[string]os.FileInfo{} 26 if stat.IsDir() == true { 27 28 err = afutil.Walk(f.Name(), func(path string, f os.FileInfo, err error) error { 29 fileList[path] = f 30 return nil 31 }) 32 if err != nil { 33 return nil, err 34 } 35 } else { 36 fileList[f.Name()] = stat 37 } 38 39 // pipe content to a tar stream 40 tarReader, tarWriter := io.Pipe() 41 42 // stream content into the pipe 43 tw := tar.NewWriter(tarWriter) 44 45 // copy file content in the background 46 go func() { 47 for path, fileinfo := range fileList { 48 // we ignore the error for now but log them 49 fReader, err := os.Open(path) 50 if err == nil { 51 // send tar header 52 hdr := &tar.Header{ 53 Name: path, 54 Mode: int64(fileinfo.Mode()), 55 Size: fileinfo.Size(), 56 } 57 58 if err := tw.WriteHeader(hdr); err != nil { 59 log.Error().Str("file", path).Err(err).Msg("local> could not write tar header") 60 } 61 62 _, err := io.Copy(tw, fReader) 63 if err != nil { 64 log.Error().Str("file", path).Err(err).Msg("local> could not write tar data") 65 } 66 } else { 67 log.Error().Str("file", path).Err(err).Msg("local> could not stream file") 68 } 69 } 70 tarWriter.Close() 71 }() 72 73 return tarReader, nil 74 }