#include <pakfire/string.h>
#include <pakfire/util.h>
+#define MAX_SCRIPTLETS 9
+
struct pakfire_archive {
struct pakfire* pakfire;
int nrefs;
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;
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);
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;
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
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
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;