github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/syft/pkg/cataloger/internal/unionreader/union_reader.go (about) 1 package unionreader 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 8 macho "github.com/anchore/go-macholibre" 9 "github.com/anchore/syft/internal/log" 10 ) 11 12 // unionReader is a single interface with all reading functions needed by multi-arch binary catalogers 13 // cataloger. 14 type UnionReader interface { 15 io.Reader 16 io.ReaderAt 17 io.Seeker 18 io.Closer 19 } 20 21 // getReaders extracts one or more io.ReaderAt objects representing binaries that can be processed (multiple binaries in the case for multi-architecture binaries). 22 func GetReaders(f UnionReader) ([]io.ReaderAt, error) { 23 if macho.IsUniversalMachoBinary(f) { 24 machoReaders, err := macho.ExtractReaders(f) 25 if err != nil { 26 log.Debugf("extracting readers: %v", err) 27 return nil, err 28 } 29 30 var readers []io.ReaderAt 31 for _, e := range machoReaders { 32 readers = append(readers, e.Reader) 33 } 34 35 return readers, nil 36 } 37 38 return []io.ReaderAt{f}, nil 39 } 40 41 func GetUnionReader(readerCloser io.ReadCloser) (UnionReader, error) { 42 reader, ok := readerCloser.(UnionReader) 43 if ok { 44 return reader, nil 45 } 46 47 b, err := io.ReadAll(readerCloser) 48 if err != nil { 49 return nil, fmt.Errorf("unable to read contents from binary: %w", err) 50 } 51 52 bytesReader := bytes.NewReader(b) 53 54 reader = struct { 55 io.ReadCloser 56 io.ReaderAt 57 io.Seeker 58 }{ 59 ReadCloser: io.NopCloser(bytesReader), 60 ReaderAt: bytesReader, 61 Seeker: bytesReader, 62 } 63 64 return reader, nil 65 }