summaryrefslogtreecommitdiff
path: root/debuginfod/debuginfod-client.c
diff options
context:
space:
mode:
authorNoah Sanci <nsanci@redhat.com>2021-07-28 14:46:05 -0400
committerNoah Sanci <nsanci@redhat.com>2021-08-27 14:32:29 -0400
commited7638571f188e346dd466c195b9ebda028d1c65 (patch)
tree8592d39eb794d5ae36fda0a0aac344843f033bf8 /debuginfod/debuginfod-client.c
parentd3f914023abcd6ae76b168da97518e5e7dbd761a (diff)
downloadelfutils-nsanci/verbose-headers.tar.gz
debuginfod: PR27277 - Describe retrieved files when verbosensanci/verbose-headers
There appear to exist use cases that intend to simply check for the existence of content in a debuginfod server, without actually downloading it. In HTTP land, the HEAD operation is the natural expression of this. Instead of implementing a HEAD/describe option, allow users, with enough verbosity, to print the HTTP response headers upon retrieving a file. E.g output: HTTP/1.1 200 OK Connection: Keep-Alive Content-Length: 2428240 Cache-Control: public Last-Modified: Sat, 15 May 2021 20:49:51 GMT X-FILE: "file name" X-FILE-SIZE: "byte length of file" Content-Type: application/octet-stream Date: Tue, 03 Aug 2021 18:50:36 GMT https://sourceware.org/bugzilla/show_bug.cgi?id=27277 Signed-off-by: Noah Sanci <nsanci@redhat.com>
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);
}