go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/fsutil/stream.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  	"bufio"
     9  	"bytes"
    10  	"fmt"
    11  	"io"
    12  	"os"
    13  
    14  	"github.com/rs/zerolog/log"
    15  )
    16  
    17  // StreamFileAsTar task t
    18  func StreamFileAsTar(
    19  	path string, // file path
    20  	stat os.FileInfo, // stat of the file
    21  	fileReader io.ReadCloser, // raw file byte stream
    22  	writer io.WriteCloser, // tar output stream
    23  ) {
    24  	// close all open connection
    25  	defer fileReader.Close()
    26  
    27  	// stream content into the pipe
    28  	tw := tar.NewWriter(writer)
    29  	bufReader := bufio.NewReader(fileReader)
    30  	defer tw.Close()
    31  	defer writer.Close()
    32  
    33  	// send tar header
    34  	hdr := &tar.Header{
    35  		Name: path,
    36  		Mode: int64(stat.Mode()),
    37  		Size: stat.Size(),
    38  	}
    39  	if err := tw.WriteHeader(hdr); err != nil {
    40  		fmt.Print(err)
    41  		writer.Close()
    42  	}
    43  
    44  	// copy file content
    45  	if _, err := io.Copy(writer, bufReader); err != nil {
    46  		fmt.Print(err)
    47  		writer.Close()
    48  	}
    49  }
    50  
    51  func ExtractFileFromTarStream(path string, tarReader io.Reader) (*bufio.Reader, error) {
    52  	log.Debug().Str("path", path).Msg("fsutil> extract file from tar")
    53  	var fileBuffer bytes.Buffer
    54  	bufWriter := bufio.NewWriter(&fileBuffer)
    55  
    56  	// read stream tar, extract on the fly and put it on stdout
    57  	tr := tar.NewReader(tarReader)
    58  	for {
    59  		h, err := tr.Next()
    60  		if err == io.EOF {
    61  			break
    62  		}
    63  		if err != nil {
    64  			return nil, err
    65  		}
    66  		// log.Debug().Msgf("File %s, Size: %d", h.Name, h.Size)
    67  		if h.Name == path {
    68  			log.Debug().Str("path", path).Msg("fsutil> found file")
    69  			if _, err := io.CopyN(bufWriter, tr, h.Size); err != nil {
    70  				return nil, err
    71  			}
    72  		}
    73  	}
    74  
    75  	bufWriter.Flush()
    76  	return bufio.NewReader(&fileBuffer), nil
    77  }