]> git.ipfire.org Git - people/ms/pakfire.git/commitdiff
packager: Append payload to the archive
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 21 Aug 2022 13:33:34 +0000 (13:33 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sun, 21 Aug 2022 13:33:34 +0000 (13:33 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/packager.c

index 43b6ce96e2f8b2f42e18669968be32fc5f49ba7a..afe0d2c517c6875f9a4575654353b70ed74084b1 100644 (file)
@@ -331,60 +331,78 @@ static int pakfire_packager_write_metadata(struct pakfire_packager* packager,
        return r;
 }
 
-static int pakfire_packager_write_archive(struct pakfire_packager* packager,
-               struct archive* a, const char* filename,
-               struct archive** payload, FILE* f) {
-       struct stat st;
+static int pakfire_packager_copy_archive(struct pakfire_packager* packager,
+               struct archive* a, FILE* f) {
+       struct archive* payload = NULL;
+       struct archive_entry* entry = NULL;
+       int r;
 
-       DEBUG(packager->pakfire, "Writing '%s' to package\n", filename);
-
-       // Close the payload
-       if (*payload) {
-               archive_write_free(*payload);
-               *payload = NULL;
-       }
+       DEBUG(packager->pakfire, "Copying payload\n");
 
        // Reset fd to beginning of the file
        rewind(f);
 
-       int fd = fileno(f);
+       // Re-open the payload archive for reading
+       payload = archive_read_new();
+       if (!payload) {
+               ERROR(packager->pakfire, "Could not create archive reader: %m\n");
+               r = 1;
+               goto ERROR;
+       }
 
-       // Stat the payload file
-       int r = fstat(fd, &st);
+       // We expect a tar archive
+       r = archive_read_support_format_tar(payload);
        if (r) {
-               ERROR(packager->pakfire, "stat() on fd %d failed: %m\n", fd);
-               return 1;
+               ERROR(packager->pakfire, "Could not add support for tar: %s\n",
+                       archive_error_string(payload));
+               goto ERROR;
        }
 
-       // Create a new file
-       struct archive_entry* entry = pakfire_packager_create_file(packager,
-                       filename, st.st_size, 0444);
-       if (!entry)
-               return 1;
-
-       // This is the end of the header
-       r = archive_write_header(a, entry);
+       // Open the file handle
+       r = archive_read_open_FILE(payload, f);
        if (r) {
-               ERROR(packager->pakfire, "Error writing header: %s\n", archive_error_string(a));
+               ERROR(packager->pakfire, "Could not open payload: %s\n",
+                       archive_error_string(payload));
                goto ERROR;
        }
 
-       // Copy data
-       r = pakfire_archive_copy_data_from_file(packager->pakfire, a, f);
-       if (r) {
-               const char* error = archive_error_string(a);
-               if (!error)
-                       error = strerror(errno);
+       // Copy all files into our archive
+       for (;;) {
+               r = archive_read_next_header(payload, &entry);
 
-               ERROR(packager->pakfire, "Could not copy payload: %s\n", error);
-               goto ERROR;
+               // End when we have reached the end of the archive
+               if (r == ARCHIVE_EOF) {
+                       r = 0;
+                       break;
+               }
+
+               // Raise any other errors
+               else if (r) {
+                       ERROR(packager->pakfire, "Could not read next header: %s\n",
+                               archive_error_string(payload));
+                       goto ERROR;
+               }
+
+               // Write the entry
+               r = archive_write_header(a, entry);
+               if (r) {
+                       ERROR(packager->pakfire, "Could not write entry: %s\n",
+                               archive_error_string(a));
+                       goto ERROR;
+               }
+
+               // Copy the data
+               r = pakfire_archive_copy_data(packager->pakfire, payload, a);
+               if (r)
+                       goto ERROR;
        }
 
        // Success
        r = 0;
 
 ERROR:
-       archive_entry_free(entry);
+       if (payload)
+               archive_read_free(payload);
 
        return r;
 }
@@ -418,8 +436,20 @@ static int pakfire_packager_write_scriptlet(struct pakfire_packager* packager,
        It will create a new archive and write the package to the given file descriptor.
 */
 int pakfire_packager_finish(struct pakfire_packager* packager, FILE* f) {
+       struct archive* a = NULL;
        int r = 1;
 
+       // Close the payload
+       if (packager->payload) {
+               r = archive_write_free(packager->payload);
+               if (r) {
+                       ERROR(packager->pakfire, "Could not close payload: %s\n",
+                               archive_error_string(packager->payload));
+                       goto ERROR;
+               }
+               packager->payload = NULL;
+       }
+
        // Add requires feature markers
        if (pakfire_package_has_rich_deps(packager->pkg))
                pakfire_package_add_requires(packager->pkg, "pakfire(RichDependencies)");
@@ -435,7 +465,7 @@ int pakfire_packager_finish(struct pakfire_packager* packager, FILE* f) {
        }
 
        // Open a new archive
-       struct archive* a = archive_write_new();
+       a = archive_write_new();
        if (!a) {
                ERROR(packager->pakfire, "archive_write_new() failed\n");
                goto ERROR;
@@ -514,8 +544,7 @@ int pakfire_packager_finish(struct pakfire_packager* packager, FILE* f) {
 
        // Write the payload
        if (packager->files) {
-               r = pakfire_packager_write_archive(packager, a, "DATA",
-                       &packager->payload, packager->fpayload);
+               r = pakfire_packager_copy_archive(packager, a, packager->fpayload);
                if (r) {
                        ERROR(packager->pakfire, "Could not add payload to archive: %s\n",
                                archive_error_string(a));