mirror of
https://github.com/anchore/syft.git
synced 2026-11-06 01:16:32 +01:00
Add ability to scan snaps (as a source) (#3929)
This commit is contained in:
@@ -4,6 +4,9 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/diskfs/go-diskfs/filesystem/squashfs"
|
||||
|
||||
macho "github.com/anchore/go-macholibre"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
@@ -48,12 +51,15 @@ func GetUnionReader(readerCloser io.ReadCloser) (UnionReader, error) {
|
||||
// file.LocationReadCloser embeds a ReadCloser, which is likely
|
||||
// to implement UnionReader. Check whether the embedded read closer
|
||||
// implements UnionReader, and just return that if so.
|
||||
r, ok := readerCloser.(file.LocationReadCloser)
|
||||
if ok {
|
||||
ur, ok := r.ReadCloser.(UnionReader)
|
||||
if ok {
|
||||
return ur, nil
|
||||
}
|
||||
|
||||
if r, ok := readerCloser.(file.LocationReadCloser); ok {
|
||||
return GetUnionReader(r.ReadCloser)
|
||||
}
|
||||
|
||||
if r, ok := readerCloser.(*squashfs.File); ok {
|
||||
// seeking is implemented, but not io.ReaderAt. Lets wrap it to prevent from degrading performance
|
||||
// by copying all data.
|
||||
return newReaderAtAdapter(r), nil
|
||||
}
|
||||
|
||||
b, err := io.ReadAll(readerCloser)
|
||||
@@ -75,3 +81,58 @@ func GetUnionReader(readerCloser io.ReadCloser) (UnionReader, error) {
|
||||
|
||||
return reader, nil
|
||||
}
|
||||
|
||||
type readerAtAdapter struct {
|
||||
io.ReadSeekCloser
|
||||
mu *sync.Mutex
|
||||
}
|
||||
|
||||
func newReaderAtAdapter(rs io.ReadSeekCloser) UnionReader {
|
||||
return &readerAtAdapter{
|
||||
ReadSeekCloser: rs,
|
||||
mu: &sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *readerAtAdapter) Read(p []byte) (n int, err error) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
return r.ReadSeekCloser.Read(p)
|
||||
}
|
||||
|
||||
func (r *readerAtAdapter) Seek(offset int64, whence int) (int64, error) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
return r.ReadSeekCloser.Seek(offset, whence)
|
||||
}
|
||||
|
||||
func (r *readerAtAdapter) ReadAt(p []byte, off int64) (n int, err error) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
currentPos, err := r.ReadSeekCloser.Seek(0, io.SeekCurrent) // save current pos
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
_, err = r.ReadSeekCloser.Seek(off, io.SeekStart) // seek to absolute position `off`
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
n, err = r.ReadSeekCloser.Read(p) // read from that absolute position
|
||||
|
||||
// restore the position for the stateful read/seek operations
|
||||
if restoreErr := r.restorePosition(currentPos); restoreErr != nil {
|
||||
if err == nil {
|
||||
err = restoreErr
|
||||
}
|
||||
}
|
||||
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (r *readerAtAdapter) restorePosition(pos int64) error {
|
||||
_, err := r.ReadSeekCloser.Seek(pos, io.SeekStart)
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user