From 102041d295d0554fa6c2b2d9fd302d9422aa426a Mon Sep 17 00:00:00 2001 From: "Jaime A. Garcia" Date: Wed, 27 Apr 2016 22:27:52 +0000 Subject: [PATCH] fix to check whether resume download is supported When pack is going to be downloaded an option for curl called resume is activated no matter what, however although major http server support 'Range' command that enables this functionality, not all complies with this, when swupd client tries to re-download a partial file from one of the server that does not support 'Range' it will just throw an error and stop to work until partial download is deleted by hand. This patch address that issue by checking first whether server supports 'Range' command and if not then disable 'resume' of packs. Signed-off-by: Jaime A. Garcia --- include/swupd.h | 1 + src/curl.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++- src/version.c | 2 ++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/include/swupd.h b/include/swupd.h index 02c81112..3e1c58ac 100644 --- a/include/swupd.h +++ b/include/swupd.h @@ -198,6 +198,7 @@ extern int swupd_curl_get_file(const char *url, char *filename, struct file *fil #define SWUPD_CURL_CONNECT_TIMEOUT 30 #define SWUPD_CURL_RCV_TIMEOUT 120 extern CURLcode swupd_curl_set_basic_options(CURL *curl, const char *url); +void swupd_curl_test_resume(void); extern struct list *subs; extern void free_subscriptions(void); diff --git a/src/curl.c b/src/curl.c index 1103e324..9d20bbaa 100644 --- a/src/curl.c +++ b/src/curl.c @@ -50,6 +50,7 @@ static CURL *curl = NULL; static int curr_version = -1; static int req_version = -1; +static bool resume_download_enabled = true; struct version_container { size_t offset; @@ -237,7 +238,7 @@ int swupd_curl_get_file(const char *url, char *filename, struct file *file, local->staging = filename; if (lstat(filename, &stat) == 0) { - if (pack) { + if (pack && resume_download_enabled) { curl_ret = curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, (curl_off_t)stat.st_size); } else { unlink(filename); @@ -372,6 +373,62 @@ exit: return err; } +void swupd_curl_test_resume(void) +{ +#define RESUME_BYTE_RANGE 2 + + CURLcode curl_ret; + char *version_string = NULL; + char *url = NULL; + + if (!curl) { + abort(); + } + + curl_easy_reset(curl); + version_string = malloc(LINE_MAX); + if (version_string == NULL) { + abort(); + } + + string_or_die(&url, "%s/version/format%s/latest", version_url, format_string); + + curl_ret = curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, (curl_off_t)RESUME_BYTE_RANGE); + if (curl_ret != CURLE_OK) { + goto exit; + } + + curl_ret = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, swupd_download_version_to_memory); + if (curl_ret != CURLE_OK) { + goto exit; + } + curl_ret = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)version_string); + if (curl_ret != CURLE_OK) { + goto exit; + } + curl_ret = curl_easy_setopt(curl, CURLOPT_COOKIE, "request=uncached"); + if (curl_ret != CURLE_OK) { + goto exit; + } + + curl_ret = swupd_curl_set_basic_options(curl, url); + if (curl_ret != CURLE_OK) { + goto exit; + } + + curl_ret = curl_easy_perform(curl); + + if (curl_ret == CURLE_RANGE_ERROR) { + printf("Range command not supported by server, download resume disabled.\n"); + resume_download_enabled = false; + } +exit: + free(version_string); + free(url); + + return; +} + static CURLcode swupd_curl_set_security_opts(CURL *curl) { CURLcode curl_ret = CURLE_OK; diff --git a/src/version.c b/src/version.c index 23a5eab1..103440a5 100644 --- a/src/version.c +++ b/src/version.c @@ -76,6 +76,8 @@ bool check_network(void) have_network = false; } else { have_network = true; + /* check if server supports Range command (resume) */ + swupd_curl_test_resume(); } }