aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-core/swupd-client/swupd-client/0002-downloads-open-FILE-in-advance-and-use-default-write.patch
blob: 4d8339ac9bc8e8340cdeb5f947a07a3d1c771bfc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
From 26c603ad25469d3e37fc00b78ad161b34093f5fa Mon Sep 17 00:00:00 2001
From: Patrick Ohly <patrick.ohly@intel.com>
Date: Tue, 15 Nov 2016 15:01:38 +0100
Subject: [PATCH 2/3] 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>
---
 include/swupd.h |  5 ++---
 src/curl.c      | 59 +++++++++++++--------------------------------------------
 src/download.c  |  6 ++++--
 3 files changed, 19 insertions(+), 51 deletions(-)

diff --git a/include/swupd.h b/include/swupd.h
index 3bac8b2..ed4b82c 100644
--- a/include/swupd.h
+++ b/include/swupd.h
@@ -89,7 +89,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;
@@ -110,7 +109,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;
@@ -200,7 +199,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 cab1ef2..009fdd5 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;
-	}
-
-	/* 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;
-		}
+	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;
 	}
-
-	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 c4a7a07..397d56c 100644
--- a/src/download.c
+++ b/src/download.c
@@ -475,6 +475,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 */
@@ -510,11 +511,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;
 	}
@@ -536,6 +537,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!*/
-- 
2.1.4