mirror of
https://github.com/clearlinux/swupd-client.git
synced 2026-10-03 23:38:25 +00:00
downloads: open FILE in advance and use default write handler
Now that the number of pending downloads is kept below a certain limit (see poll_fewer_than()) it is possible to open files before starting the transfer. Using the default curl write handler and explicit open/close of the file makes the code simpler. Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
This commit is contained in:
+2
-3
@@ -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);
|
||||
|
||||
+13
-46
@@ -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;
|
||||
}
|
||||
|
||||
+4
-2
@@ -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!*/
|
||||
|
||||
Reference in New Issue
Block a user