]> git.ipfire.org Git - pakfire.git/commitdiff
libpakfire: Parse checksums file in archives
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 24 Nov 2017 15:19:04 +0000 (16:19 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 24 Nov 2017 16:31:48 +0000 (17:31 +0100)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/archive.c
src/libpakfire/include/pakfire/archive.h

index 4576c282e3ad1d0ddb07e906b524052951fc0013..7a60035c5c6bc069ffa0fb47c7da11ef5d17e2f2 100644 (file)
@@ -19,6 +19,7 @@
 #############################################################################*/
 
 #include <assert.h>
+#include <ctype.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
@@ -128,6 +129,23 @@ static int payload_archive_open(struct archive** a, struct archive* source_archi
        return archive_read_open1(*a);
 }
 
+static archive_checksum_t* pakfire_archive_checksum_create(const char* filename, const char* checksum, archive_checksum_algo_t algo) {
+       archive_checksum_t* c = pakfire_calloc(1, sizeof(*c));
+       if (c) {
+               c->filename = pakfire_strdup(filename);
+               c->checksum = pakfire_strdup(checksum);
+               c->algo = algo;
+       }
+
+       return c;
+}
+
+static void pakfire_archive_checksum_free(archive_checksum_t* c) {
+       pakfire_free(c->filename);
+       pakfire_free(c->checksum);
+       pakfire_free(c);
+}
+
 PakfireArchive pakfire_archive_create() {
        PakfireArchive archive = pakfire_calloc(1, sizeof(*archive));
        if (archive) {
@@ -141,6 +159,11 @@ void pakfire_archive_free(PakfireArchive archive) {
        if (archive->path)
                pakfire_free(archive->path);
 
+       // Free checksums
+       archive_checksum_t** checksums = archive->checksums;
+       while (*checksums)
+               pakfire_archive_checksum_free(*checksums++);
+
        pakfire_free(archive);
 }
 
@@ -194,6 +217,73 @@ static int pakfire_archive_parse_entry_filelist(PakfireArchive archive,
        return 0;
 }
 
+static int pakfire_archive_parse_entry_checksums(PakfireArchive archive,
+               struct archive* a, struct archive_entry* e) {
+       char* data;
+       size_t data_size;
+
+       int r = archive_read(a, (void**)&data, &data_size);
+       if (r)
+               return 1;
+
+       // Empty file
+       if (data_size <= 0)
+               return 1;
+
+       // Terminate string.
+       data[data_size] = '\0';
+
+       // Allocate some space to save the checksums
+       archive->checksums = pakfire_calloc(10, sizeof(*archive->checksums));
+
+       const char* filename = NULL;
+       const char* checksum = NULL;
+       archive_checksum_algo_t algo = PAKFIRE_CHECKSUM_SHA512;
+
+       char* p = data;
+       while (*p) {
+               // Filename starts here
+               filename = p;
+
+               // Find end of filename
+               while (!isspace(*p))
+                       p++;
+
+               // Terminate filename
+               *p++ = '\0';
+
+               // Skip any spaces
+               while (isspace(*p))
+                       p++;
+
+               // Checksum starts here
+               checksum = p;
+
+               // Find end of checksum
+               while (!isspace(*p))
+                       p++;
+
+               // Terminate the checksum
+               *p++ = '\0';
+
+               // Add new checksum object
+               if (filename && checksum) {
+                       *archive->checksums++ = pakfire_archive_checksum_create(filename, checksum, algo);
+               }
+
+               // Eat up any space before next thing starts
+               while (isspace(*p))
+                       p++;
+       }
+
+       // Terminate the list
+       *archive->checksums = NULL;
+
+       pakfire_free(data);
+
+       return 0;
+}
+
 static int pakfire_archive_read_metadata(PakfireArchive archive, struct archive* a) {
        int ret;
 
@@ -228,6 +318,12 @@ static int pakfire_archive_read_metadata(PakfireArchive archive, struct archive*
                                ret = pakfire_archive_parse_entry_filelist(archive, a, entry);
                                if (ret)
                                        return PAKFIRE_E_PKG_INVALID;
+
+                       // Parse the checksums
+                       } else if (strcmp(PAKFIRE_ARCHIVE_FN_CHECKSUMS, entry_name) == 0) {
+                               ret = pakfire_archive_parse_entry_checksums(archive, a, entry);
+                               if (ret)
+                                       return PAKFIRE_E_PKG_INVALID;
                        }
                }
        }
index 3e3e65dc550b2332bc9de4ebb136e97f80cb7e04..2bbea8f6549cc73713818a1205763021421c4aea 100644 (file)
@@ -44,6 +44,7 @@ enum pakfire_archive_flags {
        PAKFIRE_ARCHIVE_USE_PAYLOAD = 1 << 0,
 };
 
+#define PAKFIRE_ARCHIVE_FN_CHECKSUMS           "chksums"
 #define PAKFIRE_ARCHIVE_FN_FILELIST                    "filelist"
 #define PAKFIRE_ARCHIVE_FN_FORMAT                      "pakfire-format"
 #define PAKFIRE_ARCHIVE_FN_METADATA                    "info"
@@ -54,6 +55,17 @@ enum pakfire_archive_flags {
 #define PAKFIRE_ARCHIVE_BLOCKSIZE                      10240
 #define PAKFIRE_ARCHIVE_FORMAT_SIZE                    5
 
+typedef enum archive_checksum_algo {
+       PAKFIRE_CHECKSUM_UNKNOWN = 0,
+       PAKFIRE_CHECKSUM_SHA512,
+} archive_checksum_algo_t;
+
+typedef struct archive_checksum {
+       char* filename;
+       char* checksum;
+       archive_checksum_algo_t algo;
+} archive_checksum_t;
+
 struct _PakfireArchive {
        char* path;
 
@@ -61,6 +73,7 @@ struct _PakfireArchive {
        int format;
 
        PakfireFile filelist;
+       archive_checksum_t** checksums;
 };
 
 struct payload_archive_data {