int s, const char *f, char **p) { return -ENOSYS; }
void debuginfod_set_progressfn(debuginfod_client *c,
debuginfod_progressfn_t fn) { }
+void debuginfod_set_verbose_fd(debuginfod_client *c, int fd) { }
void debuginfod_set_user_data (debuginfod_client *c, void *d) { }
void* debuginfod_get_user_data (debuginfod_client *c) { return NULL; }
const char* debuginfod_get_url (debuginfod_client *c) { return NULL; }
debuginfod_end needs to terminate. */
int default_progressfn_printed_p;
+ /* File descriptor to output any verbose messages if > 0. */
+ int verbose_fd;
+
/* 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
/* URL queried by this handle. */
char url[PATH_MAX];
+ /* error buffer for this handle. */
+ char errbuf[CURL_ERROR_SIZE];
+
/* This handle. */
CURL *handle;
char *target_cache_tmppath = NULL;
char suffix[PATH_MAX + 1]; /* +1 for zero terminator. */
char build_id_bytes[MAX_BUILD_ID_BYTES * 2 + 1];
+ int vfd = c->verbose_fd;
int rc;
- /* Clear the obsolete URL from a previous _find operation. */
- free (c->url);
- c->url = NULL;
-
- add_default_headers(c);
+ if (vfd >= 0)
+ {
+ dprintf (vfd, "debuginfod_find_%s ", type);
+ if (build_id_len == 0) /* expect clean hexadecimal */
+ dprintf (vfd, "%s", (const char *) build_id);
+ else
+ for (int i = 0; i < build_id_len; i++)
+ dprintf (vfd, "%02x", build_id[i]);
+ if (filename != NULL)
+ dprintf (vfd, " %s\n", filename);
+ dprintf (vfd, "\n");
+ }
/* 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);
+ if (vfd >= 0)
+ dprintf (vfd, "server urls \"%s\"\n",
+ urls_envvar != NULL ? urls_envvar : "");
if (urls_envvar == NULL || urls_envvar[0] == '\0')
{
rc = -ENOSYS;
goto out;
}
+ /* Clear the obsolete URL from a previous _find operation. */
+ free (c->url);
+ c->url = NULL;
+
+ add_default_headers(c);
+
/* Copy lowercase hex representation of build_id into buf. */
+ if (vfd >= 0)
+ dprintf (vfd, "checking build-id\n");
if ((build_id_len >= MAX_BUILD_ID_BYTES) ||
(build_id_len == 0 &&
strlen ((const char *) build_id) > MAX_BUILD_ID_BYTES*2))
- return -EINVAL;
+ {
+ rc = -EINVAL;
+ goto out;
+ }
+
if (build_id_len == 0) /* expect clean hexadecimal */
strcpy (build_id_bytes, (const char *) build_id);
else
if (filename != NULL)
{
+ if (vfd >= 0)
+ dprintf (vfd, "checking filename\n");
if (filename[0] != '/') // must start with /
- return -EINVAL;
+ {
+ rc = -EINVAL;
+ goto out;
+ }
/* copy the filename to suffix, s,/,#,g */
unsigned q = 0;
else
suffix[0] = '\0';
+ if (suffix[0] != '\0' && vfd >= 0)
+ dprintf (vfd, "suffix %s\n", suffix);
+
/* set paths needed to perform the query
example format
/* XXX combine these */
xalloc_str (interval_path, "%s/%s", cache_path, cache_clean_interval_filename);
xalloc_str (maxage_path, "%s/%s", cache_path, cache_max_unused_age_filename);
+
+ if (vfd >= 0)
+ dprintf (vfd, "checking cache dir %s\n", cache_path);
+
rc = debuginfod_init_cache(cache_path, interval_path, maxage_path);
if (rc != 0)
goto out;
if (timeout_envvar != NULL)
timeout = atoi (timeout_envvar);
+ if (vfd >= 0)
+ dprintf (vfd, "using timeout %ld\n", timeout);
+
/* make a copy of the envvar so it can be safely modified. */
server_urls = strdup(urls_envvar);
if (server_urls == NULL)
/* Initialize each handle. */
for (int i = 0; i < num_urls && server_url != NULL; i++)
{
+ if (vfd >= 0)
+ dprintf (vfd, "init server %d %s\n", i, server_url);
+
data[i].fd = fd;
data[i].target_handle = &target_handle;
data[i].handle = curl_easy_init();
snprintf(data[i].url, PATH_MAX, "%s%s/%s/%s", server_url,
slashbuildid, build_id_bytes, type);
+ if (vfd >= 0)
+ dprintf (vfd, "url %d %s\n", i, data[i].url);
+
curl_easy_setopt(data[i].handle, CURLOPT_URL, data[i].url);
+ if (vfd >= 0)
+ curl_easy_setopt(data[i].handle, CURLOPT_ERRORBUFFER, data[i].errbuf);
curl_easy_setopt(data[i].handle,
CURLOPT_WRITEFUNCTION,
debuginfod_write_callback);
}
/* Query servers in parallel. */
+ if (vfd >= 0)
+ dprintf (vfd, "query %d urls in parallel\n", num_urls);
int still_running;
long loops = 0;
+ int committed_to = -1;
+ bool verbose_reported = false;
do
{
/* Wait 1 second, the minimum DEBUGINFOD_TIMEOUT. */
/* If the target file has been found, abort the other queries. */
if (target_handle != NULL)
- for (int i = 0; i < num_urls; i++)
- if (data[i].handle != target_handle)
- curl_multi_remove_handle(curlm, data[i].handle);
+ {
+ for (int i = 0; i < num_urls; i++)
+ if (data[i].handle != target_handle)
+ curl_multi_remove_handle(curlm, data[i].handle);
+ else
+ committed_to = i;
+ }
+
+ if (vfd >= 0 && !verbose_reported && committed_to >= 0)
+ {
+ bool pnl = (c->default_progressfn_printed_p && vfd == STDERR_FILENO);
+ dprintf (vfd, "%scommitted to url %d\n", pnl ? "\n" : "",
+ committed_to);
+ if (pnl)
+ c->default_progressfn_printed_p = 0;
+ verbose_reported = true;
+ }
CURLMcode curlm_res = curl_multi_perform(curlm, &still_running);
if (curlm_res != CURLM_OK)
msg = curl_multi_info_read(curlm, &num_msg);
if (msg != NULL && msg->msg == CURLMSG_DONE)
{
+ if (vfd >= 0)
+ {
+ bool pnl = (c->default_progressfn_printed_p
+ && vfd == STDERR_FILENO);
+ dprintf (vfd, "%sserver response %s\n", pnl ? "\n" : "",
+ curl_easy_strerror (msg->data.result));
+ if (pnl)
+ c->default_progressfn_printed_p = 0;
+ for (int i = 0; i < num_urls; i++)
+ if (msg->easy_handle == data[i].handle)
+ {
+ if (strlen (data[i].errbuf) > 0)
+ dprintf (vfd, "url %d %s\n", i, data[i].errbuf);
+ break;
+ }
+ }
+
if (msg->data.result != CURLE_OK)
{
/* Unsucessful query, determine error code. */
if (verified_handle == NULL)
goto out1;
+ if (vfd >= 0)
+ {
+ bool pnl = c->default_progressfn_printed_p && vfd == STDERR_FILENO;
+ dprintf (vfd, "%sgot file from server\n", pnl ? "\n" : "");
+ if (pnl)
+ c->default_progressfn_printed_p = 0;
+ }
+
/* we've got one!!!! */
time_t mtime;
CURLcode curl_res = curl_easy_getinfo(verified_handle, CURLINFO_FILETIME, (void*) &mtime);
if (c->default_progressfn_printed_p)
dprintf(STDERR_FILENO, "\n");
+ if (vfd >= 0)
+ {
+ if (rc < 0)
+ dprintf (vfd, "not found %s (err=%d)\n", strerror (-rc), rc);
+ else
+ dprintf (vfd, "found %s (fd=%d)\n", target_cache_path, rc);
+ }
+
free (cache_path);
free (maxage_path);
free (interval_path);
{
if (getenv(DEBUGINFOD_PROGRESS_ENV_VAR))
client->progressfn = default_progressfn;
+ if (getenv(DEBUGINFOD_VERBOSE_ENV_VAR))
+ client->verbose_fd = STDERR_FILENO;
+ else
+ client->verbose_fd = -1;
}
return client;
}
client->progressfn = fn;
}
+void
+debuginfod_set_verbose_fd(debuginfod_client *client, int fd)
+{
+ client->verbose_fd = fd;
+}
+
/* NB: these are thread-unsafe. */
__attribute__((constructor)) attribute_hidden void libdebuginfod_ctor(void)