diff --git a/Makefile.am b/Makefile.am index 30145e07..38c93a82 100644 --- a/Makefile.am +++ b/Makefile.am @@ -152,6 +152,7 @@ dist_check_SCRIPTS = \ test/functional/checkupdate/new-version/test.bats \ test/functional/checkupdate/no-server-content/test.bats \ test/functional/checkupdate/no-target-content/test.bats \ + test/functional/checkupdate/slow-server/test.bats \ test/functional/checkupdate/version-match/test.bats \ test/functional/hashdump/file-hash/test.bats \ test/functional/hashdump/file-hash-no-path-prefix/test.bats \ diff --git a/src/curl.c b/src/curl.c index 5a54133d..1103e324 100644 --- a/src/curl.c +++ b/src/curl.c @@ -51,6 +51,11 @@ static CURL *curl = NULL; static int curr_version = -1; static int req_version = -1; +struct version_container { + size_t offset; + char *version; +}; + int swupd_curl_init(void) { CURLcode curl_ret; @@ -143,15 +148,16 @@ double swupd_query_url_content_size(char *url) static size_t swupd_download_version_to_memory(void *ptr, size_t size, size_t nmemb, void *userdata) { - char *tmp_version = (char *)userdata; + struct version_container *tmp_version = (struct version_container *)userdata; size_t data_len = size * nmemb; - if (data_len >= LINE_MAX) { + if (data_len + tmp_version->offset >= LINE_MAX) { return 0; } - memcpy(tmp_version, ptr, data_len); - tmp_version[data_len] = '\0'; + memcpy(tmp_version->version + tmp_version->offset, ptr, data_len); + tmp_version->version[data_len + tmp_version->offset] = '\0'; + tmp_version->offset += data_len; return data_len; } @@ -251,6 +257,9 @@ int swupd_curl_get_file(const char *url, char *filename, struct file *file, goto exit; } } else { + struct version_container vc = { 0 }; + vc.version = in_memory_version_string; + // only download latest version number, storing in the provided pointer printf("Attempting to download version string to memory\n"); @@ -258,7 +267,7 @@ int swupd_curl_get_file(const char *url, char *filename, struct file *file, if (curl_ret != CURLE_OK) { goto exit; } - curl_ret = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)in_memory_version_string); + curl_ret = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&vc); if (curl_ret != CURLE_OK) { goto exit; } diff --git a/src/version.c b/src/version.c index 090be2e6..23a5eab1 100644 --- a/src/version.c +++ b/src/version.c @@ -41,7 +41,7 @@ int get_latest_version(void) int ret = 0; char *tmp_version; - tmp_version = malloc(LINE_MAX); + tmp_version = calloc(LINE_MAX, 1); if (tmp_version == NULL) { abort(); } diff --git a/test/functional/checkupdate/slow-server/server.py b/test/functional/checkupdate/slow-server/server.py new file mode 100755 index 00000000..89234c0a --- /dev/null +++ b/test/functional/checkupdate/slow-server/server.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +import http.server as server +import sys +import time + + +class SlowResponse(server.BaseHTTPRequestHandler): + """Handler that returns data with a set delay between writes""" + def do_GET(self): + self.send_response(200) + self.send_header("Content-type", "text/html") + self.end_headers() + response = "99990" + delay = 0.00001 # seconds + for c in response: + self.wfile.write(str.encode(c)) + time.sleep(delay) + + +if __name__ == '__main__': + print(sys.argv) + addr = ('', int(sys.argv[1])) + httpd = server.HTTPServer(addr, SlowResponse) + httpd.serve_forever() diff --git a/test/functional/checkupdate/slow-server/target-dir/usr/lib/os-release b/test/functional/checkupdate/slow-server/target-dir/usr/lib/os-release new file mode 100644 index 00000000..d20f3873 --- /dev/null +++ b/test/functional/checkupdate/slow-server/target-dir/usr/lib/os-release @@ -0,0 +1,9 @@ +NAME="Clear Linux Software for Intel Architecture" +VERSION=1 +ID=clear-linux-os +VERSION_ID=10 +PRETTY_NAME="Clear Linux Software for Intel Architecture" +ANSI_COLOR="1;35" +HOME_URL="https://clearlinux.org" +SUPPORT_URL="https://clearlinux.org" +BUG_REPORT_URL="https://bugs.clearlinux.org/jira" diff --git a/test/functional/checkupdate/slow-server/test.bats b/test/functional/checkupdate/slow-server/test.bats new file mode 100755 index 00000000..a81fb2f0 --- /dev/null +++ b/test/functional/checkupdate/slow-server/test.bats @@ -0,0 +1,34 @@ +#!/usr/bin/env bats + +load "../../swupdlib" + +server_pid="" +port="" + +setup() { + for i in $(seq 8080 8180); do + "$DIR/server.py" $i & + sleep .2 + server_pid=$! + if [ -d /proc/$server_pid ]; then + port=$i + break + fi + done +} + +teardown() { + kill $server_pid +} + +@test "check-update with a slow server" { + slow_opts="-p $DIR/target-dir -F staging -u http://localhost:$port/" + run sudo sh -c "$SWUPD check-update $slow_opts" + + echo "$output" + [ "${lines[2]}" = "Querying server version." ] + [ "${lines[3]}" = "Attempting to download version string to memory" ] + [ "${lines[4]}" = "There is a new OS version available: 99990" ] +} + +# vi: ft=sh ts=8 sw=2 sts=2 et tw=80