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); }