int pkg_fetch_file_to_fd(const char *url, int dest, time_t t) { FILE *remote = NULL; struct url *u; struct url_stat st; off_t done = 0; off_t r; int64_t max_retry, retry; time_t begin_dl; time_t now; time_t last = 0; char buf[10240]; char *doc; char docpath[MAXPATHLEN]; int retcode = EPKG_OK; bool srv = false; bool http = false; char zone[MAXHOSTNAMELEN + 13]; struct dns_srvinfo *srv_current = NULL; struct http_mirror *http_current = NULL; const char *mt; fetchTimeout = 30; if (pkg_config_int64(PKG_CONFIG_FETCH_RETRY, &max_retry) == EPKG_FATAL) max_retry = 3; retry = max_retry; u = fetchParseURL(url); doc = u->doc; while (remote == NULL) { if (retry == max_retry) { pkg_config_string(PKG_CONFIG_MIRRORS, &mt); if (mt != NULL && strncasecmp(mt, "srv", 3) == 0 && \ strcmp(u->scheme, "file") != 0) { srv = true; snprintf(zone, sizeof(zone), "_%s._tcp.%s", u->scheme, u->host); pthread_mutex_lock(&mirror_mtx); if (srv_mirrors != NULL) srv_mirrors = dns_getsrvinfo(zone); pthread_mutex_unlock(&mirror_mtx); srv_current = srv_mirrors; } else if (mt != NULL && strncasecmp(mt, "http", 4) == 0 && \ strcmp(u->scheme, "file") != 0 && \ strcmp(u->scheme, "ftp") != 0) { http = true; snprintf(zone, sizeof(zone), "%s://%s", u->scheme, u->host); pthread_mutex_lock(&mirror_mtx); if (STAILQ_EMPTY(&http_mirrors)) gethttpmirrors(zone); pthread_mutex_unlock(&mirror_mtx); http_current = STAILQ_FIRST(&http_mirrors); } } if (srv && srv_mirrors != NULL) strlcpy(u->host, srv_current->host, sizeof(u->host)); else if (http && !STAILQ_EMPTY(&http_mirrors)) { strlcpy(u->scheme, http_current->url->scheme, sizeof(u->scheme)); strlcpy(u->host, http_current->url->host, sizeof(u->host)); snprintf(docpath, MAXPATHLEN, "%s%s", http_current->url->doc, doc); u->doc = docpath; u->port = http_current->url->port; } remote = fetchXGet(u, &st, ""); if (remote == NULL) { --retry; if (retry <= 0) { pkg_emit_error("%s: %s", url, fetchLastErrString); retcode = EPKG_FATAL; goto cleanup; } if (srv && srv_mirrors != NULL) { srv_current = srv_current->next; if (srv_current == NULL) srv_current = srv_mirrors; } else if (http && !STAILQ_EMPTY(&http_mirrors)) { http_current = STAILQ_NEXT(http_current, next); if (http_current == NULL) http_current = STAILQ_FIRST(&http_mirrors); } else { sleep(1); } } } if (t != 0) { if (st.mtime <= t) { retcode = EPKG_UPTODATE; goto cleanup; } } begin_dl = time(NULL); while (done < st.size) { if ((r = fread(buf, 1, sizeof(buf), remote)) < 1) break; if (write(dest, buf, r) != r) { pkg_emit_errno("write", ""); retcode = EPKG_FATAL; goto cleanup; } done += r; now = time(NULL); /* Only call the callback every second */ if (now > last || done == st.size) { pkg_emit_fetching(url, st.size, done, (now - begin_dl)); last = now; } } if (ferror(remote)) { pkg_emit_error("%s: %s", url, fetchLastErrString); retcode = EPKG_FATAL; goto cleanup; } cleanup: if (remote != NULL) fclose(remote); /* restore original doc */ u->doc = doc; fetchFreeURL(u); return (retcode); }
int pkg_fetch_file_to_fd(const char *url, int dest, time_t t) { FILE *remote = NULL; struct url *u; struct url_stat st; off_t done = 0; off_t r; int64_t max_retry, retry; time_t begin_dl; time_t now; time_t last = 0; char buf[10240]; int retcode = EPKG_OK; bool srv = false; char zone[MAXHOSTNAMELEN + 12]; struct dns_srvinfo *mirrors, *current; current = mirrors = NULL; fetchTimeout = 30; if (pkg_config_int64(PKG_CONFIG_FETCH_RETRY, &max_retry) == EPKG_FATAL) max_retry = 3; retry = max_retry; u = fetchParseURL(url); while (remote == NULL) { if (retry == max_retry) { pkg_config_bool(PKG_CONFIG_SRV_MIRROR, &srv); if (srv) { if (strcmp(u->scheme, "file") != 0) { snprintf(zone, sizeof(zone), "_%s._tcp.%s", u->scheme, u->host); mirrors = dns_getsrvinfo(zone); current = mirrors; } } } if (mirrors != NULL) strlcpy(u->host, current->host, sizeof(u->host)); remote = fetchXGet(u, &st, ""); if (remote == NULL) { --retry; if (retry <= 0) { pkg_emit_error("%s: %s", url, fetchLastErrString); retcode = EPKG_FATAL; goto cleanup; } if (mirrors == NULL) { sleep(1); } else { current = current->next; if (current == NULL) current = mirrors; } } } if (t != 0) { if (st.mtime <= t) { retcode = EPKG_UPTODATE; goto cleanup; } } begin_dl = time(NULL); while (done < st.size) { if ((r = fread(buf, 1, sizeof(buf), remote)) < 1) break; if (write(dest, buf, r) != r) { pkg_emit_errno("write", ""); retcode = EPKG_FATAL; goto cleanup; } done += r; now = time(NULL); /* Only call the callback every second */ if (now > last || done == st.size) { pkg_emit_fetching(url, st.size, done, (now - begin_dl)); last = now; } } if (ferror(remote)) { pkg_emit_error("%s: %s", url, fetchLastErrString); retcode = EPKG_FATAL; goto cleanup; } cleanup: if (remote != NULL) fclose(remote); fetchFreeURL(u); return (retcode); }