From: Michael Tremer Date: Tue, 6 Apr 2021 17:08:28 +0000 (+0000) Subject: archive: Refactor reading checksums X-Git-Tag: 0.9.28~1285^2~422 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6cdbff8013cb1557035a450d8b3e4add44ddf00e;p=pakfire.git archive: Refactor reading checksums Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/archive.c b/src/libpakfire/archive.c index b94f7ef84..baf362e6c 100644 --- a/src/libpakfire/archive.c +++ b/src/libpakfire/archive.c @@ -18,13 +18,13 @@ # # #############################################################################*/ -#include #include #include #include #include #include #include +#include #include #include @@ -55,12 +55,13 @@ #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; }