]> git.ipfire.org Git - pakfire.git/commitdiff
archive: Build reading payload files for format >= 6
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 1 Sep 2022 17:58:04 +0000 (17:58 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 1 Sep 2022 17:58:04 +0000 (17:58 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/archive.c

index 777d6c5eebd848d344d60e4d2f030a8e70cc208c..d763a20dfb685c9442119339369b4d7cc546b246 100644 (file)
@@ -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;