47#include <openssl/sha.h>
49#include "xbps_api_impl.h"
67 strftime(buf,
sizeof(buf),
"%d %b %Y %H:%M", &tm);
72xbps_fetch_set_cache_connection(
int global,
int per_host)
75 global = XBPS_FETCH_CACHECONN;
77 per_host = XBPS_FETCH_CACHECONN_HOST;
79 fetchConnectionCacheInit(global, per_host);
83xbps_fetch_unset_cache_connection(
void)
85 fetchConnectionCacheClose();
91 if (fetchLastErrCode == 0 || fetchLastErrCode == FETCH_OK)
94 return fetchLastErrString;
100 struct stat st, st_tmpfile, *stp;
101 struct url *url = NULL;
102 struct url_stat url_st;
103 struct fetchIO *fio = NULL;
104 struct timespec ts[2];
105 off_t bytes_dload = 0;
106 ssize_t bytes_read = 0, bytes_written = 0;
107 char buf[4096], *tempfile = NULL;
110 bool refetch =
false, restart =
false;
116 if (digest != NULL) {
117 assert(digestlen >= XBPS_SHA256_DIGEST_SIZE);
118 if (digestlen < XBPS_SHA256_DIGEST_SIZE) {
122 SHA256_Init(&sha256);
126 fetchLastErrCode = 0;
128 if (!filename || (url = fetchParseURL(uri)) == NULL)
131 memset(&fetch_flags, 0,
sizeof(fetch_flags));
139 memset(&st_tmpfile, 0,
sizeof(st_tmpfile));
140 if (stat(tempfile, &st_tmpfile) == 0) {
141 if (st_tmpfile.st_size > 0)
144 if (errno != ENOENT) {
152 memset(&st, 0,
sizeof(st));
153 if (stat(filename, &st) == 0) {
155 url->last_modified = st.st_mtime;
158 if (errno != ENOENT) {
163 if (refetch && !restart) {
169 url->offset = stp->st_size;
174 fio = fetchXGet(url, &url_st, fetch_flags);
177 xbps_dbg_printf(
"st.st_size: %zd\n", (ssize_t)stp->st_size);
178 xbps_dbg_printf(
"st.st_atime: %s\n", print_time(&stp->st_atime));
179 xbps_dbg_printf(
"st.st_mtime: %s\n", print_time(&stp->st_mtime));
180 xbps_dbg_printf(
"url_stat.size: %zd\n", (ssize_t)url_st.size);
181 xbps_dbg_printf(
"url_stat.atime: %s\n", print_time(&url_st.atime));
182 xbps_dbg_printf(
"url_stat.mtime: %s\n", print_time(&url_st.mtime));
185 if (fetchLastErrCode == FETCH_UNCHANGED) {
188 }
else if (fetchLastErrCode == FETCH_PROTO && url_st.size == stp->st_size) {
195 if (url_st.size == -1) {
196 xbps_dbg_printf(
"Remote file size is unknown, resume "
197 "not possible...\n");
199 }
else if (stp->st_size > url_st.size) {
204 xbps_dbg_printf(
"Local file %s is greater than remote, "
205 "removing local file and refetching...\n", filename);
206 (void)remove(tempfile);
209 xbps_dbg_printf(
"url->scheme: %s\n", url->scheme);
210 xbps_dbg_printf(
"url->host: %s\n", url->host);
211 xbps_dbg_printf(
"url->port: %d\n", url->port);
212 xbps_dbg_printf(
"url->doc: %s\n", url->doc);
213 xbps_dbg_printf(
"url->offset: %zd\n", (ssize_t)url->offset);
214 xbps_dbg_printf(
"url->length: %zu\n", url->length);
215 xbps_dbg_printf(
"url->last_modified: %s\n",
216 print_time(&url->last_modified));
221 fd = open(tempfile, O_RDWR|O_CLOEXEC);
223 fd = open(tempfile, O_WRONLY|O_CREAT|O_CLOEXEC|O_TRUNC, 0644);
236 while ((bytes_read = read(fd, buf,
sizeof(buf))) > 0) {
237 SHA256_Update(&sha256, buf, bytes_read);
239 if (bytes_read == -1) {
240 xbps_dbg_printf(
"IO error while reading %s: %s\n",
241 tempfile, strerror(errno));
247 lseek(fd, 0, SEEK_END);
255 xbps_set_cb_fetch(xhp, url_st.size, url->offset, url->offset,
256 filename,
true,
false,
false);
260 while ((bytes_read = fetchIO_read(fio, buf,
sizeof(buf))) > 0) {
262 SHA256_Update(&sha256, buf, bytes_read);
263 bytes_written = write(fd, buf, (
size_t)bytes_read);
264 if (bytes_written != bytes_read) {
265 xbps_dbg_printf(
"Couldn't write to %s!\n", tempfile);
269 bytes_dload += bytes_read;
274 xbps_set_cb_fetch(xhp, url_st.size, url->offset,
275 url->offset + bytes_dload,
276 filename,
false,
true,
false);
278 if (bytes_read == -1) {
279 xbps_dbg_printf(
"IO error while fetching %s: %s\n",
280 filename, fetchLastErrString);
284 }
else if (url_st.size > 0 && ((bytes_dload + url->offset) != url_st.size)) {
285 xbps_dbg_printf(
"file %s is truncated\n", filename);
295 xbps_set_cb_fetch(xhp, url_st.size, url->offset, bytes_dload,
296 filename,
false,
false,
true);
302 ts[0].tv_sec = url_st.atime ? url_st.atime : url_st.mtime;
303 ts[1].tv_sec = url_st.mtime;
304 ts[0].tv_nsec = ts[1].tv_nsec = 0;
305 if (futimens(fd, ts) == -1) {
314 if (rename(tempfile, filename) == -1) {
315 xbps_dbg_printf(
"failed to rename %s to %s: %s",
316 tempfile, filename, strerror(errno));
323 SHA256_Final(digest, &sha256);
340 const char *filename,
const char *flags)
347 const char *flags,
unsigned char *digest,
size_t digestlen)
349 const char *filename;
353 if ((filename = strrchr(uri,
'/')) == NULL)
int xbps_fetch_file_sha256(struct xbps_handle *xhp, const char *uri, const char *flags, unsigned char *digest, size_t digestlen)
const char * xbps_fetch_error_string(void)
int xbps_fetch_file_dest(struct xbps_handle *xhp, const char *uri, const char *filename, const char *flags)
int xbps_fetch_file(struct xbps_handle *xhp, const char *uri, const char *flags)
int xbps_fetch_file_dest_sha256(struct xbps_handle *xhp, const char *uri, const char *filename, const char *flags, unsigned char *digest, size_t digestlen)
Generic XBPS structure handler for initialization.
char * xbps_xasprintf(const char *fmt,...) __attribute__((format(printf
size_t xbps_strlcpy(char *dst, const char *src, size_t dstsize)
size_t xbps_strlcat(char *dst, const char *src, size_t dstsize)