]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
debuginfod client API: add get_url function
authorFrank Ch. Eigler <fche@redhat.com>
Sat, 21 Mar 2020 01:33:52 +0000 (21:33 -0400)
committerFrank Ch. Eigler <fche@redhat.com>
Sun, 22 Mar 2020 20:46:16 +0000 (16:46 -0400)
This function lets a client know, during or after a progressfn
callback, what the url of the winning outgoing download is/was.

Signed-off-by: Frank Ch. Eigler <fche@redhat.com>
debuginfod/ChangeLog
debuginfod/debuginfod-client.c
debuginfod/debuginfod-find.c
debuginfod/debuginfod.h
debuginfod/libdebuginfod.map
doc/ChangeLog
doc/Makefile.am
doc/debuginfod_find_debuginfo.3
doc/debuginfod_get_url.3 [new file with mode: 0644]
tests/ChangeLog
tests/run-debuginfod-find.sh

index a26f6b271bd0d26899bd9cdda454b320d7083b6e..2410430c2361309d74af42f298b19bc0194284ee 100644 (file)
@@ -1,3 +1,12 @@
+2020-03-22  Frank Ch. Eigler  <fche@redhat.com>
+
+       * debuginfod-client.c (struct debuginfod_client): Add url field.
+       (struct handle_data): Add client field as backpointer.
+       (debuginfod_write_callback): Compute & save URL.
+       (default_progressfn): Print front pieces of the URL.
+       (debuginfod_query_server): Clear URL and cleanup after progressfn.
+       * debuginfod-find.c (main): Print URL at transfer conclusion.
+
 2020-03-22  Frank Ch. Eigler  <fche@redhat.com>
 
        * debuginfod.h, libdebuginfod.map: New functions for _get/set_user().
index 2730dbf7aee5e8d8f3b16a6af4a624b3c629d49b..58a04b9a734b7d50f3bfefc3fe8d06e90d29d3db 100644 (file)
@@ -82,6 +82,9 @@ struct debuginfod_client
   /* Stores user data. */
   void* user_data;
 
+  /* Stores current/last url, if any. */
+  char* url;
+
   /* Can contain all other context, like cache_path, server_urls,
      timeout or other info gotten from environment variables, the
      handle data, etc. So those don't have to be reparsed and
@@ -128,6 +131,9 @@ struct handle_data
   /* This handle.  */
   CURL *handle;
 
+  /* The client object whom we're serving. */
+  debuginfod_client *client;
+
   /* Pointer to handle that should write to fd. Initially points to NULL,
      then points to the first handle that begins writing the target file
      to the cache. Used to ensure that a file is not downloaded from
@@ -144,7 +150,17 @@ debuginfod_write_callback (char *ptr, size_t size, size_t nmemb, void *data)
 
   /* Indicate to other handles that they can abort their transfer.  */
   if (*d->target_handle == NULL)
-    *d->target_handle = d->handle;
+    {
+      *d->target_handle = d->handle;
+      /* update the client object */
+      const char *url = NULL;
+      (void) curl_easy_getinfo (d->handle, CURLINFO_EFFECTIVE_URL, &url);
+      if (url)
+        {
+          free (d->client->url);
+          d->client->url = strdup(url); /* ok if fails */
+        }
+    }
 
   /* If this handle isn't the target handle, abort transfer.  */
   if (*d->target_handle != d->handle)
