summaryrefslogtreecommitdiff
path: root/debuginfod
diff options
context:
space:
mode:
Diffstat (limited to 'debuginfod')
-rw-r--r--debuginfod/ChangeLog15
-rw-r--r--debuginfod/debuginfod-client.c58
-rw-r--r--debuginfod/debuginfod.cxx11
3 files changed, 80 insertions, 4 deletions
diff --git a/debuginfod/ChangeLog b/debuginfod/ChangeLog
index 395af94f..d911d5b5 100644
--- a/debuginfod/ChangeLog
+++ b/debuginfod/ChangeLog
@@ -16,6 +16,21 @@
* debuginfod.cxx (handler_cb): Fix after_you unique_set key
to the entire incoming URL.
+2021-08-02 Noah Sanci <nsanci@redhat.com>
+
+ PR27277
+ * debuginfod-client.c (struct debuginfod_client): New field
+ winning_headers.
+ (struct handle_data): New field response_data.
+ (header_callback): Store received headers in response_data.
+ (debuginfod_query_server): Activate CURLOPT_HEADERFUNCTION.
+ Save winning response_data.
+ (debuginfod_end): free client winning headers.
+ * debuginfod.cxx (handle_buildid_f_match): remove X-FILE path. Add
+ X-FILE and X-FILE-SIZE headers.
+ (handle_buildid_r_match): remove X-FILE path. Add X-FILE, X-FILE-SIZE
+ headers, and X-ARCHIVE headers.
+
2021-07-26 Noah Sanci <nsanci@redhat.com>
PR27982
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);
}
diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx
index 6e182a84..e9b7e76c 100644
--- a/debuginfod/debuginfod.cxx
+++ b/debuginfod/debuginfod.cxx
@@ -1068,6 +1068,9 @@ handle_buildid_f_match (bool internal_req_t,
else
{
MHD_add_response_header (r, "Content-Type", "application/octet-stream");
+ std::string file = b_source0.substr(b_source0.find_last_of("/")+1, b_source0.length());
+ MHD_add_response_header (r, "X-FILE-SIZE", to_string(s.st_size).c_str() );
+ MHD_add_response_header (r, "X-FILE", file.c_str() );
add_mhd_last_modified (r, s.st_mtime);
if (verbose > 1)
obatched(clog) << "serving file " << b_source0 << endl;
@@ -1537,6 +1540,9 @@ handle_buildid_r_match (bool internal_req_p,
inc_metric ("http_responses_total","result","archive fdcache");
MHD_add_response_header (r, "Content-Type", "application/octet-stream");
+ MHD_add_response_header (r, "X-FILE-SIZE", to_string(fs.st_size).c_str());
+ MHD_add_response_header (r, "X-ARCHIVE", b_source0.c_str());
+ MHD_add_response_header (r, "X-FILE", b_source1.c_str());
add_mhd_last_modified (r, fs.st_mtime);
if (verbose > 1)
obatched(clog) << "serving fdcache archive " << b_source0 << " file " << b_source1 << endl;
@@ -1678,6 +1684,11 @@ handle_buildid_r_match (bool internal_req_p,
else
{
MHD_add_response_header (r, "Content-Type", "application/octet-stream");
+ std::string file = b_source1.substr(b_source1.find_last_of("/")+1, b_source1.length());
+ MHD_add_response_header (r, "X-FILE-SIZE", to_string(fs.st_size).c_str());
+ MHD_add_response_header (r, "X-ARCHIVE", b_source0.c_str());
+ MHD_add_response_header (r, "X-FILE", file.c_str());
+
add_mhd_last_modified (r, archive_entry_mtime(e));
if (verbose > 1)
obatched(clog) << "serving archive " << b_source0 << " file " << b_source1 << endl;