diff --git a/ext/featurefmt/apk/apk.go b/ext/featurefmt/apk/apk.go index f0d29d21..6389b825 100644 --- a/ext/featurefmt/apk/apk.go +++ b/ext/featurefmt/apk/apk.go @@ -55,6 +55,7 @@ func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error) line := scanner.Text() if len(line) < 2 { if valid(&pkg) { + pkg.Type = database.BinaryPackage packages.Add(pkg) pkg = database.Feature{VersionFormat: dpkg.ParserName} } @@ -81,6 +82,7 @@ func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error) // in case of no terminal line if valid(&pkg) { + pkg.Type = database.BinaryPackage packages.Add(pkg) } diff --git a/ext/featurefmt/apk/apk_test.go b/ext/featurefmt/apk/apk_test.go index 60461ed5..72ec5098 100644 --- a/ext/featurefmt/apk/apk_test.go +++ b/ext/featurefmt/apk/apk_test.go @@ -28,17 +28,17 @@ func TestAPKFeatureDetection(t *testing.T) { "valid case", map[string]string{"lib/apk/db/installed": "apk/testdata/valid"}, []database.Feature{ - {"musl", "1.1.14-r10", "", "", dpkg.ParserName}, - {"busybox", "1.24.2-r9", "", "", dpkg.ParserName}, - {"alpine-baselayout", "3.0.3-r0", "", "", dpkg.ParserName}, - {"alpine-keys", "1.1-r0", "", "", dpkg.ParserName}, - {"zlib", "1.2.8-r2", "", "", dpkg.ParserName}, - {"libcrypto1.0", "1.0.2h-r1", "", "", dpkg.ParserName}, - {"libssl1.0", "1.0.2h-r1", "", "", dpkg.ParserName}, - {"apk-tools", "2.6.7-r0", "", "", dpkg.ParserName}, - {"scanelf", "1.1.6-r0", "", "", dpkg.ParserName}, - {"musl-utils", "1.1.14-r10", "", "", dpkg.ParserName}, - {"libc-utils", "0.7-r0", "", "", dpkg.ParserName}, + {"apk-tools", "2.6.7-r0", "dpkg", "binary"}, + {"musl", "1.1.14-r10", "dpkg", "binary"}, + {"libssl1.0", "1.0.2h-r1", "dpkg", "binary"}, + {"libc-utils", "0.7-r0", "dpkg", "binary"}, + {"busybox", "1.24.2-r9", "dpkg", "binary"}, + {"scanelf", "1.1.6-r0", "dpkg", "binary"}, + {"alpine-keys", "1.1-r0", "dpkg", "binary"}, + {"libcrypto1.0", "1.0.2h-r1", "dpkg", "binary"}, + {"zlib", "1.2.8-r2", "dpkg", "binary"}, + {"musl-utils", "1.1.14-r10", "dpkg", "binary"}, + {"alpine-baselayout", "3.0.3-r0", "dpkg", "binary"}, }, }, } { diff --git a/ext/featurefmt/dpkg/dpkg.go b/ext/featurefmt/dpkg/dpkg.go index 4e0b60e2..e68f7be1 100644 --- a/ext/featurefmt/dpkg/dpkg.go +++ b/ext/featurefmt/dpkg/dpkg.go @@ -37,45 +37,59 @@ var ( type lister struct{} +func (l lister) RequiredFilenames() []string { + return []string{"var/lib/dpkg/status"} +} + func init() { featurefmt.RegisterLister("dpkg", "1.0", &lister{}) } -func valid(pkg *database.Feature) bool { - return pkg.Name != "" && pkg.Version != "" -} - -func addSourcePackage(pkg *database.Feature) { - if pkg.SourceName == "" { - pkg.SourceName = pkg.Name - } - - if pkg.SourceVersion == "" { - pkg.SourceVersion = pkg.Version - } -} - func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error) { f, hasFile := files["var/lib/dpkg/status"] if !hasFile { return []database.Feature{}, nil } - var ( - pkg = database.Feature{VersionFormat: dpkg.ParserName} - pkgs = mapset.NewSet() - err error - ) - + packages := mapset.NewSet() scanner := bufio.NewScanner(strings.NewReader(string(f))) for scanner.Scan() { - line := scanner.Text() - if strings.HasPrefix(line, "Package: ") { - // Package line - // Defines the name of the package + line := strings.TrimSpace(scanner.Text()) + if line == "" { + continue + } - pkg.Name = strings.TrimSpace(strings.TrimPrefix(line, "Package: ")) - pkg.Version = "" + binary, source := parseDpkgDB(scanner) + if binary != nil { + packages.Add(*binary) + } + + if source != nil { + packages.Add(*source) + } + } + + return database.ConvertFeatureSetToFeatures(packages), nil +} + +// parseDpkgDB consumes the status file scanner exactly one package info, until +// EOF or empty space, and generate the parsed packages from it. +func parseDpkgDB(scanner *bufio.Scanner) (binaryPackage *database.Feature, sourcePackage *database.Feature) { + var ( + name string + version string + sourceName string + sourceVersion string + ) + + for { + line := strings.TrimSpace(scanner.Text()) + if line == "" { + break + } + + if strings.HasPrefix(line, "Package: ") { + name = strings.TrimSpace(strings.TrimPrefix(line, "Package: ")) } else if strings.HasPrefix(line, "Source: ") { // Source line (Optional) // Gives the name of the source package @@ -87,14 +101,9 @@ func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error) md[dpkgSrcCaptureRegexpNames[i]] = strings.TrimSpace(n) } - pkg.SourceName = md["name"] + sourceName = md["name"] if md["version"] != "" { - version := md["version"] - if err = versionfmt.Valid(dpkg.ParserName, version); err != nil { - log.WithError(err).WithField("version", string(line[1])).Warning("could not parse package version. skipping") - } else { - pkg.SourceVersion = version - } + sourceVersion = md["version"] } } else if strings.HasPrefix(line, "Version: ") { // Version line @@ -102,25 +111,43 @@ func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error) // This version is less important than a version retrieved from a Source line // because the Debian vulnerabilities often skips the epoch from the Version field // which is not present in the Source version, and because +bX revisions don't matter - version := strings.TrimPrefix(line, "Version: ") - if err = versionfmt.Valid(dpkg.ParserName, version); err != nil { - log.WithError(err).WithField("version", string(line[1])).Warning("could not parse package version. skipping") - } else { - pkg.Version = version - } - } else if line == "" { - pkg = database.Feature{VersionFormat: dpkg.ParserName} + version = strings.TrimPrefix(line, "Version: ") } - if valid(&pkg) { - addSourcePackage(&pkg) - pkgs.Add(pkg) + if !scanner.Scan() { + break } } - return database.ConvertFeatureSetToFeatures(pkgs), nil -} + if name != "" && version != "" { + if err := versionfmt.Valid(dpkg.ParserName, version); err != nil { + log.WithError(err).WithFields(log.Fields{"name": name, "version": version}).Warning("skipped unparseable package") + } else { + binaryPackage = &database.Feature{name, version, dpkg.ParserName, database.BinaryPackage} + } + } -func (l lister) RequiredFilenames() []string { - return []string{"var/lib/dpkg/status"} + // Source version and names are computed from binary package names and versions + // in dpkg. + // Source package name: + // https://git.dpkg.org/cgit/dpkg/dpkg.git/tree/lib/dpkg/pkg-format.c#n338 + // Source package version: + // https://git.dpkg.org/cgit/dpkg/dpkg.git/tree/lib/dpkg/pkg-format.c#n355 + if sourceName == "" { + sourceName = name + } + + if sourceVersion == "" { + sourceVersion = version + } + + if sourceName != "" && sourceVersion != "" { + if err := versionfmt.Valid(dpkg.ParserName, version); err != nil { + log.WithError(err).WithFields(log.Fields{"name": name, "version": version}).Warning("skipped unparseable package") + } else { + sourcePackage = &database.Feature{sourceName, sourceVersion, dpkg.ParserName, database.SourcePackage} + } + } + + return } diff --git a/ext/featurefmt/dpkg/dpkg_test.go b/ext/featurefmt/dpkg/dpkg_test.go index ff1de7a0..6bfb9bc7 100644 --- a/ext/featurefmt/dpkg/dpkg_test.go +++ b/ext/featurefmt/dpkg/dpkg_test.go @@ -28,105 +28,168 @@ func TestListFeatures(t *testing.T) { "valid status file", map[string]string{"var/lib/dpkg/status": "dpkg/testdata/valid"}, []database.Feature{ - {"adduser", "3.116ubuntu1", "adduser", "3.116ubuntu1", dpkg.ParserName}, - {"apt", "1.6.3ubuntu0.1", "apt", "1.6.3ubuntu0.1", dpkg.ParserName}, - {"base-files", "10.1ubuntu2.2", "base-files", "10.1ubuntu2.2", dpkg.ParserName}, - {"base-passwd", "3.5.44", "base-passwd", "3.5.44", dpkg.ParserName}, - {"bash", "4.4.18-2ubuntu1", "bash", "4.4.18-2ubuntu1", dpkg.ParserName}, - {"bsdutils", "1:2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName}, - {"bzip2", "1.0.6-8.1", "bzip2", "1.0.6-8.1", dpkg.ParserName}, - {"coreutils", "8.28-1ubuntu1", "coreutils", "8.28-1ubuntu1", dpkg.ParserName}, - {"dash", "0.5.8-2.10", "dash", "0.5.8-2.10", dpkg.ParserName}, - {"debconf", "1.5.66", "debconf", "1.5.66", dpkg.ParserName}, - {"debianutils", "4.8.4", "debianutils", "4.8.4", dpkg.ParserName}, - {"diffutils", "1:3.6-1", "diffutils", "1:3.6-1", dpkg.ParserName}, - {"dpkg", "1.19.0.5ubuntu2", "dpkg", "1.19.0.5ubuntu2", dpkg.ParserName}, - {"e2fsprogs", "1.44.1-1", "e2fsprogs", "1.44.1-1", dpkg.ParserName}, - {"fdisk", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName}, - {"findutils", "4.6.0+git+20170828-2", "findutils", "4.6.0+git+20170828-2", dpkg.ParserName}, - {"gcc-8-base", "8-20180414-1ubuntu2", "gcc-8", "8-20180414-1ubuntu2", dpkg.ParserName}, - {"gpgv", "2.2.4-1ubuntu1.1", "gnupg2", "2.2.4-1ubuntu1.1", dpkg.ParserName}, - {"grep", "3.1-2", "grep", "3.1-2", dpkg.ParserName}, - {"gzip", "1.6-5ubuntu1", "gzip", "1.6-5ubuntu1", dpkg.ParserName}, - {"hostname", "3.20", "hostname", "3.20", dpkg.ParserName}, - {"init-system-helpers", "1.51", "init-system-helpers", "1.51", dpkg.ParserName}, - {"libacl1", "2.2.52-3build1", "acl", "2.2.52-3build1", dpkg.ParserName}, - {"libapt-pkg5.0", "1.6.3ubuntu0.1", "apt", "1.6.3ubuntu0.1", dpkg.ParserName}, - {"libattr1", "1:2.4.47-2build1", "attr", "1:2.4.47-2build1", dpkg.ParserName}, - {"libaudit-common", "1:2.8.2-1ubuntu1", "audit", "1:2.8.2-1ubuntu1", dpkg.ParserName}, - {"libaudit1", "1:2.8.2-1ubuntu1", "audit", "1:2.8.2-1ubuntu1", dpkg.ParserName}, - {"libblkid1", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName}, - {"libbz2-1.0", "1.0.6-8.1", "bzip2", "1.0.6-8.1", dpkg.ParserName}, - {"libc-bin", "2.27-3ubuntu1", "glibc", "2.27-3ubuntu1", dpkg.ParserName}, - {"libc6", "2.27-3ubuntu1", "glibc", "2.27-3ubuntu1", dpkg.ParserName}, - {"libcap-ng0", "0.7.7-3.1", "libcap-ng", "0.7.7-3.1", dpkg.ParserName}, - {"libcom-err2", "1.44.1-1", "e2fsprogs", "1.44.1-1", dpkg.ParserName}, - {"libdb5.3", "5.3.28-13.1ubuntu1", "db5.3", "5.3.28-13.1ubuntu1", dpkg.ParserName}, - {"libdebconfclient0", "0.213ubuntu1", "cdebconf", "0.213ubuntu1", dpkg.ParserName}, - {"libext2fs2", "1.44.1-1", "e2fsprogs", "1.44.1-1", dpkg.ParserName}, - {"libfdisk1", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName}, - {"libffi6", "3.2.1-8", "libffi", "3.2.1-8", dpkg.ParserName}, - {"libgcc1", "1:8-20180414-1ubuntu2", "gcc-8", "8-20180414-1ubuntu2", dpkg.ParserName}, - {"libgcrypt20", "1.8.1-4ubuntu1.1", "libgcrypt20", "1.8.1-4ubuntu1.1", dpkg.ParserName}, - {"libgmp10", "2:6.1.2+dfsg-2", "gmp", "2:6.1.2+dfsg-2", dpkg.ParserName}, - {"libgnutls30", "3.5.18-1ubuntu1", "gnutls28", "3.5.18-1ubuntu1", dpkg.ParserName}, - {"libgpg-error0", "1.27-6", "libgpg-error", "1.27-6", dpkg.ParserName}, - {"libhogweed4", "3.4-1", "nettle", "3.4-1", dpkg.ParserName}, - {"libidn2-0", "2.0.4-1.1build2", "libidn2", "2.0.4-1.1build2", dpkg.ParserName}, - {"liblz4-1", "0.0~r131-2ubuntu3", "lz4", "0.0~r131-2ubuntu3", dpkg.ParserName}, - {"liblzma5", "5.2.2-1.3", "xz-utils", "5.2.2-1.3", dpkg.ParserName}, - {"libmount1", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName}, - {"libncurses5", "6.1-1ubuntu1.18.04", "ncurses", "6.1-1ubuntu1.18.04", dpkg.ParserName}, - {"libncursesw5", "6.1-1ubuntu1.18.04", "ncurses", "6.1-1ubuntu1.18.04", dpkg.ParserName}, - {"libnettle6", "3.4-1", "nettle", "3.4-1", dpkg.ParserName}, - {"libp11-kit0", "0.23.9-2", "p11-kit", "0.23.9-2", dpkg.ParserName}, - {"libpam-modules", "1.1.8-3.6ubuntu2", "pam", "1.1.8-3.6ubuntu2", dpkg.ParserName}, - {"libpam-modules-bin", "1.1.8-3.6ubuntu2", "pam", "1.1.8-3.6ubuntu2", dpkg.ParserName}, - {"libpam-runtime", "1.1.8-3.6ubuntu2", "pam", "1.1.8-3.6ubuntu2", dpkg.ParserName}, - {"libpam0g", "1.1.8-3.6ubuntu2", "pam", "1.1.8-3.6ubuntu2", dpkg.ParserName}, - {"libpcre3", "2:8.39-9", "pcre3", "2:8.39-9", dpkg.ParserName}, - {"libprocps6", "2:3.3.12-3ubuntu1.1", "procps", "2:3.3.12-3ubuntu1.1", dpkg.ParserName}, - {"libseccomp2", "2.3.1-2.1ubuntu4", "libseccomp", "2.3.1-2.1ubuntu4", dpkg.ParserName}, - {"libselinux1", "2.7-2build2", "libselinux", "2.7-2build2", dpkg.ParserName}, - {"libsemanage-common", "2.7-2build2", "libsemanage", "2.7-2build2", dpkg.ParserName}, - {"libsemanage1", "2.7-2build2", "libsemanage", "2.7-2build2", dpkg.ParserName}, - {"libsepol1", "2.7-1", "libsepol", "2.7-1", dpkg.ParserName}, - {"libsmartcols1", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName}, - {"libss2", "1.44.1-1", "e2fsprogs", "1.44.1-1", dpkg.ParserName}, - {"libstdc++6", "8-20180414-1ubuntu2", "gcc-8", "8-20180414-1ubuntu2", dpkg.ParserName}, - {"libsystemd0", "237-3ubuntu10.3", "systemd", "237-3ubuntu10.3", dpkg.ParserName}, - {"libtasn1-6", "4.13-2", "libtasn1-6", "4.13-2", dpkg.ParserName}, - {"libtinfo5", "6.1-1ubuntu1.18.04", "ncurses", "6.1-1ubuntu1.18.04", dpkg.ParserName}, - {"libudev1", "237-3ubuntu10.3", "systemd", "237-3ubuntu10.3", dpkg.ParserName}, - {"libunistring2", "0.9.9-0ubuntu1", "libunistring", "0.9.9-0ubuntu1", dpkg.ParserName}, - {"libuuid1", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName}, - {"libzstd1", "1.3.3+dfsg-2ubuntu1", "libzstd", "1.3.3+dfsg-2ubuntu1", dpkg.ParserName}, - {"login", "1:4.5-1ubuntu1", "shadow", "1:4.5-1ubuntu1", dpkg.ParserName}, - {"lsb-base", "9.20170808ubuntu1", "lsb", "9.20170808ubuntu1", dpkg.ParserName}, - {"mawk", "1.3.3-17ubuntu3", "mawk", "1.3.3-17ubuntu3", dpkg.ParserName}, - {"mount", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName}, - {"ncurses-base", "6.1-1ubuntu1.18.04", "ncurses", "6.1-1ubuntu1.18.04", dpkg.ParserName}, - {"ncurses-bin", "6.1-1ubuntu1.18.04", "ncurses", "6.1-1ubuntu1.18.04", dpkg.ParserName}, - {"passwd", "1:4.5-1ubuntu1", "shadow", "1:4.5-1ubuntu1", dpkg.ParserName}, - {"perl-base", "5.26.1-6ubuntu0.2", "perl", "5.26.1-6ubuntu0.2", dpkg.ParserName}, - {"procps", "2:3.3.12-3ubuntu1.1", "procps", "2:3.3.12-3ubuntu1.1", dpkg.ParserName}, - {"sed", "4.4-2", "sed", "4.4-2", dpkg.ParserName}, - {"sensible-utils", "0.0.12", "sensible-utils", "0.0.12", dpkg.ParserName}, - {"sysvinit-utils", "2.88dsf-59.10ubuntu1", "sysvinit", "2.88dsf-59.10ubuntu1", dpkg.ParserName}, - {"tar", "1.29b-2", "tar", "1.29b-2", dpkg.ParserName}, - {"ubuntu-keyring", "2018.02.28", "ubuntu-keyring", "2018.02.28", dpkg.ParserName}, - {"util-linux", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName}, - {"zlib1g", "1:1.2.11.dfsg-0ubuntu2", "zlib", "1:1.2.11.dfsg-0ubuntu2", dpkg.ParserName}, + {"libapt-pkg5.0", "1.6.3ubuntu0.1", "dpkg", "binary"}, + {"perl-base", "5.26.1-6ubuntu0.2", "dpkg", "binary"}, + {"libmount1", "2.31.1-0.4ubuntu3.1", "dpkg", "binary"}, + {"perl", "5.26.1-6ubuntu0.2", "dpkg", "source"}, + {"libgnutls30", "3.5.18-1ubuntu1", "dpkg", "binary"}, + {"liblzma5", "5.2.2-1.3", "dpkg", "binary"}, + {"ncurses-bin", "6.1-1ubuntu1.18.04", "dpkg", "binary"}, + {"lsb", "9.20170808ubuntu1", "dpkg", "source"}, + {"sed", "4.4-2", "dpkg", "source"}, + {"libsystemd0", "237-3ubuntu10.3", "dpkg", "binary"}, + {"procps", "2:3.3.12-3ubuntu1.1", "dpkg", "source"}, + {"login", "1:4.5-1ubuntu1", "dpkg", "binary"}, + {"libunistring2", "0.9.9-0ubuntu1", "dpkg", "binary"}, + {"sed", "4.4-2", "dpkg", "binary"}, + {"libselinux", "2.7-2build2", "dpkg", "source"}, + {"libseccomp", "2.3.1-2.1ubuntu4", "dpkg", "source"}, + {"libss2", "1.44.1-1", "dpkg", "binary"}, + {"liblz4-1", "0.0~r131-2ubuntu3", "dpkg", "binary"}, + {"libsemanage1", "2.7-2build2", "dpkg", "binary"}, + {"libtasn1-6", "4.13-2", "dpkg", "source"}, + {"libzstd1", "1.3.3+dfsg-2ubuntu1", "dpkg", "binary"}, + {"fdisk", "2.31.1-0.4ubuntu3.1", "dpkg", "binary"}, + {"xz-utils", "5.2.2-1.3", "dpkg", "source"}, + {"lsb-base", "9.20170808ubuntu1", "dpkg", "binary"}, + {"libpam-modules-bin", "1.1.8-3.6ubuntu2", "dpkg", "binary"}, + {"dash", "0.5.8-2.10", "dpkg", "binary"}, + {"gnupg2", "2.2.4-1ubuntu1.1", "dpkg", "source"}, + {"libfdisk1", "2.31.1-0.4ubuntu3.1", "dpkg", "binary"}, + {"lz4", "0.0~r131-2ubuntu3", "dpkg", "source"}, + {"libpam0g", "1.1.8-3.6ubuntu2", "dpkg", "binary"}, + {"libc-bin", "2.27-3ubuntu1", "dpkg", "binary"}, + {"libcap-ng", "0.7.7-3.1", "dpkg", "source"}, + {"libcom-err2", "1.44.1-1", "dpkg", "binary"}, + {"libudev1", "237-3ubuntu10.3", "dpkg", "binary"}, + {"debconf", "1.5.66", "dpkg", "binary"}, + {"tar", "1.29b-2", "dpkg", "binary"}, + {"diffutils", "1:3.6-1", "dpkg", "source"}, + {"gcc-8", "8-20180414-1ubuntu2", "dpkg", "source"}, + {"e2fsprogs", "1.44.1-1", "dpkg", "source"}, + {"bzip2", "1.0.6-8.1", "dpkg", "source"}, + {"diffutils", "1:3.6-1", "dpkg", "binary"}, + {"grep", "3.1-2", "dpkg", "binary"}, + {"libgcc1", "1:8-20180414-1ubuntu2", "dpkg", "binary"}, + {"bash", "4.4.18-2ubuntu1", "dpkg", "source"}, + {"libtinfo5", "6.1-1ubuntu1.18.04", "dpkg", "binary"}, + {"procps", "2:3.3.12-3ubuntu1.1", "dpkg", "binary"}, + {"bzip2", "1.0.6-8.1", "dpkg", "binary"}, + {"init-system-helpers", "1.51", "dpkg", "binary"}, + {"libncursesw5", "6.1-1ubuntu1.18.04", "dpkg", "binary"}, + {"init-system-helpers", "1.51", "dpkg", "source"}, + {"libpam-modules", "1.1.8-3.6ubuntu2", "dpkg", "binary"}, + {"libext2fs2", "1.44.1-1", "dpkg", "binary"}, + {"libacl1", "2.2.52-3build1", "dpkg", "binary"}, + {"hostname", "3.20", "dpkg", "binary"}, + {"libgpg-error", "1.27-6", "dpkg", "source"}, + {"acl", "2.2.52-3build1", "dpkg", "source"}, + {"apt", "1.6.3ubuntu0.1", "dpkg", "binary"}, + {"base-files", "10.1ubuntu2.2", "dpkg", "source"}, + {"libgpg-error0", "1.27-6", "dpkg", "binary"}, + {"audit", "1:2.8.2-1ubuntu1", "dpkg", "source"}, + {"hostname", "3.20", "dpkg", "source"}, + {"gzip", "1.6-5ubuntu1", "dpkg", "binary"}, + {"libc6", "2.27-3ubuntu1", "dpkg", "binary"}, + {"libnettle6", "3.4-1", "dpkg", "binary"}, + {"sysvinit-utils", "2.88dsf-59.10ubuntu1", "dpkg", "binary"}, + {"debianutils", "4.8.4", "dpkg", "source"}, + {"libstdc++6", "8-20180414-1ubuntu2", "dpkg", "binary"}, + {"libsepol", "2.7-1", "dpkg", "source"}, + {"libpcre3", "2:8.39-9", "dpkg", "binary"}, + {"libuuid1", "2.31.1-0.4ubuntu3.1", "dpkg", "binary"}, + {"systemd", "237-3ubuntu10.3", "dpkg", "source"}, + {"tar", "1.29b-2", "dpkg", "source"}, + {"ubuntu-keyring", "2018.02.28", "dpkg", "source"}, + {"passwd", "1:4.5-1ubuntu1", "dpkg", "binary"}, + {"sysvinit", "2.88dsf-59.10ubuntu1", "dpkg", "source"}, + {"libidn2-0", "2.0.4-1.1build2", "dpkg", "binary"}, + {"libhogweed4", "3.4-1", "dpkg", "binary"}, + {"db5.3", "5.3.28-13.1ubuntu1", "dpkg", "source"}, + {"sensible-utils", "0.0.12", "dpkg", "source"}, + {"dpkg", "1.19.0.5ubuntu2", "dpkg", "source"}, + {"libp11-kit0", "0.23.9-2", "dpkg", "binary"}, + {"glibc", "2.27-3ubuntu1", "dpkg", "source"}, + {"mount", "2.31.1-0.4ubuntu3.1", "dpkg", "binary"}, + {"libsemanage-common", "2.7-2build2", "dpkg", "binary"}, + {"libblkid1", "2.31.1-0.4ubuntu3.1", "dpkg", "binary"}, + {"libdebconfclient0", "0.213ubuntu1", "dpkg", "binary"}, + {"libffi", "3.2.1-8", "dpkg", "source"}, + {"pam", "1.1.8-3.6ubuntu2", "dpkg", "source"}, + {"bsdutils", "1:2.31.1-0.4ubuntu3.1", "dpkg", "binary"}, + {"libtasn1-6", "4.13-2", "dpkg", "binary"}, + {"libaudit-common", "1:2.8.2-1ubuntu1", "dpkg", "binary"}, + {"gpgv", "2.2.4-1ubuntu1.1", "dpkg", "binary"}, + {"libzstd", "1.3.3+dfsg-2ubuntu1", "dpkg", "source"}, + {"base-passwd", "3.5.44", "dpkg", "source"}, + {"adduser", "3.116ubuntu1", "dpkg", "binary"}, + {"libattr1", "1:2.4.47-2build1", "dpkg", "binary"}, + {"libncurses5", "6.1-1ubuntu1.18.04", "dpkg", "binary"}, + {"coreutils", "8.28-1ubuntu1", "dpkg", "binary"}, + {"base-passwd", "3.5.44", "dpkg", "binary"}, + {"ubuntu-keyring", "2018.02.28", "dpkg", "binary"}, + {"adduser", "3.116ubuntu1", "dpkg", "source"}, + {"libsmartcols1", "2.31.1-0.4ubuntu3.1", "dpkg", "binary"}, + {"libunistring", "0.9.9-0ubuntu1", "dpkg", "source"}, + {"mawk", "1.3.3-17ubuntu3", "dpkg", "source"}, + {"coreutils", "8.28-1ubuntu1", "dpkg", "source"}, + {"attr", "1:2.4.47-2build1", "dpkg", "source"}, + {"gmp", "2:6.1.2+dfsg-2", "dpkg", "source"}, + {"libsemanage", "2.7-2build2", "dpkg", "source"}, + {"libselinux1", "2.7-2build2", "dpkg", "binary"}, + {"libseccomp2", "2.3.1-2.1ubuntu4", "dpkg", "binary"}, + {"zlib1g", "1:1.2.11.dfsg-0ubuntu2", "dpkg", "binary"}, + {"dash", "0.5.8-2.10", "dpkg", "source"}, + {"gnutls28", "3.5.18-1ubuntu1", "dpkg", "source"}, + {"libpam-runtime", "1.1.8-3.6ubuntu2", "dpkg", "binary"}, + {"libgcrypt20", "1.8.1-4ubuntu1.1", "dpkg", "source"}, + {"sensible-utils", "0.0.12", "dpkg", "binary"}, + {"p11-kit", "0.23.9-2", "dpkg", "source"}, + {"ncurses-base", "6.1-1ubuntu1.18.04", "dpkg", "binary"}, + {"e2fsprogs", "1.44.1-1", "dpkg", "binary"}, + {"libgcrypt20", "1.8.1-4ubuntu1.1", "dpkg", "binary"}, + {"libprocps6", "2:3.3.12-3ubuntu1.1", "dpkg", "binary"}, + {"debconf", "1.5.66", "dpkg", "source"}, + {"gcc-8-base", "8-20180414-1ubuntu2", "dpkg", "binary"}, + {"base-files", "10.1ubuntu2.2", "dpkg", "binary"}, + {"libbz2-1.0", "1.0.6-8.1", "dpkg", "binary"}, + {"grep", "3.1-2", "dpkg", "source"}, + {"bash", "4.4.18-2ubuntu1", "dpkg", "binary"}, + {"libgmp10", "2:6.1.2+dfsg-2", "dpkg", "binary"}, + {"shadow", "1:4.5-1ubuntu1", "dpkg", "source"}, + {"libidn2", "2.0.4-1.1build2", "dpkg", "source"}, + {"gzip", "1.6-5ubuntu1", "dpkg", "source"}, + {"util-linux", "2.31.1-0.4ubuntu3.1", "dpkg", "binary"}, + {"libaudit1", "1:2.8.2-1ubuntu1", "dpkg", "binary"}, + {"libsepol1", "2.7-1", "dpkg", "binary"}, + {"pcre3", "2:8.39-9", "dpkg", "source"}, + {"apt", "1.6.3ubuntu0.1", "dpkg", "source"}, + {"nettle", "3.4-1", "dpkg", "source"}, + {"util-linux", "2.31.1-0.4ubuntu3.1", "dpkg", "source"}, + {"libcap-ng0", "0.7.7-3.1", "dpkg", "binary"}, + {"debianutils", "4.8.4", "dpkg", "binary"}, + {"ncurses", "6.1-1ubuntu1.18.04", "dpkg", "source"}, + {"libffi6", "3.2.1-8", "dpkg", "binary"}, + {"cdebconf", "0.213ubuntu1", "dpkg", "source"}, + {"findutils", "4.6.0+git+20170828-2", "dpkg", "source"}, + {"libdb5.3", "5.3.28-13.1ubuntu1", "dpkg", "binary"}, + {"zlib", "1:1.2.11.dfsg-0ubuntu2", "dpkg", "source"}, + {"findutils", "4.6.0+git+20170828-2", "dpkg", "binary"}, + {"dpkg", "1.19.0.5ubuntu2", "dpkg", "binary"}, + {"mawk", "1.3.3-17ubuntu3", "dpkg", "binary"}, }, }, { "corrupted status file", map[string]string{"var/lib/dpkg/status": "dpkg/testdata/corrupted"}, []database.Feature{ - {"libpam-runtime", "1.1.8-3.1ubuntu3", "pam", "1.1.8-3.1ubuntu3", dpkg.ParserName}, - {"libpam-modules-bin", "1.1.8-3.1ubuntu3", "pam", "1.1.8-3.1ubuntu3", dpkg.ParserName}, - {"makedev", "2.3.1-93ubuntu1", "makedev", "2.3.1-93ubuntu1", dpkg.ParserName}, - {"libgcc1", "1:5.1.1-12ubuntu1", "gcc-5", "5.1.1-12ubuntu1", dpkg.ParserName}, + {"libpam-modules-bin", "1.1.8-3.1ubuntu3", "dpkg", "binary"}, + {"gcc-5", "5.1.1-12ubuntu1", "dpkg", "source"}, + {"makedev", "2.3.1-93ubuntu1", "dpkg", "binary"}, + {"libgcc1", "1:5.1.1-12ubuntu1", "dpkg", "binary"}, + {"pam", "1.1.8-3.1ubuntu3", "dpkg", "source"}, + {"makedev", "2.3.1-93ubuntu1", "dpkg", "source"}, + {"libpam-runtime", "1.1.8-3.1ubuntu3", "dpkg", "binary"}, }, }, } { diff --git a/ext/featurefmt/rpm/rpm.go b/ext/featurefmt/rpm/rpm.go index 5ad70191..388212ea 100644 --- a/ext/featurefmt/rpm/rpm.go +++ b/ext/featurefmt/rpm/rpm.go @@ -45,6 +45,10 @@ func init() { featurefmt.RegisterLister("rpm", "1.0", &lister{}) } +func (l lister) RequiredFilenames() []string { + return []string{"var/lib/rpm/Packages"} +} + func isIgnored(packageName string) bool { for _, pkg := range ignoredPackages { if pkg == packageName { @@ -55,12 +59,6 @@ func isIgnored(packageName string) bool { return false } -func valid(pkg *database.Feature) bool { - return pkg.Name != "" && pkg.Version != "" && - ((pkg.SourceName == "" && pkg.SourceVersion != "") || - (pkg.SourceName != "" && pkg.SourceVersion != "")) -} - func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error) { f, hasFile := files["var/lib/rpm/Packages"] if !hasFile { @@ -84,7 +82,7 @@ func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error) // Extract binary package names because RHSA refers to binary package names. out, err := exec.Command("rpm", "--dbpath", tmpDir, "-qa", "--qf", "%{NAME} %{EPOCH}:%{VERSION}-%{RELEASE} %{SOURCERPM}\n").CombinedOutput() if err != nil { - log.WithError(err).WithField("output", string(out)).Error("could not query RPM") + log.WithError(err).WithField("output", string(out)).Error("failed to query RPM") // Do not bubble up because we probably won't be able to fix it, // the database must be corrupted return []database.Feature{}, nil @@ -93,39 +91,51 @@ func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error) packages := mapset.NewSet() scanner := bufio.NewScanner(strings.NewReader(string(out))) for scanner.Scan() { - line := strings.Split(scanner.Text(), " ") - if len(line) != 3 { - // We may see warnings on some RPM versions: - // "warning: Generating 12 missing index(es), please wait..." - continue + rpmPackage, srpmPackage := parseRPMOutput(scanner.Text()) + if rpmPackage != nil { + packages.Add(*rpmPackage) } - if isIgnored(line[0]) { - continue - } - - pkg := database.Feature{Name: line[0], VersionFormat: rpm.ParserName} - pkg.Version = strings.Replace(line[1], "(none):", "", -1) - if err := versionfmt.Valid(rpm.ParserName, pkg.Version); err != nil { - log.WithError(err).WithField("version", line[1]).Warning("skipped unparseable package") - continue - } - - if err := parseSourceRPM(line[2], &pkg); err != nil { - log.WithError(err).WithField("sourcerpm", line[2]).Warning("skipped unparseable package") - continue - } - - if valid(&pkg) { - packages.Add(pkg) + if srpmPackage != nil { + packages.Add(*srpmPackage) } } return database.ConvertFeatureSetToFeatures(packages), nil } -func (l lister) RequiredFilenames() []string { - return []string{"var/lib/rpm/Packages"} +func parseRPMOutput(raw string) (rpmPackage *database.Feature, srpmPackage *database.Feature) { + line := strings.Split(raw, " ") + if len(line) != 3 { + // We may see warnings on some RPM versions: + // "warning: Generating 12 missing index(es), please wait..." + return + } + + if isIgnored(line[0]) { + return + } + + name, version, srpm := line[0], strings.Replace(line[1], "(none):", "", -1), line[2] + if err := versionfmt.Valid(rpm.ParserName, version); err != nil { + log.WithError(err).WithFields(log.Fields{"name": name, "version": version}).Warning("skipped unparseable package") + return + } + + rpmPackage = &database.Feature{name, version, rpm.ParserName, database.BinaryPackage} + srpmName, srpmVersion, srpmRelease, _, err := parseSourceRPM(srpm) + if err != nil { + log.WithError(err).WithFields(log.Fields{"name": name, "sourcerpm": srpm}).Warning("skipped unparseable package") + return + } + + srpmVersion = srpmVersion + "-" + srpmRelease + if err = versionfmt.Valid(rpm.ParserName, srpmVersion); err != nil { + return + } + + srpmPackage = &database.Feature{srpmName, srpmVersion, rpm.ParserName, database.SourcePackage} + return } type rpmParserState string @@ -140,11 +150,9 @@ const ( // parseSourceRPM parses the source rpm package representation string // http://ftp.rpm.org/max-rpm/ch-rpm-file-format.html -func parseSourceRPM(sourceRPM string, pkg *database.Feature) error { +func parseSourceRPM(sourceRPM string) (name string, version string, release string, architecture string, err error) { state := parseRPM previousCheckPoint := len(sourceRPM) - release := "" - version := "" for i := len(sourceRPM) - 1; i >= 0; i-- { switch state { case parseRPM: @@ -153,16 +161,18 @@ func parseSourceRPM(sourceRPM string, pkg *database.Feature) error { packageType := strutil.Substring(sourceRPM, i+1, len(sourceRPM)) previousCheckPoint = i if packageType != "rpm" { - return fmt.Errorf("unexpected package type, expect: 'rpm', got: '%s'", packageType) + err = fmt.Errorf("unexpected package type, expect: 'rpm', got: '%s'", packageType) + return } } case parseArchitecture: if string(sourceRPM[i]) == "." { state = parseRelease - architecture := strutil.Substring(sourceRPM, i+1, previousCheckPoint) + architecture = strutil.Substring(sourceRPM, i+1, previousCheckPoint) previousCheckPoint = i if architecture != "src" && architecture != "nosrc" { - return fmt.Errorf("unexpected package architecture, expect: 'src' or 'nosrc', got: '%s'", architecture) + err = fmt.Errorf("unexpected package architecture, expect: 'src' or 'nosrc', got: '%s'", architecture) + return } } case parseRelease: @@ -171,7 +181,8 @@ func parseSourceRPM(sourceRPM string, pkg *database.Feature) error { release = strutil.Substring(sourceRPM, i+1, previousCheckPoint) previousCheckPoint = i if release == "" { - return fmt.Errorf("unexpected package release, expect: not empty") + err = fmt.Errorf("unexpected package release, expect: not empty") + return } } case parseVersion: @@ -181,7 +192,8 @@ func parseSourceRPM(sourceRPM string, pkg *database.Feature) error { version = strutil.Substring(sourceRPM, i+1, previousCheckPoint) previousCheckPoint = i if version == "" { - return fmt.Errorf("unexpected package version, expect: not empty") + err = fmt.Errorf("unexpected package version, expect: not empty") + return } break } @@ -189,20 +201,15 @@ func parseSourceRPM(sourceRPM string, pkg *database.Feature) error { } if state != terminate { - return fmt.Errorf("unexpected termination while parsing '%s'", state) + err = fmt.Errorf("unexpected termination while parsing '%s'", state) + return } - concatVersion := version + "-" + release - if err := versionfmt.Valid(rpm.ParserName, concatVersion); err != nil { - return err - } - - name := strutil.Substring(sourceRPM, 0, previousCheckPoint) + name = strutil.Substring(sourceRPM, 0, previousCheckPoint) if name == "" { - return fmt.Errorf("unexpected package name, expect: not empty") + err = fmt.Errorf("unexpected package name, expect: not empty") + return } - pkg.SourceName = name - pkg.SourceVersion = concatVersion - return nil + return } diff --git a/ext/featurefmt/rpm/rpm_test.go b/ext/featurefmt/rpm/rpm_test.go index d727d203..ae5a70c5 100644 --- a/ext/featurefmt/rpm/rpm_test.go +++ b/ext/featurefmt/rpm/rpm_test.go @@ -25,179 +25,307 @@ import ( ) var expectedBigCaseInfo = []database.Feature{ - {"publicsuffix-list-dafsa", "20180514-1.fc28", "publicsuffix-list", "20180514-1.fc28", rpm.ParserName}, - {"libreport-filesystem", "2.9.5-1.fc28", "libreport", "2.9.5-1.fc28", rpm.ParserName}, - {"fedora-gpg-keys", "28-5", "fedora-repos", "28-5", rpm.ParserName}, - {"fedora-release", "28-2", "fedora-release", "28-2", rpm.ParserName}, - {"filesystem", "3.8-2.fc28", "filesystem", "3.8-2.fc28", rpm.ParserName}, - {"tzdata", "2018e-1.fc28", "tzdata", "2018e-1.fc28", rpm.ParserName}, - {"pcre2", "10.31-10.fc28", "pcre2", "10.31-10.fc28", rpm.ParserName}, - {"glibc-minimal-langpack", "2.27-32.fc28", "glibc", "2.27-32.fc28", rpm.ParserName}, - {"glibc-common", "2.27-32.fc28", "glibc", "2.27-32.fc28", rpm.ParserName}, - {"bash", "4.4.23-1.fc28", "bash", "4.4.23-1.fc28", rpm.ParserName}, - {"zlib", "1.2.11-8.fc28", "zlib", "1.2.11-8.fc28", rpm.ParserName}, - {"bzip2-libs", "1.0.6-26.fc28", "bzip2", "1.0.6-26.fc28", rpm.ParserName}, - {"libcap", "2.25-9.fc28", "libcap", "2.25-9.fc28", rpm.ParserName}, - {"libgpg-error", "1.31-1.fc28", "libgpg-error", "1.31-1.fc28", rpm.ParserName}, - {"libzstd", "1.3.5-1.fc28", "zstd", "1.3.5-1.fc28", rpm.ParserName}, - {"expat", "2.2.5-3.fc28", "expat", "2.2.5-3.fc28", rpm.ParserName}, - {"nss-util", "3.38.0-1.0.fc28", "nss-util", "3.38.0-1.0.fc28", rpm.ParserName}, - {"libcom_err", "1.44.2-0.fc28", "e2fsprogs", "1.44.2-0.fc28", rpm.ParserName}, - {"libffi", "3.1-16.fc28", "libffi", "3.1-16.fc28", rpm.ParserName}, - {"libgcrypt", "1.8.3-1.fc28", "libgcrypt", "1.8.3-1.fc28", rpm.ParserName}, - {"libxml2", "2.9.8-4.fc28", "libxml2", "2.9.8-4.fc28", rpm.ParserName}, - {"libacl", "2.2.53-1.fc28", "acl", "2.2.53-1.fc28", rpm.ParserName}, - {"sed", "4.5-1.fc28", "sed", "4.5-1.fc28", rpm.ParserName}, - {"libmount", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28", rpm.ParserName}, - {"p11-kit", "0.23.12-1.fc28", "p11-kit", "0.23.12-1.fc28", rpm.ParserName}, - {"libidn2", "2.0.5-1.fc28", "libidn2", "2.0.5-1.fc28", rpm.ParserName}, - {"libcap-ng", "0.7.9-4.fc28", "libcap-ng", "0.7.9-4.fc28", rpm.ParserName}, - {"lz4-libs", "1.8.1.2-4.fc28", "lz4", "1.8.1.2-4.fc28", rpm.ParserName}, - {"libassuan", "2.5.1-3.fc28", "libassuan", "2.5.1-3.fc28", rpm.ParserName}, - {"keyutils-libs", "1.5.10-6.fc28", "keyutils", "1.5.10-6.fc28", rpm.ParserName}, - {"glib2", "2.56.1-4.fc28", "glib2", "2.56.1-4.fc28", rpm.ParserName}, - {"systemd-libs", "238-9.git0e0aa59.fc28", "systemd", "238-9.git0e0aa59.fc28", rpm.ParserName}, - {"dbus-libs", "1:1.12.10-1.fc28", "dbus", "1.12.10-1.fc28", rpm.ParserName}, - {"libtasn1", "4.13-2.fc28", "libtasn1", "4.13-2.fc28", rpm.ParserName}, - {"ca-certificates", "2018.2.24-1.0.fc28", "ca-certificates", "2018.2.24-1.0.fc28", rpm.ParserName}, - {"libarchive", "3.3.1-4.fc28", "libarchive", "3.3.1-4.fc28", rpm.ParserName}, - {"openssl", "1:1.1.0h-3.fc28", "openssl", "1.1.0h-3.fc28", rpm.ParserName}, - {"libusbx", "1.0.22-1.fc28", "libusbx", "1.0.22-1.fc28", rpm.ParserName}, - {"libsemanage", "2.8-2.fc28", "libsemanage", "2.8-2.fc28", rpm.ParserName}, - {"libutempter", "1.1.6-14.fc28", "libutempter", "1.1.6-14.fc28", rpm.ParserName}, - {"mpfr", "3.1.6-1.fc28", "mpfr", "3.1.6-1.fc28", rpm.ParserName}, - {"gnutls", "3.6.3-4.fc28", "gnutls", "3.6.3-4.fc28", rpm.ParserName}, - {"gzip", "1.9-3.fc28", "gzip", "1.9-3.fc28", rpm.ParserName}, - {"acl", "2.2.53-1.fc28", "acl", "2.2.53-1.fc28", rpm.ParserName}, - {"nss-softokn-freebl", "3.38.0-1.0.fc28", "nss-softokn", "3.38.0-1.0.fc28", rpm.ParserName}, - {"nss", "3.38.0-1.0.fc28", "nss", "3.38.0-1.0.fc28", rpm.ParserName}, - {"libmetalink", "0.1.3-6.fc28", "libmetalink", "0.1.3-6.fc28", rpm.ParserName}, - {"libdb-utils", "5.3.28-30.fc28", "libdb", "5.3.28-30.fc28", rpm.ParserName}, - {"file-libs", "5.33-7.fc28", "file", "5.33-7.fc28", rpm.ParserName}, - {"libsss_idmap", "1.16.3-2.fc28", "sssd", "1.16.3-2.fc28", rpm.ParserName}, - {"libsigsegv", "2.11-5.fc28", "libsigsegv", "2.11-5.fc28", rpm.ParserName}, - {"krb5-libs", "1.16.1-13.fc28", "krb5", "1.16.1-13.fc28", rpm.ParserName}, - {"libnsl2", "1.2.0-2.20180605git4a062cf.fc28", "libnsl2", "1.2.0-2.20180605git4a062cf.fc28", rpm.ParserName}, - {"python3-pip", "9.0.3-2.fc28", "python-pip", "9.0.3-2.fc28", rpm.ParserName}, - {"python3", "3.6.6-1.fc28", "python3", "3.6.6-1.fc28", rpm.ParserName}, - {"pam", "1.3.1-1.fc28", "pam", "1.3.1-1.fc28", rpm.ParserName}, - {"python3-gobject-base", "3.28.3-1.fc28", "pygobject3", "3.28.3-1.fc28", rpm.ParserName}, - {"python3-smartcols", "0.3.0-2.fc28", "python-smartcols", "0.3.0-2.fc28", rpm.ParserName}, - {"python3-iniparse", "0.4-30.fc28", "python-iniparse", "0.4-30.fc28", rpm.ParserName}, - {"openldap", "2.4.46-3.fc28", "openldap", "2.4.46-3.fc28", rpm.ParserName}, - {"libseccomp", "2.3.3-2.fc28", "libseccomp", "2.3.3-2.fc28", rpm.ParserName}, - {"npth", "1.5-4.fc28", "npth", "1.5-4.fc28", rpm.ParserName}, - {"gpgme", "1.10.0-4.fc28", "gpgme", "1.10.0-4.fc28", rpm.ParserName}, - {"json-c", "0.13.1-2.fc28", "json-c", "0.13.1-2.fc28", rpm.ParserName}, - {"libyaml", "0.1.7-5.fc28", "libyaml", "0.1.7-5.fc28", rpm.ParserName}, - {"libpkgconf", "1.4.2-1.fc28", "pkgconf", "1.4.2-1.fc28", rpm.ParserName}, - {"pkgconf-pkg-config", "1.4.2-1.fc28", "pkgconf", "1.4.2-1.fc28", rpm.ParserName}, - {"iptables-libs", "1.6.2-3.fc28", "iptables", "1.6.2-3.fc28", rpm.ParserName}, - {"device-mapper-libs", "1.02.146-5.fc28", "lvm2", "2.02.177-5.fc28", rpm.ParserName}, - {"systemd-pam", "238-9.git0e0aa59.fc28", "systemd", "238-9.git0e0aa59.fc28", rpm.ParserName}, - {"systemd", "238-9.git0e0aa59.fc28", "systemd", "238-9.git0e0aa59.fc28", rpm.ParserName}, - {"elfutils-default-yama-scope", "0.173-1.fc28", "elfutils", "0.173-1.fc28", rpm.ParserName}, - {"libcurl", "7.59.0-6.fc28", "curl", "7.59.0-6.fc28", rpm.ParserName}, - {"python3-librepo", "1.8.1-7.fc28", "librepo", "1.8.1-7.fc28", rpm.ParserName}, - {"rpm-plugin-selinux", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28", rpm.ParserName}, - {"rpm", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28", rpm.ParserName}, - {"libdnf", "0.11.1-3.fc28", "libdnf", "0.11.1-3.fc28", rpm.ParserName}, - {"rpm-build-libs", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28", rpm.ParserName}, - {"python3-rpm", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28", rpm.ParserName}, - {"dnf", "2.7.5-12.fc28", "dnf", "2.7.5-12.fc28", rpm.ParserName}, - {"deltarpm", "3.6-25.fc28", "deltarpm", "3.6-25.fc28", rpm.ParserName}, - {"sssd-client", "1.16.3-2.fc28", "sssd", "1.16.3-2.fc28", rpm.ParserName}, - {"cracklib-dicts", "2.9.6-13.fc28", "cracklib", "2.9.6-13.fc28", rpm.ParserName}, - {"tar", "2:1.30-3.fc28", "tar", "1.30-3.fc28", rpm.ParserName}, - {"diffutils", "3.6-4.fc28", "diffutils", "3.6-4.fc28", rpm.ParserName}, - {"langpacks-en", "1.0-12.fc28", "langpacks", "1.0-12.fc28", rpm.ParserName}, - {"libgcc", "8.1.1-5.fc28", "gcc", "8.1.1-5.fc28", rpm.ParserName}, - {"pkgconf-m4", "1.4.2-1.fc28", "pkgconf", "1.4.2-1.fc28", rpm.ParserName}, - {"dnf-conf", "2.7.5-12.fc28", "dnf", "2.7.5-12.fc28", rpm.ParserName}, - {"fedora-repos", "28-5", "fedora-repos", "28-5", rpm.ParserName}, - {"setup", "2.11.4-1.fc28", "setup", "2.11.4-1.fc28", rpm.ParserName}, - {"basesystem", "11-5.fc28", "basesystem", "11-5.fc28", rpm.ParserName}, - {"ncurses-base", "6.1-5.20180224.fc28", "ncurses", "6.1-5.20180224.fc28", rpm.ParserName}, - {"libselinux", "2.8-1.fc28", "libselinux", "2.8-1.fc28", rpm.ParserName}, - {"ncurses-libs", "6.1-5.20180224.fc28", "ncurses", "6.1-5.20180224.fc28", rpm.ParserName}, - {"glibc", "2.27-32.fc28", "glibc", "2.27-32.fc28", rpm.ParserName}, - {"libsepol", "2.8-1.fc28", "libsepol", "2.8-1.fc28", rpm.ParserName}, - {"xz-libs", "5.2.4-2.fc28", "xz", "5.2.4-2.fc28", rpm.ParserName}, - {"info", "6.5-4.fc28", "texinfo", "6.5-4.fc28", rpm.ParserName}, - {"libdb", "5.3.28-30.fc28", "libdb", "5.3.28-30.fc28", rpm.ParserName}, - {"elfutils-libelf", "0.173-1.fc28", "elfutils", "0.173-1.fc28", rpm.ParserName}, - {"popt", "1.16-14.fc28", "popt", "1.16-14.fc28", rpm.ParserName}, - {"nspr", "4.19.0-1.fc28", "nspr", "4.19.0-1.fc28", rpm.ParserName}, - {"libxcrypt", "4.1.2-1.fc28", "libxcrypt", "4.1.2-1.fc28", rpm.ParserName}, - {"lua-libs", "5.3.4-10.fc28", "lua", "5.3.4-10.fc28", rpm.ParserName}, - {"libuuid", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28", rpm.ParserName}, - {"readline", "7.0-11.fc28", "readline", "7.0-11.fc28", rpm.ParserName}, - {"libattr", "2.4.48-3.fc28", "attr", "2.4.48-3.fc28", rpm.ParserName}, - {"coreutils-single", "8.29-7.fc28", "coreutils", "8.29-7.fc28", rpm.ParserName}, - {"libblkid", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28", rpm.ParserName}, - {"gmp", "1:6.1.2-7.fc28", "gmp", "6.1.2-7.fc28", rpm.ParserName}, - {"libunistring", "0.9.10-1.fc28", "libunistring", "0.9.10-1.fc28", rpm.ParserName}, - {"sqlite-libs", "3.22.0-4.fc28", "sqlite", "3.22.0-4.fc28", rpm.ParserName}, - {"audit-libs", "2.8.4-2.fc28", "audit", "2.8.4-2.fc28", rpm.ParserName}, - {"chkconfig", "1.10-4.fc28", "chkconfig", "1.10-4.fc28", rpm.ParserName}, - {"libsmartcols", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28", rpm.ParserName}, - {"pcre", "8.42-3.fc28", "pcre", "8.42-3.fc28", rpm.ParserName}, - {"grep", "3.1-5.fc28", "grep", "3.1-5.fc28", rpm.ParserName}, - {"crypto-policies", "20180425-5.git6ad4018.fc28", "crypto-policies", "20180425-5.git6ad4018.fc28", rpm.ParserName}, - {"gdbm-libs", "1:1.14.1-4.fc28", "gdbm", "1.14.1-4.fc28", rpm.ParserName}, - {"p11-kit-trust", "0.23.12-1.fc28", "p11-kit", "0.23.12-1.fc28", rpm.ParserName}, - {"openssl-libs", "1:1.1.0h-3.fc28", "openssl", "1.1.0h-3.fc28", rpm.ParserName}, - {"ima-evm-utils", "1.1-2.fc28", "ima-evm-utils", "1.1-2.fc28", rpm.ParserName}, - {"gdbm", "1:1.14.1-4.fc28", "gdbm", "1.14.1-4.fc28", rpm.ParserName}, - {"gobject-introspection", "1.56.1-1.fc28", "gobject-introspection", "1.56.1-1.fc28", rpm.ParserName}, - {"shadow-utils", "2:4.6-1.fc28", "shadow-utils", "4.6-1.fc28", rpm.ParserName}, - {"libpsl", "0.20.2-2.fc28", "libpsl", "0.20.2-2.fc28", rpm.ParserName}, - {"nettle", "3.4-2.fc28", "nettle", "3.4-2.fc28", rpm.ParserName}, - {"libfdisk", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28", rpm.ParserName}, - {"cracklib", "2.9.6-13.fc28", "cracklib", "2.9.6-13.fc28", rpm.ParserName}, - {"libcomps", "0.1.8-11.fc28", "libcomps", "0.1.8-11.fc28", rpm.ParserName}, - {"nss-softokn", "3.38.0-1.0.fc28", "nss-softokn", "3.38.0-1.0.fc28", rpm.ParserName}, - {"nss-sysinit", "3.38.0-1.0.fc28", "nss", "3.38.0-1.0.fc28", rpm.ParserName}, - {"libksba", "1.3.5-7.fc28", "libksba", "1.3.5-7.fc28", rpm.ParserName}, - {"kmod-libs", "25-2.fc28", "kmod", "25-2.fc28", rpm.ParserName}, - {"libsss_nss_idmap", "1.16.3-2.fc28", "sssd", "1.16.3-2.fc28", rpm.ParserName}, - {"libverto", "0.3.0-5.fc28", "libverto", "0.3.0-5.fc28", rpm.ParserName}, - {"gawk", "4.2.1-1.fc28", "gawk", "4.2.1-1.fc28", rpm.ParserName}, - {"libtirpc", "1.0.3-3.rc2.fc28", "libtirpc", "1.0.3-3.rc2.fc28", rpm.ParserName}, - {"python3-libs", "3.6.6-1.fc28", "python3", "3.6.6-1.fc28", rpm.ParserName}, - {"python3-setuptools", "39.2.0-6.fc28", "python-setuptools", "39.2.0-6.fc28", rpm.ParserName}, - {"libpwquality", "1.4.0-7.fc28", "libpwquality", "1.4.0-7.fc28", rpm.ParserName}, - {"util-linux", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28", rpm.ParserName}, - {"python3-libcomps", "0.1.8-11.fc28", "libcomps", "0.1.8-11.fc28", rpm.ParserName}, - {"python3-six", "1.11.0-3.fc28", "python-six", "1.11.0-3.fc28", rpm.ParserName}, - {"cyrus-sasl-lib", "2.1.27-0.2rc7.fc28", "cyrus-sasl", "2.1.27-0.2rc7.fc28", rpm.ParserName}, - {"libssh", "0.8.2-1.fc28", "libssh", "0.8.2-1.fc28", rpm.ParserName}, - {"qrencode-libs", "3.4.4-5.fc28", "qrencode", "3.4.4-5.fc28", rpm.ParserName}, - {"gnupg2", "2.2.8-1.fc28", "gnupg2", "2.2.8-1.fc28", rpm.ParserName}, - {"python3-gpg", "1.10.0-4.fc28", "gpgme", "1.10.0-4.fc28", rpm.ParserName}, - {"libargon2", "20161029-5.fc28", "argon2", "20161029-5.fc28", rpm.ParserName}, - {"libmodulemd", "1.6.2-2.fc28", "libmodulemd", "1.6.2-2.fc28", rpm.ParserName}, - {"pkgconf", "1.4.2-1.fc28", "pkgconf", "1.4.2-1.fc28", rpm.ParserName}, - {"libpcap", "14:1.9.0-1.fc28", "libpcap", "1.9.0-1.fc28", rpm.ParserName}, - {"device-mapper", "1.02.146-5.fc28", "lvm2", "2.02.177-5.fc28", rpm.ParserName}, - {"cryptsetup-libs", "2.0.4-1.fc28", "cryptsetup", "2.0.4-1.fc28", rpm.ParserName}, - {"elfutils-libs", "0.173-1.fc28", "elfutils", "0.173-1.fc28", rpm.ParserName}, - {"dbus", "1:1.12.10-1.fc28", "dbus", "1.12.10-1.fc28", rpm.ParserName}, - {"libnghttp2", "1.32.1-1.fc28", "nghttp2", "1.32.1-1.fc28", rpm.ParserName}, - {"librepo", "1.8.1-7.fc28", "librepo", "1.8.1-7.fc28", rpm.ParserName}, - {"curl", "7.59.0-6.fc28", "curl", "7.59.0-6.fc28", rpm.ParserName}, - {"rpm-libs", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28", rpm.ParserName}, - {"libsolv", "0.6.35-1.fc28", "libsolv", "0.6.35-1.fc28", rpm.ParserName}, - {"python3-hawkey", "0.11.1-3.fc28", "libdnf", "0.11.1-3.fc28", rpm.ParserName}, - {"rpm-sign-libs", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28", rpm.ParserName}, - {"python3-dnf", "2.7.5-12.fc28", "dnf", "2.7.5-12.fc28", rpm.ParserName}, - {"dnf-yum", "2.7.5-12.fc28", "dnf", "2.7.5-12.fc28", rpm.ParserName}, - {"rpm-plugin-systemd-inhibit", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28", rpm.ParserName}, - {"nss-tools", "3.38.0-1.0.fc28", "nss", "3.38.0-1.0.fc28", rpm.ParserName}, - {"openssl-pkcs11", "0.4.8-1.fc28", "openssl-pkcs11", "0.4.8-1.fc28", rpm.ParserName}, - {"vim-minimal", "2:8.1.328-1.fc28", "vim", "8.1.328-1.fc28", rpm.ParserName}, - {"glibc-langpack-en", "2.27-32.fc28", "glibc", "2.27-32.fc28", rpm.ParserName}, - {"rootfiles", "8.1-22.fc28", "rootfiles", "8.1-22.fc28", rpm.ParserName}, + {"libmount", "2.32.1-1.fc28", "rpm", "binary"}, + {"libffi", "3.1-16.fc28", "rpm", "binary"}, + {"libunistring", "0.9.10-1.fc28", "rpm", "binary"}, + {"fedora-repos", "28-5", "rpm", "binary"}, + {"libarchive", "3.3.1-4.fc28", "rpm", "source"}, + {"langpacks", "1.0-12.fc28", "rpm", "source"}, + {"readline", "7.0-11.fc28", "rpm", "source"}, + {"gzip", "1.9-3.fc28", "rpm", "source"}, + {"libverto", "0.3.0-5.fc28", "rpm", "source"}, + {"ncurses-base", "6.1-5.20180224.fc28", "rpm", "binary"}, + {"libfdisk", "2.32.1-1.fc28", "rpm", "binary"}, + {"libselinux", "2.8-1.fc28", "rpm", "source"}, + {"nss-util", "3.38.0-1.0.fc28", "rpm", "source"}, + {"mpfr", "3.1.6-1.fc28", "rpm", "source"}, + {"libunistring", "0.9.10-1.fc28", "rpm", "source"}, + {"libpcap", "14:1.9.0-1.fc28", "rpm", "binary"}, + {"libarchive", "3.3.1-4.fc28", "rpm", "binary"}, + {"gmp", "1:6.1.2-7.fc28", "rpm", "binary"}, + {"crypto-policies", "20180425-5.git6ad4018.fc28", "rpm", "source"}, + {"gzip", "1.9-3.fc28", "rpm", "binary"}, + {"fedora-release", "28-2", "rpm", "source"}, + {"zlib", "1.2.11-8.fc28", "rpm", "binary"}, + {"crypto-policies", "20180425-5.git6ad4018.fc28", "rpm", "binary"}, + {"lz4", "1.8.1.2-4.fc28", "rpm", "source"}, + {"keyutils", "1.5.10-6.fc28", "rpm", "source"}, + {"gpgme", "1.10.0-4.fc28", "rpm", "binary"}, + {"libgpg-error", "1.31-1.fc28", "rpm", "binary"}, + {"gnutls", "3.6.3-4.fc28", "rpm", "source"}, + {"coreutils", "8.29-7.fc28", "rpm", "source"}, + {"libsepol", "2.8-1.fc28", "rpm", "source"}, + {"libssh", "0.8.2-1.fc28", "rpm", "binary"}, + {"libpwquality", "1.4.0-7.fc28", "rpm", "binary"}, + {"dnf-conf", "2.7.5-12.fc28", "rpm", "binary"}, + {"basesystem", "11-5.fc28", "rpm", "source"}, + {"setup", "2.11.4-1.fc28", "rpm", "binary"}, + {"libmetalink", "0.1.3-6.fc28", "rpm", "source"}, + {"texinfo", "6.5-4.fc28", "rpm", "source"}, + {"expat", "2.2.5-3.fc28", "rpm", "source"}, + {"ncurses", "6.1-5.20180224.fc28", "rpm", "source"}, + {"libpwquality", "1.4.0-7.fc28", "rpm", "source"}, + {"pcre", "8.42-3.fc28", "rpm", "binary"}, + {"sssd", "1.16.3-2.fc28", "rpm", "source"}, + {"basesystem", "11-5.fc28", "rpm", "binary"}, + {"systemd-pam", "238-9.git0e0aa59.fc28", "rpm", "binary"}, + {"python3-six", "1.11.0-3.fc28", "rpm", "binary"}, + {"libcurl", "7.59.0-6.fc28", "rpm", "binary"}, + {"qrencode", "3.4.4-5.fc28", "rpm", "source"}, + {"xz", "5.2.4-2.fc28", "rpm", "source"}, + {"libpkgconf", "1.4.2-1.fc28", "rpm", "binary"}, + {"libzstd", "1.3.5-1.fc28", "rpm", "binary"}, + {"bash", "4.4.23-1.fc28", "rpm", "binary"}, + {"cyrus-sasl", "2.1.27-0.2rc7.fc28", "rpm", "source"}, + {"ncurses-libs", "6.1-5.20180224.fc28", "rpm", "binary"}, + {"xz-libs", "5.2.4-2.fc28", "rpm", "binary"}, + {"dbus", "1.12.10-1.fc28", "rpm", "source"}, + {"grep", "3.1-5.fc28", "rpm", "binary"}, + {"libusbx", "1.0.22-1.fc28", "rpm", "binary"}, + {"audit", "2.8.4-2.fc28", "rpm", "source"}, + {"sed", "4.5-1.fc28", "rpm", "binary"}, + {"sqlite", "3.22.0-4.fc28", "rpm", "source"}, + {"openldap", "2.4.46-3.fc28", "rpm", "binary"}, + {"gawk", "4.2.1-1.fc28", "rpm", "binary"}, + {"gpgme", "1.10.0-4.fc28", "rpm", "source"}, + {"lvm2", "2.02.177-5.fc28", "rpm", "source"}, + {"nspr", "4.19.0-1.fc28", "rpm", "source"}, + {"libsolv", "0.6.35-1.fc28", "rpm", "source"}, + {"info", "6.5-4.fc28", "rpm", "binary"}, + {"openssl-libs", "1:1.1.0h-3.fc28", "rpm", "binary"}, + {"libxcrypt", "4.1.2-1.fc28", "rpm", "binary"}, + {"libselinux", "2.8-1.fc28", "rpm", "binary"}, + {"libgcc", "8.1.1-5.fc28", "rpm", "binary"}, + {"cracklib", "2.9.6-13.fc28", "rpm", "binary"}, + {"python3-libs", "3.6.6-1.fc28", "rpm", "binary"}, + {"glibc-langpack-en", "2.27-32.fc28", "rpm", "binary"}, + {"json-c", "0.13.1-2.fc28", "rpm", "binary"}, + {"gnupg2", "2.2.8-1.fc28", "rpm", "source"}, + {"openssl", "1:1.1.0h-3.fc28", "rpm", "binary"}, + {"glibc-common", "2.27-32.fc28", "rpm", "binary"}, + {"p11-kit-trust", "0.23.12-1.fc28", "rpm", "binary"}, + {"zstd", "1.3.5-1.fc28", "rpm", "source"}, + {"libxml2", "2.9.8-4.fc28", "rpm", "source"}, + {"dbus", "1:1.12.10-1.fc28", "rpm", "binary"}, + {"ca-certificates", "2018.2.24-1.0.fc28", "rpm", "binary"}, + {"libcomps", "0.1.8-11.fc28", "rpm", "binary"}, + {"nss", "3.38.0-1.0.fc28", "rpm", "binary"}, + {"libcom_err", "1.44.2-0.fc28", "rpm", "binary"}, + {"keyutils-libs", "1.5.10-6.fc28", "rpm", "binary"}, + {"libseccomp", "2.3.3-2.fc28", "rpm", "binary"}, + {"elfutils-libs", "0.173-1.fc28", "rpm", "binary"}, + {"libuuid", "2.32.1-1.fc28", "rpm", "binary"}, + {"pkgconf", "1.4.2-1.fc28", "rpm", "source"}, + {"grep", "3.1-5.fc28", "rpm", "source"}, + {"libpcap", "1.9.0-1.fc28", "rpm", "source"}, + {"deltarpm", "3.6-25.fc28", "rpm", "binary"}, + {"krb5-libs", "1.16.1-13.fc28", "rpm", "binary"}, + {"glibc", "2.27-32.fc28", "rpm", "binary"}, + {"libseccomp", "2.3.3-2.fc28", "rpm", "source"}, + {"libsemanage", "2.8-2.fc28", "rpm", "binary"}, + {"openssl-pkcs11", "0.4.8-1.fc28", "rpm", "binary"}, + {"libxml2", "2.9.8-4.fc28", "rpm", "binary"}, + {"e2fsprogs", "1.44.2-0.fc28", "rpm", "source"}, + {"file-libs", "5.33-7.fc28", "rpm", "binary"}, + {"elfutils-default-yama-scope", "0.173-1.fc28", "rpm", "binary"}, + {"glibc", "2.27-32.fc28", "rpm", "source"}, + {"publicsuffix-list-dafsa", "20180514-1.fc28", "rpm", "binary"}, + {"popt", "1.16-14.fc28", "rpm", "binary"}, + {"libnsl2", "1.2.0-2.20180605git4a062cf.fc28", "rpm", "binary"}, + {"lua-libs", "5.3.4-10.fc28", "rpm", "binary"}, + {"libsemanage", "2.8-2.fc28", "rpm", "source"}, + {"glibc-minimal-langpack", "2.27-32.fc28", "rpm", "binary"}, + {"attr", "2.4.48-3.fc28", "rpm", "source"}, + {"gdbm", "1.14.1-4.fc28", "rpm", "source"}, + {"pkgconf", "1.4.2-1.fc28", "rpm", "binary"}, + {"acl", "2.2.53-1.fc28", "rpm", "source"}, + {"gnutls", "3.6.3-4.fc28", "rpm", "binary"}, + {"fedora-repos", "28-5", "rpm", "source"}, + {"python3-pip", "9.0.3-2.fc28", "rpm", "binary"}, + {"libnsl2", "1.2.0-2.20180605git4a062cf.fc28", "rpm", "source"}, + {"rpm", "4.14.1-9.fc28", "rpm", "binary"}, + {"libutempter", "1.1.6-14.fc28", "rpm", "source"}, + {"libdnf", "0.11.1-3.fc28", "rpm", "source"}, + {"vim-minimal", "2:8.1.328-1.fc28", "rpm", "binary"}, + {"tzdata", "2018e-1.fc28", "rpm", "binary"}, + {"nettle", "3.4-2.fc28", "rpm", "binary"}, + {"python-pip", "9.0.3-2.fc28", "rpm", "source"}, + {"python-six", "1.11.0-3.fc28", "rpm", "source"}, + {"diffutils", "3.6-4.fc28", "rpm", "binary"}, + {"rpm-plugin-selinux", "4.14.1-9.fc28", "rpm", "binary"}, + {"shadow-utils", "2:4.6-1.fc28", "rpm", "binary"}, + {"pkgconf-pkg-config", "1.4.2-1.fc28", "rpm", "binary"}, + {"cracklib-dicts", "2.9.6-13.fc28", "rpm", "binary"}, + {"libblkid", "2.32.1-1.fc28", "rpm", "binary"}, + {"python-setuptools", "39.2.0-6.fc28", "rpm", "source"}, + {"libsss_idmap", "1.16.3-2.fc28", "rpm", "binary"}, + {"libksba", "1.3.5-7.fc28", "rpm", "source"}, + {"sssd-client", "1.16.3-2.fc28", "rpm", "binary"}, + {"curl", "7.59.0-6.fc28", "rpm", "binary"}, + {"pam", "1.3.1-1.fc28", "rpm", "binary"}, + {"libsigsegv", "2.11-5.fc28", "rpm", "binary"}, + {"langpacks-en", "1.0-12.fc28", "rpm", "binary"}, + {"nss-softokn-freebl", "3.38.0-1.0.fc28", "rpm", "binary"}, + {"glib2", "2.56.1-4.fc28", "rpm", "binary"}, + {"python3-gobject-base", "3.28.3-1.fc28", "rpm", "binary"}, + {"libffi", "3.1-16.fc28", "rpm", "source"}, + {"libmodulemd", "1.6.2-2.fc28", "rpm", "source"}, + {"openssl", "1.1.0h-3.fc28", "rpm", "source"}, + {"libyaml", "0.1.7-5.fc28", "rpm", "source"}, + {"pam", "1.3.1-1.fc28", "rpm", "source"}, + {"iptables", "1.6.2-3.fc28", "rpm", "source"}, + {"util-linux", "2.32.1-1.fc28", "rpm", "source"}, + {"libsmartcols", "2.32.1-1.fc28", "rpm", "binary"}, + {"dnf", "2.7.5-12.fc28", "rpm", "binary"}, + {"glib2", "2.56.1-4.fc28", "rpm", "source"}, + {"lua", "5.3.4-10.fc28", "rpm", "source"}, + {"nss-softokn", "3.38.0-1.0.fc28", "rpm", "source"}, + {"python3-dnf", "2.7.5-12.fc28", "rpm", "binary"}, + {"filesystem", "3.8-2.fc28", "rpm", "binary"}, + {"libsss_nss_idmap", "1.16.3-2.fc28", "rpm", "binary"}, + {"pcre2", "10.31-10.fc28", "rpm", "source"}, + {"libyaml", "0.1.7-5.fc28", "rpm", "binary"}, + {"python3-rpm", "4.14.1-9.fc28", "rpm", "binary"}, + {"zlib", "1.2.11-8.fc28", "rpm", "source"}, + {"libutempter", "1.1.6-14.fc28", "rpm", "binary"}, + {"pcre2", "10.31-10.fc28", "rpm", "binary"}, + {"libtirpc", "1.0.3-3.rc2.fc28", "rpm", "source"}, + {"pkgconf-m4", "1.4.2-1.fc28", "rpm", "binary"}, + {"libreport", "2.9.5-1.fc28", "rpm", "source"}, + {"vim", "8.1.328-1.fc28", "rpm", "source"}, + {"file", "5.33-7.fc28", "rpm", "source"}, + {"shadow-utils", "4.6-1.fc28", "rpm", "source"}, + {"sqlite-libs", "3.22.0-4.fc28", "rpm", "binary"}, + {"setup", "2.11.4-1.fc28", "rpm", "source"}, + {"gcc", "8.1.1-5.fc28", "rpm", "source"}, + {"mpfr", "3.1.6-1.fc28", "rpm", "binary"}, + {"device-mapper", "1.02.146-5.fc28", "rpm", "binary"}, + {"p11-kit", "0.23.12-1.fc28", "rpm", "source"}, + {"fedora-release", "28-2", "rpm", "binary"}, + {"libnghttp2", "1.32.1-1.fc28", "rpm", "binary"}, + {"libcap-ng", "0.7.9-4.fc28", "rpm", "source"}, + {"iptables-libs", "1.6.2-3.fc28", "rpm", "binary"}, + {"audit-libs", "2.8.4-2.fc28", "rpm", "binary"}, + {"libsigsegv", "2.11-5.fc28", "rpm", "source"}, + {"rootfiles", "8.1-22.fc28", "rpm", "source"}, + {"kmod-libs", "25-2.fc28", "rpm", "binary"}, + {"lz4-libs", "1.8.1.2-4.fc28", "rpm", "binary"}, + {"libassuan", "2.5.1-3.fc28", "rpm", "source"}, + {"p11-kit", "0.23.12-1.fc28", "rpm", "binary"}, + {"nss-sysinit", "3.38.0-1.0.fc28", "rpm", "binary"}, + {"libcap-ng", "0.7.9-4.fc28", "rpm", "binary"}, + {"bash", "4.4.23-1.fc28", "rpm", "source"}, + {"pygobject3", "3.28.3-1.fc28", "rpm", "source"}, + {"dnf-yum", "2.7.5-12.fc28", "rpm", "binary"}, + {"nss-softokn", "3.38.0-1.0.fc28", "rpm", "binary"}, + {"expat", "2.2.5-3.fc28", "rpm", "binary"}, + {"libassuan", "2.5.1-3.fc28", "rpm", "binary"}, + {"libdb", "5.3.28-30.fc28", "rpm", "binary"}, + {"tar", "2:1.30-3.fc28", "rpm", "binary"}, + {"sed", "4.5-1.fc28", "rpm", "source"}, + {"libmetalink", "0.1.3-6.fc28", "rpm", "binary"}, + {"python-smartcols", "0.3.0-2.fc28", "rpm", "source"}, + {"systemd", "238-9.git0e0aa59.fc28", "rpm", "source"}, + {"python-iniparse", "0.4-30.fc28", "rpm", "source"}, + {"libsepol", "2.8-1.fc28", "rpm", "binary"}, + {"libattr", "2.4.48-3.fc28", "rpm", "binary"}, + {"python3-smartcols", "0.3.0-2.fc28", "rpm", "binary"}, + {"libdb", "5.3.28-30.fc28", "rpm", "source"}, + {"libmodulemd", "1.6.2-2.fc28", "rpm", "binary"}, + {"python3-hawkey", "0.11.1-3.fc28", "rpm", "binary"}, + {"dbus-libs", "1:1.12.10-1.fc28", "rpm", "binary"}, + {"chkconfig", "1.10-4.fc28", "rpm", "source"}, + {"libargon2", "20161029-5.fc28", "rpm", "binary"}, + {"openssl-pkcs11", "0.4.8-1.fc28", "rpm", "source"}, + {"libusbx", "1.0.22-1.fc28", "rpm", "source"}, + {"python3-setuptools", "39.2.0-6.fc28", "rpm", "binary"}, + {"chkconfig", "1.10-4.fc28", "rpm", "binary"}, + {"openldap", "2.4.46-3.fc28", "rpm", "source"}, + {"bzip2", "1.0.6-26.fc28", "rpm", "source"}, + {"npth", "1.5-4.fc28", "rpm", "source"}, + {"libtirpc", "1.0.3-3.rc2.fc28", "rpm", "binary"}, + {"util-linux", "2.32.1-1.fc28", "rpm", "binary"}, + {"nss", "3.38.0-1.0.fc28", "rpm", "source"}, + {"elfutils", "0.173-1.fc28", "rpm", "source"}, + {"libcomps", "0.1.8-11.fc28", "rpm", "source"}, + {"libxcrypt", "4.1.2-1.fc28", "rpm", "source"}, + {"gnupg2", "2.2.8-1.fc28", "rpm", "binary"}, + {"libdnf", "0.11.1-3.fc28", "rpm", "binary"}, + {"cracklib", "2.9.6-13.fc28", "rpm", "source"}, + {"libidn2", "2.0.5-1.fc28", "rpm", "source"}, + {"bzip2-libs", "1.0.6-26.fc28", "rpm", "binary"}, + {"json-c", "0.13.1-2.fc28", "rpm", "source"}, + {"gdbm", "1:1.14.1-4.fc28", "rpm", "binary"}, + {"pcre", "8.42-3.fc28", "rpm", "source"}, + {"systemd", "238-9.git0e0aa59.fc28", "rpm", "binary"}, + {"cryptsetup-libs", "2.0.4-1.fc28", "rpm", "binary"}, + {"dnf", "2.7.5-12.fc28", "rpm", "source"}, + {"ca-certificates", "2018.2.24-1.0.fc28", "rpm", "source"}, + {"libidn2", "2.0.5-1.fc28", "rpm", "binary"}, + {"libpsl", "0.20.2-2.fc28", "rpm", "binary"}, + {"gdbm-libs", "1:1.14.1-4.fc28", "rpm", "binary"}, + {"kmod", "25-2.fc28", "rpm", "source"}, + {"libreport-filesystem", "2.9.5-1.fc28", "rpm", "binary"}, + {"ima-evm-utils", "1.1-2.fc28", "rpm", "source"}, + {"nghttp2", "1.32.1-1.fc28", "rpm", "source"}, + {"cyrus-sasl-lib", "2.1.27-0.2rc7.fc28", "rpm", "binary"}, + {"libsolv", "0.6.35-1.fc28", "rpm", "binary"}, + {"cryptsetup", "2.0.4-1.fc28", "rpm", "source"}, + {"filesystem", "3.8-2.fc28", "rpm", "source"}, + {"libcap", "2.25-9.fc28", "rpm", "source"}, + {"libpsl", "0.20.2-2.fc28", "rpm", "source"}, + {"deltarpm", "3.6-25.fc28", "rpm", "source"}, + {"fedora-gpg-keys", "28-5", "rpm", "binary"}, + {"ima-evm-utils", "1.1-2.fc28", "rpm", "binary"}, + {"nss-tools", "3.38.0-1.0.fc28", "rpm", "binary"}, + {"libtasn1", "4.13-2.fc28", "rpm", "source"}, + {"elfutils-libelf", "0.173-1.fc28", "rpm", "binary"}, + {"device-mapper-libs", "1.02.146-5.fc28", "rpm", "binary"}, + {"gobject-introspection", "1.56.1-1.fc28", "rpm", "source"}, + {"publicsuffix-list", "20180514-1.fc28", "rpm", "source"}, + {"libcap", "2.25-9.fc28", "rpm", "binary"}, + {"librepo", "1.8.1-7.fc28", "rpm", "binary"}, + {"rpm-sign-libs", "4.14.1-9.fc28", "rpm", "binary"}, + {"coreutils-single", "8.29-7.fc28", "rpm", "binary"}, + {"libacl", "2.2.53-1.fc28", "rpm", "binary"}, + {"popt", "1.16-14.fc28", "rpm", "source"}, + {"libtasn1", "4.13-2.fc28", "rpm", "binary"}, + {"gawk", "4.2.1-1.fc28", "rpm", "source"}, + {"diffutils", "3.6-4.fc28", "rpm", "source"}, + {"libgpg-error", "1.31-1.fc28", "rpm", "source"}, + {"libdb-utils", "5.3.28-30.fc28", "rpm", "binary"}, + {"python3-iniparse", "0.4-30.fc28", "rpm", "binary"}, + {"acl", "2.2.53-1.fc28", "rpm", "binary"}, + {"libssh", "0.8.2-1.fc28", "rpm", "source"}, + {"python3-librepo", "1.8.1-7.fc28", "rpm", "binary"}, + {"gobject-introspection", "1.56.1-1.fc28", "rpm", "binary"}, + {"rpm", "4.14.1-9.fc28", "rpm", "source"}, + {"libgcrypt", "1.8.3-1.fc28", "rpm", "source"}, + {"curl", "7.59.0-6.fc28", "rpm", "source"}, + {"tzdata", "2018e-1.fc28", "rpm", "source"}, + {"krb5", "1.16.1-13.fc28", "rpm", "source"}, + {"librepo", "1.8.1-7.fc28", "rpm", "source"}, + {"python3-gpg", "1.10.0-4.fc28", "rpm", "binary"}, + {"nettle", "3.4-2.fc28", "rpm", "source"}, + {"libgcrypt", "1.8.3-1.fc28", "rpm", "binary"}, + {"python3", "3.6.6-1.fc28", "rpm", "binary"}, + {"python3-libcomps", "0.1.8-11.fc28", "rpm", "binary"}, + {"rpm-libs", "4.14.1-9.fc28", "rpm", "binary"}, + {"nspr", "4.19.0-1.fc28", "rpm", "binary"}, + {"argon2", "20161029-5.fc28", "rpm", "source"}, + {"tar", "1.30-3.fc28", "rpm", "source"}, + {"qrencode-libs", "3.4.4-5.fc28", "rpm", "binary"}, + {"gmp", "6.1.2-7.fc28", "rpm", "source"}, + {"libverto", "0.3.0-5.fc28", "rpm", "binary"}, + {"python3", "3.6.6-1.fc28", "rpm", "source"}, + {"libksba", "1.3.5-7.fc28", "rpm", "binary"}, + {"readline", "7.0-11.fc28", "rpm", "binary"}, + {"rpm-build-libs", "4.14.1-9.fc28", "rpm", "binary"}, + {"npth", "1.5-4.fc28", "rpm", "binary"}, + {"rootfiles", "8.1-22.fc28", "rpm", "binary"}, + {"rpm-plugin-systemd-inhibit", "4.14.1-9.fc28", "rpm", "binary"}, + {"systemd-libs", "238-9.git0e0aa59.fc28", "rpm", "binary"}, + {"nss-util", "3.38.0-1.0.fc28", "rpm", "binary"}, } func TestRpmFeatureDetection(t *testing.T) { @@ -206,8 +334,10 @@ func TestRpmFeatureDetection(t *testing.T) { "valid small case", map[string]string{"var/lib/rpm/Packages": "rpm/testdata/valid"}, []database.Feature{ - {"centos-release", "7-1.1503.el7.centos.2.8", "centos-release", "7-1.1503.el7.centos.2.8", rpm.ParserName}, - {"filesystem", "3.2-18.el7", "filesystem", "3.2-18.el7", rpm.ParserName}, + {"centos-release", "7-1.1503.el7.centos.2.8", "rpm", "binary"}, + {"filesystem", "3.2-18.el7", "rpm", "binary"}, + {"centos-release", "7-1.1503.el7.centos.2.8", "rpm", "source"}, + {"filesystem", "3.2-18.el7", "rpm", "source"}, }, }, { @@ -248,15 +378,14 @@ func TestParseSourceRPM(t *testing.T) { // actual expected: name="lua", version="5.3.4", release="10.fc-28" {"lua-5.3.4-10.fc-28.src.rpm", "lua-5.3.4", "10.fc-28", ""}, } { - pkg := database.Feature{} - err := parseSourceRPM(test.sourceRPM, &pkg) + name, version, release, _, err := parseSourceRPM(test.sourceRPM) if test.expectedErr != "" { require.EqualError(t, err, test.expectedErr) continue } require.Nil(t, err) - require.Equal(t, test.expectedName, pkg.SourceName) - require.Equal(t, test.expectedVersion, pkg.SourceVersion) + require.Equal(t, test.expectedName, name) + require.Equal(t, test.expectedVersion, version+"-"+release) } }