]> git.ipfire.org Git - pakfire.git/commitdiff
libpakfire: Make archive signatures an exportable object
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 27 Nov 2017 13:12:50 +0000 (14:12 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 27 Nov 2017 13:12:50 +0000 (14:12 +0100)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/_pakfire/_pakfiremodule.c
src/_pakfire/archive.c
src/_pakfire/archive.h
src/libpakfire/archive.c
src/libpakfire/include/pakfire/archive.h
src/libpakfire/include/pakfire/types.h
src/libpakfire/libpakfire.sym

index 0af859b88045f619bf85f959b506cc37f43c3f19..a10bb233cd1748ceede30dc2511a95385db48ad9 100644 (file)
@@ -142,6 +142,13 @@ PyMODINIT_FUNC PyInit__pakfire(void) {
        Py_INCREF(&ArchiveType);
        PyModule_AddObject(module, "Archive", (PyObject *)&ArchiveType);
 
+       // Archive Signature
+       if (PyType_Ready(&ArchiveSignatureType) < 0)
+               return NULL;
+
+       Py_INCREF(&ArchiveSignatureType);
+       PyModule_AddObject(module, "ArchiveSignature", (PyObject *)&ArchiveSignatureType);
+
        // Key
        if (PyType_Ready(&KeyType) < 0)
                return NULL;
index 439c97f6f0642da683fc4645f1c78969abb1846b..f66d86bf3095419a6628cd8927f1faa47451c2cc 100644 (file)
@@ -38,7 +38,7 @@ static PyObject* Archive_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
 
 static void Archive_dealloc(ArchiveObject* self) {
        if (self->archive)
-               pakfire_archive_free(self->archive);
+               pakfire_archive_unref(self->archive);
 
        Py_DECREF(self->pakfire);
 
@@ -56,6 +56,7 @@ static int Archive_init(ArchiveObject* self, PyObject* args, PyObject* kwds) {
        Py_INCREF(self->pakfire);
 
        self->archive = pakfire_archive_open(self->pakfire->pakfire, filename);
+       assert(self->archive);
 
        return 0;
 }
@@ -116,21 +117,18 @@ static PyObject* Archive_verify(ArchiveObject* self) {
 static PyObject* Archive_get_signatures(ArchiveObject* self) {
        PyObject* list = PyList_New(0);
 
-       char** head = pakfire_archive_get_signatures(self->archive);
+       PakfireArchiveSignature* head = pakfire_archive_get_signatures(self->archive);
 
-       char** signatures = head;
-       while (*signatures) {
-               char* signature = *signatures++;
+       PakfireArchiveSignature* signatures = head;
+       while (signatures && *signatures) {
+               PakfireArchiveSignature signature = *signatures++;
 
-               PyObject* object = PyUnicode_FromString(signature);
+               PyObject* object = new_archive_signature(self, signature);
                PyList_Append(list, object);
 
                Py_DECREF(object);
-               pakfire_free(signature);
        }
 
-       pakfire_free(head);
-
        return list;
 }
 
@@ -184,3 +182,51 @@ PyTypeObject ArchiveType = {
        //tp_str:             (reprfunc)Archive_str,
        //tp_richcompare:     (richcmpfunc)Archive_richcompare,
 };
+
+// Archive Signature
+
+static PyObject* ArchiveSignature_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
+       ArchiveSignatureObject* self = (ArchiveSignatureObject *)type->tp_alloc(type, 0);
+       if (self) {
+               self->signature = NULL;
+       }
+
+       return (PyObject *)self;
+}
+
+PyObject* new_archive_signature(ArchiveObject* archive, PakfireArchiveSignature signature) {
+       ArchiveSignatureObject* s = (ArchiveSignatureObject*)ArchiveSignature_new(&ArchiveSignatureType, NULL, NULL);
+       if (s)
+               s->signature = pakfire_archive_signature_ref(signature);
+
+       return (PyObject *)s;
+}
+
+static void ArchiveSignature_dealloc(ArchiveSignatureObject* self) {
+       if (self->signature)
+               pakfire_archive_signature_unref(self->signature);
+
+       Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject* ArchiveSignature_str(ArchiveSignatureObject* self) {
+       const char* data = pakfire_archive_signature_get_data(self->signature);
+
+       return PyUnicode_FromString(data);
+}
+
+static struct PyGetSetDef ArchiveSignature_getsetters[] = {
+       { NULL },
+};
+
+PyTypeObject ArchiveSignatureType = {
+       PyVarObject_HEAD_INIT(NULL, 0)
+       tp_name:            "_pakfire.ArchiveSignature",
+       tp_basicsize:       sizeof(ArchiveSignatureObject),
+       tp_flags:           Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+       tp_new:             ArchiveSignature_new,
+       tp_dealloc:         (destructor)ArchiveSignature_dealloc,
+       tp_doc:             "ArchiveSignature object",
+       tp_getset:          ArchiveSignature_getsetters,
+       tp_str:             (reprfunc)ArchiveSignature_str,
+};
index 0630627c2c03a1a33eb4c704818ea105bb8a43cb..89cca394f205652ea41e25aad1d8e66953c5aec4 100644 (file)
@@ -35,4 +35,13 @@ typedef struct {
 
 extern PyTypeObject ArchiveType;
 
+typedef struct {
+       PyObject_HEAD
+       PakfireArchiveSignature signature;
+} ArchiveSignatureObject;
+
+extern PyTypeObject ArchiveSignatureType;
+
+PyObject* new_archive_signature(ArchiveObject* archive, PakfireArchiveSignature signature);
+
 #endif /* PYTHON_PAKFIRE_ARCHIVE_H */
index d97c36ccf1803985e2c3148730d39b491db50452..a89b7654e7c68ac2b433088457fb3c2f87874f79 100644 (file)
@@ -167,24 +167,40 @@ static archive_checksum_t* pakfire_archive_checksum_find(PakfireArchive archive,
        return NULL;
 }
 
-static archive_signature_t* pakfire_archive_signature_create(const char* sigdata) {
-       archive_signature_t* s = pakfire_calloc(1, sizeof(*s));
-       if (s) {
-               s->sigdata = pakfire_strdup(sigdata);
+static PakfireArchiveSignature pakfire_archive_signature_create(PakfireArchive archive, const char* sigdata) {
+       PakfireArchiveSignature signature = pakfire_calloc(1, sizeof(*signature));
+       if (signature) {
+               signature->nrefs = 1;
+               signature->sigdata = pakfire_strdup(sigdata);
        }
 
-       return s;
+       return signature;
 }
 
-static void pakfire_archive_signature_free(archive_signature_t* s) {
-       pakfire_free(s->sigdata);
-       pakfire_free(s);
+static void pakfire_archive_signature_free(PakfireArchiveSignature signature) {
+       if (signature->key)
+               pakfire_key_unref(signature->key);
+
+       pakfire_free(signature->sigdata);
+       pakfire_free(signature);
 }
 
-size_t pakfire_archive_count_signatures(PakfireArchive archive) {
+PakfireArchiveSignature pakfire_archive_signature_ref(PakfireArchiveSignature signature) {
+       ++signature->nrefs;
+
+       return signature;
+}
+
+void pakfire_archive_signature_unref(PakfireArchiveSignature signature) {
+       if (--signature->nrefs > 0)
+               return;
+
+       pakfire_archive_signature_free(signature);
+}
+
+size_t _pakfire_archive_count_signatures(const PakfireArchiveSignature* signatures) {
        size_t i = 0;
 
-       archive_signature_t** signatures = archive->signatures;
        while (signatures && *signatures++) {
                i++;
        }
@@ -192,9 +208,16 @@ size_t pakfire_archive_count_signatures(PakfireArchive archive) {
        return i;
 }
 
+size_t pakfire_archive_count_signatures(PakfireArchive archive) {
+       PakfireArchiveSignature* signatures = pakfire_archive_get_signatures(archive);
+
+       return _pakfire_archive_count_signatures(signatures);
+}
+
 PakfireArchive pakfire_archive_create(Pakfire pakfire) {
        PakfireArchive archive = pakfire_calloc(1, sizeof(*archive));
        if (archive) {
+               archive->nrefs = 1;
                archive->pakfire = pakfire_ref(pakfire);
                archive->format = -1;
 
@@ -204,7 +227,13 @@ PakfireArchive pakfire_archive_create(Pakfire pakfire) {
        return archive;
 }
 
-void pakfire_archive_free(PakfireArchive archive) {
+PakfireArchive pakfire_archive_ref(PakfireArchive archive) {
+       ++archive->nrefs;
+
+       return archive;
+}
+
+static void pakfire_archive_free(PakfireArchive archive) {
        if (archive->path)
                pakfire_free(archive->path);
 
@@ -214,14 +243,25 @@ void pakfire_archive_free(PakfireArchive archive) {
                pakfire_archive_checksum_free(*checksums++);
 
        // Free signatures
-       archive_signature_t** signatures = archive->signatures;
-       while (signatures && *signatures)
-               pakfire_archive_signature_free(*signatures++);
+       if (archive->signatures) {
+               PakfireArchiveSignature* signatures = archive->signatures;
+               while (signatures && *signatures)
+                       pakfire_archive_signature_unref(*signatures++);
+
+               pakfire_free(archive->signatures);
+       }
 
        pakfire_unref(archive->pakfire);
        pakfire_free(archive);
 }
 
+void pakfire_archive_unref(PakfireArchive archive) {
+       if (--archive->nrefs > 0)
+               return;
+
+       pakfire_archive_free(archive);
+}
+
 static int pakfire_archive_parse_entry_format(PakfireArchive archive,
                struct archive* a, struct archive_entry* e) {
        char format[PAKFIRE_ARCHIVE_FORMAT_SIZE + 1];
@@ -339,100 +379,80 @@ static int pakfire_archive_parse_entry_checksums(PakfireArchive archive,
        return 0;
 }
 
-static int pakfire_archive_parse_entry_signature(PakfireArchive archive,
-               struct archive* a, struct archive_entry* e) {
-       char* data;
-       size_t data_size;
+static int pakfire_archive_walk(PakfireArchive archive,
+               int (*callback)(PakfireArchive archive, struct archive* a, struct archive_entry* e, const char* pathname)) {
+       struct archive_entry* e;
+       int r = 0;
 
-       int r = archive_read(a, (void**)&data, &data_size);
+       // Open the archive file
+       struct archive* a;
+       r = archive_open(archive, &a);
        if (r)
-               return 1;
-
-       // Terminate string.
-       data[data_size] = '\0';
+               return r;
 
-       archive_signature_t* signature = pakfire_archive_signature_create(data);
-       if (!signature)
-               return 1;
-
-       if (archive->signatures) {
-               // Count signatures
-               size_t num_signatures = pakfire_archive_count_signatures(archive) + 1;
-
-               // Resize the array
-               archive->signatures = pakfire_realloc(archive->signatures, sizeof(*archive->signatures) * num_signatures);
-       } else {
-               archive->signatures = pakfire_calloc(2, sizeof(*archive->signatures));
-       }
+       // Walk through the archive
+       int ret;
+       while ((ret = archive_read_next_header(a, &e)) == ARCHIVE_OK) {
+               const char* pathname = archive_entry_pathname(e);
 
-       // Look for last element
-       archive_signature_t** signatures = archive->signatures;
-       while (*signatures) {
-               *signatures++;
+               r = callback(archive, a, e, pathname);
+               if (r)
+                       break;
        }
 
-       // Append signature
-       *signatures++ = signature;
-
-       // Terminate list
-       *signatures = NULL;
+       // Close the archive again
+       archive_close(a);
 
-       return 0;
+       return r;
 }
 
-static int pakfire_archive_read_metadata(PakfireArchive archive, struct archive* a) {
+static int pakfire_archive_read_metadata_entry(PakfireArchive archive, struct archive* a,
+               struct archive_entry* e, const char* entry_name) {
        int ret;
 
-       struct archive_entry* entry;
-       while ((ret = archive_read_next_header(a, &entry)) == ARCHIVE_OK) {
-               const char* entry_name = archive_entry_pathname(entry);
-
-               /* The first file in a pakfire package file must be
-                * the pakfire-format file, so we know with what version of
-                * the package format we are dealing with.
-                */
-               if (archive->format < 0) {
-                       if (strcmp(PAKFIRE_ARCHIVE_FN_FORMAT, entry_name) == 0) {
-                               ret = pakfire_archive_parse_entry_format(archive, a, entry);
-                               if (ret)
-                                       return PAKFIRE_E_PKG_INVALID;
-
-                       } else {
+       /* The first file in a pakfire package file must be
+               * the pakfire-format file, so we know with what version of
+               * the package format we are dealing with.
+               */
+       if (archive->format < 0) {
+               if (strcmp(PAKFIRE_ARCHIVE_FN_FORMAT, entry_name) == 0) {
+                       ret = pakfire_archive_parse_entry_format(archive, a, e);
+                       if (ret)
                                return PAKFIRE_E_PKG_INVALID;
-                       }
 
-               // If the format is set, we can go on...
                } else {
-                       // Parse the metadata
-                       if (strcmp(PAKFIRE_ARCHIVE_FN_METADATA, entry_name) == 0) {
-                               ret = pakfire_archive_parse_entry_metadata(archive, a, entry);
-                               if (ret)
-                                       return PAKFIRE_E_PKG_INVALID;
-
-                       // Parse the filelist
-                       } else if (strcmp(PAKFIRE_ARCHIVE_FN_FILELIST, entry_name) == 0) {
-                               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;
-
-                       // Parse signatures
-                       } else if (strncmp(PAKFIRE_ARCHIVE_FN_SIGNATURES, entry_name, strlen(PAKFIRE_ARCHIVE_FN_SIGNATURES)) == 0) {
-                               ret = pakfire_archive_parse_entry_signature(archive, a, entry);
-                               if (ret)
-                                       return PAKFIRE_E_PKG_INVALID;
-                       }
+                       return PAKFIRE_E_PKG_INVALID;
+               }
+
+       // If the format is set, we can go on...
+       } else {
+               // Parse the metadata
+               if (strcmp(PAKFIRE_ARCHIVE_FN_METADATA, entry_name) == 0) {
+                       ret = pakfire_archive_parse_entry_metadata(archive, a, e);
+                       if (ret)
+                               return PAKFIRE_E_PKG_INVALID;
+
+               // Parse the filelist
+               } else if (strcmp(PAKFIRE_ARCHIVE_FN_FILELIST, entry_name) == 0) {
+                       ret = pakfire_archive_parse_entry_filelist(archive, a, e);
+                       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, e);
+                       if (ret)
+                               return PAKFIRE_E_PKG_INVALID;
                }
        }
 
        return 0;
 }
 
+static int pakfire_archive_read_metadata(PakfireArchive archive, struct archive* a) {
+       return pakfire_archive_walk(archive, pakfire_archive_read_metadata_entry);
+}
+
 static int archive_copy_data(struct archive* in, struct archive* out) {
        int r;
        const void* buff;
@@ -658,32 +678,77 @@ PakfireFile pakfire_archive_get_filelist(PakfireArchive archive) {
        return archive->filelist;
 }
 
-char** pakfire_archive_get_signatures(PakfireArchive archive) {
-       size_t size = pakfire_archive_count_signatures(archive);
+const char* pakfire_archive_signature_get_data(PakfireArchiveSignature signature) {
+       return signature->sigdata;
+}
 
-       char** head = pakfire_calloc(size, sizeof(*head));
-       if (!head)
-               return NULL;
+static int pakfire_archive_parse_entry_signature(PakfireArchive archive,
+               struct archive* a, struct archive_entry* e) {
+       char* data;
+       size_t data_size;
 
-       char** list = head;
-       archive_signature_t** signatures = archive->signatures;
-       while (signatures && *signatures) {
-               archive_signature_t* signature = *signatures++;
+       int r = archive_read(a, (void**)&data, &data_size);
+       if (r)
+               return 1;
+
+       // Terminate string.
+       data[data_size] = '\0';
+
+       PakfireArchiveSignature signature = pakfire_archive_signature_create(archive, data);
+       if (!signature)
+               return 1;
+
+       if (archive->signatures) {
+               // Count signatures
+               size_t num_signatures = _pakfire_archive_count_signatures(archive->signatures) + 1;
 
-               *list++ = pakfire_strdup(signature->sigdata);
+               // Resize the array
+               archive->signatures = pakfire_realloc(archive->signatures, sizeof(*archive->signatures) * num_signatures);
+       } else {
+               archive->signatures = pakfire_calloc(2, sizeof(*archive->signatures));
        }
 
+       // Look for last element
+       PakfireArchiveSignature* signatures = archive->signatures;
+       while (signatures && *signatures) {
+               *signatures++;
+       }
+
+       // Append signature
+       *signatures++ = signature;
+
        // Terminate list
-       *list = NULL;
+       *signatures = NULL;
+
+       return 0;
+}
+
+static int pakfire_archive_read_signature_entry(PakfireArchive archive, struct archive* a, struct archive_entry* e, const char* entry_name) {
+       if (strncmp(PAKFIRE_ARCHIVE_FN_SIGNATURES, entry_name, strlen(PAKFIRE_ARCHIVE_FN_SIGNATURES)) == 0) {
+               int ret = pakfire_archive_parse_entry_signature(archive, a, e);
+               if (ret)
+                       return PAKFIRE_E_PKG_INVALID;
+       }
+
+       return 0;
+}
+
+static int pakfire_archive_load_signatures(PakfireArchive archive) {
+       return pakfire_archive_walk(archive, pakfire_archive_read_signature_entry);
+}
+
+PakfireArchiveSignature* pakfire_archive_get_signatures(PakfireArchive archive) {
+       if (!archive->signatures_loaded++)
+               pakfire_archive_load_signatures(archive);
 
-       return head;
+       return archive->signatures;
 }
 
 static pakfire_archive_verify_status_t pakfire_archive_verify_checksums(PakfireArchive archive) {
        pakfire_archive_verify_status_t status = PAKFIRE_ARCHIVE_VERIFY_INVALID;
 
        // Cannot validate anything if no signatures are available
-       archive_signature_t** signatures = archive->signatures;
+       PakfireArchiveSignature* signatures = pakfire_archive_get_signatures(archive);
        if (!signatures)
                return PAKFIRE_ARCHIVE_VERIFY_OK;
 
@@ -708,7 +773,7 @@ static pakfire_archive_verify_status_t pakfire_archive_verify_checksums(PakfireA
 
        // Try for each signature
        while (signatures && *signatures) {
-               archive_signature_t* signature = *signatures++;
+               PakfireArchiveSignature signature = *signatures++;
 
                gpgme_data_t sigdata;
                error = gpgme_data_new_from_mem(&sigdata, signature->sigdata, strlen(signature->sigdata), 0);
index 48b10c1dfc1f1f474647045601b79cc54b18b0c8..90c31a985a5ae58b68ab57c6579d211851eccf28 100644 (file)
@@ -35,7 +35,8 @@ typedef enum pakfire_archive_verify_status {
 } pakfire_archive_verify_status_t;
 
 PakfireArchive pakfire_archive_create(Pakfire pakfire);
-void pakfire_archive_free(PakfireArchive archive);
+PakfireArchive pakfire_archive_ref(PakfireArchive archive);
+void pakfire_archive_unref(PakfireArchive archive);
 
 PakfireArchive pakfire_archive_open(Pakfire pakfire, const char* path);
 
@@ -49,12 +50,16 @@ unsigned int pakfire_archive_get_format(PakfireArchive archive);
 
 PakfireFile pakfire_archive_get_filelist(PakfireArchive archive);
 
-size_t pakfire_archive_count_signatures(PakfireArchive archive);
-char** pakfire_archive_get_signatures(PakfireArchive archive);
-
 pakfire_archive_verify_status_t pakfire_archive_verify(PakfireArchive archive);
 const char* pakfire_archive_verify_strerror(pakfire_archive_verify_status_t status);
 
+size_t pakfire_archive_count_signatures(PakfireArchive archive);
+PakfireArchiveSignature* pakfire_archive_get_signatures(PakfireArchive archive);
+
+PakfireArchiveSignature pakfire_archive_signature_ref(PakfireArchiveSignature signature);
+void pakfire_archive_signature_unref(PakfireArchiveSignature signature);
+const char* pakfire_archive_signature_get_data(PakfireArchiveSignature signature);
+
 enum pakfire_archive_flags {
        PAKFIRE_ARCHIVE_USE_PAYLOAD = 1 << 0,
 };
@@ -82,10 +87,6 @@ typedef struct archive_checksum {
        archive_checksum_algo_t algo;
 } archive_checksum_t;
 
-typedef struct archive_signature {
-       char* sigdata;
-} archive_signature_t;
-
 struct _PakfireArchive {
        Pakfire pakfire;
        char* path;
@@ -95,7 +96,18 @@ struct _PakfireArchive {
 
        PakfireFile filelist;
        archive_checksum_t** checksums;
-       archive_signature_t** signatures;
+
+       // Signatures
+       PakfireArchiveSignature* signatures;
+       int signatures_loaded;
+
+       int nrefs;
+};
+
+struct _PakfireArchiveSignature {
+       PakfireKey key;
+       char* sigdata;
+       int nrefs;
 };
 
 struct payload_archive_data {
index 300b8567b0ac2909d04605addb456ea1e3419c4d..2899ff2c64f7734533a24528ca124985619c4c1d 100644 (file)
@@ -23,6 +23,7 @@
 
 typedef struct _Pakfire* Pakfire;
 typedef struct _PakfireArchive* PakfireArchive;
+typedef struct _PakfireArchiveSignature* PakfireArchiveSignature;
 typedef struct _PakfireCache* PakfireCache;
 typedef struct _PakfireFile* PakfireFile;
 typedef struct _PakfireFilter* PakfireFilter;
index 460b5f6565924e7d779af4756b18a46c22695b6c..c34cf108f6ec84cee4e3e9000f6fe65e9e8f1824 100644 (file)
@@ -32,16 +32,22 @@ global:
        pakfire_archive_count_signatures;
        pakfire_archive_create;
        pakfire_archive_extract;
-       pakfire_archive_free;
        pakfire_archive_get_filelist;
        pakfire_archive_get_format;
        pakfire_archive_get_path;
        pakfire_archive_get_signatures;
        pakfire_archive_open;
        pakfire_archive_read;
+       pakfire_archive_ref;
+       pakfire_archive_unref;
        pakfire_archive_verify;
        pakfire_archive_verify_strerror;
 
+       # archive signature
+       pakfire_archive_signature_get_data;
+       pakfire_archive_signature_ref;
+       pakfire_archive_signature_unref;
+
        # file
        pakfire_file_append;
        pakfire_file_cmp;