From 93eff9504d11516b8a90ec94dc5857524b9b679b Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Mon, 3 Feb 2025 11:35:14 +0000 Subject: [PATCH] repo: Parse the entire repository metadata Signed-off-by: Michael Tremer --- src/pakfire/digest.c | 33 ++++++++++++++ src/pakfire/digest.h | 5 +++ src/pakfire/repo.c | 101 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 130 insertions(+), 9 deletions(-) diff --git a/src/pakfire/digest.c b/src/pakfire/digest.c index beea8a00..bbd6b6f8 100644 --- a/src/pakfire/digest.c +++ b/src/pakfire/digest.c @@ -619,3 +619,36 @@ int pakfire_digests_compare_one(struct pakfire_ctx* ctx, struct pakfire_digests* return pakfire_digests_compare(ctx, digests1, &digests2, type); } + +int pakfire_digests_set_hexdigest(struct pakfire_digests* digests, + const enum pakfire_digest_types type, const char* hexdigest) { + switch (type) { + case PAKFIRE_DIGEST_SHA3_512: + return pakfire_unhexlify(digests->sha3_512, hexdigest); + + case PAKFIRE_DIGEST_SHA3_256: + return pakfire_unhexlify(digests->sha3_256, hexdigest); + + case PAKFIRE_DIGEST_BLAKE2B512: + return pakfire_unhexlify(digests->blake2b512, hexdigest); + + case PAKFIRE_DIGEST_BLAKE2S256: + return pakfire_unhexlify(digests->blake2s256, hexdigest); + + case PAKFIRE_DIGEST_SHA2_512: + return pakfire_unhexlify(digests->sha2_512, hexdigest); + + case PAKFIRE_DIGEST_SHA2_256: + return pakfire_unhexlify(digests->sha2_256, hexdigest); + + default: + return -EINVAL; + } +} + +int pakfire_digests_import(struct pakfire_digests* dst, struct pakfire_digests* src) { + // Copy everything + memcpy(dst, src, sizeof(*dst)); + + return 0; +} diff --git a/src/pakfire/digest.h b/src/pakfire/digest.h index 0da13013..0b6770a1 100644 --- a/src/pakfire/digest.h +++ b/src/pakfire/digest.h @@ -112,4 +112,9 @@ int pakfire_digests_compare(struct pakfire_ctx* ctx, const struct pakfire_digest int pakfire_digests_compare_one(struct pakfire_ctx* ctx, struct pakfire_digests* digests1, const enum pakfire_digest_types type, const unsigned char* digest, const size_t length); +int pakfire_digests_set_hexdigest(struct pakfire_digests* digests, + const enum pakfire_digest_types type, const char* hexdigest); + +int pakfire_digests_import(struct pakfire_digests* dst, struct pakfire_digests* src); + #endif /* PAKFIRE_DIGEST_H */ diff --git a/src/pakfire/repo.c b/src/pakfire/repo.c index 8726ff50..41aef5d7 100644 --- a/src/pakfire/repo.c +++ b/src/pakfire/repo.c @@ -66,6 +66,18 @@ struct pakfire_repomd { // Revision int64_t revision; + + // Package Database + struct { + // Path + char path[PATH_MAX]; + + // Size + size_t size; + + // Digests + struct pakfire_digests digests; + } packages; }; struct pakfire_repo_appdata { @@ -609,12 +621,19 @@ ERROR: static int pakfire_repo_parse_repomd(struct pakfire_repo* self, struct pakfire_repomd* repomd, struct json_object* root) { + struct json_object* files = NULL; + struct json_object* file = NULL; + struct json_object* chksums = NULL; + const char* type = NULL; + const char* filename = NULL; + ssize_t size = 0; + struct pakfire_digests digests = {}; int r; // Parse version r = pakfire_json_get_int64(root, "version", &repomd->version); if (r < 0) - goto ERROR; + return r; // Check if we support this version switch (repomd->version) { @@ -623,8 +642,7 @@ static int pakfire_repo_parse_repomd(struct pakfire_repo* self, default: ERROR(self->ctx, "Unsupported version of repository metadata: %ld\n", repomd->version); - r = -ENOTSUP; - goto ERROR; + return -ENOTSUP; } DEBUG(self->ctx, "Parsing repository metadata in version %ld\n", repomd->version); @@ -632,12 +650,71 @@ static int pakfire_repo_parse_repomd(struct pakfire_repo* self, // Parse revision r = pakfire_json_get_int64(root, "revision", &repomd->revision); if (r < 0) - goto ERROR; + return r; - // XXX There is more to do here... + // Fetch files + r = pakfire_json_get_array(root, "files", &files); + if (r < 0) + return r; -ERROR: - return r; + // Iterate over all files + for (size_t i = 0; i < json_object_array_length(files); i++) { + file = json_object_array_get_idx(files, i); + + // Read type + r = pakfire_json_get_string(file, "type", &type); + if (r < 0) + return r; + + // Read filename + r = pakfire_json_get_string(file, "filename", &filename); + if (r < 0) + return r; + + // Read size + r = pakfire_json_get_int64(file, "size", &size); + if (r < 0) + return r; + + // Fetch checksums + r = pakfire_json_get_object(file, "chksums", &chksums); + if (r < 0) + return r; + + // Parse checksums + json_object_object_foreach(chksums, digest_name, hexdigest) { + enum pakfire_digest_types digest_type = pakfire_digest_get_by_name(digest_name); + + // Import the hexdigest + r = pakfire_digests_set_hexdigest(&digests, digest_type, json_object_get_string(hexdigest)); + if (r < 0) + return r; + } + + // We found the packages database + if (pakfire_string_equals(type, "packages")) { + // Store the filename + r = pakfire_string_set(repomd->packages.path, filename); + if (r < 0) + return r; + + // Store the filelist + repomd->packages.size = size; + + // Store the digests + r = pakfire_digests_import(&repomd->packages.digests, &digests); + if (r < 0) + return r; + + // Since we currently only know this one file, we can stop once we found it + break; + } + + // Reset the digests + pakfire_digests_reset(&digests, PAKFIRE_DIGESTS_ALL); + } + + return 0; } static int pakfire_repo_read_metadata(struct pakfire_repo* repo, const char* path) { @@ -660,6 +737,9 @@ static int pakfire_repo_read_metadata(struct pakfire_repo* repo, const char* pat return pakfire_repo_scan(repo, 0); } + // Log some message + DEBUG(repo->ctx, "Repository metadata is not available\n"); + // Otherwise accept this and hope we will be able to download some data return 0; @@ -671,8 +751,11 @@ static int pakfire_repo_read_metadata(struct pakfire_repo* repo, const char* pat // Parse the JSON object r = pakfire_repo_parse_repomd(repo, &repo->appdata->repomd, json); - if (r < 0) + if (r < 0) { + ERROR(repo->ctx, "Could not parse repository metadata for %s: %s\n", + pakfire_repo_get_name(repo), strerror(-r)); goto ERROR; + } @@ -961,7 +1044,7 @@ static int pakfire_repo_refresh_metadata(struct pakfire_repo* repo, const int fo // Parse metadata from disk r = pakfire_repo_read_metadata(repo, path); if (r < 0) - return + return r; // Potentially download new metadata r = pakfire_repo_download_metadata(repo, path, force); -- 2.39.5