]> git.ipfire.org Git - pakfire.git/commitdiff
compress: Build a common compression function
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 5 Sep 2022 13:18:45 +0000 (13:18 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 5 Sep 2022 13:18:45 +0000 (13:18 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/compress.c
src/libpakfire/include/pakfire/compress.h
src/libpakfire/snapshot.c

index a8050cdc94b801c120fc78982b060e926628986e..0621cf06946e7cd717310d2f5c3adf555997069e 100644 (file)
@@ -807,3 +807,167 @@ ERROR:
 
        return r;
 }
+
+// Common compression
+
+struct pakfire_compress {
+       // Reference to Pakfire
+       struct pakfire* pakfire;
+
+       // Flags
+       int flags;
+
+       // The archive to write to
+       struct archive* archive;
+
+       // The filelist of all files to write
+       struct pakfire_filelist* filelist;
+
+       // The progressbar
+       struct pakfire_progressbar* progressbar;
+
+       // Digests to write to the archive
+       int digests;
+};
+
+static int pakfire_compress_progressbar_create(struct pakfire_progressbar** progressbar,
+               const char* message, int flags) {
+       int r;
+
+       // Create the progressbar
+       r = pakfire_progressbar_create(progressbar, NULL);
+       if (r)
+               return r;
+
+       // Add message
+       if (message) {
+               r = pakfire_progressbar_add_string(*progressbar, "%s", message);
+               if (r)
+                       return r;
+       }
+
+       // Add bar
+       r = pakfire_progressbar_add_bar(*progressbar);
+       if (r)
+               return r;
+
+       // Add throughput
+       if (flags & PAKFIRE_COMPRESS_SHOW_THROUGHPUT) {
+               r = pakfire_progressbar_add_transfer_speed(*progressbar);
+               if (r)
+                       return r;
+       }
+
+       // Add percentage
+       r = pakfire_progressbar_add_percentage(*progressbar);
+       if (r)
+               return r;
+
+       // Success
+       return 0;
+}
+
+static int __pakfire_compress(struct pakfire* pakfire, struct pakfire_file* file, void* p) {
+       struct archive_entry* entry = NULL;
+       FILE* f = NULL;
+       int r = 1;
+
+       struct pakfire_compress* data = (struct pakfire_compress*)p;
+
+       // Fetch type
+       const mode_t type = pakfire_file_get_type(file);
+
+       // Fetch the filelist
+       const size_t size = pakfire_file_get_size(file);
+
+       // Generate file metadata into an archive entry
+       entry = pakfire_file_archive_entry(file, data->digests);
+       if (!entry) {
+               r = 1;
+               goto ERROR;
+       }
+
+       // Write the header
+       r = archive_write_header(data->archive, entry);
+       if (r) {
+               ERROR(pakfire, "Error writing file header: %s\n",
+                       archive_error_string(data->archive));
+               goto ERROR;
+       }
+
+       // Copy the data of regular files
+       if (type == S_IFREG) {
+               // Open the file
+               f = pakfire_file_open(file);
+               if (!f) {
+                       r = 1;
+                       goto ERROR;
+               }
+
+               // Copy the payload into the archive
+               r = pakfire_archive_copy_data_from_file(pakfire, data->archive, f);
+               if (r)
+                       goto ERROR;
+       }
+
+       // Write trailer
+       r = archive_write_finish_entry(data->archive);
+       if (r)
+               goto ERROR;
+
+       // Update the progressbar
+       if (data->progressbar)
+               pakfire_progressbar_increment(data->progressbar, size);
+
+ERROR:
+       if (f)
+               fclose(f);
+       if (entry)
+               archive_entry_free(entry);
+
+       return r;
+}
+
+int pakfire_compress(struct pakfire* pakfire, struct archive* archive,
+               struct pakfire_filelist* filelist, const char* message, int flags, int digests) {
+       int r = 1;
+
+       struct pakfire_compress data = {
+               .pakfire  = pakfire,
+               .archive  = archive,
+               .filelist = filelist,
+               .flags    = flags,
+               .digests  = digests,
+       };
+
+       // Should we show a progress bar?
+       const int no_progress = flags & PAKFIRE_COMPRESS_NO_PROGRESS;
+
+       // Fetch the length of the filelist
+       const size_t size = pakfire_filelist_total_size(filelist);
+
+       // Create the progressbar
+       if (!no_progress) {
+               r = pakfire_compress_progressbar_create(&data.progressbar, message, flags);
+               if (r)
+                       goto ERROR;
+
+               // Start progressbar
+               pakfire_progressbar_start(data.progressbar, size);
+       }
+
+       // Walk through the entire filelist
+       r = pakfire_filelist_walk(filelist, __pakfire_compress, &data);
+       if (r)
+               goto ERROR;
+
+       // Finish the progressbar
+       if (data.progressbar)
+               pakfire_progressbar_finish(data.progressbar);
+
+ERROR:
+       if (data.progressbar)
+               pakfire_progressbar_unref(data.progressbar);
+
+       return r;
+}
index b3c3629a690bec8fb67ca0807e75d5ec63ee7af0..ca8239e44d3a9c2e62d5e62b39d7d279eba5a060 100644 (file)
@@ -67,6 +67,15 @@ int pakfire_extract(struct pakfire* pakfire, struct archive* archive,
        size_t size, struct pakfire_filelist* filelist, const char* prefix,
        const char* message, int flags);
 
+// Compress
+enum pakfire_compress_flags {
+       PAKFIRE_COMPRESS_NO_PROGRESS     = (1 << 1),
+       PAKFIRE_COMPRESS_SHOW_THROUGHPUT = (1 << 2),
+};
+
+int pakfire_compress(struct pakfire* pakfire, struct archive* archive,
+       struct pakfire_filelist* filelist, const char* message, int flags, int digests);
+
 #endif
 
 #endif /* PAKFIRE_COMPRESS_H */
index 0b1d0319446f3f8c74effeb1bbb9451be6084bbd..4fb7b682a49850ffa424cf85b16dd80b38783dbb 100644 (file)
@@ -84,7 +84,7 @@ ERROR:
 
 int pakfire_snapshot_create(struct pakfire* pakfire, const char* path) {
        struct pakfire_filelist* filelist = NULL;
-       struct archive* a = NULL;
+       struct archive* archive = NULL;
        int r = 1;
 
        // Check input
@@ -119,69 +119,22 @@ int pakfire_snapshot_create(struct pakfire* pakfire, const char* path) {
        // Sort the filelist in place
        pakfire_filelist_sort(filelist);
 
-       a = pakfire_snapshot_create_archive(pakfire, path);
-       if (!a) {
+       archive = pakfire_snapshot_create_archive(pakfire, path);
+       if (!archive) {
                ERROR(pakfire, "Could not open archive for writing\n");
                goto ERROR;
        }
 
-       for (unsigned int i = 0; i < size; i++) {
-               struct pakfire_file* file = pakfire_filelist_get(filelist, i);
-               if (!file)
-                       continue;
-
-               FILE* f = NULL;
-
-               // Make archive entry
-               struct archive_entry* entry = pakfire_file_archive_entry(file, PAKFIRE_DIGEST_UNDEFINED);
-               if (!entry) {
-                       ERROR(pakfire, "Could not make archive entry from file: %m\n");
-                       r = 1;
-                       goto OUT;
-               }
-
-               // Write header
-               r = archive_write_header(a, entry);
-               if (r) {
-                       ERROR(pakfire, "Could not write header: %s\n", archive_error_string(a));
-                       goto OUT;
-               }
-
-               // Copy payload
-               if (archive_entry_filetype(entry) == AE_IFREG) {
-                       f = pakfire_file_open(file);
-                       if (!f) {
-                               r = 1;
-                               goto OUT;
-                       }
-
-                       r = pakfire_archive_copy_data_from_file(pakfire, a, f);
-                       if (r) {
-                               ERROR(pakfire, "Could not copy %s\n", archive_entry_pathname(entry));
-                               goto OUT;
-                       }
-               }
-
-               // Write trailer
-               r = archive_write_finish_entry(a);
-               if (r)
-                       goto OUT;
-
-OUT:
-               if (file)
-                       pakfire_file_unref(file);
-               if (f)
-                       fclose(f);
-
-               // Move on to ERROR
-               if (r)
-                       goto ERROR;
-       }
+       // Write the payload to the archive
+       r = pakfire_compress(pakfire, archive, filelist, _("Writing snapshot..."),
+               PAKFIRE_COMPRESS_SHOW_THROUGHPUT, 0);
+       if (r)
+               goto ERROR;
 
        // Close archive
-       r = archive_write_close(a);
+       r = archive_write_close(archive);
        if (r) {
-               ERROR(pakfire, "Could not close archive: %s\n", archive_error_string(a));
+               ERROR(pakfire, "Could not close archive: %s\n", archive_error_string(archive));
                goto ERROR;
        }
 
@@ -191,8 +144,8 @@ OUT:
 ERROR:
        if (filelist)
                pakfire_filelist_unref(filelist);
-       if (a)
-               archive_write_free(a);
+       if (archive)
+               archive_write_free(archive);
 
        return r;
 }