From: Michael Tremer Date: Thu, 1 Sep 2022 19:04:40 +0000 (+0000) Subject: walk: Attempt to create some common function to walk through archives X-Git-Tag: 0.9.28~337 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d9302cc396408cdf9773047693fd10befae91c69;p=pakfire.git walk: Attempt to create some common function to walk through archives We are (re-)implementing this over and over again with different, but very similar features, so it might make a lot more sense to try to unify this code. Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/archive.c b/src/libpakfire/archive.c index d763a20df..1bc9776bb 100644 --- a/src/libpakfire/archive.c +++ b/src/libpakfire/archive.c @@ -135,61 +135,9 @@ ERROR: return r; } -static int pakfire_archive_walk_entries(struct pakfire_archive* archive, struct archive* a, - int (*callback)(struct pakfire_archive* archive, struct archive* a, - struct archive_entry* e, void* data), - int (*filter_callback)(struct pakfire_archive* archive, struct archive* a, - struct archive_entry* e, void* data), - void* data) { - struct archive_entry* e = NULL; - - // Walk through the archive - while (1) { - int r = archive_read_next_header(a, &e); - - // Return OK when we reached the end of the archive - if (r == ARCHIVE_EOF) - return ARCHIVE_OK; - - // Raise any other errors - else if (r) - return r; - - // Call the filter callback before we call the actual callback - if (filter_callback) { - r = filter_callback(archive, a, e, data); - - // End processing the archive if the filter callback asked us to - if (r == ARCHIVE_EOF) - break; - - // Skip this file - else if (r == ARCHIVE_RETRY) - continue; - - // Raise any errors - else if (r) - return r; - } - - // Run callback - if (callback) { - r = callback(archive, a, e, data); - if (r) - return r; - } - } - - return 0; -} - static int pakfire_archive_walk(struct pakfire_archive* archive, - int (*callback)(struct pakfire_archive* archive, struct archive* a, - struct archive_entry* e, void* data), - int (*filter_callback)(struct pakfire_archive* archive, struct archive* a, - struct archive_entry* e, void* data), - void* data) { - struct archive* a; + pakfire_walk_callback callback, pakfire_walk_filter_callback filter_callback, void* data) { + struct archive* a = NULL; // Open the archive file int r = open_archive(archive, &a); @@ -197,10 +145,11 @@ static int pakfire_archive_walk(struct pakfire_archive* archive, return r; // Walk through the archive - r = pakfire_archive_walk_entries(archive, a, callback, filter_callback, data); + r = pakfire_walk(archive->pakfire, a, callback, filter_callback, data); // Close the archive - close_archive(archive, a); + if (a) + close_archive(archive, a); return r; } @@ -512,8 +461,10 @@ static int pakfire_archive_parse_scriptlet(struct pakfire_archive* archive, return 0; } -static int __pakfire_archive_read_metadata(struct pakfire_archive* archive, - struct archive* a, struct archive_entry* entry, void* p) { +static int __pakfire_archive_read_metadata(struct pakfire* pakfire, struct archive* a, + struct archive_entry* entry, void* p) { + struct pakfire_archive* archive = (struct pakfire_archive*)p; + char* data = NULL; size_t length = 0; int r; @@ -572,8 +523,10 @@ ERROR: return r; } -static int __pakfire_archive_filter_metadata(struct pakfire_archive* archive, - struct archive* a, struct archive_entry* entry, void* data) { +static int __pakfire_archive_filter_metadata(struct pakfire* pakfire, + struct archive* a, struct archive_entry* entry, void* p) { + struct pakfire_archive* archive = (struct pakfire_archive*)p; + const char* path = archive_entry_pathname(entry); // Format >= 6 @@ -765,13 +718,17 @@ ERROR: } struct pakfire_archive_read { + struct pakfire_archive* archive; const char* path; char** data; size_t* length; }; -static int __pakfire_archive_filter_payload(struct pakfire_archive* archive, - struct archive* a, struct archive_entry* entry, void* data) { +static int __pakfire_archive_filter_payload(struct pakfire* pakfire, + struct archive* a, struct archive_entry* entry, void* p) { + struct pakfire_archive_read* _read = (struct pakfire_archive_read*)p; + struct pakfire_archive* archive = _read->archive; + const char* path = NULL; // Format >= 6 @@ -787,15 +744,15 @@ static int __pakfire_archive_filter_payload(struct pakfire_archive* archive, return ARCHIVE_OK; } -static int __pakfire_archive_read_payload(struct pakfire_archive* archive, - struct archive* a, struct archive_entry* entry, void* data) { - struct pakfire_archive_read* _read = (struct pakfire_archive_read*)data; +static int __pakfire_archive_read_payload(struct pakfire* pakfire, + struct archive* a, struct archive_entry* entry, void* p) { + struct pakfire_archive_read* _read = (struct pakfire_archive_read*)p; int r; const char* path = archive_entry_pathname(entry); if (strcmp(_read->path, path) == 0) { - r = pakfire_archive_copy_data_to_buffer(archive->pakfire, a, entry, + r = pakfire_archive_copy_data_to_buffer(pakfire, a, entry, _read->data, _read->length); if (r) return r; diff --git a/src/libpakfire/compress.c b/src/libpakfire/compress.c index c05a53803..5eca76160 100644 --- a/src/libpakfire/compress.c +++ b/src/libpakfire/compress.c @@ -518,6 +518,78 @@ ERROR: return NULL; } +/* + Helper function to conditionally walk through an archive + and perform actions based on the callback. +*/ +int pakfire_walk(struct pakfire* pakfire, struct archive* archive, + pakfire_walk_callback callback, pakfire_walk_filter_callback filter_callback, + void* p) { + struct archive_entry* entry = NULL; + int r; + + // Walk through the archive + for (;;) { + r = archive_read_next_header(archive, &entry); + + // Handle the return code + switch (r) { + // Return OK when we reached the end of the archive + case ARCHIVE_EOF: + return 0; + + // Raise any other errors + default: + return r; + } + + // Call the filter callback before we call the actual callback + if (filter_callback) { + r = filter_callback(pakfire, archive, entry, p); + + // Handle the return code + switch (r) { + case PAKFIRE_WALK_OK: + break; + + case PAKFIRE_WALK_DONE: + DEBUG(pakfire, "Filter callback sent DONE\n"); + return 0; + + case PAKFIRE_WALK_SKIP: + DEBUG(pakfire, "Filter callback sent SKIP\n"); + continue; + + // Raise any other errors + default: + DEBUG(pakfire, "Filter callback received an error: %d\n", r); + return r; + } + } + + // Run callback + if (callback) { + r = callback(pakfire, archive, entry, p); + + // Handle the return code + switch (r) { + case PAKFIRE_WALK_OK: + break; + + case PAKFIRE_WALK_DONE: + DEBUG(pakfire, "Callback sent DONE\n"); + return 0; + + // Raise any other errors + default: + return r; + } + } + } + + return 0; +} + // Common extraction struct pakfire_extract { diff --git a/src/libpakfire/include/pakfire/compress.h b/src/libpakfire/include/pakfire/compress.h index 9ade14a20..b3c3629a6 100644 --- a/src/libpakfire/include/pakfire/compress.h +++ b/src/libpakfire/include/pakfire/compress.h @@ -36,6 +36,26 @@ FILE* pakfire_xzfopen(FILE* f, const char* mode); // ZSTD FILE* pakfire_zstdfopen(FILE* f, const char* mode); +// Walk + +typedef int (*pakfire_walk_callback) + (struct pakfire* pakfire, struct archive* a, struct archive_entry* e, void* p); +typedef int (*pakfire_walk_filter_callback) + (struct pakfire* pakfire, struct archive* a, struct archive_entry* e, void* p); + +enum pakfire_walk_codes { + PAKFIRE_WALK_OK = 0, + + // After this code has been sent, we will not process any further entries + PAKFIRE_WALK_DONE = -10, + + // Request the next entry (only in filter callback) + PAKFIRE_WALK_SKIP = -20, +}; + +int pakfire_walk(struct pakfire* pakfire, struct archive* archive, + pakfire_walk_callback callback, pakfire_walk_filter_callback filter_callback, void* p); + // Extract enum pakfire_extract_flags { PAKFIRE_EXTRACT_DRY_RUN = (1 << 0),