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(); } }