From: Michael Tremer Date: Mon, 5 Sep 2022 13:18:45 +0000 (+0000) Subject: compress: Build a common compression function X-Git-Tag: 0.9.28~333 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1e0d6cca18414386a2bc23db363dc2442ca7bc3c;p=pakfire.git compress: Build a common compression function Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/compress.c b/src/libpakfire/compress.c index a8050cdc9..0621cf069 100644 --- a/src/libpakfire/compress.c +++ b/src/libpakfire/compress.c @@ -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; +} diff --git a/src/libpakfire/include/pakfire/compress.h b/src/libpakfire/include/pakfire/compress.h index b3c3629a6..ca8239e44 100644 --- a/src/libpakfire/include/pakfire/compress.h +++ b/src/libpakfire/include/pakfire/compress.h @@ -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 */ diff --git a/src/libpakfire/snapshot.c b/src/libpakfire/snapshot.c index 0b1d03194..4fb7b682a 100644 --- a/src/libpakfire/snapshot.c +++ b/src/libpakfire/snapshot.c @@ -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; }