Py_RETURN_NONE;
}
+static PyObject* Pakfire_restore_snapshot(PakfireObject* self, PyObject* args) {
+ const char* path = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &path))
+ return NULL;
+
+ FILE* f = fopen(path, "r");
+ if (!f) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+
+ int r = pakfire_snapshot_restore(self->pakfire, f);
+ fclose(f);
+
+ if (r) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
static struct PyMethodDef Pakfire_methods[] = {
{
"bind",
METH_VARARGS,
NULL
},
+ {
+ "restore_snapshot",
+ (PyCFunction)Pakfire_restore_snapshot,
+ METH_VARARGS,
+ NULL,
+ },
{
"version_compare",
(PyCFunction)Pakfire_version_compare,
#include <errno.h>
#include <stdio.h>
+#include <stdlib.h>
#include <archive.h>
pakfire_file_unref(file);
}
+ // Close archive
+ r = archive_write_close(a);
+ if (r) {
+ ERROR(pakfire, "Could not close archive: %s\n", archive_error_string(a));
+ goto ERROR;
+ }
+
// Success
r = 0;
}
PAKFIRE_EXPORT int pakfire_snapshot_restore(Pakfire pakfire, FILE* f) {
- return 0;
+ int r = 1;
+
+ struct archive* a = archive_read_new();
+ if (!a)
+ return 1;
+
+ // All snapshots are tarballs
+ archive_read_support_format_tar(a);
+
+ // And they are compressed using ZSTD
+ archive_read_support_filter_zstd(a);
+
+ struct archive* disk = archive_write_disk_new();
+ if (!disk)
+ goto ERROR;
+
+ // Set flags for extracting contents
+ const int flags =
+ ARCHIVE_EXTRACT_ACL |
+ ARCHIVE_EXTRACT_OWNER |
+ ARCHIVE_EXTRACT_PERM |
+ ARCHIVE_EXTRACT_SPARSE |
+ ARCHIVE_EXTRACT_TIME |
+ ARCHIVE_EXTRACT_UNLINK |
+ ARCHIVE_EXTRACT_XATTR;
+
+ archive_write_disk_set_options(disk, flags);
+
+ // Open the given file for reading
+ r = archive_read_open_FILE(a, f);
+ if (r) {
+ ERROR(pakfire, "Could not open archive: %s\n", archive_error_string(a));
+ goto ERROR;
+ }
+
+ struct archive_entry* e = NULL;
+ while (1) {
+ r = archive_read_next_header(a, &e);
+ if (r == ARCHIVE_EOF)
+ break;
+ else if (r) {
+ ERROR(pakfire, "Could not read header: %s\n", archive_error_string(a));
+ goto ERROR;
+ }
+
+ const char* path = archive_entry_pathname(e);
+
+ DEBUG(pakfire, "Extracting %s...\n", path);
+
+ // Update path
+ char* sourcepath = pakfire_make_path(pakfire, path);
+ if (!sourcepath)
+ goto ERROR;
+
+ archive_entry_set_pathname(e, sourcepath);
+ free(sourcepath);
+
+ // Extract the file
+ r = archive_read_extract2(a, e, disk);
+ if (r) {
+ ERROR(pakfire, "Could not extract %s: %s\n",
+ archive_entry_pathname(e), archive_error_string(a));
+ goto ERROR;
+ }
+ }
+
+ // Success
+ r = 0;
+
+ERROR:
+ if (disk)
+ archive_write_free(disk);
+ archive_read_free(a);
+
+ return r;
}