]> git.ipfire.org Git - pakfire.git/commitdiff
repo: Parse the entire repository metadata
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 3 Feb 2025 11:35:14 +0000 (11:35 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 3 Feb 2025 11:35:14 +0000 (11:35 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/pakfire/digest.c
src/pakfire/digest.h
src/pakfire/repo.c

index beea8a00f968a01ecc2838a69b553f227a8e51ff..bbd6b6f824aa0c5a8ace56180c2aa65710981aa6 100644 (file)
@@ -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;
+}
index 0da130130107765db792f281d2efcd6772d09d8b..0b6770a1c9faa47857715c456b8cd1612d3de82b 100644 (file)
@@ -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 */
index 8726ff5005a0377e123f33a5438f74ae195495e7..41aef5d75a669a178e29a4bc9aaa8ceac7ccf43b 100644 (file)
@@ -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);