diff --git a/include/swupd.h b/include/swupd.h index 76f46f51..532ea4ea 100644 --- a/include/swupd.h +++ b/include/swupd.h @@ -91,7 +91,6 @@ struct file { int last_change; struct update_stat stat; - unsigned int fd_valid : 1; unsigned int is_dir : 1; unsigned int is_file : 1; unsigned int is_link : 1; @@ -112,7 +111,7 @@ struct file { char *staging; /* output name used during download & staging */ CURL *curl; /* curl handle if downloading */ - int fd; /* file written into during downloading, unset when fd_valid is false */ + FILE *fh; /* file written into during downloading */ }; extern bool download_only; @@ -232,7 +231,7 @@ extern void swupd_curl_cleanup(void); extern void swupd_curl_set_current_version(int v); extern void swupd_curl_set_requested_version(int v); extern double swupd_query_url_content_size(char *url); -extern size_t swupd_download_file(void *ptr, size_t size, size_t nmemb, void *userdata); +extern CURLcode swupd_download_file_start(struct file *file); extern CURLcode swupd_download_file_complete(CURLcode curl_ret, struct file *file); extern int swupd_curl_get_file(const char *url, char *filename, struct file *file, struct version_container *tmp_version, bool pack); diff --git a/src/curl.c b/src/curl.c index 401b2b43..863c7246 100644 --- a/src/curl.c +++ b/src/curl.c @@ -158,62 +158,28 @@ static size_t swupd_download_version_to_memory(void *ptr, size_t size, size_t nm return data_len; } -/* curl easy CURLOPT_WRITEFUNCTION callback */ -size_t swupd_download_file(void *ptr, size_t size, size_t nmemb, void *userdata) +CURLcode swupd_download_file_start(struct file *file) { - struct file *file = (struct file *)userdata; - const char *outfile; - int fd; - FILE *f; - size_t written, remaining; - - outfile = file->staging; - if (file->fd_valid) { - fd = file->fd; - } else { - fd = open(outfile, O_CREAT | O_RDWR | O_CLOEXEC | O_APPEND, 00600); - if (fd < 0) { - fprintf(stderr, "Cannot open file for write \\*outfile=\"%s\",strerror=\"%s\"*\\\n", - outfile, strerror(errno)); - return -1; - } - file->fd = fd; - file->fd_valid = 1; + file->fh = fopen(file->staging, "w"); + if (!file->fh) { + fprintf(stderr, "Cannot open file for write \\*outfile=\"%s\",strerror=\"%s\"*\\\n", + file->staging, strerror(errno)); + return CURLE_WRITE_ERROR; } - - /* handle short writes with repeated write() calls */ - for (remaining = size * nmemb; remaining; remaining -= written) { - written = write(fd, ptr, size*nmemb); - if (written < 0) { - if (errno == EINTR) { - written = 0; - continue; - } - fprintf(stderr, "write error \\*outfile=\"%s\",strerror=\"%s\"*\\\n", - outfile, strerror(errno)); - return -1; - } - } - - if (fdatasync(fd)) { - fprintf(stderr, "fdatasync \\*outfile=\"%s\",strerror=\"%s\"*\\\n", outfile, strerror(errno)); - return -1; - } - - return size*nmemb; + return CURLE_OK; } CURLcode swupd_download_file_complete(CURLcode curl_ret, struct file *file) { - if (file->fd_valid) { - if (close(file->fd)) { + if (file->fh) { + if (fclose(file->fh)) { fprintf(stderr, "Cannot close file after write \\*outfile=\"%s\",strerror=\"%s\"*\\\n", file->staging, strerror(errno)); if (curl_ret == CURLE_OK) { curl_ret = CURLE_WRITE_ERROR; } } - file->fd_valid = 0; + file->fh = NULL; } return curl_ret; } @@ -246,6 +212,7 @@ int swupd_curl_get_file(const char *url, char *filename, struct file *file, if (file) { local = file; + local->fh = NULL; } else { local = calloc(1, sizeof(struct file)); if (!local) { @@ -266,11 +233,11 @@ 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_WRITEFUNCTION, swupd_download_file); + curl_ret = swupd_download_file_start(local); if (curl_ret != CURLE_OK) { goto exit; } - curl_ret = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)local); + curl_ret = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)local->fh); if (curl_ret != CURLE_OK) { goto exit; } diff --git a/src/download.c b/src/download.c index 0288d9ad..1121bd51 100644 --- a/src/download.c +++ b/src/download.c @@ -525,6 +525,7 @@ void full_download(struct file *file) CURLMcode curlm_ret = CURLM_OK; CURLcode curl_ret = CURLE_OK; + file->fh = NULL; ret = swupd_curl_hashmap_insert(file); if (ret > 0) { /* no download needed */ /* File already exists - report success */ @@ -567,11 +568,11 @@ void full_download(struct file *file) if (curl_ret != CURLE_OK) { goto out_bad; } - curl_ret = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, swupd_download_file); + curl_ret = swupd_download_file_start(file); if (curl_ret != CURLE_OK) { goto out_bad; } - curl_ret = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)file); + curl_ret = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)file->fh); if (curl_ret != CURLE_OK) { goto out_bad; } @@ -597,6 +598,7 @@ void full_download(struct file *file) goto out_good; out_bad: + (void) swupd_download_file_complete(CURLE_OK, file); failed = list_prepend_data(failed, file); if (curl != NULL) { /* Must remove handle out of multi queue first!*/