]> git.ipfire.org Git - pakfire.git/commitdiff
oci: Move the layer inside an uncompressed outer tarball
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 8 Feb 2025 14:11:18 +0000 (14:11 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 8 Feb 2025 14:11:18 +0000 (14:11 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/pakfire/archive_writer.c
src/pakfire/archive_writer.h
src/pakfire/oci.c

index ccb2244c329cbc649cc71eaccabbbce58f1815fe..bdb88262422b45b8ca687e2fb8579a11c6f957e2 100644 (file)
@@ -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
index cce26bad0cb4b49b96bf4a7dfd380738caa1d4f6..134f1a76519f15358e84abec207d59df652fb764 100644 (file)
@@ -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;
 
index 1d5b74b62141bd3fbfc99141bad2e56743b44f08..e35c790096c95168877f7f8d4a1ede26f8dc9c56 100644 (file)
 #include <stdlib.h>
 
 #include <pakfire/archive_writer.h>
+#include <pakfire/ctx.h>
+#include <pakfire/hasher.h>
+#include <pakfire/hashes.h>
 #include <pakfire/i18n.h>
 #include <pakfire/logging.h>
 #include <pakfire/oci.h>
 #include <pakfire/pakfire.h>
+#include <pakfire/path.h>
+#include <pakfire/util.h>
 
-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;
 }