summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@redhat.com>2021-09-22 16:13:03 -0400
committerFrank Ch. Eigler <fche@redhat.com>2021-09-22 16:13:03 -0400
commite849e408ee31f412502c2eb078b4700bd1e39e60 (patch)
tree6ca381d6d204a28e68b4338a1427356072aa7a90
parent54280d4e36eb44866a3396dd5d75b226b3b276b1 (diff)
downloadelfutils-nsanci/pr28284-webapi.tar.gz
C API interfacensanci/pr28284-webapi
-rw-r--r--debuginfod/debuginfod-client.c105
-rw-r--r--debuginfod/debuginfod.h.in22
-rw-r--r--debuginfod/libdebuginfod.map5
3 files changed, 109 insertions, 23 deletions
diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c
index 88e45567..b94b9209 100644
--- a/debuginfod/debuginfod-client.c
+++ b/debuginfod/debuginfod-client.c
@@ -127,7 +127,6 @@ 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
@@ -187,6 +186,10 @@ struct handle_data
/* Response http headers for this client handle, sent from the server */
char *response_data;
size_t response_data_size;
+
+ /* synonymous with 'describe', but used in the context of the
+ * http response. */
+ char head_request;
};
static size_t
@@ -504,8 +507,7 @@ default_progressfn (debuginfod_client *c, long a, long b)
/* This is a callback function that receives http response headers in buffer for use
* in this program. https://curl.se/libcurl/c/CURLOPT_HEADERFUNCTION.html is the
- * online documentation.
- */
+ * online documentation. */
static size_t
header_callback (char * buffer, size_t size, size_t numitems, void * userdata)
{
@@ -514,6 +516,22 @@ header_callback (char * buffer, size_t size, size_t numitems, void * userdata)
/* Temporary buffer for realloc */
char *temp = NULL;
struct handle_data *data = (struct handle_data *) userdata;
+ curl_off_t resp;
+ curl_easy_getinfo(data->handle, CURLINFO_RESPONSE_CODE, &resp);
+ if (*data->target_handle == NULL &&
+ (resp == 200 || resp == 406) &&
+ data->head_request)
+ {
+ *data->target_handle = data->handle;
+ /* update the client object */
+ const char *url = NULL;
+ (void) curl_easy_getinfo (data->handle, CURLINFO_EFFECTIVE_URL, &url);
+ if (url)
+ {
+ free (data->client->url);
+ data->client->url = strdup(url); /* ok if fails */
+ }
+ }
if (data->response_data == NULL)
{
temp = malloc(numitems+1);
@@ -544,6 +562,7 @@ debuginfod_query_server (debuginfod_client *c,
const unsigned char *build_id,
int build_id_len,
const char *type,
+ const char describe,
const char *filename,
char **path)
{
@@ -972,6 +991,11 @@ debuginfod_query_server (debuginfod_client *c,
snprintf(data[i].url, PATH_MAX, "%s/%s/%s", server_url, build_id_bytes, type);
if (vfd >= 0)
dprintf (vfd, "url %d %s\n", i, data[i].url);
+ data[i].head_request = describe;
+ /* PR28284 when describing simply send HEAD request
+ * (done with CURLOPT_NOBODY) */
+ if (describe)
+ curl_easy_setopt(data[i].handle, CURLOPT_NOBODY, 1);
curl_easy_setopt(data[i].handle, CURLOPT_URL, data[i].url);
if (vfd >= 0)
@@ -1017,10 +1041,11 @@ debuginfod_query_server (debuginfod_client *c,
int still_running;
long loops = 0;
int committed_to = -1;
+ char *committed_response = NULL;
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)
+
+ if (maxtime > 0 && clock_gettime(CLOCK_MONOTONIC_RAW, &start_time) == -1)
{
rc = errno;
goto out2;
@@ -1057,16 +1082,18 @@ debuginfod_query_server (debuginfod_client *c,
else
{
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 (committed_response == NULL)
+ {
+ committed_response = data[i].response_data;
+ /* PR28284 if verbose or describing and winning headers exist
+ * print them. */
+ if ((vfd >= 0 || describe) && committed_response != NULL)
+ dprintf(vfd, "%s\n", committed_response);
+ data[i].response_data = NULL;
}
-
}
- }
+
+ }
if (vfd >= 0 && !verbose_reported && committed_to >= 0)
{
@@ -1077,7 +1104,7 @@ debuginfod_query_server (debuginfod_client *c,
c->default_progressfn_printed_p = 0;
verbose_reported = true;
}
-
+
if (curlm_res != CURLM_OK)
{
switch (curlm_res)
@@ -1309,8 +1336,6 @@ debuginfod_query_server (debuginfod_client *c,
curl_easy_cleanup (data[i].handle);
free(data[i].response_data);
}
- free(c->winning_headers);
- c->winning_headers = NULL;
goto query_in_parallel;
}
else
@@ -1347,7 +1372,12 @@ debuginfod_query_server (debuginfod_client *c,
goto out2;
/* Perhaps we need not give up right away; could retry or something ... */
}
-
+ if (describe)
+ {
+ xalloc_str(*path,
+ "X-DEBUGINFOD-URL: %s\n%s", c->url ?: "", committed_response);
+ // XXX: xalloc_str is wrong here (wrong goto out;)
+ }
/* remove all handles from multi */
for (int i = 0; i < num_urls; i++)
{
@@ -1364,7 +1394,7 @@ debuginfod_query_server (debuginfod_client *c,
/* don't close fd - we're returning it */
/* don't unlink the tmppath; it's already been renamed. */
- if (path != NULL)
+ if (path != NULL && !describe)
*path = strdup(target_cache_path);
rc = fd;
@@ -1407,7 +1437,7 @@ debuginfod_query_server (debuginfod_client *c,
if (c->default_progressfn_printed_p)
dprintf(STDERR_FILENO, "\n");
- if (vfd >= 0)
+ if (vfd >= 0 && !describe)
{
if (rc < 0)
dprintf (vfd, "not found %s (err=%d)\n", strerror (-rc), rc);
@@ -1489,7 +1519,6 @@ 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);
}
@@ -1500,7 +1529,7 @@ debuginfod_find_debuginfo (debuginfod_client *client,
char **path)
{
return debuginfod_query_server(client, build_id, build_id_len,
- "debuginfo", NULL, path);
+ "debuginfo", 0, NULL, path);
}
@@ -1511,7 +1540,7 @@ debuginfod_find_executable(debuginfod_client *client,
char **path)
{
return debuginfod_query_server(client, build_id, build_id_len,
- "executable", NULL, path);
+ "executable", 0, NULL, path);
}
/* See debuginfod.h */
@@ -1520,9 +1549,39 @@ int debuginfod_find_source(debuginfod_client *client,
const char *filename, char **path)
{
return debuginfod_query_server(client, build_id, build_id_len,
- "source", filename, path);
+ "source", 0, filename, path);
}
+/* See debuginfod.h */
+int
+debuginfod_describe_debuginfo (debuginfod_client *client,
+ const unsigned char *build_id, int build_id_len,
+ char **header)
+{
+ return debuginfod_query_server(client, build_id, build_id_len,
+ "debuginfo", 1, NULL, header);
+}
+
+
+/* See debuginfod.h */
+int
+debuginfod_describe_executable(debuginfod_client *client,
+ const unsigned char *build_id, int build_id_len,
+ char **header)
+{
+ return debuginfod_query_server(client, build_id, build_id_len,
+ "executable", 1, NULL, header);
+}
+
+/* See debuginfod.h */
+int
+debuginfod_describe_source(debuginfod_client *client,
+ const unsigned char *build_id, int build_id_len,
+ const char *filename, char **header)
+{
+ return debuginfod_query_server(client, build_id, build_id_len,
+ "source", 1, filename, header);
+}
/* Add an outgoing HTTP header. */
int debuginfod_add_http_header (debuginfod_client *client, const char* header)
diff --git a/debuginfod/debuginfod.h.in b/debuginfod/debuginfod.h.in
index c358df4d..50240c4b 100644
--- a/debuginfod/debuginfod.h.in
+++ b/debuginfod/debuginfod.h.in
@@ -78,6 +78,28 @@ int debuginfod_find_source (debuginfod_client *client,
const char *filename,
char **path);
+/* The _describe_ variants of the query functions return a set of HTTP-like
+ headers that would result from a new lookup. No content is collected.
+ If successful, return zero, otherwise return a posix error code. If
+ successful, set *headers a strdup()'d copy of the headers.
+ Caller must free() it later. */
+
+int debuginfod_describe_debuginfo (debuginfod_client *client,
+ const unsigned char *build_id,
+ int build_id_len,
+ char **headers);
+
+int debuginfod_describe_executable (debuginfod_client *client,
+ const unsigned char *build_id,
+ int build_id_len,
+ char **headers);
+
+int debuginfod_describe_source (debuginfod_client *client,
+ const unsigned char *build_id,
+ int build_id_len,
+ const char *filename,
+ char **headers);
+
typedef int (*debuginfod_progressfn_t)(debuginfod_client *c, long a, long b);
void debuginfod_set_progressfn(debuginfod_client *c,
debuginfod_progressfn_t fn);
diff --git a/debuginfod/libdebuginfod.map b/debuginfod/libdebuginfod.map
index 7d2f5882..480f7bf8 100644
--- a/debuginfod/libdebuginfod.map
+++ b/debuginfod/libdebuginfod.map
@@ -18,3 +18,8 @@ ELFUTILS_0.179 {
ELFUTILS_0.183 {
debuginfod_set_verbose_fd;
} ELFUTILS_0.179;
+ELFUTILS_0.186 {
+ debuginfod_describe_debuginfo;
+ debuginfod_describe_executable;
+ debuginfod_describe_source;
+} ELFUTILS_0.183;