ATF_TC_BODY(check_symlinks, tc) { unsigned char *sum; ATF_REQUIRE_EQ(symlink("foo", "bar"), 0); sum = pkg_checksum_symlink("bar", PKG_HASH_TYPE_SHA256_HEX); ATF_REQUIRE_STREQ(sum, "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"); ATF_CHECK(pkg_checksum_validate_file("bar", "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae") == 0); free(sum); sum = pkg_checksum_generate_file("bar", PKG_HASH_TYPE_SHA256_HEX); ATF_REQUIRE_STREQ(sum, "1$2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"); free(sum); sum = pkg_checksum_generate_file("bar", PKG_HASH_TYPE_BLAKE2_BASE32); ATF_REQUIRE_STREQ(sum, "2$kgygnaah7wxsgn1wkuic4j78zq8dicmx53picmma99ogmkbd7k5nhuxr5xxemz6yzjab15oor3tjt7nupj8mh764y7kddbne7qw9agn"); free(sum); ATF_CHECK(pkg_checksum_validate_file("bar", "2$kgygnaah7wxsgn1wkuic4j78zq8dicmx53picmma99ogmkbd7k5nhuxr5xxemz6yzjab15oor3tjt7nupj8mh764y7kddbne7qw9agn") == 0); ATF_CHECK(pkg_checksum_validate_file("bar", "1$2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae") == 0); }
ATF_TC_BODY(check_files, tc) { FILE *f; unsigned char *sum; f = fopen("foo", "w"); fprintf(f, "bar\n"); fclose(f); sum = pkg_checksum_file("foo", PKG_HASH_TYPE_SHA256_HEX); ATF_REQUIRE_STREQ(sum, "7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730"); ATF_CHECK(pkg_checksum_validate_file("foo", "7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730") == 0); free(sum); sum=pkg_checksum_generate_file("foo", PKG_HASH_TYPE_SHA256_HEX); ATF_REQUIRE_STREQ(sum, "1$7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730"); }
static int pkg_repo_binary_try_fetch(struct pkg_repo *repo, struct pkg *pkg, bool already_tried, bool mirror, const char *destdir) { char dest[MAXPATHLEN]; char url[MAXPATHLEN]; char *dir = NULL; bool fetched = false; struct stat st; char *path = NULL; const char *packagesite = NULL; ssize_t offset = -1; int retcode = EPKG_OK; assert((pkg->type & PKG_REMOTE) == PKG_REMOTE); if (mirror) { const char *cachedir; if (destdir != NULL) cachedir = destdir; else cachedir = pkg_object_string(pkg_config_get("PKG_CACHEDIR")); snprintf(dest, sizeof(dest), "%s/%s", cachedir, pkg->repopath); } else pkg_repo_binary_get_cached_name(repo, pkg, dest, sizeof(dest)); /* If it is already in the local cachedir, dont bother to * download it */ if (stat(dest, &st) == 0) { /* try to resume */ if (pkg->pkgsize > st.st_size) { offset = st.st_size; pkg_debug(1, "Resuming fetch"); } else { goto checksum; } } /* Create the dirs in cachedir */ dir = strdup(dest); if (dir == NULL || (path = dirname(dir)) == 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 URL. */ packagesite = pkg_repo_url(repo); if (packagesite == NULL || packagesite[0] == '\0') { pkg_emit_error("URL is not defined"); retcode = 1; goto cleanup; } if (packagesite[strlen(packagesite) - 1] == '/') pkg_snprintf(url, sizeof(url), "%S%R", packagesite, pkg); else pkg_snprintf(url, sizeof(url), "%S/%R", packagesite, pkg); if (!mirror && strncasecmp(packagesite, "file://", 7) == 0) { free(dir); return (EPKG_OK); } retcode = pkg_fetch_file(repo, url, dest, 0, offset, pkg->pkgsize); fetched = true; if (retcode != EPKG_OK) goto cleanup; checksum: /* checksum calculation is expensive, if size does not match, skip it and assume failed checksum. */ if (stat(dest, &st) == -1 || pkg->pkgsize != st.st_size) { if (already_tried) { pkg_emit_error("cached package %s-%s: " "size mismatch, cannot continue", pkg->name, pkg->version); retcode = EPKG_FATAL; goto cleanup; } unlink(dest); free(dir); pkg_emit_error("cached package %s-%s: " "size mismatch, fetching from remote", pkg->name, pkg->version); return (pkg_repo_binary_try_fetch(repo, pkg, true, mirror, destdir)); } if (pkg_checksum_validate_file(dest, pkg->sum) != 0) { if (already_tried || fetched) { pkg_emit_error("%s-%s failed checksum " "from repository", pkg->name, pkg->version); retcode = EPKG_FATAL; } else { pkg_emit_error("cached package %s-%s: " "checksum mismatch, fetching from remote", pkg->name, pkg->version); unlink(dest); return (pkg_repo_binary_try_fetch(repo, pkg, true, mirror, destdir)); } } cleanup: if (retcode != EPKG_OK) unlink(dest); else if (!mirror && path != NULL) { (void)pkg_repo_binary_create_symlink(pkg, dest, path); } /* allowed even if dir is NULL */ free(dir); return (retcode); }