Re: Possible workaround/fix for usrmerge issues with dpkg-query -S (#858331 / #848622)
Hi Simon,
> so multiple file names in a single call, and probably expect the same
> file name to be returned to match the response back to the query.
>
> We'd need a new format, for example like
>
> libc6:amd64: /usr/lib/x86_64-linux-gnu/libc.so.6
> (/lib/x86_64-linux-gnu/libc.so.6)
>
What if we return it in the existing format; but just output the "real"
filename you supplied if it matches via the realpath.
So for your example it would be:
libselinux1:amd64: /lib/x86_64-linux-gnu/libselinux.so.1
libc6:amd64: /lib/x86_64-linux-gnu/libc.so.6
libpcre2-8-0:amd64: /lib/x86_64-linux-gnu/libpcre2-8.so.0
In the attached patch I have implemented the change to output the
"real" path and also changed the realpath search to not require an
extra argument; but instead just use it as a fallback when no match
is found with the normal path lookup. This way the realpath change
is transparent and all existing callers benefit from this change.
I think that transparency is important as a lot of container builds are
dependent on this. For example look at this github search:
https://github.com/search?q=%22dpkg-query+-S%22&type=code
to get an idea about the number of users of dpkg-query -S
(yes a lot of the matches are dpkg-query -s as the search is case
in-sensitive; but still a quite long list that are potentially impacted by
#858331 / #848622)
--
Best regards,
Eric de Ruiter
diff --git a/src/query/main.c b/src/query/main.c
index 24dccc8c4..caf0504c5 100644
--- a/src/query/main.c
+++ b/src/query/main.c
@@ -294,7 +294,7 @@ listpackages(const char *const *argv)
}
static int
-searchoutput(struct fsys_namenode *namenode)
+searchoutput(struct fsys_namenode *namenode, const char *realpath)
{
struct fsys_node_pkgs_iter *iter;
struct pkginfo *pkg_owner;
@@ -327,10 +327,47 @@ searchoutput(struct fsys_namenode *namenode)
}
fsys_node_pkgs_iter_free(iter);
- if (found) printf(": %s\n",namenode->name);
+ if (found) printf(": %s\n",realpath ? realpath : namenode->name);
return found + (namenode->divert ? 1 : 0);
}
+static int
+searchfile_realpath(const char *file)
+{
+ struct fsys_hash_iter *iter;
+ char *real, *resolved, *namenode_real;
+ struct varbuf path = VARBUF_INIT;
+ struct fsys_namenode *namenode;
+ int found = 0;
+
+ varbuf_reset(&path);
+ varbuf_add_str(&path, "*/");
+ varbuf_add_str(&path, path_basename(file));
+ varbuf_end_str(&path);
+
+ real = realpath(file, NULL);
+ if (real == NULL) {
+ notice(_("unable to get realpath of %s; results might not be complete"), file);
+ return found;
+ }
+ iter = fsys_hash_iter_new();
+ resolved = malloc(PATH_MAX);
+ while ((namenode = fsys_hash_iter_next(iter)) != NULL) {
+ if (fnmatch(path.buf,namenode->name,0)) continue;
+ namenode_real = realpath(namenode->name, resolved);
+ if (namenode_real == NULL) {
+ notice(_("unable to get realpath of %s; results might not be complete"), namenode->name);
+ }
+ if (strcmp(real, namenode_real) != 0) continue;
+ found += searchoutput(namenode, file);
+ }
+ fsys_hash_iter_free(iter);
+ free(real);
+ free(resolved);
+ varbuf_destroy(&path);
+ return found;
+}
+
static int
searchfiles(const char *const *argv)
{
@@ -367,14 +404,17 @@ searchfiles(const char *const *argv)
varbuf_trunc(&path, path_trim_slash_slashdot(path.buf));
namenode = fsys_hash_find_node(path.buf, 0);
- found += searchoutput(namenode);
+ found += searchoutput(namenode, NULL);
+ if (!found) {
+ found += searchfile_realpath(path.buf);
+ }
} else {
struct fsys_hash_iter *iter;
iter = fsys_hash_iter_new();
while ((namenode = fsys_hash_iter_next(iter)) != NULL) {
if (fnmatch(thisarg,namenode->name,0)) continue;
- found+= searchoutput(namenode);
+ found += searchoutput(namenode, NULL);
}
fsys_hash_iter_free(iter);
}
Reply to: