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