From 1ea7b3608dd0cdf18e64270030c7d7267fc99ec6 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Wed, 17 Aug 2022 13:11:14 +0000 Subject: [PATCH] snapshot: Refactor composing archive Signed-off-by: Michael Tremer --- src/libpakfire/build.c | 23 +++++---- src/libpakfire/snapshot.c | 104 +++++++++++++++++++++----------------- 2 files changed, 71 insertions(+), 56 deletions(-) diff --git a/src/libpakfire/build.c b/src/libpakfire/build.c index c5fdd9a5..7c37fbdc 100644 --- a/src/libpakfire/build.c +++ b/src/libpakfire/build.c @@ -1165,28 +1165,29 @@ static int pakfire_build_init(struct pakfire_build* build) { } } + // Compose path for snapshot + r = pakfire_make_cache_path(build->pakfire, path, "%s", "snapshot.tar.zst"); + if (r < 0) { + ERROR(build->pakfire, "Could not compose snapshot path: %m\n"); + return 1; + } + // Tells us whether we need to (re-)create the snapshot int snapshot_needs_update = 0; - // Check if the user wants a snapshot extracted + // Extract snapshot if (!pakfire_build_has_flag(build, PAKFIRE_BUILD_DISABLE_SNAPSHOT)) { - // Extract snapshot - r = pakfire_make_cache_path(build->pakfire, path, "%s", "snapshot.tar.zst"); - if (r < 0) { - ERROR(build->pakfire, "Could not compose snapshot path: %m\n"); - return 1; - } - // Open the snapshot f = fopen(path, "r"); // Try restoring the snapshot if (f) { r = pakfire_snapshot_restore(build->pakfire, f); - if (r) { - fclose(f); + fclose(f); + + // Exit on error + if (r) return r; - } } } diff --git a/src/libpakfire/snapshot.c b/src/libpakfire/snapshot.c index 968b225b..8214a594 100644 --- a/src/libpakfire/snapshot.c +++ b/src/libpakfire/snapshot.c @@ -116,84 +116,97 @@ ERROR: return NULL; } -int pakfire_snapshot_create(struct pakfire* pakfire, FILE* f) { +int pakfire_snapshot_create(struct pakfire* pakfire, FILE* snapshot) { + struct pakfire_filelist* filelist = NULL; + struct archive* a = NULL; int r = 1; - if (!f) { + if (!snapshot) { errno = EINVAL; return 1; } + // Create a new filelist + r = pakfire_filelist_create(&filelist, pakfire); + if (r) + goto ERROR; + const char* root = pakfire_get_path(pakfire); INFO(pakfire, "Creating snapshot of %s...\n", root); - struct archive* a = pakfire_snapshot_create_archive(pakfire, f); - if (!a) { - ERROR(pakfire, "Could not open archive for writing\n"); - return 1; - } - - // Create disk reader - struct archive* reader = pakfire_make_archive_disk_reader(pakfire, 1); - if (!reader) + // Scan for all files + r = pakfire_filelist_scan(filelist, root, NULL, NULL); + if (r) goto ERROR; - // Open path - r = archive_read_disk_open(reader, root); - if (r) { - ERROR(pakfire, "Could not open %s: %s\n", root, archive_error_string(reader)); + const size_t size = pakfire_filelist_size(filelist); + + // Check if we have any files + if (!size) { + ERROR(pakfire, "The snapshot is unexpectedly empty\n"); + r = 1; goto ERROR; } - struct archive_entry* entry = NULL; - while (1) { - r = archive_read_next_header(reader, &entry); - if (r == ARCHIVE_EOF) - break; - else if (r == ARCHIVE_RETRY) - continue; - else if (r) { - ERROR(pakfire, "Could not read next entry: %s\n", archive_error_string(reader)); - goto ERROR; - } - - const char* full_path = archive_entry_pathname(entry); + // Sort the filelist in place + pakfire_filelist_sort(filelist); - // Compute the relative path - const char* path = pakfire_path_relpath(root, full_path); - if (!path) - continue; + a = pakfire_snapshot_create_archive(pakfire, snapshot); + if (!a) { + ERROR(pakfire, "Could not open archive for writing\n"); + goto ERROR; + } - // Skip mountpoints - if (pakfire_is_mountpoint(pakfire, full_path)) { - DEBUG(pakfire, "Skipping mountpoint %s...\n", path); + for (unsigned int i = 0; i < size; i++) { + struct pakfire_file* file = pakfire_filelist_get(filelist, i); + if (!file) continue; - } - archive_read_disk_descend(reader); + FILE* f = NULL; - // Reset path to relative path in archive - archive_entry_set_pathname(entry, path); + // Make archive entry + struct archive_entry* entry = pakfire_file_archive_entry(file); + 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 ERROR; + goto OUT; } // Copy payload if (archive_entry_filetype(entry) == AE_IFREG) { - r = pakfire_archive_copy_data(pakfire, reader, a); + 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 ERROR; + 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; } @@ -209,9 +222,10 @@ int pakfire_snapshot_create(struct pakfire* pakfire, FILE* f) { r = 0; ERROR: - if (reader) - archive_read_free(reader); - archive_write_free(a); + if (filelist) + pakfire_filelist_unref(filelist); + if (a) + archive_write_free(a); return r; } -- 2.47.3