mirror of
https://github.com/anchore/syft.git
synced 2026-10-30 14:02:26 +01:00
refactoring archive indexing
Signed-off-by: Kudryavcev Nikolay <kydry.nikolau@gmail.com>
This commit is contained in:
@@ -16,8 +16,8 @@ import (
|
||||
type archiveAccessPath struct {
|
||||
realPath string
|
||||
accessPath string
|
||||
archiveDepth int
|
||||
archiveRealPath string
|
||||
archiveDepth int
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -100,7 +100,11 @@ func (r *Directory) buildIndex() error {
|
||||
func (r *Directory) buildArchiveIndex(archiveTempDir string, archives []string, maxArchiveIndexDepth int) error {
|
||||
archivesToIndex := make([]archiveAccessPath, len(archives))
|
||||
for i, archive := range archives {
|
||||
archivesToIndex[i] = archiveAccessPath{realPath: archive, accessPath: archive, archiveRealPath: archive}
|
||||
archivesToIndex[i] = archiveAccessPath{
|
||||
realPath: archive,
|
||||
accessPath: archive,
|
||||
archiveRealPath: archive,
|
||||
}
|
||||
}
|
||||
|
||||
loop:
|
||||
@@ -119,59 +123,59 @@ loop:
|
||||
continue
|
||||
}
|
||||
|
||||
archivePath, err := os.MkdirTemp(archiveTempDir, archiveContentTempPathPattern)
|
||||
envelopedUnarchiver, err := archiver.ByExtension(currentArchivePath.archiveRealPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not determine archive envelope type: %w", err)
|
||||
}
|
||||
|
||||
unarchiver, ok := envelopedUnarchiver.(archiver.Unarchiver)
|
||||
if !ok {
|
||||
return fmt.Errorf("unarchiver %T is not an archiver", envelopedUnarchiver)
|
||||
}
|
||||
|
||||
archiveDestinationTempDir, err := os.MkdirTemp(archiveTempDir, archiveContentTempPathPattern)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create tempdir for archive processing: %w", err)
|
||||
}
|
||||
|
||||
archiveRealPath, err := filepath.EvalSymlinks(archivePath)
|
||||
archiveDestinationPath, err := filepath.EvalSymlinks(archiveDestinationTempDir)
|
||||
if err != nil {
|
||||
var pathErr *os.PathError
|
||||
if errors.As(err, &pathErr) {
|
||||
// we can't index the path, but we shouldn't consider this to be fatal
|
||||
// TODO: known-unknowns
|
||||
log.WithFields("archivePath", archivePath, "error", err).Trace("unable to evaluate symlink while indexing branch")
|
||||
return nil
|
||||
log.WithFields("archivePath", archiveDestinationTempDir, "error", err).Trace("unable to evaluate symlink while indexing branch")
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
envelopedUnarchiver, err := archiver.ByExtension(currentArchivePath.archiveRealPath)
|
||||
if err != nil {
|
||||
return err
|
||||
if err = unarchiver.Unarchive(currentArchivePath.archiveRealPath, archiveDestinationPath); err != nil {
|
||||
return fmt.Errorf("unable to unarchive nested file: %w", err)
|
||||
}
|
||||
|
||||
unarchiver, ok := envelopedUnarchiver.(archiver.Unarchiver)
|
||||
if !ok {
|
||||
return ErrSkipPath
|
||||
}
|
||||
|
||||
if err = unarchiver.Unarchive(currentArchivePath.archiveRealPath, archiveRealPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d, err := newFromDirectoryWithoutIndex(archiveRealPath, "")
|
||||
d, err := newFromDirectoryWithoutIndex(archiveDestinationPath, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = d.buildIndex(); err != nil {
|
||||
return err
|
||||
return fmt.Errorf("unable to build index of archive: %w", err)
|
||||
}
|
||||
|
||||
for _, archive := range d.indexer.archivePaths {
|
||||
archivesToIndex = append(archivesToIndex, archiveAccessPath{
|
||||
realPath: currentArchivePath.realPath,
|
||||
accessPath: strings.Replace(archive, archiveRealPath, currentArchivePath.accessPath, 1),
|
||||
archiveDepth: currentArchivePath.archiveDepth + 1,
|
||||
accessPath: strings.Replace(archive, archiveDestinationPath, currentArchivePath.accessPath, 1),
|
||||
archiveRealPath: archive,
|
||||
archiveDepth: currentArchivePath.archiveDepth + 1,
|
||||
})
|
||||
}
|
||||
|
||||
d.chroot = r.chroot
|
||||
d.realPath = currentArchivePath.realPath
|
||||
d.accessPath = currentArchivePath.accessPath
|
||||
d.tempDir = archiveRealPath
|
||||
d.archiveRealPath = archiveDestinationPath
|
||||
|
||||
r.archives = append(r.archives, &d.filetreeResolver)
|
||||
}
|
||||
|
||||
@@ -21,10 +21,10 @@ type filetreeResolver struct {
|
||||
index filetree.IndexReader
|
||||
searchContext filetree.Searcher
|
||||
|
||||
realPath string
|
||||
accessPath string
|
||||
tempDir string
|
||||
archives []*filetreeResolver
|
||||
realPath string
|
||||
accessPath string
|
||||
archiveRealPath string
|
||||
archives []*filetreeResolver
|
||||
}
|
||||
|
||||
func (r *filetreeResolver) requestPath(userPath string) (string, error) {
|
||||
@@ -33,8 +33,8 @@ func (r *filetreeResolver) requestPath(userPath string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if r.accessPath != "" && r.tempDir != "" {
|
||||
return strings.Replace(requestPath, r.accessPath, r.tempDir, 1), nil
|
||||
if r.accessPath != "" && r.archiveRealPath != "" {
|
||||
return strings.Replace(requestPath, r.accessPath, r.archiveRealPath, 1), nil
|
||||
}
|
||||
|
||||
return requestPath, nil
|
||||
@@ -42,15 +42,19 @@ func (r *filetreeResolver) requestPath(userPath string) (string, error) {
|
||||
|
||||
// responsePath takes a path from the underlying fs domain and converts it to a path that is relative to the root of the file resolver.
|
||||
func (r filetreeResolver) responsePath(path string) string {
|
||||
if r.tempDir != "" && strings.HasPrefix(path, r.tempDir) {
|
||||
if r.archiveRealPath != "" && strings.HasPrefix(path, r.archiveRealPath) {
|
||||
path = r.realPath
|
||||
}
|
||||
|
||||
return r.chroot.ToChrootPath(path)
|
||||
}
|
||||
|
||||
func (r filetreeResolver) responseAccessPath(path string) string {
|
||||
responsePath := strings.Replace(path, r.tempDir, r.accessPath, 1)
|
||||
return r.chroot.ToChrootPath(responsePath)
|
||||
if r.accessPath != "" && r.archiveRealPath != "" {
|
||||
path = strings.Replace(path, r.archiveRealPath, r.accessPath, 1)
|
||||
}
|
||||
|
||||
return r.chroot.ToChrootPath(path)
|
||||
}
|
||||
|
||||
// HasPath indicates if the given path exists in the underlying source.
|
||||
@@ -138,7 +142,11 @@ func (r filetreeResolver) requestGlob(pattern string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strings.Replace(nativeGlob, r.accessPath, r.tempDir, 1), nil
|
||||
if r.accessPath != "" && r.archiveRealPath != "" {
|
||||
return strings.Replace(nativeGlob, r.accessPath, r.archiveRealPath, 1), nil
|
||||
}
|
||||
|
||||
return nativeGlob, nil
|
||||
}
|
||||
|
||||
// FilesByGlob returns all file.References that match the given path glob pattern from any layer in the image.
|
||||
|
||||
@@ -1664,6 +1664,7 @@ func TestFileResolver_AllLocations_errorOnDirRequest(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFileResolver_AllLocations(t *testing.T) {
|
||||
defer goleak.VerifyNone(t)
|
||||
// Verify both the parent and the file itself are indexed
|
||||
filePath := "./test-fixtures/system_paths/target/home/place"
|
||||
parentPath, err := absoluteSymlinkFreePathToParent(filePath)
|
||||
@@ -1685,11 +1686,10 @@ func TestFileResolver_AllLocations(t *testing.T) {
|
||||
sort.Strings(pathsList)
|
||||
|
||||
assert.ElementsMatchf(t, expected, pathsList, "expected all paths to be indexed, but found different paths: \n%s", cmp.Diff(expected, paths.List()))
|
||||
|
||||
goleak.VerifyNone(t)
|
||||
}
|
||||
|
||||
func Test_FileResolver_AllLocationsDoesNotLeakGoRoutine(t *testing.T) {
|
||||
defer goleak.VerifyNone(t)
|
||||
filePath := "./test-fixtures/system_paths/target/home/place"
|
||||
parentPath, err := absoluteSymlinkFreePathToParent(filePath)
|
||||
require.NoError(t, err)
|
||||
@@ -1703,6 +1703,4 @@ func Test_FileResolver_AllLocationsDoesNotLeakGoRoutine(t *testing.T) {
|
||||
break
|
||||
}
|
||||
cancel()
|
||||
|
||||
goleak.VerifyNone(t)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user