From 31a87ad5c97bdb13350fa19d60255c182363f9e7 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Sat, 8 Feb 2025 14:11:18 +0000 Subject: [PATCH] oci: Move the layer inside an uncompressed outer tarball Signed-off-by: Michael Tremer --- src/pakfire/archive_writer.c | 11 ++- src/pakfire/archive_writer.h | 3 + src/pakfire/oci.c | 125 ++++++++++++++++++++++++++++++++--- 3 files changed, 130 insertions(+), 9 deletions(-) diff --git a/src/pakfire/archive_writer.c b/src/pakfire/archive_writer.c index ccb2244c..bdb88262 100644 --- a/src/pakfire/archive_writer.c +++ b/src/pakfire/archive_writer.c @@ -55,7 +55,7 @@ struct pakfire_archive_writer { // Compression enum pakfire_archive_writer_compression { - PAKFIRE_COMPRESSION_NONE, + PAKFIRE_COMPRESSION_NONE = 0, PAKFIRE_COMPRESSION_ZSTD, } compression; unsigned int compression_level; @@ -97,6 +97,15 @@ static int pakfire_archive_writer_setup_format( self->checksums = PAKFIRE_HASH_SHA3_512|PAKFIRE_HASH_BLAKE2B512; break; + // OCI Image + case PAKFIRE_FORMAT_OCI: + // Use the GNU tar format + self->container = PAKFIRE_CONTAINER_GNU; + + // Use no compression + self->compression = PAKFIRE_COMPRESSION_NONE; + break; + // OCI Layer case PAKFIRE_FORMAT_OCI_LAYER: // Use the GNU tar format diff --git a/src/pakfire/archive_writer.h b/src/pakfire/archive_writer.h index cce26bad..134f1a76 100644 --- a/src/pakfire/archive_writer.h +++ b/src/pakfire/archive_writer.h @@ -30,6 +30,9 @@ struct pakfire_archive_writer; typedef enum pakfire_archive_writer_formats { PAKFIRE_FORMAT_ARCHIVE, + + // OCI Images + PAKFIRE_FORMAT_OCI, PAKFIRE_FORMAT_OCI_LAYER, } pakfire_archive_writer_format; diff --git a/src/pakfire/oci.c b/src/pakfire/oci.c index 1d5b74b6..e35c7900 100644 --- a/src/pakfire/oci.c +++ b/src/pakfire/oci.c @@ -23,36 +23,145 @@ #include #include +#include +#include +#include #include #include #include #include +#include +#include -int pakfire_oci_mkimage(struct pakfire* pakfire, FILE* f) { - struct pakfire_archive_writer* writer = NULL; +struct pakfire_oci_writer { + // Context + struct pakfire_ctx* ctx; + + // Pakfire + struct pakfire* pakfire; + + // Root + const char* root; + + // Image writer + struct pakfire_archive_writer* image; + + // Hexdigest of the layer + char* layer_hexdigest; +}; + +static int pakfire_oci_writer_make_layer(struct pakfire_oci_writer* self) { + char path[PATH_MAX] = PAKFIRE_TMP_DIR "/pakfire-oci-layer.XXXXXX"; + struct pakfire_archive_writer* layer = NULL; + struct pakfire_hashes hashes = {}; + char filename[PATH_MAX]; + FILE* f = NULL; int r; // Fetch the pakfire root - const char* root = pakfire_get_path(pakfire); + const char* root = pakfire_get_path(self->pakfire); + + // Make a new temporary file + f = pakfire_mktemp(path, 0); + if (!f) { + ERROR(self->ctx, "Failed to create a temporary file: %m\n"); + r = -errno; + goto ERROR; + } + + // Drop the file straight away + unlink(path); // Make a new archive writer - r = pakfire_archive_writer_create(&writer, pakfire, PAKFIRE_FORMAT_OCI_LAYER, f); + r = pakfire_archive_writer_create(&layer, self->pakfire, PAKFIRE_FORMAT_OCI_LAYER, f); if (r < 0) goto ERROR; // Set the title - r = pakfire_archive_writer_set_title(writer, "%s", _("Writing Layer")); + r = pakfire_archive_writer_set_title(layer, "%s", _("Writing Layer")); if (r < 0) goto ERROR; // Write all files - r = pakfire_archive_writer_write_everything(writer, root); + r = pakfire_archive_writer_write_everything(layer, root); + if (r < 0) + goto ERROR; + + // Rewind + r = pakfire_rewind(f); + if (r < 0) + goto ERROR; + + // Compute hashes of the file + r = pakfire_hash_file(self->ctx, f, PAKFIRE_HASH_SHA2_512, &hashes); + if (r < 0) + goto ERROR; + + // Read the hexdigest of the file + r = pakfire_hashes_get_hex(&hashes, PAKFIRE_HASH_SHA2_512, &self->layer_hexdigest); + if (r < 0) + goto ERROR; + + // Make the filename of the layer version + r = pakfire_path_format(filename, "%s/VERSION", self->layer_hexdigest); + if (r < 0) + goto ERROR; + + // Write the version file + r = pakfire_archive_writer_create_file(self->image, filename, 0644, "1.0", strlen("1.0")); + if (r < 0) + goto ERROR; + + // Make the filename of the layer file + r = pakfire_path_format(filename, "%s/layer.tar", self->layer_hexdigest); + if (r < 0) + goto ERROR; + + // Rewind + r = pakfire_rewind(f); + if (r < 0) + goto ERROR; + + // Write the layer to the image + r = pakfire_archive_writer_create_file_from_file(self->image, filename, 0644, f); + if (r < 0) { + ERROR(self->ctx, "Failed to add the layer to the image: %s\n", strerror(-r)); + goto ERROR; + } + +ERROR: + if (layer) + pakfire_archive_writer_unref(layer); + if (f) + fclose(f); + + return r; +} + +int pakfire_oci_mkimage(struct pakfire* pakfire, FILE* f) { + struct pakfire_oci_writer writer = { + .ctx = pakfire_ctx(pakfire), + .pakfire = pakfire, + }; + int r; + + // Make a new archive writer + r = pakfire_archive_writer_create(&writer.image, pakfire, PAKFIRE_FORMAT_OCI, f); + if (r < 0) + goto ERROR; + + // Make the layer + r = pakfire_oci_writer_make_layer(&writer); if (r < 0) goto ERROR; ERROR: - if (writer) - pakfire_archive_writer_unref(writer); + if (writer.image) + pakfire_archive_writer_unref(writer.image); + if (writer.layer_hexdigest) + free(writer.layer_hexdigest); + if (writer.ctx) + pakfire_ctx_unref(writer.ctx); return r; } -- 2.39.5