]> git.ipfire.org Git - pakfire.git/commitdiff
archive: Refactor reading checksums
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 6 Apr 2021 17:08:28 +0000 (17:08 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 6 Apr 2021 17:14:09 +0000 (17:14 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/archive.c

index b94f7ef84c2f0313229cf673b7ff02453ce87291..baf362e6c2ee44abd42c02655d24ed52b09ba2fb 100644 (file)
 #                                                                             #
 #############################################################################*/
 
-#include <assert.h>
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <gpgme.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/queue.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
 
 #define BLOCKSIZE      1024 * 1024 // 1MB
 
-typedef struct archive_checksum {
-       Pakfire pakfire;
-       char* filename;
+struct pakfire_archive_chksum {
+       STAILQ_ENTRY(pakfire_archive_chksum) nodes;
+
+       char path[PATH_MAX];
        archive_checksum_algo_t algo;
        unsigned char digest[EVP_MAX_MD_SIZE];
-} archive_checksum_t;
+};
 
 struct _PakfireArchive {
        Pakfire pakfire;
@@ -72,7 +73,9 @@ struct _PakfireArchive {
        PakfireParser parser;
 
        PakfireFilelist filelist;
-       archive_checksum_t** checksums;
+
+       // Checksums
+       STAILQ_HEAD(chksums, pakfire_archive_chksum) chksums;
 
        // Signatures
        PakfireArchiveSignature* signatures;
@@ -200,6 +203,8 @@ static int payload_archive_open(struct archive** a, struct archive* source_archi
        return archive_read_open1(*a);
 }
 
+// Checksum Stuff
+
 static const char* checksum_algo_string(archive_checksum_algo_t algo) {
        switch (algo) {
                case PAKFIRE_CHECKSUM_SHA512:
@@ -226,48 +231,57 @@ static int read_hexdigest(unsigned char* dst, size_t l, const char* src) {
        return 0;
 }
 
-static void pakfire_archive_checksum_free(archive_checksum_t* c) {
-       DEBUG(c->pakfire, "Releasing archive checksum at %p\n", c);
+static int pakfire_archive_add_chksum(PakfireArchive archive, const char* path,
+               archive_checksum_algo_t algo, const char* hexdigest) {
+       int r = 1;
 
-       pakfire_unref(c->pakfire);
-       free(c->filename);
-       free(c);
-}
+       // Allocate a new chksum object
+       struct pakfire_archive_chksum* chksum = calloc(1, sizeof(*chksum));
+       if (!chksum)
+               return ENOMEM;
 
-static archive_checksum_t* pakfire_archive_checksum_create(Pakfire pakfire, const char* filename, archive_checksum_algo_t algo, const char* s) {
-       archive_checksum_t* c = calloc(1, sizeof(*c));
-       if (c) {
-               c->pakfire = pakfire_ref(pakfire);
-               c->filename = strdup(filename);
-               c->algo = algo;
-
-               int r = read_hexdigest(c->digest, sizeof(c->digest), s);
-               if (r) {
-                       pakfire_archive_checksum_free(c);
-                       return NULL;
-               }
+       // Store path
+       r = pakfire_string_set(chksum->path, path);
+       if (r < 0)
+               goto ERROR;
 
-               DEBUG(c->pakfire, "Allocated archive checksum for %s (%s)\n",
-                       c->filename, checksum_algo_string(c->algo));
-       }
+       // Store algo
+       chksum->algo = algo;
 
-       return c;
-}
+       // Store hexdigest as digest
+       r = read_hexdigest(chksum->digest, sizeof(chksum->digest), hexdigest);
+       if (r)
+               goto ERROR;
+
+       // Append it
+       STAILQ_INSERT_TAIL(&archive->chksums, chksum, nodes);
+
+       DEBUG(archive->pakfire, "Read checksum for %s - %s:%s\n",
+               path, checksum_algo_string(algo), hexdigest);
+
+       return 0;
 
-static archive_checksum_t* pakfire_archive_checksum_find(PakfireArchive archive, const char* filename) {
-       archive_checksum_t** checksums = archive->checksums;
+ERROR:
+       free(chksum);
+
+       return r;
+}
 
-       while (checksums && *checksums) {
-               archive_checksum_t* checksum = *checksums++;
+static struct pakfire_archive_chksum* pakfire_archive_find_chksum(
+               PakfireArchive archive, const char* path) {
+       struct pakfire_archive_chksum* chksum = NULL;
 
-               if (strcmp(checksum->filename, filename) == 0)
-                       return checksum;
+       STAILQ_FOREACH(chksum, &archive->chksums, nodes) {
+               if (strcmp(chksum->path, path) == 0)
+                       return chksum;
        }
 
        // Nothing found
        return NULL;
 }
 
+// Signature Stuff
+
 static PakfireArchiveSignature pakfire_archive_signature_create(PakfireArchive archive, const char* sigdata) {
        PakfireArchiveSignature signature = calloc(1, sizeof(*signature));
        if (signature) {
@@ -332,6 +346,8 @@ PAKFIRE_EXPORT PakfireArchive pakfire_archive_create(Pakfire pakfire) {
                archive->format = -1;
                archive->parser = pakfire_parser_create(pakfire, NULL, NULL, 0);
                archive->signatures = NULL;
+
+               STAILQ_INIT(&archive->chksums);
        }
 
        return archive;
@@ -343,9 +359,22 @@ PAKFIRE_EXPORT PakfireArchive pakfire_archive_ref(PakfireArchive archive) {
        return archive;
 }
 
+static void pakfire_archive_free_chksums(PakfireArchive archive) {
+       struct pakfire_archive_chksum* chksum;
+
+       while ((chksum = STAILQ_FIRST(&archive->chksums))) {
+               STAILQ_REMOVE_HEAD(&archive->chksums, nodes);
+
+               free(chksum);
+       }
+}
+
 static void pakfire_archive_free(PakfireArchive archive) {
        DEBUG(archive->pakfire, "Releasing archive at %p\n", archive);
 
+       // Free all checksums
+       pakfire_archive_free_chksums(archive);
+
        // Release OpenSSL context
        if (archive->mdctx)
                EVP_MD_CTX_free(archive->mdctx);
@@ -353,11 +382,6 @@ static void pakfire_archive_free(PakfireArchive archive) {
        if (archive->path)
                free(archive->path);
 
-       // Free checksums
-       archive_checksum_t** checksums = archive->checksums;
-       while (checksums && *checksums)
-               pakfire_archive_checksum_free(*checksums++);
-
        // Free signatures
        if (archive->signatures) {
                PakfireArchiveSignature* signatures = archive->signatures;
@@ -463,9 +487,6 @@ static int pakfire_archive_parse_entry_checksums(PakfireArchive archive,
        // Terminate string.
        data[data_size] = '\0';
 
-       // Allocate some space to save the checksums
-       archive_checksum_t** checksums = archive->checksums = calloc(10, sizeof(*archive->checksums));
-
        const char* filename = NULL;
        const char* checksum = NULL;
        archive_checksum_algo_t algo = PAKFIRE_CHECKSUM_SHA512;
@@ -498,7 +519,9 @@ static int pakfire_archive_parse_entry_checksums(PakfireArchive archive,
 
                // Add new checksum object
                if (filename && checksum) {
-                       *checksums++ = pakfire_archive_checksum_create(archive->pakfire, filename, algo, checksum);
+                       r = pakfire_archive_add_chksum(archive, filename, algo, checksum);
+                       if (r)
+                               goto ERROR;
                }
 
                // Eat up any space before next thing starts
@@ -506,9 +529,7 @@ static int pakfire_archive_parse_entry_checksums(PakfireArchive archive,
                        p++;
        }
 
-       // Terminate the list
-       *checksums = NULL;
-
+ERROR:
        free(data);
 
        return 0;
@@ -1217,7 +1238,8 @@ ABORT:
        return status;
 }
 
-static pakfire_archive_verify_status_t pakfire_archive_verify_file(Pakfire pakfire, struct archive* a, const archive_checksum_t* checksum) {
+static pakfire_archive_verify_status_t pakfire_archive_verify_file(Pakfire pakfire,
+               struct archive* a, const struct pakfire_archive_chksum* chksum) {
        pakfire_archive_verify_status_t status = PAKFIRE_ARCHIVE_VERIFY_ERROR;
 
        int r;
@@ -1227,7 +1249,7 @@ static pakfire_archive_verify_status_t pakfire_archive_verify_file(Pakfire pakfi
        EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
 
        // Select algorithm
-       switch (checksum->algo) {
+       switch (chksum->algo) {
                case PAKFIRE_CHECKSUM_SHA512:
                        md = EVP_sha512();
                        break;
@@ -1278,11 +1300,11 @@ static pakfire_archive_verify_status_t pakfire_archive_verify_file(Pakfire pakfi
        }
 
        // Compare digests
-       if (CRYPTO_memcmp(digest, checksum->digest, EVP_MD_CTX_size(mdctx)) == 0) {
-               DEBUG(pakfire, "Checksum of %s is OK\n", checksum->filename);
+       if (CRYPTO_memcmp(digest, chksum->digest, EVP_MD_CTX_size(mdctx)) == 0) {
+               DEBUG(pakfire, "Checksum of %s is OK\n", chksum->path);
                status = PAKFIRE_ARCHIVE_VERIFY_OK;
        } else {
-               DEBUG(pakfire, "Checksum of %s did not match\n", checksum->filename);
+               DEBUG(pakfire, "Checksum of %s did not match\n", chksum->path);
                status = PAKFIRE_ARCHIVE_VERIFY_INVALID;
        }
 
@@ -1316,14 +1338,14 @@ PAKFIRE_EXPORT pakfire_archive_verify_status_t pakfire_archive_verify(PakfireArc
                const char* entry_name = archive_entry_pathname(entry);
 
                // See if we have a checksum for this file
-               const archive_checksum_t* checksum = pakfire_archive_checksum_find(archive, entry_name);
-               if (!checksum) {
+               const struct pakfire_archive_chksum* chksum = pakfire_archive_find_chksum(archive, entry_name);
+               if (!chksum) {
                        DEBUG(archive->pakfire, "Could not find checksum for %s\n", entry_name);
                        continue;
                }
 
                // Compare the checksums
-               status = pakfire_archive_verify_file(archive->pakfire, a, checksum);
+               status = pakfire_archive_verify_file(archive->pakfire, a, chksum);
                if (status)
                        goto END;
        }