go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/connection/ssh/cat/cat_file.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package cat
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/base64"
     9  	"io"
    10  	"os"
    11  	"strings"
    12  
    13  	"github.com/cockroachdb/errors"
    14  	"github.com/kballard/go-shellquote"
    15  )
    16  
    17  func NewFile(catfs *Fs, path string, useBase64encoding bool) *File {
    18  	return &File{catfs: catfs, path: path, useBase64encoding: useBase64encoding}
    19  }
    20  
    21  type File struct {
    22  	catfs             *Fs
    23  	buf               *bytes.Buffer
    24  	path              string
    25  	useBase64encoding bool
    26  }
    27  
    28  func (f *File) readContent() (*bytes.Buffer, error) {
    29  	// we need shellquote to escape filenames with spaces
    30  	catCmd := shellquote.Join("cat", f.path)
    31  	if f.useBase64encoding {
    32  		catCmd = catCmd + " | base64"
    33  	}
    34  
    35  	cmd, err := f.catfs.commandRunner.RunCommand(catCmd)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  
    40  	data, err := io.ReadAll(cmd.Stdout)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	if f.useBase64encoding {
    46  		data, err = base64.StdEncoding.DecodeString(string(data))
    47  		if err != nil {
    48  			return nil, errors.Wrap(err, "could not decode base64 data stream")
    49  		}
    50  	}
    51  
    52  	return bytes.NewBuffer(data), nil
    53  }
    54  
    55  func (f *File) Close() error {
    56  	return nil
    57  }
    58  
    59  func (f *File) Name() string {
    60  	return f.path
    61  }
    62  
    63  func (f *File) Stat() (os.FileInfo, error) {
    64  	return f.catfs.Stat(f.path)
    65  }
    66  
    67  func (f *File) Sync() error {
    68  	return nil
    69  }
    70  
    71  func (f *File) Truncate(size int64) error {
    72  	return nil
    73  }
    74  
    75  func (f *File) Read(b []byte) (n int, err error) {
    76  	if f.buf == nil {
    77  		bufData, err := f.readContent()
    78  		if err != nil {
    79  			return 0, err
    80  		}
    81  		f.buf = bufData
    82  	}
    83  	return f.buf.Read(b)
    84  }
    85  
    86  func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
    87  	return 0, errors.New("not implemented")
    88  }
    89  
    90  func (f *File) Readdir(count int) (res []os.FileInfo, err error) {
    91  	return nil, errors.New("not implemented")
    92  }
    93  
    94  func (f *File) Readdirnames(n int) (names []string, err error) {
    95  	// TODO: input n is ignored
    96  
    97  	cmd, err := f.catfs.commandRunner.RunCommand("ls -1 '" + f.path + "'")
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  
   102  	data, err := io.ReadAll(cmd.Stdout)
   103  	if err != nil {
   104  		return nil, err
   105  	}
   106  
   107  	list := strings.Split(strings.TrimSpace(string(data)), "\n")
   108  
   109  	if list != nil {
   110  		// filter . and ..
   111  		keep := func(x string) bool {
   112  			if x == "." || x == ".." || x == "" {
   113  				return false
   114  			}
   115  			return true
   116  		}
   117  		m := 0
   118  		for _, x := range list {
   119  			if keep(x) {
   120  				list[m] = x
   121  				m++
   122  			}
   123  		}
   124  		list = list[:m]
   125  	}
   126  
   127  	return list, nil
   128  }
   129  
   130  func (f *File) Seek(offset int64, whence int) (int64, error) {
   131  	return 0, errors.New("not implemented")
   132  }
   133  
   134  func (f *File) Write(b []byte) (n int, err error) {
   135  	return 0, errors.New("not implemented")
   136  }
   137  
   138  func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
   139  	return 0, errors.New("not implemented")
   140  }
   141  
   142  func (f *File) WriteString(s string) (ret int, err error) {
   143  	return 0, errors.New("not implemented")
   144  }