#include <stdlib.h>
#include <sys/mount.h>
-#include <archive.h>
-
-// Enable legacy logging
-#define PAKFIRE_LEGACY_LOGGING
-
-#include <pakfire/compress.h>
-#include <pakfire/db.h>
-#include <pakfire/file.h>
-#include <pakfire/filelist.h>
-#include <pakfire/i18n.h>
#include <pakfire/logging.h>
#include <pakfire/path.h>
-#include <pakfire/private.h>
-#include <pakfire/repo.h>
#include <pakfire/snapshot.h>
#include <pakfire/string.h>
#include <pakfire/util.h>
return 0;
}
-
-#define pakfire_snapshot_path(pakfire, path) \
- __pakfire_snapshot_path(pakfire, path, sizeof(path))
-
-static int __pakfire_snapshot_path(struct pakfire* pakfire, char* path, const size_t length) {
- int r;
-
- // Compose path for snapshot
- r = __pakfire_cache_path(pakfire, path, length, "%s", "snapshot.tar.zst");
- if (r)
- ERROR(pakfire, "Could not compose snapshot path: %m\n");
-
- return r;
-}
-
-int pakfire_snapshot_compress(struct pakfire* pakfire, FILE* f) {
- struct pakfire_filelist* filelist = NULL;
- struct archive* archive = NULL;
- int r = 1;
-
- // Check input
- if (!f) {
- 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);
-
- DEBUG(pakfire, "Creating snapshot of %s...\n", root);
-
- // Scan for all files
- r = pakfire_filelist_scan(filelist, root, NULL, NULL, 0);
- if (r)
- goto ERROR;
-
- // Check if we have any files
- if (pakfire_filelist_is_empty(filelist)) {
- ERROR(pakfire, "The snapshot is unexpectedly empty\n");
- r = 1;
- goto ERROR;
- }
-
- // Create a new archive that is being compressed as fast as possible
- r = pakfire_compress_create_archive(pakfire, &archive, f, PAKFIRE_COMPRESS_ZSTD, 1);
- if (r)
- goto ERROR;
-
- // Write the payload to the archive
- r = pakfire_compress(pakfire, archive, filelist, _("Storing Snapshot"),
- PAKFIRE_COMPRESS_SHOW_THROUGHPUT, 0);
- if (r)
- goto ERROR;
-
- // Close archive
- r = archive_write_close(archive);
- if (r) {
- ERROR(pakfire, "Could not close archive: %s\n", archive_error_string(archive));
- goto ERROR;
- }
-
- // Success
- r = 0;
-
-ERROR:
- if (filelist)
- pakfire_filelist_unref(filelist);
- if (archive)
- archive_write_free(archive);
-
- return r;
-}
-
-int pakfire_snapshot_store(struct pakfire* pakfire) {
- FILE* f = NULL;
- char tmppath[PATH_MAX];
- char path[PATH_MAX];
- int r;
-
- // Compose the destination path
- r = pakfire_snapshot_path(pakfire, path);
- if (r)
- goto ERROR;
-
- // Make the temporary path
- r = pakfire_string_format(tmppath, "%s.XXXXXX", path);
- if (r)
- goto ERROR;
-
- // Create a new temporary file
- f = pakfire_mktemp(tmppath, 0644);
- if (!f) {
- ERROR(pakfire, "Could not create a new snapshot: %m\n");
- r = 1;
- goto ERROR;
- }
-
- // Write the snapshot
- r = pakfire_snapshot_compress(pakfire, f);
- if (r)
- goto ERROR;
-
- // Unlink any previous snapshots
- unlink(path);
-
- // Link the new snapshot
- r = link(tmppath, path);
- if (r) {
- ERROR(pakfire, "Could not create snapshot %s: %m\n", path);
- goto ERROR;
- }
-
-ERROR:
- if (f)
- fclose(f);
- if (*tmppath)
- unlink(tmppath);
-
- return r;
-}
-
-int pakfire_snapshot_extract(struct pakfire* pakfire, FILE* f) {
- struct stat st;
- int r = 1;
-
- // Check input
- if (!f) {
- errno = EINVAL;
- return 1;
- }
-
- // Stat the input file
- r = fstat(fileno(f), &st);
- if (r) {
- ERROR(pakfire, "Could not stat snapshot: %m\n");
- return 1;
- }
-
- const char* path = pakfire_get_path(pakfire);
-
- struct archive* archive = archive_read_new();
- if (!archive)
- return 1;
-
- // All snapshots are tarballs
- archive_read_support_format_tar(archive);
-
- // And they are compressed using ZSTD
- archive_read_support_filter_zstd(archive);
-
- // Open the given file for reading
- r = archive_read_open_FILE(archive, f);
- if (r) {
- ERROR(pakfire, "Could not open archive: %s\n", archive_error_string(archive));
- goto ERROR;
- }
-
- // Extract snapshot
- r = pakfire_extract(pakfire, archive, st.st_size, NULL, path,
- _("Restoring Snapshot"), NULL, PAKFIRE_EXTRACT_SHOW_THROUGHPUT);
- if (r)
- goto ERROR;
-
-ERROR:
- if (archive)
- archive_read_free(archive);
-
- return r;
-}
-
-int pakfire_snapshot_restore(struct pakfire* pakfire) {
- struct pakfire_repo* repo = NULL;
- struct pakfire_db* db = NULL;
- char path[PATH_MAX];
- FILE* f = NULL;
- int r;
-
- // Make path
- r = pakfire_snapshot_path(pakfire, path);
- if (r)
- goto ERROR;
-
- // Open the snapshot
- f = fopen(path, "r");
- if (!f) {
- // It is not fatal if the snapshot doesn't exist
- if (errno == ENOENT)
- return 0;
-
- ERROR(pakfire, "Could not open snapshot file %s: %m\n", path);
- return 1;
- }
-
- // Extract the archive
- r = pakfire_snapshot_extract(pakfire, f);
- if (r)
- goto ERROR;
-
- repo = pakfire_get_installed_repo(pakfire);
- if (!repo)
- goto ERROR;
-
- // Reload the database
- r = pakfire_db_open(&db, pakfire, PAKFIRE_DB_READWRITE);
- if (r)
- goto ERROR;
-
- r = pakfire_db_load(db, repo);
-
-ERROR:
- if (repo)
- pakfire_repo_unref(repo);
- if (db)
- pakfire_db_unref(db);
- if (f)
- fclose(f);
-
- return r;
-}