+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().
/* 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
/* 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
/* 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)
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);
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)
{
/* 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);
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;
}
{
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;
}
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);
}
/* debuginfod connection handle. */
static debuginfod_client *client;
+static int verbose;
int progressfn(debuginfod_client *c __attribute__((__unused__)),
long a, long b)
(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;
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)
/* 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);
global:
debuginfod_set_user_data;
debuginfod_get_user_data;
+ debuginfod_get_url;
};
+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 ...
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
.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
.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
--- /dev/null
+.so man3/debuginfod_find_debuginfo.3
+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
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