http_get_strbuf and http_get_file allow respectively to retrieve contents of an URL to a strbuf or an opened file handle. Both these functions are the beginning of the http code refactoring. Signed-off-by: Mike Hommey <mh@xxxxxxxxxxxx> --- http.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ http.h | 17 +++++++++++++ 2 files changed, 102 insertions(+), 0 deletions(-) diff --git a/http.c b/http.c index ee58799..82534cf 100644 --- a/http.c +++ b/http.c @@ -638,3 +638,88 @@ int http_fetch_ref(const char *base, struct ref *ref) free(url); return ret; } + +/* http_request() targets */ +#define HTTP_REQUEST_STRBUF 0 +#define HTTP_REQUEST_FILE 1 + +static int http_request(const char *url, void *result, int target, int options) +{ + struct active_request_slot *slot; + struct slot_results results; + struct curl_slist *headers = NULL; + struct strbuf buf = STRBUF_INIT; + + slot = get_active_slot(); + slot->results = &results; + curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); + + if (result == NULL) { + curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1); + } else { + curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0); + curl_easy_setopt(slot->curl, CURLOPT_FILE, result); + + if (target == HTTP_REQUEST_FILE) { + long posn = ftell(result); + curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, + fwrite); + if (posn > 0) { + strbuf_addf(&buf, "Range: bytes=%ld-", posn); + headers = curl_slist_append(headers, buf.buf); + strbuf_reset(&buf); + } + slot->local = result; + } else + curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, + fwrite_buffer); + } + + strbuf_addstr(&buf, "Pragma:"); + if (options & HTTP_NO_CACHE) + strbuf_addstr(&buf, " no-cache"); + + headers = curl_slist_append(headers, buf.buf); + strbuf_release(&buf); + + curl_easy_setopt(slot->curl, CURLOPT_URL, url); + curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers); + + if (start_active_slot(slot)) { + run_active_slot(slot); + if (results.curl_result == CURLE_OK) + return HTTP_OK; + else if (missing_target(&results)) + return HTTP_MISSING_TARGET; + } + return HTTP_ERROR; +} + +int http_get_strbuf(const char *url, struct strbuf *result, int options) +{ + return http_request(url, result, HTTP_REQUEST_STRBUF, options); +} + +int http_get_file(const char *url, const char *filename, int options) +{ + int ret; + struct strbuf tmpfile = STRBUF_INIT; + FILE *result; + + strbuf_addf(&tmpfile, "%s.temp", filename); + result = fopen(tmpfile.buf, "a"); + if (! result) { + error("Unable to open local file %s", tmpfile.buf); + ret = HTTP_ERROR; + goto cleanup; + } + + ret = http_request(url, result, HTTP_REQUEST_FILE, options); + fclose(result); + + if ((ret == HTTP_OK) && move_temp_to_file(tmpfile.buf, filename)) + ret = HTTP_ERROR; +cleanup: + strbuf_release(&tmpfile); + return ret; +} diff --git a/http.h b/http.h index 905b462..323c780 100644 --- a/http.h +++ b/http.h @@ -104,4 +104,21 @@ static inline int missing__target(int code, int result) extern int http_fetch_ref(const char *base, struct ref *ref); +/* Options for http_request_*() */ +#define HTTP_NO_CACHE 1 + +/* Return values for http_request_*() */ +#define HTTP_OK 0 +#define HTTP_MISSING_TARGET 1 +#define HTTP_ERROR 2 + +/* Requests an url and stores the result in a strbuf. + * If the result pointer is NULL, a HTTP HEAD request is made instead of GET. */ +int http_get_strbuf(const char *url, struct strbuf *result, int options); + +/* Downloads an url and stores the result in the given file. + * If a previous interrupted download is detected (i.e. a previous temporary + * file is still around) the download is resumed. */ +int http_get_file(const char *url, const char *filename, int options); + #endif /* HTTP_H */ -- 1.6.1.141.gb32a -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html