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