a5e32e
From ba659220886c1a315f50fb91b9af4615b1a8757e Mon Sep 17 00:00:00 2001
a5e32e
From: Michal Domonkos <mdomonko@redhat.com>
a5e32e
Date: Mon, 16 Aug 2021 18:21:02 +0200
a5e32e
Subject: [PATCH] Add support for RPMDBI_BASENAMES on file queries
a5e32e
a5e32e
There are legitimate reasons (such as rhbz#1940895 or the included test)
a5e32e
for wanting the former behavior where all file states were considered in
a5e32e
file queries prior to commit 9ad57bda4a82b9847826daa766b4421d877bb3d9,
a5e32e
so celebrate the tenth anniversary of that commit by adding a CLI switch
a5e32e
(a new package selector --path), as contemplated back then.
a5e32e
a5e32e
Update the man page for --file to reflect it's current behavior and make
a5e32e
--path that more obvious.
a5e32e
a5e32e
Resolves: rhbz#1940895
a5e32e
a5e32e
Combined with:
a5e32e
d1aebda01033bc8ba0d748b49f6fad9a5c0caa3f
a5e32e
f62b6d27cd741406a52a7e9c5b1d6f581dbd3af8
a5e32e
a5e32e
Backported for 4.16.1.3.
a5e32e
---
a5e32e
 doc/rpm.8         |  9 ++++++--
a5e32e
 lib/poptQV.c      |  6 +++++-
a5e32e
 lib/query.c       |  7 +++++--
a5e32e
 lib/rpmcli.h      |  1 +
a5e32e
 tests/rpmquery.at | 52 +++++++++++++++++++++++++++++++++++++++++++++++
a5e32e
 5 files changed, 70 insertions(+), 5 deletions(-)
a5e32e
a5e32e
diff --git a/doc/rpm.8 b/doc/rpm.8
a5e32e
index 80055b675..ab7364cf6 100644
a5e32e
--- a/doc/rpm.8
a5e32e
+++ b/doc/rpm.8
a5e32e
@@ -57,7 +57,7 @@ rpm \- RPM Package Manager
a5e32e
 .PP
a5e32e
 
a5e32e
  [\fB\fIPACKAGE_NAME\fB\fR]
a5e32e
- [\fB-a,--all [\fISELECTOR\fR]\fR] [\fB-f,--file \fIFILE\fB\fR]
a5e32e
+ [\fB-a,--all [\fISELECTOR\fR]\fR] [\fB-f,--file \fIFILE\fB\fR] [\fB--path \fIPATH\fB\fR]
a5e32e
  [\fB-g,--group \fIGROUP\fB\fR] [\fB-p,--package \fIPACKAGE_FILE\fB\fR]
a5e32e
  [\fB--hdrid \fISHA1\fB\fR] [\fB--pkgid \fIMD5\fB\fR] [\fB--tid \fITID\fB\fR]
a5e32e
  [\fB--querybynumber \fIHDRNUM\fB\fR] [\fB--triggeredby \fIPACKAGE_NAME\fB\fR]
a5e32e
@@ -569,7 +569,7 @@ starts with "b".
a5e32e
 List duplicated packages.
a5e32e
 .TP
a5e32e
 \fB-f, --file \fIFILE\fB\fR
a5e32e
-Query package owning \fIFILE\fR.
a5e32e
+Query package owning installed \fIFILE\fR.
a5e32e
 .TP
a5e32e
 \fB--filecaps\fR
a5e32e
 List file names with POSIX1.e capabilities.
a5e32e
@@ -612,6 +612,11 @@ that will be expanded to paths that are substituted in place of
a5e32e
 the package manifest as additional \fIPACKAGE_FILE\fR
a5e32e
 arguments to the query.
a5e32e
 .TP
a5e32e
+\fB--path \fIPATH\fB\fR
a5e32e
+Query package(s) owning \fIPATH\fR, whether the file is installed or not.
a5e32e
+Multiple packages may own a \fIPATH\fR, but the file is only owned by the
a5e32e
+package installed last.
a5e32e
+.TP
a5e32e
 \fB--pkgid \fIMD5\fB\fR
a5e32e
 Query package that contains a given package identifier, i.e. the
a5e32e
 \fIMD5\fR digest of the combined header and
a5e32e
diff --git a/lib/poptQV.c b/lib/poptQV.c
a5e32e
index d9d1fad75..9b6101009 100644
a5e32e
--- a/lib/poptQV.c
a5e32e
+++ b/lib/poptQV.c
a5e32e
@@ -27,6 +27,7 @@ struct rpmQVKArguments_s rpmQVKArgs;
a5e32e
 #define POPT_WHATENHANCES	-1014
a5e32e
 #define POPT_WHATOBSOLETES	-1015
a5e32e
 #define POPT_WHATCONFLICTS	-1016
a5e32e
+#define POPT_QUERYBYPATH	-1017
a5e32e
 
a5e32e
 /* ========== Query/Verify/Signature source args */
a5e32e
 static void rpmQVSourceArgCallback( poptContext con,
a5e32e
@@ -58,6 +59,7 @@ static void rpmQVSourceArgCallback( poptContext con,
a5e32e
     case POPT_WHATSUPPLEMENTS: qva->qva_source |= RPMQV_WHATSUPPLEMENTS; break;
a5e32e
     case POPT_WHATENHANCES: qva->qva_source |= RPMQV_WHATENHANCES; break;
a5e32e
     case POPT_TRIGGEREDBY: qva->qva_source |= RPMQV_TRIGGEREDBY; break;
a5e32e
+    case POPT_QUERYBYPATH: qva->qva_source |= RPMQV_PATH_ALL; break;
a5e32e
     case POPT_QUERYBYPKGID: qva->qva_source |= RPMQV_PKGID; break;
a5e32e
     case POPT_QUERYBYHDRID: qva->qva_source |= RPMQV_HDRID; break;
a5e32e
     case POPT_QUERYBYTID: qva->qva_source |= RPMQV_TID; break;
a5e32e
@@ -80,7 +82,9 @@ struct poptOption rpmQVSourcePoptTable[] = {
a5e32e
  { "checksig", 'K', POPT_ARGFLAG_DOC_HIDDEN, NULL, 'K',
a5e32e
 	N_("rpm checksig mode"), NULL },
a5e32e
  { "file", 'f', 0, 0, 'f',
a5e32e
-	N_("query/verify package(s) owning file"), "FILE" },
a5e32e
+	N_("query/verify package(s) owning installed file"), "FILE" },
a5e32e
+ { "path", '\0', 0, 0, POPT_QUERYBYPATH,
a5e32e
+	N_("query/verify package(s) owning path, installed or not"), "PATH" },
a5e32e
  { "group", 'g', 0, 0, 'g',
a5e32e
 	N_("query/verify package(s) in group"), "GROUP" },
a5e32e
  { "package", 'p', 0, 0, 'p',
a5e32e
diff --git a/lib/query.c b/lib/query.c
a5e32e
index fdabe6e52..9a71f0dc5 100644
a5e32e
--- a/lib/query.c
a5e32e
+++ b/lib/query.c
a5e32e
@@ -445,6 +445,7 @@ static rpmdbMatchIterator initQueryIterator(QVA_t qva, rpmts ts, const char * ar
a5e32e
 	}
a5e32e
 	/* fallthrough on absolute and relative paths */
a5e32e
     case RPMQV_PATH:
a5e32e
+    case RPMQV_PATH_ALL:
a5e32e
     {   char * fn;
a5e32e
 
a5e32e
 	for (s = arg; *s != '\0'; s++)
a5e32e
@@ -463,8 +464,10 @@ static rpmdbMatchIterator initQueryIterator(QVA_t qva, rpmts ts, const char * ar
a5e32e
 	    fn = xstrdup(arg);
a5e32e
 	(void) rpmCleanPath(fn);
a5e32e
 
a5e32e
-	/* XXX Add a switch to enable former BASENAMES behavior? */
a5e32e
-	mi = rpmtsInitIterator(ts, RPMDBI_INSTFILENAMES, fn, 0);
a5e32e
+	rpmDbiTagVal tag = RPMDBI_INSTFILENAMES;
a5e32e
+	if (qva->qva_source == RPMQV_PATH_ALL)
a5e32e
+	    tag = RPMDBI_BASENAMES;
a5e32e
+	mi = rpmtsInitIterator(ts, tag, fn, 0);
a5e32e
 	if (mi == NULL)
a5e32e
 	    mi = rpmtsInitIterator(ts, RPMDBI_PROVIDENAME, fn, 0);
a5e32e
 
a5e32e
diff --git a/lib/rpmcli.h b/lib/rpmcli.h
a5e32e
index 4886c2453..3961418e7 100644
a5e32e
--- a/lib/rpmcli.h
a5e32e
+++ b/lib/rpmcli.h
a5e32e
@@ -101,6 +101,7 @@ enum rpmQVSources_e {
a5e32e
     RPMQV_SPECBUILTRPMS,	/*!< ... from pkgs which would be built from spec */
a5e32e
     RPMQV_WHATOBSOLETES,	/*!< ... from obsoletes db search. */
a5e32e
     RPMQV_WHATCONFLICTS,	/*!< ... from conflicts db search. */
a5e32e
+    RPMQV_PATH_ALL,	/*!< ... from file path db search (all states). */
a5e32e
 };
a5e32e
 
a5e32e
 typedef rpmFlags rpmQVSources;
a5e32e
diff --git a/tests/rpmquery.at b/tests/rpmquery.at
a5e32e
index 9a4f1cb76..335d5ee0d 100644
a5e32e
--- a/tests/rpmquery.at
a5e32e
+++ b/tests/rpmquery.at
a5e32e
@@ -201,6 +201,58 @@ runroot rpm \
a5e32e
 
a5e32e
 AT_CLEANUP
a5e32e
 
a5e32e
+# ------------------------------
a5e32e
+# query a package by a file
a5e32e
+AT_SETUP([rpm -qf])
a5e32e
+AT_KEYWORDS([query])
a5e32e
+AT_CHECK([
a5e32e
+RPMDB_INIT
a5e32e
+runroot rpm \
a5e32e
+  --nodeps \
a5e32e
+  -i /data/RPMS/hello-1.0-1.i386.rpm
a5e32e
+runroot rpm \
a5e32e
+  -qf /usr/local/bin/hello
a5e32e
+],
a5e32e
+[0],
a5e32e
+[hello-1.0-1.i386
a5e32e
+],
a5e32e
+[])
a5e32e
+AT_CLEANUP
a5e32e
+
a5e32e
+AT_SETUP([rpm -qf on non-installed file])
a5e32e
+AT_KEYWORDS([query])
a5e32e
+AT_CHECK([
a5e32e
+RPMDB_INIT
a5e32e
+runroot rpm \
a5e32e
+  --nodeps \
a5e32e
+  --excludedocs \
a5e32e
+  -i /data/RPMS/hello-1.0-1.i386.rpm
a5e32e
+runroot rpm \
a5e32e
+  -qf /usr/share/doc/hello-1.0/FAQ
a5e32e
+],
a5e32e
+[1],
a5e32e
+[],
a5e32e
+[error: file /usr/share/doc/hello-1.0/FAQ: No such file or directory
a5e32e
+])
a5e32e
+AT_CLEANUP
a5e32e
+
a5e32e
+AT_SETUP([rpm -q --path on non-installed file])
a5e32e
+AT_KEYWORDS([query])
a5e32e
+AT_CHECK([
a5e32e
+RPMDB_INIT
a5e32e
+runroot rpm \
a5e32e
+  --nodeps \
a5e32e
+  --excludedocs \
a5e32e
+  -i /data/RPMS/hello-1.0-1.i386.rpm
a5e32e
+runroot rpm \
a5e32e
+  -q --path /usr/share/doc/hello-1.0/FAQ
a5e32e
+],
a5e32e
+[0],
a5e32e
+[hello-1.0-1.i386
a5e32e
+],
a5e32e
+[])
a5e32e
+AT_CLEANUP
a5e32e
+
a5e32e
 # ------------------------------
a5e32e
 AT_SETUP([integer array query])
a5e32e
 AT_KEYWORDS([query])
a5e32e
-- 
a5e32e
2.35.1
a5e32e