github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/syft/pkg/cataloger/rpm/parse_rpm_manifest.go (about) 1 package rpm 2 3 import ( 4 "bufio" 5 "errors" 6 "io" 7 "strings" 8 9 "github.com/anchore/syft/internal/log" 10 "github.com/anchore/syft/syft/artifact" 11 "github.com/anchore/syft/syft/file" 12 "github.com/anchore/syft/syft/pkg" 13 "github.com/anchore/syft/syft/pkg/cataloger/generic" 14 ) 15 16 // Parses an RPM manifest file, as used in Mariner distroless containers, and returns the Packages listed 17 func parseRpmManifest(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { 18 r := bufio.NewReader(reader) 19 allPkgs := make([]pkg.Package, 0) 20 21 for { 22 line, err := r.ReadString('\n') 23 if err != nil { 24 if errors.Is(err, io.EOF) { 25 break 26 } 27 return nil, nil, err 28 } 29 30 if line == "" { 31 continue 32 } 33 34 p, err := parseRpmManifestEntry(strings.TrimSuffix(line, "\n"), reader.Location) 35 if err != nil { 36 log.Warnf("unable to parse RPM manifest entry: %w", err) 37 continue 38 } 39 40 if !pkg.IsValid(p) { 41 continue 42 } 43 44 p.SetID() 45 allPkgs = append(allPkgs, *p) 46 } 47 48 return allPkgs, nil, nil 49 } 50 51 // Parses an entry in an RPM manifest file as used in Mariner distroless containers 52 // Each line is the output of : 53 // rpm --query --all --query-format "%{NAME}\t%{VERSION}-%{RELEASE}\t%{INSTALLTIME}\t%{BUILDTIME}\t%{VENDOR}\t%{EPOCH}\t%{SIZE}\t%{ARCH}\t%{EPOCHNUM}\t%{SOURCERPM}\n" 54 // https://github.com/microsoft/CBL-Mariner/blob/3df18fac373aba13a54bd02466e64969574f13af/toolkit/docs/how_it_works/5_misc.md?plain=1#L150 55 func parseRpmManifestEntry(entry string, location file.Location) (*pkg.Package, error) { 56 metadata, err := newMetadataFromManifestLine(entry) 57 if err != nil { 58 return nil, err 59 } 60 61 if metadata == nil { 62 return nil, nil 63 } 64 65 p := newPackage(location, *metadata, nil) 66 67 return &p, nil 68 }