From: Michael Tremer Date: Thu, 1 Sep 2022 11:42:41 +0000 (+0000) Subject: archive: Parse scriptlets when the archive is opened for the first time X-Git-Tag: 0.9.28~341 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c3e629fdf6dd5534aebdbbb1c6d43666cdc411d8;p=pakfire.git archive: Parse scriptlets when the archive is opened for the first time Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/archive.c b/src/libpakfire/archive.c index f97ce86d7..777d6c5ee 100644 --- a/src/libpakfire/archive.c +++ b/src/libpakfire/archive.c @@ -49,6 +49,8 @@ #include #include +#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;