33 #include <sys/param.h>
34 #include <sys/types.h>
43 #include "xbps_api_impl.h"
60 strftime(buf,
sizeof(buf),
"%d %b %Y %H:%M", &tm);
65 xbps_fetch_set_cache_connection(
int global,
int per_host)
68 global = XBPS_FETCH_CACHECONN;
70 per_host = XBPS_FETCH_CACHECONN_HOST;
72 fetchConnectionCacheInit(global, per_host);
76 xbps_fetch_unset_cache_connection(
void)
78 fetchConnectionCacheClose();
84 if (fetchLastErrCode == 0 || fetchLastErrCode == FETCH_OK)
87 return fetchLastErrString;
93 struct stat st, st_tmpfile, *stp;
94 struct url *url = NULL;
95 struct url_stat url_st;
96 struct fetchIO *fio = NULL;
97 struct timespec ts[2];
98 off_t bytes_dload = -1;
99 ssize_t bytes_read = -1, bytes_written = -1;
100 char buf[4096], *filename, *tempfile;
102 bool refetch =
false, restart =
false;
108 fetchLastErrCode = 0;
110 fetchRestartCalls = 1;
114 filename = strrchr(uri,
'/') + 1;
115 if (filename == NULL)
122 memset(&st_tmpfile, 0,
sizeof(st_tmpfile));
123 if (stat(tempfile, &st_tmpfile) == 0) {
124 if (st_tmpfile.st_size > 0)
127 if (errno != ENOENT) {
135 memset(&st, 0,
sizeof(st));
136 if (stat(filename, &st) == 0) {
140 if (errno != ENOENT) {
148 if ((url = fetchParseURL(uri)) == NULL) {
161 if ((rv = fetchStat(url, &url_st, NULL)) == -1)
167 if (restart && url_st.size && url_st.mtime &&
168 url_st.size == stp->st_size &&
169 url_st.mtime == stp->st_mtime)
175 if (restart && url_st.size && url_st.size == st.st_size)
186 fio = fetchGet(url, flags);
193 url->offset = stp->st_size;
194 fio = fetchXGet(url, &url_st, flags);
198 xbps_dbg_printf(xhp,
"st.st_size: %zd\n", (ssize_t)stp->st_size);
199 xbps_dbg_printf(xhp,
"st.st_atime: %s\n", print_time(&stp->st_atime));
200 xbps_dbg_printf(xhp,
"st.st_mtime: %s\n", print_time(&stp->st_mtime));
201 xbps_dbg_printf(xhp,
"url->scheme: %s\n", url->scheme);
202 xbps_dbg_printf(xhp,
"url->host: %s\n", url->host);
203 xbps_dbg_printf(xhp,
"url->port: %d\n", url->port);
204 xbps_dbg_printf(xhp,
"url->doc: %s\n", url->doc);
205 xbps_dbg_printf(xhp,
"url->offset: %zd\n", (ssize_t)url->offset);
206 xbps_dbg_printf(xhp,
"url->length: %zu\n", url->length);
207 xbps_dbg_printf(xhp,
"url->last_modified: %s\n",
208 print_time(&url->last_modified));
209 xbps_dbg_printf(xhp,
"url_stat.size: %zd\n", (ssize_t)url_st.size);
210 xbps_dbg_printf(xhp,
"url_stat.atime: %s\n", print_time(&url_st.atime));
211 xbps_dbg_printf(xhp,
"url_stat.mtime: %s\n", print_time(&url_st.mtime));
213 if (fio == NULL && fetchLastErrCode != FETCH_OK) {
214 if (!refetch && restart && fetchLastErrCode == FETCH_UNAVAIL) {
221 if (url->length == 0)
227 if (url_st.size == -1) {
228 xbps_dbg_printf(xhp,
"Remote file size is unknown, resume "
229 "not possible...\n");
231 }
else if (stp->st_size > url_st.size) {
236 xbps_dbg_printf(xhp,
"Local file %s is greater than remote, "
237 "removing local file and refetching...\n", filename);
238 (void)
remove(tempfile);
240 }
else if (restart && url_st.mtime && url_st.size &&
241 url_st.size == stp->st_size &&
242 url_st.mtime == stp->st_mtime) {
250 fd = open(tempfile, O_WRONLY|O_APPEND|O_CLOEXEC);
252 fd = open(tempfile, O_WRONLY|O_CREAT|O_CLOEXEC|O_TRUNC, 0644);
263 xbps_set_cb_fetch(xhp, url_st.size, url->offset, url->offset,
264 filename,
true,
false,
false);
268 while ((bytes_read = fetchIO_read(fio, buf,
sizeof(buf))) > 0) {
269 bytes_written = write(fd, buf, (
size_t)bytes_read);
270 if (bytes_written != bytes_read) {
272 "Couldn't write to %s!\n", tempfile);
276 bytes_dload += bytes_read;
281 xbps_set_cb_fetch(xhp, url_st.size, url->offset,
282 url->offset + bytes_dload,
283 filename,
false,
true,
false);
285 if (bytes_read == -1) {
286 xbps_dbg_printf(xhp,
"IO error while fetching %s: %s\n",
287 filename, fetchLastErrString);
300 xbps_set_cb_fetch(xhp, url_st.size, url->offset, bytes_dload,
301 filename,
false,
false,
true);
306 ts[0].tv_sec = url_st.atime ? url_st.atime : url_st.mtime;
307 ts[1].tv_sec = url_st.mtime;
308 ts[0].tv_nsec = ts[1].tv_nsec = 0;
309 if (futimens(fd, ts) == -1) {
318 if (rename(tempfile, filename) == -1) {
319 xbps_dbg_printf(xhp,
"failed to rename %s to %s: %s",
320 tempfile, filename, strerror(errno));
333 if (tempfile != NULL)