From: Michael Tremer Date: Thu, 1 Sep 2022 17:58:04 +0000 (+0000) Subject: archive: Build reading payload files for format >= 6 X-Git-Tag: 0.9.28~339 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=13bcf4702d9701222f1fc218681611730c600e20;p=pakfire.git archive: Build reading payload files for format >= 6 Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/archive.c b/src/libpakfire/archive.c index 777d6c5ee..d763a20df 100644 --- a/src/libpakfire/archive.c +++ b/src/libpakfire/archive.c @@ -738,32 +738,23 @@ PAKFIRE_EXPORT char* pakfire_archive_get(struct pakfire_archive* archive, return pakfire_parser_get(archive->parser, namespace, key); } -PAKFIRE_EXPORT int pakfire_archive_read(struct pakfire_archive* archive, const char* filename, - char** data, size_t* size) { +static int __pakfire_archive_read_legacy(struct pakfire_archive* archive, + const char* path, char** data, size_t* length) { + int r = 1; + struct archive* a = NULL; struct archive_entry* entry = NULL; - int r = 0; - - if (!filename || !data || !size) { - errno = EINVAL; - return 1; - } - - // Strip leading / from filenames, because the payload does - // not have leading slashes. - while (*filename == '/') - filename++; struct archive* payload = pakfire_archive_open_payload(archive, &a, NULL); if (!payload) goto ERROR; - r = find_archive_entry(archive, &entry, payload, filename); + r = find_archive_entry(archive, &entry, payload, path); if (r) goto ERROR; r = pakfire_archive_copy_data_to_buffer(archive->pakfire, payload, entry, - data, size); + data, length); ERROR: if (payload) @@ -773,6 +764,76 @@ ERROR: return r; } +struct pakfire_archive_read { + 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) { + const char* path = NULL; + + // Format >= 6 + if (archive->format >= 6) { + path = archive_entry_pathname(entry); + + // Skip any hidden files + if (path && *path == '.') + return ARCHIVE_RETRY; + } + + // Otherwise permit reading any files + 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; + 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, + _read->data, _read->length); + if (r) + return r; + } + + return 0; +} + +static int __pakfire_archive_read(struct pakfire_archive* archive, + const char* path, char** data, size_t* length) { + struct pakfire_archive_read _read = { + .path = path, + .data = data, + .length = length, + }; + + // Walk through the archive + return pakfire_archive_walk(archive, __pakfire_archive_read_payload, + __pakfire_archive_filter_payload, &_read); +} + +PAKFIRE_EXPORT int pakfire_archive_read(struct pakfire_archive* archive, + const char* path, char** data, size_t* length) { + // Strip leading / from filenames, because tarballs don't use any leading slashes + path = pakfire_path_relpath("/", path); + + // Check inputs + if (!path || !data || !length) { + errno = EINVAL; + return 1; + } + + if (archive->format >= 6) + return __pakfire_archive_read(archive, path, data, length); + else + return __pakfire_archive_read_legacy(archive, path, data, length); +} + int pakfire_archive_copy(struct pakfire_archive* archive, const char* path) { if (!path) { errno = EINVAL;