RFC: deb/ddeb support for debuginfod

Frank Ch. Eigler fche@redhat.com
Sat Nov 30 15:58:00 GMT 2019


Hi -

I present the following quick hack to add .deb/.ddeb support to
debuginfod.  It works ... but my reservation is political. :-)
It works by letting the RPM-scanning code paths recognize .deb
and .ddeb files by their suffix, and run them through a different
stream-extractor (dpkg-deb --fsys-tarfile instead of rpm2cpio).
Otherwise, nothing needs to change!

And that's kind of the problem.  The program diagnostics, options, all
mention 'rpm'.  I'd like your opinion about whether the proposed man
page's explanation is good enough -- or whether debian fans would be
so gravely offended by the preservation of the 'rpm' term that we must
hide it.

commit bb6a05faf5905e55f3289c70388b339113f843dd
Author: Frank Ch. Eigler <fche@redhat.com>
Date:   Sat Nov 30 10:46:44 2019 -0500

    deb/ddeb support prototype

diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx
index aa7ffcf..851d0bd 100644
--- a/debuginfod/debuginfod.cxx
+++ b/debuginfod/debuginfod.cxx
@@ -106,6 +106,17 @@ using namespace std;
 #endif
 
 
+inline bool
+string_endswith(const string& haystack, const string& needle)
+{
+  return (haystack.size() >= needle.size() &&
+	  haystack.substr(haystack.size()-needle.size()) == needle);
+}
+
+    
+
+
+
 // Roll this identifier for every sqlite schema incompatiblity.
 #define BUILDIDS "buildids9"
 
@@ -323,7 +334,7 @@ static const struct argp_option options[] =
   {
    { NULL, 0, NULL, 0, "Scanners:", 1 },
    { "scan-file-dir", 'F', NULL, 0, "Enable ELF/DWARF file scanning threads.", 0 },
-   { "scan-rpm-dir", 'R', NULL, 0, "Enable RPM scanning threads.", 0 },
+   { "scan-rpm-dir", 'R', NULL, 0, "Enable RPM/DEB scanning threads.", 0 },
    // "source-oci-imageregistry"  ... 
 
    { NULL, 0, NULL, 0, "Options:", 2 },
@@ -851,7 +862,11 @@ handle_buildid_r_match (int64_t b_mtime,
       return 0;
     }
 
-  string popen_cmd = string("rpm2cpio " + shell_escape(b_source0));
+  string popen_cmd;
+  if (string_endswith(b_source0, "rpm"))
+    popen_cmd = string("rpm2cpio " + shell_escape(b_source0));
+  else // .deb or .ddeb
+    popen_cmd = string("dpkg-deb --fsys-tarfile " + shell_escape(b_source0));
   FILE* fp = popen (popen_cmd.c_str(), "r"); // "e" O_CLOEXEC?
   if (fp == NULL)
     throw libc_exception (errno, string("popen ") + popen_cmd);
@@ -863,9 +878,9 @@ handle_buildid_r_match (int64_t b_mtime,
     throw archive_exception("cannot create archive reader");
   defer_dtor<struct archive*,int> archive_closer (a, archive_read_free);
 
-  rc = archive_read_support_format_cpio(a);
+  rc = archive_read_support_format_all(a);
   if (rc != ARCHIVE_OK)
-    throw archive_exception(a, "cannot select cpio format");
+    throw archive_exception(a, "cannot select all format");
   rc = archive_read_support_filter_all(a);
   if (rc != ARCHIVE_OK)
     throw archive_exception(a, "cannot select all filters");
@@ -1867,7 +1882,11 @@ rpm_classify (const string& rps, sqlite_ps& ps_upsert_buildids, sqlite_ps& ps_up
               unsigned& fts_executable, unsigned& fts_debuginfo, unsigned& fts_sref, unsigned& fts_sdef,
               bool& fts_sref_complete_p)
 {
-  string popen_cmd = string("rpm2cpio " + shell_escape(rps));
+  string popen_cmd;
+  if (string_endswith(rps, "rpm"))
+    popen_cmd = string("rpm2cpio " + shell_escape(rps));
+  else // .deb or .ddeb
+    popen_cmd = string("dpkg-deb --fsys-tarfile " + shell_escape(rps));
   FILE* fp = popen (popen_cmd.c_str(), "r"); // "e" O_CLOEXEC?
   if (fp == NULL)
     throw libc_exception (errno, string("popen ") + popen_cmd);
@@ -1879,9 +1898,9 @@ rpm_classify (const string& rps, sqlite_ps& ps_upsert_buildids, sqlite_ps& ps_up
     throw archive_exception("cannot create archive reader");
   defer_dtor<struct archive*,int> archive_closer (a, archive_read_free);
 
-  int rc = archive_read_support_format_cpio(a);
+  int rc = archive_read_support_format_all(a);
   if (rc != ARCHIVE_OK)
-    throw archive_exception(a, "cannot select cpio format");
+    throw archive_exception(a, "cannot select all formats");
   rc = archive_read_support_filter_all(a);
   if (rc != ARCHIVE_OK)
     throw archive_exception(a, "cannot select all filters");
@@ -2118,9 +2137,12 @@ scan_source_rpm_path (const string& dir)
               {
                 // heuristic: reject if file name does not end with ".rpm"
                 // (alternative: try opening with librpm etc., caching)
-                string suffix = ".rpm";
-                if (rps.size() < suffix.size() ||
-                    rps.substr(rps.size()-suffix.size()) != suffix)
+		auto suffixes = vector<string> {".rpm", ".deb", ".ddeb"};
+		bool any = false;
+		for (auto&& suffix : suffixes)
+		  if (string_endswith (rps, suffix))
+		    any = true;
+		if (! any)
                   continue;
                 fts_rpm ++;
 
diff --git a/doc/debuginfod.8 b/doc/debuginfod.8
index 210550e..5ad3389 100644
--- a/doc/debuginfod.8
+++ b/doc/debuginfod.8
@@ -56,14 +56,19 @@ or even use debuginfod itself:
 .ESAMPLE
 
 If the \fB\-R\fP option is given each listed PATH creates a thread to
-scan for ELF/DWARF/source files contained in matching RPMs under the
-given physical directory.  Duplicate directories are ignored.  You may
-use a file name for a PATH, but source code indexing may be
-incomplete; prefer using a directory that contains normal RPMs
-alongside debuginfo/debugsource RPMs.  Because of complications such
-as DWZ-compressed debuginfo, may require \fItwo\fP scan passes to
-identify all source code.  Source files for RPMs are only served
-from other RPMs, so the caution for \-F does not apply.
+scan for ELF/DWARF/source files contained in matching RPMs or DEBs or
+DDEBs under the given physical directory.  (The terms RPM and DEB and
+DDEB are used interchangeably here and in debuginfod diagnostic
+messages.  The different file types are simply recognied by their
+extensions.)  Duplicate directories are ignored.  You may use a file
+name for a PATH, but source code indexing may be incomplete; prefer
+using a directory that contains normal RPMs alongside
+debuginfo/debugsource RPMs.  Because of complications such as
+DWZ-compressed debuginfo, may require \fItwo\fP scan passes to
+identify all source code.  Source files for RPMs are only served from
+other RPMs, so the caution for \-F does not apply.  Note that due to
+Debian/Ubuntu packaging policies & mechanisms, debuginfod cannot resolve
+source files for DEB/DDEB at all.
 
 If no PATH is listed, or neither \-F nor \-R option is given, then
 \fBdebuginfod\fP will simply serve content that it scanned into its



More information about the Elfutils-devel mailing list