int pkg_repo_fetch(struct pkg *pkg) { char dest[MAXPATHLEN + 1]; char url[MAXPATHLEN + 1]; int fetched = 0; char cksum[SHA256_DIGEST_LENGTH * 2 +1]; char *path = NULL; const char *packagesite = NULL; const char *cachedir = NULL; bool multirepos_enabled = false; int retcode = EPKG_OK; const char *repopath, *repourl, *sum, *name, *version; assert((pkg->type & PKG_REMOTE) == PKG_REMOTE); if (pkg_config_string(PKG_CONFIG_CACHEDIR, &cachedir) != EPKG_OK) return (EPKG_FATAL); pkg_get(pkg, PKG_REPOPATH, &repopath, PKG_REPOURL, &repourl, PKG_CKSUM, &sum, PKG_NAME, &name, PKG_VERSION, &version); snprintf(dest, sizeof(dest), "%s/%s", cachedir, repopath); /* If it is already in the local cachedir, dont bother to * download it */ if (access(dest, F_OK) == 0) goto checksum; /* Create the dirs in cachedir */ if ((path = dirname(dest)) == NULL) { pkg_emit_errno("dirname", dest); retcode = EPKG_FATAL; goto cleanup; } if ((retcode = mkdirs(path)) != EPKG_OK) goto cleanup; /* * In multi-repos the remote URL is stored in pkg[PKG_REPOURL] * For a single attached database the repository URL should be * defined by PACKAGESITE. */ pkg_config_bool(PKG_CONFIG_MULTIREPOS, &multirepos_enabled); if (multirepos_enabled) { packagesite = repourl; } else { pkg_config_string(PKG_CONFIG_REPO, &packagesite); } if (packagesite == NULL || packagesite[0] == '\0') { pkg_emit_error("PACKAGESITE is not defined"); retcode = 1; goto cleanup; } if (packagesite[strlen(packagesite) - 1] == '/') snprintf(url, sizeof(url), "%s%s", packagesite, repopath); else snprintf(url, sizeof(url), "%s/%s", packagesite, repopath); retcode = pkg_fetch_file(url, dest, 0); fetched = 1; if (retcode != EPKG_OK) goto cleanup; checksum: retcode = sha256_file(dest, cksum); if (retcode == EPKG_OK) if (strcmp(cksum, sum)) { if (fetched == 1) { pkg_emit_error("%s-%s failed checksum " "from repository", name, version); retcode = EPKG_FATAL; } else { pkg_emit_error("cached package %s-%s: " "checksum mismatch, fetching from remote", name, version); unlink(dest); return (pkg_repo_fetch(pkg)); } } cleanup: if (retcode != EPKG_OK) unlink(dest); return (retcode); }
int pkg_repo_fetch(struct pkg *pkg) { char dest[MAXPATHLEN + 1]; char url[MAXPATHLEN + 1]; int fetched = 0; char cksum[SHA256_DIGEST_LENGTH * 2 +1]; char *path = NULL; const char *packagesite = NULL; int retcode = EPKG_OK; assert((pkg->type & PKG_REMOTE) == PKG_REMOTE); if ((packagesite = pkg_config("PACKAGESITE")) == NULL) { pkg_emit_error("pkg_repo_fetch(): %s", "PACKAGESITE is not defined"); return (EPKG_FATAL); } snprintf(dest, sizeof(dest), "%s/%s", pkg_config("PKG_CACHEDIR"), pkg_get(pkg, PKG_REPOPATH)); /* If it is already in the local cachedir, dont bother to download it */ if (access(dest, F_OK) == 0) goto checksum; /* Create the dirs in cachedir */ if ((path = dirname(dest)) == NULL) { pkg_emit_errno("dirname", dest); retcode = EPKG_FATAL; goto cleanup; } if ((retcode = mkdirs(path)) != 0) goto cleanup; if (packagesite[strlen(packagesite) - 1] == '/') snprintf(url, sizeof(url), "%s%s", packagesite, pkg_get(pkg, PKG_REPOPATH)); else snprintf(url, sizeof(url), "%s/%s", packagesite, pkg_get(pkg, PKG_REPOPATH)); retcode = pkg_fetch_file(url, dest); fetched = 1; if (retcode != EPKG_OK) goto cleanup; checksum: retcode = sha256_file(dest, cksum); if (retcode == EPKG_OK) if (strcmp(cksum, pkg_get(pkg, PKG_CKSUM))) { if (fetched == 1) { pkg_emit_error("%s-%s failed checksum from repository", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION)); retcode = EPKG_FATAL; } else { pkg_emit_error("cached package %s-%s: checksum mismatch, fetching from remote", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION)); unlink(dest); return (pkg_repo_fetch(pkg)); } } cleanup: if (retcode != EPKG_OK) unlink(dest); return (retcode); }