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 }