[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: