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