From: Michael Tremer Date: Thu, 25 May 2023 10:27:09 +0000 (+0000) Subject: archive: Implement extracting archives into arbitrary locations X-Git-Tag: 0.9.29~155 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1ce8f42edd52c73bfd76f773b847568bb7b51eb5;p=pakfire.git archive: Implement extracting archives into arbitrary locations Signed-off-by: Michael Tremer --- diff --git a/src/_pakfire/archive.c b/src/_pakfire/archive.c index 5c70ec749..73cdd080b 100644 --- a/src/_pakfire/archive.c +++ b/src/_pakfire/archive.c @@ -136,9 +136,16 @@ static PyObject* Archive_verify(ArchiveObject* self) { Py_RETURN_FALSE; } -static PyObject* Archive_extract(ArchiveObject* self) { +static PyObject* Archive_extract(ArchiveObject* self, PyObject* args, PyObject* kwargs) { + char* kwlist[] = { "path", NULL }; + const char* path = NULL; + const int flags = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|z", kwlist, &path)) + return NULL; + // Extract payload - int r = pakfire_archive_extract(self->archive); + int r = pakfire_archive_extract(self->archive, path, flags); if (r) { PyErr_SetFromErrno(PyExc_OSError); return NULL; @@ -211,7 +218,7 @@ static struct PyMethodDef Archive_methods[] = { { "extract", (PyCFunction)Archive_extract, - METH_NOARGS, + METH_VARARGS|METH_KEYWORDS, NULL }, { diff --git a/src/libpakfire/archive.c b/src/libpakfire/archive.c index 880c21707..a5a91ac68 100644 --- a/src/libpakfire/archive.c +++ b/src/libpakfire/archive.c @@ -810,7 +810,8 @@ int pakfire_archive_link_or_copy(struct pakfire_archive* archive, const char* pa return r; } -static int __pakfire_archive_extract(struct pakfire_archive* archive, int flags) { +static int __pakfire_archive_extract(struct pakfire_archive* archive, + const char* path, int flags) { struct pakfire_filelist* filelist = NULL; struct pakfire_package* pkg = NULL; struct archive* a = NULL; @@ -827,9 +828,21 @@ static int __pakfire_archive_extract(struct pakfire_archive* archive, int flags) DEBUG(archive->pakfire, "Extracting %s\n", archive->path); + // Copy everything to path if set + if (path) { + r = pakfire_string_set(prefix, path); + if (r) + goto ERROR; + // Set prefix for source packages - if (pakfire_package_is_source(pkg)) { - r = pakfire_string_format(prefix, "/usr/src/packages/%s", nevra); + } else if (pakfire_package_is_source(pkg)) { + r = pakfire_path(archive->pakfire, prefix, "/usr/src/packages/%s", nevra); + if (r) + goto ERROR; + + // Otherwise extract relative to the pakfire root + } else { + r = pakfire_path(archive->pakfire, prefix, "%s", "/"); if (r) goto ERROR; } @@ -869,8 +882,9 @@ ERROR: return r; } -PAKFIRE_EXPORT int pakfire_archive_extract(struct pakfire_archive* archive) { - return __pakfire_archive_extract(archive, 0); +PAKFIRE_EXPORT int pakfire_archive_extract(struct pakfire_archive* archive, + const char* path, const int flags) { + return __pakfire_archive_extract(archive, path, flags); } PAKFIRE_EXPORT const char* pakfire_archive_get_path(struct pakfire_archive* archive) { @@ -883,7 +897,7 @@ PAKFIRE_EXPORT unsigned int pakfire_archive_get_format(struct pakfire_archive* a static int pakfire_archive_load_filelist(struct pakfire_archive* archive) { // Perform a dry-run extraction - return __pakfire_archive_extract(archive, + return __pakfire_archive_extract(archive, NULL, PAKFIRE_EXTRACT_DRY_RUN|PAKFIRE_EXTRACT_NO_PROGRESS); } diff --git a/src/libpakfire/compress.c b/src/libpakfire/compress.c index c25613837..d17da9df1 100644 --- a/src/libpakfire/compress.c +++ b/src/libpakfire/compress.c @@ -623,7 +623,7 @@ struct pakfire_extract { struct pakfire_filelist* filelist; // Prepend this prefix - char prefix[PATH_MAX]; + const char* prefix; // The writer struct archive* writer; @@ -806,14 +806,15 @@ int pakfire_extract(struct pakfire* pakfire, struct archive* archive, pakfire_walk_filter_callback filter_callback, int flags) { int r = 1; - // Use an empty string if no prefix set + // Use / if no prefix is set if (!prefix) - prefix = ""; + prefix = "/"; struct pakfire_extract data = { .pakfire = pakfire, .archive = archive, .filelist = filelist, + .prefix = prefix, .flags = flags, .writer = NULL, }; @@ -824,11 +825,6 @@ int pakfire_extract(struct pakfire* pakfire, struct archive* archive, // Should we show a progress bar? const int no_progress = flags & PAKFIRE_EXTRACT_NO_PROGRESS; - // Set prefix (including pakfire path) - r = pakfire_path(pakfire, data.prefix, "%s", prefix); - if (r) - goto ERROR; - // Allocate writer if (!dry_run) { data.writer = pakfire_make_archive_disk_writer(pakfire, 1); diff --git a/src/libpakfire/include/pakfire/archive.h b/src/libpakfire/include/pakfire/archive.h index 9a15e0aae..aa4c674ae 100644 --- a/src/libpakfire/include/pakfire/archive.h +++ b/src/libpakfire/include/pakfire/archive.h @@ -36,7 +36,8 @@ struct pakfire_archive* pakfire_archive_ref(struct pakfire_archive* archive); struct pakfire_archive* pakfire_archive_unref(struct pakfire_archive* archive); FILE* pakfire_archive_read(struct pakfire_archive* archive, const char* filename); -int pakfire_archive_extract(struct pakfire_archive* archive); +int pakfire_archive_extract(struct pakfire_archive* archive, + const char* path, const int flags); const char* pakfire_archive_get_path(struct pakfire_archive* archive); diff --git a/src/libpakfire/snapshot.c b/src/libpakfire/snapshot.c index 30a1995e4..22bc34d78 100644 --- a/src/libpakfire/snapshot.c +++ b/src/libpakfire/snapshot.c @@ -178,6 +178,8 @@ int pakfire_snapshot_extract(struct pakfire* pakfire, FILE* f) { return 1; } + const char* path = pakfire_get_path(pakfire); + struct archive* archive = archive_read_new(); if (!archive) return 1; @@ -196,7 +198,7 @@ int pakfire_snapshot_extract(struct pakfire* pakfire, FILE* f) { } // Extract snapshot - r = pakfire_extract(pakfire, archive, st.st_size, NULL, NULL, + r = pakfire_extract(pakfire, archive, st.st_size, NULL, path, _("Restoring Snapshot"), NULL, PAKFIRE_EXTRACT_SHOW_THROUGHPUT); if (r) goto ERROR; diff --git a/src/libpakfire/transaction.c b/src/libpakfire/transaction.c index 6852259fc..ff5d1f53e 100644 --- a/src/libpakfire/transaction.c +++ b/src/libpakfire/transaction.c @@ -718,7 +718,7 @@ static int pakfire_transaction_extract(struct pakfire_transaction* transaction, pakfire_transaction_status(transaction, _("Installing %s..."), nevra); // Extract payload - int r = pakfire_archive_extract(archive); + int r = pakfire_archive_extract(archive, NULL, 0); if (r) { ERROR(transaction->pakfire, "Could not extract package %s: %m\n", nevra); diff --git a/src/scripts/pakfire-builder.in b/src/scripts/pakfire-builder.in index 88113db38..8740512e8 100644 --- a/src/scripts/pakfire-builder.in +++ b/src/scripts/pakfire-builder.in @@ -84,6 +84,12 @@ class Cli(object): dist.add_argument("--resultdir", nargs="?", help=_("Path were the output files should be copied to")) + # extract + extract = subparsers.add_parser("extract", help=_("Extract an archive")) + extract.add_argument("archive", nargs=1, help=_("The path to the archive")) + extract.add_argument("--path", help=_("Extract the archive into this path")) + extract.set_defaults(func=self._extract) + # info info = subparsers.add_parser("info", help=_("Print some information about the given package(s)")) @@ -259,6 +265,16 @@ class Cli(object): for pkg in pkgs: p.dist(pkg, resultdir) + def _extract(self, ns): + # Launch Pakfire + p = self.pakfire(ns) + + # Open the archive + archive = p.open(ns.archive[0]) + + # Extract the payload + archive.extract(path=ns.path) + # Some common functions def _print_packages(self, packages, unique=True, long=True, **kwargs):