diff options
author | Frank Ch. Eigler <fche@redhat.com> | 2021-09-22 16:13:03 -0400 |
---|---|---|
committer | Frank Ch. Eigler <fche@redhat.com> | 2021-09-22 16:13:03 -0400 |
commit | e849e408ee31f412502c2eb078b4700bd1e39e60 (patch) | |
tree | 6ca381d6d204a28e68b4338a1427356072aa7a90 /debuginfod | |
parent | 54280d4e36eb44866a3396dd5d75b226b3b276b1 (diff) | |
download | elfutils-nsanci/pr28284-webapi.tar.gz |
C API interfacensanci/pr28284-webapi
Diffstat (limited to 'debuginfod')
-rw-r--r-- | debuginfod/debuginfod-client.c | 105 | ||||
-rw-r--r-- | debuginfod/debuginfod.h.in | 22 | ||||
-rw-r--r-- | debuginfod/libdebuginfod.map | 5 |
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; |