summaryrefslogtreecommitdiff
path: root/debuginfod/debuginfod-client.c
diff options
context:
space:
mode:
Diffstat (limited to 'debuginfod/debuginfod-client.c')
-rw-r--r--debuginfod/debuginfod-client.c58
1 files changed, 54 insertions, 4 deletions
diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c
index 7d4b220f..eb52dddf 100644
--- a/debuginfod/debuginfod-client.c
+++ b/debuginfod/debuginfod-client.c
@@ -127,6 +127,7 @@ struct debuginfod_client
timeout or other info gotten from environment variables, the
handle data, etc. So those don't have to be reparsed and
recreated on each request. */
+ char * winning_headers;
};
/* The cache_clean_interval_s file within the debuginfod cache specifies
@@ -183,6 +184,8 @@ struct handle_data
to the cache. Used to ensure that a file is not downloaded from
multiple servers unnecessarily. */
CURL **target_handle;
+ /* Response http headers for this client handle, sent from the server */
+ char *response_data;
};
static size_t
@@ -499,6 +502,33 @@ default_progressfn (debuginfod_client *c, long a, long b)
}
+static size_t
+header_callback (char * buffer, size_t size, size_t numitems, void * userdata)
+{
+ if (size != 1)
+ return 0;
+ /* Temporary buffer for realloc */
+ char *temp = NULL;
+ size_t userlen = 0;
+ if (*(char**)userdata == NULL)
+ {
+ temp = malloc(numitems+1);
+ if (temp == NULL)
+ return 0;
+ memset(temp, '\0', numitems+1);
+ }
+ else
+ {
+ userlen = strlen(*(char**)userdata);
+ temp = realloc(*(char**)userdata, userlen + numitems + 1);
+ if (temp == NULL)
+ return 0;
+ }
+ strncat(temp, buffer, numitems);
+ *(char**)userdata = temp;
+ return numitems;
+}
+
/* Query each of the server URLs found in $DEBUGINFOD_URLS for the file
with the specified build-id, type (debuginfo, executable or source)
and filename. filename may be NULL. If found, return a file
@@ -936,10 +966,13 @@ debuginfod_query_server (debuginfod_client *c,
curl_easy_setopt (data[i].handle, CURLOPT_LOW_SPEED_LIMIT,
100 * 1024L);
}
+ data[i].response_data = NULL;
curl_easy_setopt(data[i].handle, CURLOPT_FILETIME, (long) 1);
curl_easy_setopt(data[i].handle, CURLOPT_FOLLOWLOCATION, (long) 1);
curl_easy_setopt(data[i].handle, CURLOPT_FAILONERROR, (long) 1);
curl_easy_setopt(data[i].handle, CURLOPT_NOSIGNAL, (long) 1);
+ curl_easy_setopt(data[i].handle, CURLOPT_HEADERFUNCTION, header_callback);
+ curl_easy_setopt(data[i].handle, CURLOPT_HEADERDATA, (void *) &(data[i].response_data));
#if LIBCURL_VERSION_NUM >= 0x072a00 /* 7.42.0 */
curl_easy_setopt(data[i].handle, CURLOPT_PATH_AS_IS, (long) 1);
#else
@@ -961,6 +994,7 @@ debuginfod_query_server (debuginfod_client *c,
int committed_to = -1;
bool verbose_reported = false;
struct timespec start_time, cur_time;
+ c->winning_headers = NULL;
if ( maxtime > 0 && clock_gettime(CLOCK_MONOTONIC_RAW, &start_time) == -1)
{
rc = errno;
@@ -995,8 +1029,18 @@ debuginfod_query_server (debuginfod_client *c,
if (data[i].handle != target_handle)
curl_multi_remove_handle(curlm, data[i].handle);
else
- committed_to = i;
- }
+ {
+ committed_to = i;
+ if (c->winning_headers == NULL)
+ {
+ c->winning_headers = data[committed_to].response_data;
+ if (vfd >= 0 && c->winning_headers != NULL)
+ dprintf(vfd, "\n%s", c->winning_headers);
+ data[committed_to].response_data = NULL;
+ }
+
+ }
+ }
if (vfd >= 0 && !verbose_reported && committed_to >= 0)
{
@@ -1161,10 +1205,10 @@ debuginfod_query_server (debuginfod_client *c,
{
char *effective_url = NULL;
long resp_code = 500;
- CURLcode ok1 = curl_easy_getinfo (target_handle,
+ CURLcode ok1 = curl_easy_getinfo (msg->easy_handle,
CURLINFO_EFFECTIVE_URL,
&effective_url);
- CURLcode ok2 = curl_easy_getinfo (target_handle,
+ CURLcode ok2 = curl_easy_getinfo (msg->easy_handle,
CURLINFO_RESPONSE_CODE,
&resp_code);
if(ok1 == CURLE_OK && ok2 == CURLE_OK && effective_url)
@@ -1238,7 +1282,10 @@ debuginfod_query_server (debuginfod_client *c,
{
curl_multi_remove_handle(curlm, data[i].handle); /* ok to repeat */
curl_easy_cleanup (data[i].handle);
+ free(data[i].response_data);
}
+ free(c->winning_headers);
+ c->winning_headers = NULL;
goto query_in_parallel;
}
else
@@ -1281,6 +1328,7 @@ debuginfod_query_server (debuginfod_client *c,
{
curl_multi_remove_handle(curlm, data[i].handle); /* ok to repeat */
curl_easy_cleanup (data[i].handle);
+ free (data[i].response_data);
}
for (int i = 0; i < num_urls; ++i)
@@ -1304,6 +1352,7 @@ debuginfod_query_server (debuginfod_client *c,
{
curl_multi_remove_handle(curlm, data[i].handle); /* ok to repeat */
curl_easy_cleanup (data[i].handle);
+ free (data[i].response_data);
}
unlink (target_cache_tmppath);
@@ -1415,6 +1464,7 @@ debuginfod_end (debuginfod_client *client)
curl_multi_cleanup (client->server_mhandle);
curl_slist_free_all (client->headers);
+ free (client->winning_headers);
free (client->url);
free (client);
}