@@ -410,6 +426,10 @@ debuginfod_query_server (debuginfod_client *c,
   char build_id_bytes[MAX_BUILD_ID_BYTES * 2 + 1];
   int rc;
 
+  /* Clear the obsolete URL from a previous _find operation. */
+  free (c->url);
+  c->url = NULL;
+
   /* Is there any server we can query?  If not, don't do any work,
      just return with ENOSYS.  Don't even access the cache.  */
   urls_envvar = getenv(server_urls_envvar);
@@ -620,6 +640,7 @@ debuginfod_query_server (debuginfod_client *c,
       data[i].fd = fd;
       data[i].target_handle = &target_handle;
       data[i].handle = curl_easy_init();
+      data[i].client = c;
 
       if (data[i].handle == NULL)
         {
@@ -863,6 +884,10 @@ debuginfod_query_server (debuginfod_client *c,
 
 /* general purpose exit */
  out:
+  /* Conclude the last \r status line */
+  if (getenv(DEBUGINFOD_PROGRESS_ENV_VAR))
+    dprintf(STDERR_FILENO, "\n");
+
   free (cache_path);
   free (maxage_path);
   free (interval_path);
@@ -877,12 +902,31 @@ debuginfod_query_server (debuginfod_client *c,
 static int
 default_progressfn (debuginfod_client *c, long a, long b)
 {
-  (void) c;
+  const char* url = debuginfod_get_url (c);
+  int len = 0;
 
-  dprintf(STDERR_FILENO,
-          "Downloading from debuginfod %ld/%ld%s", a, b,
-          ((a == b) ? "\n" : "\r"));
-  /* XXX: include URL - stateful */
+  /* We prefer to print the host part of the URL to keep the
+     message short. */
+  if (url != NULL)
+    {
+      const char* buildid = strstr(url, "buildid/");
+      if (buildid != NULL)
+        len = (buildid - url);
+      else
+        len = strlen(url);
+    }
+
+  if (b == 0 || url==NULL) /* early stage */
+    dprintf(STDERR_FILENO,
+            "\rDownloading %c", "-/|\\"[a % 4]);
+  else if (b < 0) /* download in progress but unknown total length */
+    dprintf(STDERR_FILENO,
+            "\rDownloading from %.*s %ld",
+            len, url, a);
+  else /* download in progress, and known total length */
+    dprintf(STDERR_FILENO,
+            "\rDownloading from %.*s %ld/%ld",
+            len, url, a, b);
 
   return 0;
 }
@@ -894,13 +938,11 @@ debuginfod_begin (void)
 {
   debuginfod_client *client;
   size_t size = sizeof (struct debuginfod_client);
-  client = (debuginfod_client *) malloc (size);
+  client = (debuginfod_client *) calloc (1, size);
   if (client != NULL)
     {
       if (getenv(DEBUGINFOD_PROGRESS_ENV_VAR))
        client->progressfn = default_progressfn;
-      else
-       client->progressfn = NULL;
     }
   return client;
 }
@@ -918,9 +960,16 @@ debuginfod_get_user_data(debuginfod_client *client)
   return client->user_data;
 }
 
+const char *
+debuginfod_get_url(debuginfod_client *client)
+{
+  return client->url;
+}
+
 void
 debuginfod_end (debuginfod_client *client)
 {
+  free (client->url);
   free (client);
 }
 
index 0b1ca9cf1d7687abd8193fd6093731941175fd59..787779c76a471c92bb09c726a7b9880e71716a89 100644 (file)
@@ -51,6 +51,7 @@ static const struct argp_option options[] =
 
 /* debuginfod connection handle.  */
 static debuginfod_client *client;
+static int verbose;
 
 int progressfn(debuginfod_client *c __attribute__((__unused__)),
               long a, long b)
@@ -66,7 +67,8 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state)
   (void) state;
   switch (key)
     {
-    case 'v': debuginfod_set_progressfn (client, & progressfn); break;
+    case 'v': verbose++;
+      debuginfod_set_progressfn (client, & progressfn); break;
     default: return ARGP_ERR_UNKNOWN;
     }
   return 0;
@@ -133,6 +135,13 @@ main(int argc, char** argv)
       return 1;
     }
 
+  if (verbose)
+    {
+      const char* url = debuginfod_get_url (client);
+      if (url != NULL)
+        fprintf(stderr, "Downloaded from %s\n", url);
+    }
+
   debuginfod_end (client);
 
   if (rc < 0)
index fe72f16e9bd827afc49f70963a2a2798e7338117..2ace5f3504884ea215ff0cc41fd062bfae5af4ef 100644 (file)
@@ -81,6 +81,9 @@ void debuginfod_set_user_data (debuginfod_client *client, void *value);
 /* Get the user parameter.  */
 void* debuginfod_get_user_data (debuginfod_client *client);
 
+/* Get the current or last active URL, if known.  */
+const char* debuginfod_get_url (debuginfod_client *client);
+
 /* Release debuginfod client connection context handle.  */
 void debuginfod_end (debuginfod_client *client);
 
index a919630dacce01abdef92fc171d16ddf293ccf73..d84e8924f7f8878c7037602f4eb81ef7f1a3ce87 100644 (file)
@@ -12,4 +12,5 @@ ELFUTILS_0.179 {
   global:
   debuginfod_set_user_data;
   debuginfod_get_user_data;
+  debuginfod_get_url;
 };
index 16b0e99f6fd4172be98909f3199e217eed7074ca..59809ea8a1e2c0b7d838a59706a9ee722f6cccac 100644 (file)
@@ -1,3 +1,9 @@
+2020-03-22  Frank Ch. Eigler  <fche@redhat.com>
+
+       * debuginfod_get_url.3: New function, documented ...
+       * debuginfod_find_debuginfo.3: ... here.
+       * Makefile.am (notrans_dist_*_man3): Add it.
+
 2020-03-22  Frank Ch. Eigler  <fche@redhat.com>
 
        * debuginfod_get_user.3, _set_user.3: New functions, documented ...
index 87d1fee0330263a01e7e42ae10eaa6f75fbfedb0..38b8226d775c428aa9f5dfd79aefd5a733548b08 100644 (file)
@@ -30,6 +30,7 @@ notrans_dist_man3_MANS += debuginfod_find_debuginfo.3
 notrans_dist_man3_MANS += debuginfod_find_executable.3
 notrans_dist_man3_MANS += debuginfod_find_source.3
 notrans_dist_man3_MANS += debuginfod_get_user_data.3
+notrans_dist_man3_MANS += debuginfod_get_url.3
 notrans_dist_man3_MANS += debuginfod_set_progressfn.3
 notrans_dist_man3_MANS += debuginfod_set_user_data.3
 notrans_dist_man1_MANS += debuginfod-find.1
index 29706513bad0a4391c14e6e56fc2959edaea8989..f7ec6cc134ba8cec73026d630f19d03c19e8a398 100644 (file)
@@ -53,6 +53,7 @@ OPTIONAL FUNCTIONS
 .BI "void debuginfod_set_user_data(debuginfod_client *" client ","
 .BI "                              void *" data ");"
 .BI "void* debuginfod_get_user_data(debuginfod_client *" client ");"
+.BI "const char* debuginfod_get_url(debuginfod_client *" client ");"
 
 .SH DESCRIPTION
 
@@ -148,6 +149,16 @@ and retrieved via
 .BR \%debuginfod_get_user_data () .
 The value is undefined if unset.
 
+.SS "URL"
+
+The URL of the current or most recent outgoing download, if known,
+may be retrieved via
+.BR \%debuginfod_get_url ()
+from the progressfn callback, or afterwards.  It may be NULL.
+The resulting string is owned by the library, and must not be modified
+or freed.  The caller should copy it if it is needed beyond the release
+of the client object.
+
 .SH "CACHE"
 If the query is successful, the \fBdebuginfod_find_*\fP() functions save
 the target file to a local cache. The location of the cache is controlled
diff --git a/doc/debuginfod_get_url.3 b/doc/debuginfod_get_url.3
new file mode 100644 (file)
index 0000000..1627993
--- /dev/null
@@ -0,0 +1 @@
+.so man3/debuginfod_find_debuginfo.3
index 33a5cf62cdc5ec17ef5d08c57b44868c5bf97a08..cefbceb4f3a8160292fd14b4eba91946384547ef 100644 (file)
@@ -1,3 +1,8 @@
+2020-03-22  Frank Ch. Eigler  <fche@redhat.com>
+
+       * run-debuginfod-find.sh: Look for URL in default progressfn
+       and from debuginfod-find -v.
+
 2020-02-19  Aaron Merey  <amerey@redhat.com>
 
        * run-debuginfod-find.sh: Run tests for verifying default
index 587eaaa3afa105197a3c68602b68da530368c91d..b64130282d86508d79acc2f802579f02e8834b3a 100755 (executable)
@@ -212,11 +212,12 @@ filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find -v debuginfo $B
 cmp $filename F/prog2
 cat vlog
 grep -q Progress vlog
+grep -q Downloaded.from vlog
 tempfiles vlog
 filename=`testrun env DEBUGINFOD_PROGRESS=1 ${abs_top_builddir}/debuginfod/debuginfod-find executable $BUILDID2 2>vlog2`
 cmp $filename F/prog2
 cat vlog2
-grep -q Downloading vlog2
+grep -q 'Downloading.*http' vlog2
 tempfiles vlog2
 filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find source $BUILDID2 ${PWD}/prog2.c`
 cmp $filename ${PWD}/prog2.c