forked from Mirrors/flatpak-builder
Update build-bundle --oci to use the new shared OCI support
parent
63c1aace83
commit
4672bc835e
|
@ -35,7 +35,7 @@
|
|||
|
||||
#include "flatpak-builtins.h"
|
||||
#include "flatpak-utils.h"
|
||||
#include "flatpak-oci.h"
|
||||
#include "flatpak-oci-registry.h"
|
||||
#include "flatpak-chain-input-stream.h"
|
||||
#include "flatpak-builtins-utils.h"
|
||||
|
||||
|
@ -268,102 +268,6 @@ timestamp_to_iso8601 (guint64 timestamp)
|
|||
return g_time_val_to_iso8601 (&stamp);
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
generate_config_json (guint64 timestamp,
|
||||
const char *layer_sha256,
|
||||
const char *arch)
|
||||
{
|
||||
g_autoptr(FlatpakJsonWriter) writer = flatpak_json_writer_new ();
|
||||
g_autofree char *created = timestamp_to_iso8601 (timestamp);
|
||||
g_autofree char *layer_digest = g_strdup_printf ("sha256:%s", layer_sha256);
|
||||
|
||||
flatpak_json_writer_add_string_property (writer, "created", created);
|
||||
flatpak_json_writer_add_string_property (writer, "architecture", flatpak_arch_to_oci_arch (arch));
|
||||
flatpak_json_writer_add_string_property (writer, "os", "linux");
|
||||
|
||||
flatpak_json_writer_add_struct_property (writer, "rootfs");
|
||||
{
|
||||
flatpak_json_writer_add_array_property (writer, "diff_ids");
|
||||
{
|
||||
flatpak_json_writer_add_array_string (writer, layer_digest);
|
||||
flatpak_json_writer_close (writer);
|
||||
}
|
||||
flatpak_json_writer_add_string_property (writer, "type", "layers");
|
||||
flatpak_json_writer_close (writer);
|
||||
}
|
||||
|
||||
return flatpak_json_writer_get_result (writer);
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
generate_manifest_json (guint64 config_size,
|
||||
const char *config_sha256,
|
||||
guint64 layer_size,
|
||||
const char *layer_sha256,
|
||||
const char *ref,
|
||||
const char *checksum,
|
||||
GVariant *commit)
|
||||
{
|
||||
g_autoptr(FlatpakJsonWriter) writer = flatpak_json_writer_new ();
|
||||
g_autofree char *config_digest = g_strdup_printf ("sha256:%s", config_sha256);
|
||||
g_autofree char *layer_digest = g_strdup_printf ("sha256:%s", layer_sha256);
|
||||
|
||||
flatpak_json_writer_add_uint64_property (writer, "schemaVersion", 2);
|
||||
flatpak_json_writer_add_string_property (writer, "mediaType", "application/vnd.oci.image.manifest.v1+json");
|
||||
flatpak_json_writer_add_struct_property (writer, "config");
|
||||
{
|
||||
flatpak_json_writer_add_string_property (writer, "mediaType", "application/vnd.oci.image.config.v1+json");
|
||||
flatpak_json_writer_add_uint64_property (writer, "size", config_size);
|
||||
flatpak_json_writer_add_string_property (writer, "digest", config_digest);
|
||||
flatpak_json_writer_close (writer);
|
||||
}
|
||||
|
||||
flatpak_json_writer_add_array_property (writer, "layers");
|
||||
{
|
||||
flatpak_json_writer_add_array_struct (writer);
|
||||
{
|
||||
flatpak_json_writer_add_string_property (writer, "mediaType", "application/vnd.oci.image.layer.v1.tar+gzip");
|
||||
flatpak_json_writer_add_uint64_property (writer, "size", layer_size);
|
||||
flatpak_json_writer_add_string_property (writer, "digest", layer_digest);
|
||||
flatpak_json_writer_close (writer);
|
||||
}
|
||||
flatpak_json_writer_close (writer);
|
||||
}
|
||||
|
||||
flatpak_json_writer_add_struct_property (writer, "annotations");
|
||||
{
|
||||
g_autofree char *parent = NULL;
|
||||
g_autofree char *subject = NULL;
|
||||
g_autofree char *body = NULL;
|
||||
g_autoptr(GVariant) metadata = NULL;
|
||||
g_autofree char *metadata_base64 = NULL;
|
||||
|
||||
flatpak_json_writer_add_string_property (writer, "org.flatpak.Ref", ref);
|
||||
|
||||
parent = ostree_commit_get_parent (commit);
|
||||
flatpak_json_writer_add_string_property (writer, "org.flatpak.ParentCommit", parent);
|
||||
|
||||
flatpak_json_writer_add_string_property (writer, "org.flatpak.Commit", checksum);
|
||||
|
||||
metadata = g_variant_get_child_value (commit, 0);
|
||||
if (g_variant_get_size (metadata) > 0)
|
||||
{
|
||||
metadata_base64 = g_base64_encode (g_variant_get_data (metadata), g_variant_get_size (metadata));
|
||||
flatpak_json_writer_add_string_property (writer, "org.flatpak.Metadata", metadata_base64);
|
||||
}
|
||||
|
||||
g_variant_get_child (commit, 3, "s", &subject);
|
||||
flatpak_json_writer_add_string_property (writer, "org.flatpak.Subject", subject);
|
||||
|
||||
g_variant_get_child (commit, 4, "s", &body);
|
||||
flatpak_json_writer_add_string_property (writer, "org.flatpak.Body", body);
|
||||
|
||||
flatpak_json_writer_close (writer);
|
||||
}
|
||||
|
||||
return flatpak_json_writer_get_result (writer);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
export_commit_to_archive (OstreeRepo *repo,
|
||||
GFile *root,
|
||||
|
@ -388,24 +292,21 @@ build_oci (OstreeRepo *repo, GFile *dir,
|
|||
GCancellable *cancellable, GError **error)
|
||||
{
|
||||
g_autoptr(GFile) root = NULL;
|
||||
g_autoptr(GFile) refs_tag = NULL;
|
||||
g_autoptr(GFile) refs = NULL;
|
||||
g_autoptr(GVariant) commit_data = NULL;
|
||||
g_autoptr(GVariant) commit_metadata = NULL;
|
||||
g_autofree char *commit_checksum = NULL;
|
||||
g_auto(GStrv) ref_parts = g_strsplit (ref, "/", -1);
|
||||
glnx_fd_close int dfd = -1;
|
||||
g_autofree char *layer_compressed_sha256 = NULL;
|
||||
g_autofree char *layer_uncompressed_sha256 = NULL;
|
||||
guint64 layer_compressed_size;
|
||||
guint64 layer_uncompressed_size;
|
||||
g_autoptr(GBytes) config = NULL;
|
||||
g_autofree char *config_sha256 = NULL;
|
||||
g_autoptr(GBytes) manifest = NULL;
|
||||
g_autoptr(FlatpakOciDir) oci_dir = NULL;
|
||||
g_autofree char *dir_uri = NULL;
|
||||
g_autoptr(FlatpakOciRegistry) registry = NULL;
|
||||
g_autoptr(FlatpakOciLayerWriter) layer_writer = NULL;
|
||||
g_autofree char *manifest_sha256 = NULL;
|
||||
struct archive *archive;
|
||||
g_autofree char *uncompressed_digest = NULL;
|
||||
g_autofree char *timestamp = NULL;
|
||||
g_autoptr(FlatpakOciImage) image = NULL;
|
||||
g_autoptr(FlatpakOciRef) layer_ref = NULL;
|
||||
g_autoptr(FlatpakOciRef) image_ref = NULL;
|
||||
g_autoptr(FlatpakOciRef) manifest_ref = NULL;
|
||||
g_autoptr(FlatpakOciManifest) manifest = NULL;
|
||||
GHashTable *annotations;
|
||||
|
||||
if (!ostree_repo_resolve_rev (repo, ref, FALSE, &commit_checksum, error))
|
||||
return FALSE;
|
||||
|
@ -419,46 +320,52 @@ build_oci (OstreeRepo *repo, GFile *dir,
|
|||
if (!ostree_repo_read_commit_detached_metadata (repo, commit_checksum, &commit_metadata, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
oci_dir = flatpak_oci_dir_new ();
|
||||
|
||||
if (!flatpak_oci_dir_ensure (oci_dir, dir, cancellable, error))
|
||||
dir_uri = g_file_get_uri (dir);
|
||||
registry = flatpak_oci_registry_new (dir_uri, TRUE, -1, cancellable, error);
|
||||
if (registry == NULL)
|
||||
return FALSE;
|
||||
|
||||
layer_writer = flatpak_oci_layer_writer_new (oci_dir);
|
||||
|
||||
archive = flatpak_oci_layer_writer_open (layer_writer, cancellable, error);
|
||||
if (archive == NULL)
|
||||
layer_writer = flatpak_oci_registry_write_layer (registry, cancellable, error);
|
||||
if (layer_writer == NULL)
|
||||
return FALSE;
|
||||
|
||||
archive = flatpak_oci_layer_writer_get_archive (layer_writer);
|
||||
|
||||
if (!export_commit_to_archive (repo, root, ostree_commit_get_timestamp (commit_data),
|
||||
archive, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_oci_layer_writer_close (layer_writer,
|
||||
&layer_uncompressed_sha256,
|
||||
&layer_uncompressed_size,
|
||||
&layer_compressed_sha256,
|
||||
&layer_compressed_size,
|
||||
cancellable, error))
|
||||
&uncompressed_digest,
|
||||
&layer_ref,
|
||||
cancellable,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
config = generate_config_json (ostree_commit_get_timestamp (commit_data),
|
||||
layer_uncompressed_sha256,
|
||||
ref_parts[2]);
|
||||
config_sha256 = flatpak_oci_dir_write_blob (oci_dir, config, cancellable, error);
|
||||
if (config_sha256 == NULL)
|
||||
|
||||
image = flatpak_oci_image_new ();
|
||||
flatpak_oci_image_set_layer (image, uncompressed_digest);
|
||||
|
||||
timestamp = timestamp_to_iso8601 (ostree_commit_get_timestamp (commit_data));
|
||||
flatpak_oci_image_set_created (image, timestamp);
|
||||
|
||||
image_ref = flatpak_oci_registry_store_json (registry, FLATPAK_JSON (image), cancellable, error);
|
||||
if (image_ref == NULL)
|
||||
return FALSE;
|
||||
|
||||
manifest = generate_manifest_json (g_bytes_get_size (config), config_sha256,
|
||||
layer_compressed_size, layer_compressed_sha256,
|
||||
ref, commit_checksum, commit_data);
|
||||
manifest_sha256 = flatpak_oci_dir_write_blob (oci_dir, manifest, cancellable, error);
|
||||
if (manifest_sha256 == NULL)
|
||||
manifest = flatpak_oci_manifest_new ();
|
||||
flatpak_oci_manifest_set_config (manifest, image_ref);
|
||||
flatpak_oci_manifest_set_layer (manifest, layer_ref);
|
||||
|
||||
annotations = flatpak_oci_manifest_get_annotations (manifest);
|
||||
flatpak_oci_add_annotations_for_commit (annotations, ref, commit_checksum, commit_data);
|
||||
|
||||
manifest_ref = flatpak_oci_registry_store_json (registry, FLATPAK_JSON (manifest), cancellable, error);
|
||||
if (manifest_ref == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!flatpak_oci_dir_set_ref (oci_dir, "latest",
|
||||
g_bytes_get_size (manifest), manifest_sha256,
|
||||
cancellable, error))
|
||||
if (!flatpak_oci_registry_set_ref (registry, "latest", manifest_ref,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
g_print ("WARNING: the oci format produced by flatpak is experimental and unstable.\n"
|
||||
|
|
|
@ -93,7 +93,7 @@ import_oci (OstreeRepo *repo, GFile *file,
|
|||
if (manifest == NULL)
|
||||
return NULL;
|
||||
|
||||
annotations = flatpak_oci_manifest_get_annotations (manifest);
|
||||
annotations = flatpak_oci_manifest_get_annotations2 (manifest);
|
||||
|
||||
if (opt_ref != NULL)
|
||||
target_ref = opt_ref;
|
||||
|
|
|
@ -39,9 +39,6 @@ typedef struct
|
|||
|
||||
G_DEFINE_TYPE (FlatpakOciDir, flatpak_oci_dir, G_TYPE_OBJECT)
|
||||
|
||||
GLNX_DEFINE_CLEANUP_FUNCTION (void *, flatpak_local_free_write_archive, archive_write_free)
|
||||
#define free_write_archive __attribute__((cleanup (flatpak_local_free_write_archive)))
|
||||
|
||||
GLNX_DEFINE_CLEANUP_FUNCTION (void *, flatpak_local_free_read_archive, archive_read_free)
|
||||
#define free_read_archive __attribute__((cleanup (flatpak_local_free_read_archive)))
|
||||
|
||||
|
@ -281,42 +278,6 @@ flatpak_oci_dir_write_blob (FlatpakOciDir *self,
|
|||
return g_steal_pointer (&sha256);
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
generate_ref_json (guint64 manifest_size,
|
||||
const char *manifest_sha256)
|
||||
{
|
||||
g_autoptr(FlatpakJsonWriter) writer = flatpak_json_writer_new ();
|
||||
g_autofree char *manifest_digest = g_strdup_printf ("sha256:%s", manifest_sha256);
|
||||
|
||||
flatpak_json_writer_add_uint64_property (writer, "size", manifest_size);
|
||||
flatpak_json_writer_add_string_property (writer, "digest", manifest_digest);
|
||||
flatpak_json_writer_add_string_property (writer, "mediaType", "application/vnd.oci.image.manifest.v1+json");
|
||||
|
||||
return flatpak_json_writer_get_result (writer);
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
flatpak_oci_dir_set_ref (FlatpakOciDir *self,
|
||||
const char *ref,
|
||||
guint64 object_size,
|
||||
const char *object_sha256,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autofree char *path = g_strdup_printf ("refs/%s", ref);
|
||||
g_autoptr(GBytes) data = NULL;
|
||||
|
||||
data = generate_ref_json (object_size, object_sha256);
|
||||
if (!glnx_file_replace_contents_at (self->dfd, path,
|
||||
g_bytes_get_data (data, NULL),
|
||||
g_bytes_get_size (data),
|
||||
0, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GBytes *
|
||||
flatpak_oci_dir_load_object (FlatpakOciDir *self,
|
||||
const char *digest,
|
||||
|
@ -632,7 +593,7 @@ flatpak_oci_manifest_get_layers (JsonObject *manifest)
|
|||
}
|
||||
|
||||
GHashTable *
|
||||
flatpak_oci_manifest_get_annotations (JsonObject *manifest)
|
||||
flatpak_oci_manifest_get_annotations2 (JsonObject *manifest)
|
||||
{
|
||||
JsonObject *annotations = NULL;
|
||||
g_autoptr(GHashTable) res = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
|
@ -670,526 +631,3 @@ flatpak_oci_config_get_created (JsonObject *config)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
struct FlatpakOciLayerWriter
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
FlatpakOciDir *dir;
|
||||
|
||||
GChecksum *uncompressed_checksum;
|
||||
GChecksum *compressed_checksum;
|
||||
struct archive *archive;
|
||||
GZlibCompressor *compressor;
|
||||
guint64 uncompressed_size;
|
||||
guint64 compressed_size;
|
||||
char *tmp_path;
|
||||
int tmp_fd;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
} FlatpakOciLayerWriterClass;
|
||||
|
||||
G_DEFINE_TYPE (FlatpakOciLayerWriter, flatpak_oci_layer_writer, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
flatpak_oci_layer_writer_reset (FlatpakOciLayerWriter *self)
|
||||
{
|
||||
if (self->tmp_path)
|
||||
{
|
||||
(void) unlinkat (self->dir->dfd, self->tmp_path, 0);
|
||||
g_free (self->tmp_path);
|
||||
self->tmp_path = NULL;
|
||||
}
|
||||
|
||||
if (self->tmp_fd != -1)
|
||||
{
|
||||
close (self->tmp_fd);
|
||||
self->tmp_fd = -1;
|
||||
}
|
||||
|
||||
g_clear_object (&self->compressor);
|
||||
|
||||
g_checksum_reset (self->uncompressed_checksum);
|
||||
g_checksum_reset (self->compressed_checksum);
|
||||
|
||||
if (self->archive)
|
||||
{
|
||||
archive_write_free (self->archive);
|
||||
self->archive = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
flatpak_oci_layer_writer_finalize (GObject *object)
|
||||
{
|
||||
FlatpakOciLayerWriter *self = FLATPAK_OCI_LAYER_WRITER (object);
|
||||
|
||||
flatpak_oci_layer_writer_reset (self);
|
||||
|
||||
g_checksum_free (self->compressed_checksum);
|
||||
g_checksum_free (self->uncompressed_checksum);
|
||||
|
||||
g_clear_object (&self->dir);
|
||||
|
||||
G_OBJECT_CLASS (flatpak_oci_layer_writer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
flatpak_oci_layer_writer_class_init (FlatpakOciLayerWriterClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = flatpak_oci_layer_writer_finalize;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
flatpak_oci_layer_writer_init (FlatpakOciLayerWriter *self)
|
||||
{
|
||||
self->uncompressed_checksum = g_checksum_new (G_CHECKSUM_SHA256);
|
||||
self->compressed_checksum = g_checksum_new (G_CHECKSUM_SHA256);
|
||||
}
|
||||
|
||||
FlatpakOciLayerWriter *
|
||||
flatpak_oci_layer_writer_new (FlatpakOciDir *dir)
|
||||
{
|
||||
FlatpakOciLayerWriter *oci_layer_writer;
|
||||
|
||||
oci_layer_writer = g_object_new (FLATPAK_TYPE_OCI_LAYER_WRITER, NULL);
|
||||
oci_layer_writer->dir = g_object_ref (dir);
|
||||
|
||||
return oci_layer_writer;
|
||||
}
|
||||
|
||||
static int
|
||||
flatpak_oci_layer_writer_open_cb (struct archive *archive,
|
||||
void *client_data)
|
||||
{
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
static gssize
|
||||
flatpak_oci_layer_writer_compress (FlatpakOciLayerWriter *self,
|
||||
const void *buffer,
|
||||
size_t length,
|
||||
gboolean at_end)
|
||||
{
|
||||
guchar compressed_buffer[8192];
|
||||
GConverterResult res;
|
||||
gsize total_bytes_read, bytes_read, bytes_written, to_write_len;
|
||||
guchar *to_write;
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
GConverterFlags flags = 0;
|
||||
bytes_read = 0;
|
||||
|
||||
total_bytes_read = 0;
|
||||
|
||||
if (at_end)
|
||||
flags |= G_CONVERTER_INPUT_AT_END;
|
||||
|
||||
do
|
||||
{
|
||||
res = g_converter_convert (G_CONVERTER (self->compressor),
|
||||
buffer, length,
|
||||
compressed_buffer, sizeof (compressed_buffer),
|
||||
flags, &bytes_read, &bytes_written,
|
||||
&local_error);
|
||||
if (res == G_CONVERTER_ERROR)
|
||||
{
|
||||
archive_set_error (self->archive, EIO, "%s", local_error->message);
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_checksum_update (self->uncompressed_checksum, buffer, bytes_read);
|
||||
g_checksum_update (self->compressed_checksum, compressed_buffer, bytes_written);
|
||||
self->uncompressed_size += bytes_read;
|
||||
self->compressed_size += bytes_written;
|
||||
|
||||
to_write_len = bytes_written;
|
||||
to_write = compressed_buffer;
|
||||
while (to_write_len > 0)
|
||||
{
|
||||
ssize_t res = write (self->tmp_fd, to_write, to_write_len);
|
||||
if (res <= 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
archive_set_error (self->archive, errno, "Write error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
to_write_len -= res;
|
||||
to_write += res;
|
||||
}
|
||||
|
||||
total_bytes_read += bytes_read;
|
||||
}
|
||||
while ((length > 0 && bytes_read == 0) || /* Repeat if we consumed nothing */
|
||||
(at_end && res != G_CONVERTER_FINISHED)); /* Or until finished if at_end */
|
||||
|
||||
return total_bytes_read;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
flatpak_oci_layer_writer_write_cb (struct archive *archive,
|
||||
void *client_data,
|
||||
const void *buffer,
|
||||
size_t length)
|
||||
{
|
||||
FlatpakOciLayerWriter *self = FLATPAK_OCI_LAYER_WRITER (client_data);
|
||||
|
||||
return flatpak_oci_layer_writer_compress (self, buffer, length, FALSE);
|
||||
}
|
||||
|
||||
static int
|
||||
flatpak_oci_layer_writer_close_cb (struct archive *archive,
|
||||
void *client_data)
|
||||
{
|
||||
FlatpakOciLayerWriter *self = FLATPAK_OCI_LAYER_WRITER (client_data);
|
||||
gssize res;
|
||||
char buffer[1] = {0};
|
||||
|
||||
res = flatpak_oci_layer_writer_compress (self, &buffer, 0, TRUE);
|
||||
if (res < 0)
|
||||
return ARCHIVE_FATAL;
|
||||
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
struct archive *
|
||||
flatpak_oci_layer_writer_open (FlatpakOciLayerWriter *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
free_write_archive struct archive *a = NULL;
|
||||
glnx_fd_close int tmp_fd = -1;
|
||||
g_autofree char *tmp_path = NULL;
|
||||
|
||||
if (!glnx_open_tmpfile_linkable_at (self->dir->dfd,
|
||||
"blobs/sha256",
|
||||
O_WRONLY,
|
||||
&tmp_fd,
|
||||
&tmp_path,
|
||||
error))
|
||||
return NULL;
|
||||
|
||||
a = archive_write_new ();
|
||||
if (archive_write_set_format_gnutar (a) != ARCHIVE_OK ||
|
||||
archive_write_add_filter_none (a) != ARCHIVE_OK)
|
||||
{
|
||||
propagate_libarchive_error (error, a);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (archive_write_open (a, self,
|
||||
flatpak_oci_layer_writer_open_cb,
|
||||
flatpak_oci_layer_writer_write_cb,
|
||||
flatpak_oci_layer_writer_close_cb) != ARCHIVE_OK)
|
||||
{
|
||||
propagate_libarchive_error (error, a);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flatpak_oci_layer_writer_reset (self);
|
||||
|
||||
self->archive = g_steal_pointer (&a);
|
||||
self->tmp_fd = glnx_steal_fd (&tmp_fd);
|
||||
self->tmp_path = g_steal_pointer (&tmp_path);
|
||||
self->compressor = g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP, -1);
|
||||
|
||||
return self->archive;
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_oci_layer_writer_close (FlatpakOciLayerWriter *self,
|
||||
char **uncompressed_sha256_out,
|
||||
guint64 *uncompressed_size_out,
|
||||
char **compressed_sha256_out,
|
||||
guint64 *compressed_size_out,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autofree char *path = NULL;
|
||||
|
||||
if (archive_write_close (self->archive) != ARCHIVE_OK)
|
||||
return propagate_libarchive_error (error, self->archive);
|
||||
|
||||
path = g_strdup_printf ("blobs/sha256/%s",
|
||||
g_checksum_get_string (self->compressed_checksum));
|
||||
|
||||
if (!glnx_link_tmpfile_at (self->dir->dfd,
|
||||
GLNX_LINK_TMPFILE_REPLACE,
|
||||
self->tmp_fd,
|
||||
self->tmp_path,
|
||||
self->dir->dfd,
|
||||
path,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
close (self->tmp_fd);
|
||||
self->tmp_fd = -1;
|
||||
g_free (self->tmp_path);
|
||||
self->tmp_path = NULL;
|
||||
|
||||
if (uncompressed_sha256_out != NULL)
|
||||
*uncompressed_sha256_out = g_strdup (g_checksum_get_string (self->uncompressed_checksum));
|
||||
if (uncompressed_size_out != NULL)
|
||||
*uncompressed_size_out = self->uncompressed_size;
|
||||
if (compressed_sha256_out != NULL)
|
||||
*compressed_sha256_out = g_strdup (g_checksum_get_string (self->compressed_checksum));
|
||||
if (compressed_size_out != NULL)
|
||||
*compressed_size_out = self->compressed_size;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
typedef struct JsonScope JsonScope;
|
||||
|
||||
struct JsonScope {
|
||||
JsonScope *parent;
|
||||
int index;
|
||||
char end_char;
|
||||
};
|
||||
|
||||
struct FlatpakJsonWriter
|
||||
{
|
||||
GString *str;
|
||||
int depth;
|
||||
JsonScope *scope;
|
||||
};
|
||||
|
||||
FlatpakJsonWriter *
|
||||
flatpak_json_writer_new ()
|
||||
{
|
||||
FlatpakJsonWriter *self = g_new0 (FlatpakJsonWriter, 1);
|
||||
self->str = g_string_new ("");
|
||||
|
||||
flatpak_json_writer_open_struct (self);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
GBytes *
|
||||
flatpak_json_writer_get_result (FlatpakJsonWriter *self)
|
||||
{
|
||||
GBytes *res = NULL;
|
||||
|
||||
if (self->str)
|
||||
{
|
||||
flatpak_json_writer_close (self);
|
||||
res = g_string_free_to_bytes (self->str);
|
||||
self->str = NULL;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_json_writer_free (FlatpakJsonWriter *self)
|
||||
{
|
||||
if (self->str)
|
||||
g_string_free (self->str, TRUE);
|
||||
g_free (self);
|
||||
}
|
||||
|
||||
static void
|
||||
flatpak_json_writer_indent (FlatpakJsonWriter *self)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < self->depth; i++)
|
||||
g_string_append (self->str, " ");
|
||||
}
|
||||
|
||||
static void
|
||||
flatpak_json_writer_add_bool (FlatpakJsonWriter *self, gboolean val)
|
||||
{
|
||||
if (val)
|
||||
g_string_append (self->str, "true");
|
||||
else
|
||||
g_string_append (self->str, "false");
|
||||
}
|
||||
|
||||
static void
|
||||
flatpak_json_writer_add_uint64 (FlatpakJsonWriter *self, guint64 val)
|
||||
{
|
||||
g_string_append_printf (self->str, "%"G_GUINT64_FORMAT, val);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
flatpak_json_writer_add_string (FlatpakJsonWriter *self, const gchar *str)
|
||||
{
|
||||
const gchar *p;
|
||||
|
||||
g_string_append_c (self->str, '"');
|
||||
|
||||
for (p = str; *p != 0; p++)
|
||||
{
|
||||
if (*p == '\\' || *p == '"')
|
||||
{
|
||||
g_string_append_c (self->str, '\\');
|
||||
g_string_append_c (self->str, *p);
|
||||
}
|
||||
else if ((*p > 0 && *p < 0x1f) || *p == 0x7f)
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case '\b':
|
||||
g_string_append (self->str, "\\b");
|
||||
break;
|
||||
|
||||
case '\f':
|
||||
g_string_append (self->str, "\\f");
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
g_string_append (self->str, "\\n");
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
g_string_append (self->str, "\\r");
|
||||
break;
|
||||
|
||||
case '\t':
|
||||
g_string_append (self->str, "\\t");
|
||||
break;
|
||||
|
||||
default:
|
||||
g_string_append_printf (self->str, "\\u00%02x", (guint) * p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_string_append_c (self->str, *p);
|
||||
}
|
||||
}
|
||||
|
||||
g_string_append_c (self->str, '"');
|
||||
}
|
||||
|
||||
static void
|
||||
flatpak_json_writer_start_item (FlatpakJsonWriter *self)
|
||||
{
|
||||
int index = self->scope->index;
|
||||
|
||||
if (index != 0)
|
||||
g_string_append (self->str, ",\n");
|
||||
else
|
||||
g_string_append (self->str, "\n");
|
||||
flatpak_json_writer_indent (self);
|
||||
self->scope->index = index + 1;
|
||||
}
|
||||
|
||||
static void
|
||||
flatpak_json_writer_open_scope (FlatpakJsonWriter *self,
|
||||
char start_char,
|
||||
char end_char)
|
||||
{
|
||||
JsonScope *scope = g_new0 (JsonScope, 1);
|
||||
|
||||
scope->parent = self->scope;
|
||||
scope->end_char = end_char;
|
||||
|
||||
self->scope = scope;
|
||||
self->depth += 1;
|
||||
|
||||
g_string_append_c (self->str, start_char);
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_json_writer_close (FlatpakJsonWriter *self)
|
||||
{
|
||||
JsonScope *scope;
|
||||
|
||||
scope = self->scope;
|
||||
self->scope = scope->parent;
|
||||
self->depth -= 1;
|
||||
|
||||
g_string_append (self->str, "\n");
|
||||
flatpak_json_writer_indent (self);
|
||||
g_string_append_c (self->str, scope->end_char);
|
||||
|
||||
g_free (scope);
|
||||
|
||||
/* Last newline in file */
|
||||
if (self->scope == NULL)
|
||||
g_string_append (self->str, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_json_writer_open_struct (FlatpakJsonWriter *self)
|
||||
{
|
||||
flatpak_json_writer_open_scope (self, '{', '}');
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_json_writer_open_array (FlatpakJsonWriter *self)
|
||||
{
|
||||
flatpak_json_writer_open_scope (self, '[', ']');
|
||||
}
|
||||
|
||||
static void
|
||||
flatpak_json_writer_add_property (FlatpakJsonWriter *self, const gchar *name)
|
||||
{
|
||||
flatpak_json_writer_start_item (self);
|
||||
flatpak_json_writer_add_string (self, name);
|
||||
g_string_append (self->str, ": ");
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_json_writer_add_struct_property (FlatpakJsonWriter *self, const gchar *name)
|
||||
{
|
||||
flatpak_json_writer_add_property (self, name);
|
||||
flatpak_json_writer_open_struct (self);
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_json_writer_add_array_property (FlatpakJsonWriter *self, const gchar *name)
|
||||
{
|
||||
flatpak_json_writer_add_property (self, name);
|
||||
flatpak_json_writer_open_array (self);
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_json_writer_add_string_property (FlatpakJsonWriter *self, const gchar *name, const char *value)
|
||||
{
|
||||
flatpak_json_writer_add_property (self, name);
|
||||
flatpak_json_writer_add_string (self, value);
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_json_writer_add_uint64_property (FlatpakJsonWriter *self, const gchar *name, guint64 value)
|
||||
{
|
||||
flatpak_json_writer_add_property (self, name);
|
||||
flatpak_json_writer_add_uint64 (self, value);
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_json_writer_add_bool_property (FlatpakJsonWriter *self, const gchar *name, gboolean value)
|
||||
{
|
||||
flatpak_json_writer_add_property (self, name);
|
||||
flatpak_json_writer_add_bool (self, value);
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_json_writer_add_array_string (FlatpakJsonWriter *self, const gchar *string)
|
||||
{
|
||||
flatpak_json_writer_start_item (self);
|
||||
flatpak_json_writer_add_string (self, string);
|
||||
}
|
||||
|
||||
void
|
||||
flatpak_json_writer_add_array_struct (FlatpakJsonWriter *self)
|
||||
{
|
||||
flatpak_json_writer_start_item (self);
|
||||
flatpak_json_writer_open_struct (self);
|
||||
}
|
||||
|
|
|
@ -37,16 +37,7 @@ GType flatpak_oci_dir_get_type (void);
|
|||
|
||||
typedef struct FlatpakOciDir FlatpakOciDir;
|
||||
|
||||
#define FLATPAK_TYPE_OCI_LAYER_WRITER flatpak_oci_layer_writer_get_type ()
|
||||
#define FLATPAK_OCI_LAYER_WRITER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_OCI_LAYER_WRITER, FlatpakOciLayerWriter))
|
||||
#define FLATPAK_IS_OCI_LAYER_WRITER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_OCI_LAYER_WRITER))
|
||||
|
||||
GType flatpak_oci_layer_writer_get_type (void);
|
||||
|
||||
typedef struct FlatpakOciLayerWriter FlatpakOciLayerWriter;
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakOciDir, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakOciLayerWriter, g_object_unref)
|
||||
|
||||
const char * flatpak_arch_to_oci_arch (const char *flatpak_arch);
|
||||
|
||||
|
@ -63,12 +54,6 @@ char * flatpak_oci_dir_write_blob (FlatpakOciDir *self,
|
|||
GBytes *data,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
gboolean flatpak_oci_dir_set_ref (FlatpakOciDir *self,
|
||||
const char *ref,
|
||||
guint64 object_size,
|
||||
const char *object_sha256,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
gboolean flatpak_oci_dir_load_ref (FlatpakOciDir *self,
|
||||
const char *ref,
|
||||
guint64 *size_out,
|
||||
|
@ -97,42 +82,9 @@ JsonObject * flatpak_oci_dir_find_manifest (FlatpakOciDir *self,
|
|||
|
||||
char * flatpak_oci_manifest_get_config (JsonObject *manifest);
|
||||
char ** flatpak_oci_manifest_get_layers (JsonObject *manifest);
|
||||
GHashTable *flatpak_oci_manifest_get_annotations (JsonObject *manifest);
|
||||
GHashTable *flatpak_oci_manifest_get_annotations2 (JsonObject *manifest);
|
||||
|
||||
guint64 flatpak_oci_config_get_created (JsonObject *config);
|
||||
|
||||
FlatpakOciLayerWriter *flatpak_oci_layer_writer_new (FlatpakOciDir *dir);
|
||||
struct archive * flatpak_oci_layer_writer_open (FlatpakOciLayerWriter *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
gboolean flatpak_oci_layer_writer_close (FlatpakOciLayerWriter *self,
|
||||
char **uncompressed_sha256_out,
|
||||
guint64 *uncompressed_size_out,
|
||||
char **compressed_sha256_out,
|
||||
guint64 *compressed_size_out,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
|
||||
|
||||
typedef struct FlatpakJsonWriter FlatpakJsonWriter;
|
||||
|
||||
FlatpakJsonWriter *flatpak_json_writer_new (void);
|
||||
GBytes *flatpak_json_writer_get_result (FlatpakJsonWriter *self);
|
||||
void flatpak_json_writer_free (FlatpakJsonWriter *self);
|
||||
|
||||
void flatpak_json_writer_open_struct (FlatpakJsonWriter *writer);
|
||||
void flatpak_json_writer_open_array (FlatpakJsonWriter *writer);
|
||||
void flatpak_json_writer_close (FlatpakJsonWriter *writer);
|
||||
void flatpak_json_writer_add_struct_property (FlatpakJsonWriter *writer, const gchar *name);
|
||||
void flatpak_json_writer_add_array_property (FlatpakJsonWriter *writer, const gchar *name);
|
||||
void flatpak_json_writer_add_string_property (FlatpakJsonWriter *writer, const gchar *name, const char *value);
|
||||
void flatpak_json_writer_add_uint64_property (FlatpakJsonWriter *writer, const gchar *name, guint64 value);
|
||||
void flatpak_json_writer_add_bool_property (FlatpakJsonWriter *writer, const gchar *name, gboolean value);
|
||||
void flatpak_json_writer_add_array_string (FlatpakJsonWriter *writer, const gchar *string);
|
||||
void flatpak_json_writer_add_array_struct (FlatpakJsonWriter *writer);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakJsonWriter, flatpak_json_writer_free)
|
||||
|
||||
|
||||
#endif /* __FLATPAK_OCI_H__ */
|
||||
|
|
Loading…
Reference in New Issue