From 5c8dd4c3a7632dcfd999bab7a5b73c3180f1b628 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 29 Nov 2023 09:42:34 -0500 Subject: [PATCH] fix file metadata cataloger to use resolved locations (#2370) Signed-off-by: Alex Goodman --- syft/file/cataloger/filemetadata/cataloger.go | 11 ++- .../cataloger/filemetadata/cataloger_test.go | 76 ++++++++++++++++--- 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/syft/file/cataloger/filemetadata/cataloger.go b/syft/file/cataloger/filemetadata/cataloger.go index bae2344f479..d0330cfe7a4 100644 --- a/syft/file/cataloger/filemetadata/cataloger.go +++ b/syft/file/cataloger/filemetadata/cataloger.go @@ -27,9 +27,16 @@ func (i *Cataloger) Catalog(resolver file.Resolver, coordinates ...file.Coordina locations = func() <-chan file.Location { ch := make(chan file.Location) go func() { - close(ch) + defer close(ch) for _, c := range coordinates { - ch <- file.NewLocationFromCoordinates(c) + locs, err := resolver.FilesByPath(c.RealPath) + if err != nil { + log.Warn("unable to get file locations for path %q: %w", c.RealPath, err) + continue + } + for _, loc := range locs { + ch <- loc + } } }() return ch diff --git a/syft/file/cataloger/filemetadata/cataloger_test.go b/syft/file/cataloger/filemetadata/cataloger_test.go index 9c84c9f76d8..8c646e5704d 100644 --- a/syft/file/cataloger/filemetadata/cataloger_test.go +++ b/syft/file/cataloger/filemetadata/cataloger_test.go @@ -21,19 +21,13 @@ func TestFileMetadataCataloger(t *testing.T) { c := NewCataloger() src, err := source.NewFromStereoscopeImageObject(img, testImage, nil) - if err != nil { - t.Fatalf("could not create source: %+v", err) - } + require.NoError(t, err) resolver, err := src.FileResolver(source.SquashedScope) - if err != nil { - t.Fatalf("could not create resolver: %+v", err) - } + require.NoError(t, err) actual, err := c.Catalog(resolver) - if err != nil { - t.Fatalf("could not catalog: %+v", err) - } + require.NoError(t, err) tests := []struct { path string @@ -156,3 +150,67 @@ func TestFileMetadataCataloger(t *testing.T) { } } + +func TestFileMetadataCataloger_GivenCoordinates(t *testing.T) { + testImage := "image-file-type-mix" + + img := imagetest.GetFixtureImage(t, "docker-archive", testImage) + + c := NewCataloger() + + src, err := source.NewFromStereoscopeImageObject(img, testImage, nil) + require.NoError(t, err) + + resolver, err := src.FileResolver(source.SquashedScope) + require.NoError(t, err) + + tests := []struct { + path string + exists bool + expected file.Metadata + err bool + }{ + { + path: "/file-1.txt", + exists: true, + expected: file.Metadata{ + FileInfo: stereoscopeFile.ManualInfo{ + NameValue: "file-1.txt", + ModeValue: 0644, + SizeValue: 7, + }, + Path: "/file-1.txt", + Type: stereoscopeFile.TypeRegular, + UserID: 1, + GroupID: 2, + MIMEType: "text/plain", + }, + }, + } + + for _, test := range tests { + t.Run(test.path, func(t *testing.T) { + _, ref, err := img.SquashedTree().File(stereoscopeFile.Path(test.path)) + require.NoError(t, err) + + l := file.NewLocationFromImage(test.path, *ref.Reference, img) + + // note: an important difference between this test and the previous is that this test is using a list + // of specific coordinates to catalog + actual, err := c.Catalog(resolver, l.Coordinates) + require.NoError(t, err) + require.Len(t, actual, 1) + + if _, ok := actual[l.Coordinates]; ok { + // we're not interested in keeping the test fixtures up to date with the latest file modification times + // thus ModTime is not under test + fi := test.expected.FileInfo.(stereoscopeFile.ManualInfo) + fi.ModTimeValue = actual[l.Coordinates].ModTime() + test.expected.FileInfo = fi + } + + assert.True(t, test.expected.Equal(actual[l.Coordinates])) + }) + } + +}