]> git.ipfire.org Git - pakfire.git/commitdiff
archive: Parse scriptlets when the archive is opened for the first time
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 1 Sep 2022 11:42:41 +0000 (11:42 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 1 Sep 2022 11:42:41 +0000 (11:42 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/archive.c

index f97ce86d7828256c1a8b221e22add24e8e8a1863..777d6c5eebd848d344d60e4d2f030a8e70cc208c 100644 (file)
@@ -49,6 +49,8 @@
 #include <pakfire/string.h>
 #include <pakfire/util.h>
 
+#define MAX_SCRIPTLETS 9
+
 struct pakfire_archive {
        struct pakfire* pakfire;
        int nrefs;
@@ -67,8 +69,8 @@ struct pakfire_archive {
        struct pakfire_filelist* filelist;
 
        // Scriptlets
-       struct pakfire_scriptlet** scriptlets;
-       int scriptlets_loaded;
+       struct pakfire_scriptlet* scriptlets[MAX_SCRIPTLETS];
+       unsigned int num_scriptlets;
 
        // Digests
        struct pakfire_digests digests;
@@ -322,11 +324,8 @@ static void pakfire_archive_free(struct pakfire_archive* archive) {
                fclose(archive->f);
 
        // Free scriptlets
-       if (archive->scriptlets) {
-               for (struct pakfire_scriptlet** scriptlet = archive->scriptlets; *scriptlet; scriptlet++)
-                       pakfire_scriptlet_unref(*scriptlet);
-               free(archive->scriptlets);
-       }
+       for (unsigned int i = 0; i < archive->num_scriptlets; i++)
+               pakfire_scriptlet_unref(archive->scriptlets[i]);
 
        if (archive->filelist)
                pakfire_filelist_unref(archive->filelist);
@@ -477,6 +476,42 @@ static int pakfire_archive_parse_format(struct pakfire_archive* archive,
        return 0;
 }
 
+static int pakfire_archive_parse_scriptlet(struct pakfire_archive* archive,
+               const char* path, const char* data, const size_t length) {
+       struct pakfire_scriptlet* scriptlet = NULL;
+       const char* type = NULL;
+       int r;
+
+       // Check for any available space
+       if (archive->num_scriptlets >= MAX_SCRIPTLETS) {
+               ERROR(archive->pakfire, "Too many scriptlets\n");
+               errno = ENOBUFS;
+               return 1;
+       }
+
+       // Determine type
+       if (archive->format >= 6)
+               type = pakfire_path_relpath(".scriptlets/", path);
+       else if (archive->format >= 1)
+               type = pakfire_path_relpath("scriptlet/", path);
+
+       if (!type) {
+               ERROR(archive->pakfire, "Could not determine the scriptlet type from '%s'\n", path);
+               errno = EINVAL;
+               return 1;
+       }
+
+       // Allocate a scriptlet
+       r = pakfire_scriptlet_create(&scriptlet, archive->pakfire, type, data, length);
+       if (r)
+               return r;
+
+       // Store scriptlet
+       archive->scriptlets[archive->num_scriptlets++] = scriptlet;
+
+       return 0;
+}
+
 static int __pakfire_archive_read_metadata(struct pakfire_archive* archive,
                struct archive* a, struct archive_entry* entry, void* p) {
        char* data = NULL;
@@ -500,6 +535,12 @@ static int __pakfire_archive_read_metadata(struct pakfire_archive* archive,
                        r = pakfire_archive_parse_json_metadata(archive, data, length);
                        if (r)
                                goto ERROR;
+
+               // Parse scriptlets
+               } else if (pakfire_string_startswith(path, ".scriptlets/")) {
+                       r = pakfire_archive_parse_scriptlet(archive, path, data, length);
+                       if (r)
+                               goto ERROR;
                }
 
        // Format >= 1
@@ -509,6 +550,12 @@ static int __pakfire_archive_read_metadata(struct pakfire_archive* archive,
                        r = pakfire_archive_parse_legacy_metadata(archive, data, length);
                        if (r)
                                goto ERROR;
+
+               // Parse scriptlets
+               } else if (pakfire_string_startswith(path, "scriptlet/")) {
+                       r = pakfire_archive_parse_scriptlet(archive, path, data, length);
+                       if (r)
+                               goto ERROR;
                }
 
        // pakfire-format
@@ -1307,71 +1354,19 @@ PAKFIRE_EXPORT int pakfire_archive_make_package(struct pakfire_archive* archive,
        return r;
 }
 
-static int pakfire_archive_load_scriptlet(struct pakfire_archive* archive,
-               struct archive* a, struct archive_entry* e, void* data) {
-       const char* path = archive_entry_pathname(e);
-
-       // Skip if this isn't a scriptlet
-       if (!pakfire_string_startswith(path, "scriptlet/"))
-               return 0;
-
-       char* buffer = NULL;
-       size_t size = 0;
-       int r;
-
-       // Fetch scriptlet
-       r = pakfire_archive_copy_data_to_buffer(archive->pakfire, a, e, &buffer, &size);
-       if (r)
-               goto ERROR;
-
-       struct pakfire_scriptlet* scriptlet = NULL;
-       const char* type = path + strlen("scriptlet/");
-
-       // Allocate a scriptlet
-       r = pakfire_scriptlet_create(&scriptlet, archive->pakfire, type, buffer, size);
-       if (r)
-               goto ERROR;
-
-       int* counter = (int*)data;
-
-       // Make space for the new scriptlet
-       archive->scriptlets = reallocarray(archive->scriptlets, *counter + 2,
-               sizeof(*archive->scriptlets));
-
-       archive->scriptlets[(*counter)++] = scriptlet;
-
-ERROR:
-       if (buffer)
-               free(buffer);
-
-       return r;
-}
-
-static int pakfire_archive_load_scriptlets(struct pakfire_archive* archive) {
-       // Nothing to do
-       if (archive->scriptlets_loaded)
-               return 0;
-
-       int counter = 0;
-
-       return pakfire_archive_walk(archive, pakfire_archive_load_scriptlet, NULL, &counter);
-}
-
 struct pakfire_scriptlet* pakfire_archive_get_scriptlet(
                struct pakfire_archive* archive, const char* type) {
-       int r = pakfire_archive_load_scriptlets(archive);
-       if (r) {
-               ERROR(archive->pakfire, "Could not load scriptlets: %m\n");
-               return NULL;
-       }
+       struct pakfire_scriptlet* scriptlet = NULL;
 
-       if (archive->scriptlets) {
-               for (struct pakfire_scriptlet** scriptlet = archive->scriptlets; *scriptlet; scriptlet++) {
-                       const char* t = pakfire_scriptlet_get_type(*scriptlet);
+       for (unsigned int i = 0; i < archive->num_scriptlets; i++) {
+               scriptlet = archive->scriptlets[i];
 
-                       if (strcmp(t, type) == 0)
-                               return pakfire_scriptlet_ref(*scriptlet);
-               }
+               // Fetch type
+               const char* t = pakfire_scriptlet_get_type(scriptlet);
+
+               // Compare type
+               if (strcmp(t, type) == 0)
+                       return pakfire_scriptlet_ref(scriptlet);
        }
 
        return NULL;