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); }
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); }
static int bootstrap_pkg(void) { struct url *u; FILE *remote; FILE *config; char *site; struct dns_srvinfo *mirrors, *current; /* To store _https._tcp. + hostname + \0 */ char zone[MAXHOSTNAMELEN + 13]; char url[MAXPATHLEN]; char conf[MAXPATHLEN]; char tmppkg[MAXPATHLEN]; const char *packagesite, *mirror_type; char buf[10240]; char pkgstatic[MAXPATHLEN]; int fd, retry, ret, max_retry; struct url_stat st; off_t done, r; time_t now; time_t last; done = 0; last = 0; max_retry = 3; ret = -1; remote = NULL; config = NULL; current = mirrors = NULL; printf("Bootstrapping pkg please wait\n"); if (config_string(PACKAGESITE, &packagesite) != 0) { warnx("No PACKAGESITE defined"); return (-1); } if (config_string(MIRROR_TYPE, &mirror_type) != 0) { warnx("No MIRROR_TYPE defined"); return (-1); } snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz", packagesite); snprintf(tmppkg, MAXPATHLEN, "%s/pkg.txz.XXXXXX", getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP); if ((fd = mkstemp(tmppkg)) == -1) { warn("mkstemp()"); return (-1); } retry = max_retry; u = fetchParseURL(url); while (remote == NULL) { if (retry == max_retry) { if (strcmp(u->scheme, "file") != 0 && strcasecmp(mirror_type, "srv") == 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) goto fetchfail; if (mirrors == NULL) { sleep(1); } else { current = current->next; if (current == NULL) current = mirrors; } } } if (remote == NULL) goto fetchfail; while (done < st.size) { if ((r = fread(buf, 1, sizeof(buf), remote)) < 1) break; if (write(fd, buf, r) != r) { warn("write()"); goto cleanup; } done += r; now = time(NULL); if (now > last || done == st.size) last = now; } if (ferror(remote)) goto fetchfail; if ((ret = extract_pkg_static(fd, pkgstatic, MAXPATHLEN)) == 0) ret = install_pkg_static(pkgstatic, tmppkg); snprintf(conf, MAXPATHLEN, "%s/etc/pkg.conf", getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE); if (access(conf, R_OK) == -1) { site = strrchr(url, '/'); if (site == NULL) goto cleanup; site[0] = '\0'; site = strrchr(url, '/'); if (site == NULL) goto cleanup; site[0] = '\0'; config = fopen(conf, "w+"); if (config == NULL) goto cleanup; fprintf(config, "packagesite: %s\n", url); fclose(config); } goto cleanup; fetchfail: warnx("Error fetching %s: %s", url, fetchLastErrString); fprintf(stderr, "A pre-built version of pkg could not be found for your system.\n"); fprintf(stderr, "Consider changing PACKAGESITE or installing it from ports: 'ports-mgmt/pkg'.\n"); cleanup: if (remote != NULL) fclose(remote); close(fd); unlink(tmppkg); return (ret); }