#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;
}