Initializes the build environment
*/
static int pakfire_build_init(struct pakfire_build* build) {
- FILE* f = NULL;
- char path[PATH_MAX];
int r;
// Don't do it again
return 0;
}
- // Compose path for snapshot
- r = pakfire_cache_path(build->pakfire, path, "%s", "snapshot.tar.zst");
- if (r) {
- 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;
// Extract snapshot
if (!pakfire_build_has_flag(build, PAKFIRE_BUILD_DISABLE_SNAPSHOT)) {
- // Open the snapshot
- f = fopen(path, "r");
-
- // Try restoring the snapshot
- if (f) {
- r = pakfire_snapshot_restore(build->pakfire, f);
- fclose(f);
-
- // Exit on error
- if (r)
- return r;
- }
+ r = pakfire_snapshot_restore(build->pakfire);
+ if (r)
+ return r;
}
// Install or update any build dependencies
// Update the snapshot if there were changes
if (!pakfire_build_has_flag(build, PAKFIRE_BUILD_DISABLE_SNAPSHOT) && snapshot_needs_update) {
- // Open snapshot file for writing
- f = fopen(path, "w");
- if (!f) {
- ERROR(build->pakfire, "Could not open snapshot file for writing: %m\n");
- return 1;
- }
-
// Create a new snapshot
- r = pakfire_snapshot_create(build->pakfire, f);
- fclose(f);
-
+ r = pakfire_snapshot_create(build->pakfire);
if (r)
return r;
}
#include <pakfire/private.h>
#include <pakfire/repo.h>
#include <pakfire/snapshot.h>
+#include <pakfire/string.h>
#include <pakfire/util.h>
+#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;
+}
+
static struct archive* pakfire_snapshot_create_archive(struct pakfire* pakfire, FILE* f) {
struct archive* a = archive_write_new();
if (!a) {
return NULL;
}
-int pakfire_snapshot_create(struct pakfire* pakfire, FILE* snapshot) {
+int pakfire_snapshot_compress(struct pakfire* pakfire, FILE* f) {
struct pakfire_filelist* filelist = NULL;
struct archive* archive = NULL;
int r = 1;
- if (!snapshot) {
+ // Check input
+ if (!f) {
errno = EINVAL;
return 1;
}
const char* root = pakfire_get_path(pakfire);
- INFO(pakfire, "Creating snapshot of %s...\n", root);
+ DEBUG(pakfire, "Creating snapshot of %s...\n", root);
// Scan for all files
r = pakfire_filelist_scan(filelist, root, NULL, NULL);
}
// Create a new archive
- archive = pakfire_snapshot_create_archive(pakfire, snapshot);
+ archive = pakfire_snapshot_create_archive(pakfire, f);
if (!archive) {
ERROR(pakfire, "Could not open archive for writing\n");
goto ERROR;
return r;
}
-static int pakfire_snapshot_extract(struct pakfire* pakfire, FILE* f) {
+int pakfire_snapshot_create(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) {
return r;
}
-int pakfire_snapshot_restore(struct pakfire* pakfire, FILE* f) {
+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) {
- errno = EINVAL;
+ // 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
- int r = pakfire_snapshot_extract(pakfire, f);
+ r = pakfire_snapshot_extract(pakfire, f);
if (r)
- return r;
+ goto ERROR;
- struct pakfire_repo* repo = pakfire_get_installed_repo(pakfire);
+ repo = pakfire_get_installed_repo(pakfire);
if (!repo)
goto ERROR;
pakfire_repo_unref(repo);
if (db)
pakfire_db_unref(db);
+ if (f)
+ fclose(f);
return r;
}
ASSERT(f);
// Create the snapshot
- ASSERT_SUCCESS(pakfire_snapshot_create(t->pakfire, f));
+ ASSERT_SUCCESS(pakfire_snapshot_compress(t->pakfire, f));
// Determine the size of the snapshot
size_t size = ftell(f);
rewind(f);
// Perform a restore
- ASSERT_SUCCESS(pakfire_snapshot_restore(t->pakfire, f));
+ ASSERT_SUCCESS(pakfire_snapshot_extract(t->pakfire, f));
// Everything passed
r = EXIT_SUCCESS;
int r = EXIT_FAILURE;
// pakfire_snapshot_create
- ASSERT_ERRNO(pakfire_snapshot_create(t->pakfire, NULL), EINVAL);
+ ASSERT_ERRNO(pakfire_snapshot_compress(t->pakfire, NULL), EINVAL);
// pakfire_snapshot_restore
- ASSERT_ERRNO(pakfire_snapshot_restore(t->pakfire, NULL), EINVAL);
+ ASSERT_ERRNO(pakfire_snapshot_extract(t->pakfire, NULL), EINVAL);
// Everything passed
r = EXIT_SUCCESS;