Import OCI initial support to common/*

tingping/wmclass
Alexander Larsson 2016-12-08 11:21:56 +01:00
parent 186ff0f002
commit 63c1aace83
8 changed files with 2843 additions and 1 deletions

View File

@ -48,6 +48,12 @@ libflatpak_common_la_SOURCES = \
common/gvdb/gvdb-builder.c \
common/flatpak-db.c \
common/flatpak-db.h \
common/flatpak-json.c \
common/flatpak-json.h \
common/flatpak-json-oci.c \
common/flatpak-json-oci.h \
common/flatpak-oci-registry.c \
common/flatpak-oci-registry.h \
$(NULL)
libflatpak_common_la_CFLAGS = \
@ -61,4 +67,4 @@ libflatpak_common_la_CFLAGS = \
$(LIBSECCOMP_CFLAGS) \
-I$(srcdir)/dbus-proxy \
$(NULL)
libflatpak_common_la_LIBADD = libglnx.la $(BASE_LIBS) $(OSTREE_LIBS) $(SOUP_LIBS) $(XAUTH_LIBS) $(LIBSECCOMP_LIBS)
libflatpak_common_la_LIBADD = libglnx.la $(BASE_LIBS) $(OSTREE_LIBS) $(SOUP_LIBS) $(JSON_LIBS) $(XAUTH_LIBS) $(LIBSECCOMP_LIBS)

View File

@ -0,0 +1,716 @@
/*
* Copyright (C) 2015 Red Hat, Inc
*
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Alexander Larsson <alexl@redhat.com>
*/
#include "config.h"
#include "string.h"
#include "flatpak-json-oci.h"
#include "flatpak-utils.h"
#include "libglnx.h"
const char *
flatpak_arch_to_oci_arch (const char *flatpak_arch)
{
if (strcmp (flatpak_arch, "x86_64") == 0)
return "amd64";
if (strcmp (flatpak_arch, "aarch64") == 0)
return "arm64";
if (strcmp (flatpak_arch, "i386") == 0)
return "386";
return flatpak_arch;
}
void
flatpak_oci_descriptor_destroy (FlatpakOciDescriptor *self)
{
g_free (self->mediatype);
g_free (self->digest);
g_strfreev (self->urls);
}
void
flatpak_oci_descriptor_free (FlatpakOciDescriptor *self)
{
flatpak_oci_descriptor_destroy (self);
g_free (self);
}
static FlatpakJsonProp flatpak_oci_descriptor_props[] = {
FLATPAK_JSON_STRING_PROP (FlatpakOciDescriptor, mediatype, "mediaType"),
FLATPAK_JSON_STRING_PROP (FlatpakOciDescriptor, digest, "digest"),
FLATPAK_JSON_INT64_PROP (FlatpakOciDescriptor, size, "size"),
FLATPAK_JSON_STRV_PROP (FlatpakOciDescriptor, urls, "urls"),
FLATPAK_JSON_LAST_PROP
};
static void
flatpak_oci_manifest_platform_destroy (FlatpakOciManifestPlatform *self)
{
g_free (self->architecture);
g_free (self->os);
g_free (self->os_version);
g_strfreev (self->os_features);
g_free (self->variant);
g_strfreev (self->features);
}
void
flatpak_oci_manifest_descriptor_destroy (FlatpakOciManifestDescriptor *self)
{
flatpak_oci_manifest_platform_destroy (&self->platform);
flatpak_oci_descriptor_destroy (&self->parent);
}
void
flatpak_oci_manifest_descriptor_free (FlatpakOciManifestDescriptor *self)
{
flatpak_oci_manifest_descriptor_destroy (self);
g_free (self);
}
static FlatpakJsonProp flatpak_oci_manifest_platform_props[] = {
FLATPAK_JSON_STRING_PROP (FlatpakOciManifestPlatform, architecture, "architecture"),
FLATPAK_JSON_STRING_PROP (FlatpakOciManifestPlatform, os, "os"),
FLATPAK_JSON_STRING_PROP (FlatpakOciManifestPlatform, os_version, "os.version"),
FLATPAK_JSON_STRING_PROP (FlatpakOciManifestPlatform, variant, "variant"),
FLATPAK_JSON_STRV_PROP (FlatpakOciManifestPlatform, os_features, "os.features"),
FLATPAK_JSON_STRV_PROP (FlatpakOciManifestPlatform, features, "features"),
FLATPAK_JSON_LAST_PROP
};
static FlatpakJsonProp flatpak_oci_manifest_descriptor_props[] = {
FLATPAK_JSON_PARENT_PROP (FlatpakOciManifestDescriptor, parent, flatpak_oci_descriptor_props),
FLATPAK_JSON_STRUCT_PROP (FlatpakOciManifestDescriptor, platform, "platform", flatpak_oci_manifest_platform_props),
FLATPAK_JSON_LAST_PROP
};
G_DEFINE_TYPE (FlatpakOciRef, flatpak_oci_ref, FLATPAK_TYPE_JSON);
static void
flatpak_oci_ref_finalize (GObject *object)
{
FlatpakOciRef *self = FLATPAK_OCI_REF (object);
flatpak_oci_descriptor_destroy (&self->descriptor);
G_OBJECT_CLASS (flatpak_oci_ref_parent_class)->finalize (object);
}
static void
flatpak_oci_ref_class_init (FlatpakOciRefClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
FlatpakJsonClass *json_class = FLATPAK_JSON_CLASS (klass);
static FlatpakJsonProp props[] = {
FLATPAK_JSON_PARENT_PROP (FlatpakOciRef, descriptor, flatpak_oci_descriptor_props),
FLATPAK_JSON_LAST_PROP
};
object_class->finalize = flatpak_oci_ref_finalize;
json_class->props = props;
json_class->mediatype = FLATPAK_OCI_MEDIA_TYPE_DESCRIPTOR;
}
static void
flatpak_oci_ref_init (FlatpakOciRef *self)
{
}
FlatpakOciRef *
flatpak_oci_ref_new (const char *mediatype,
const char *digest,
gint64 size)
{
FlatpakOciRef *ref;
ref = g_object_new (FLATPAK_TYPE_OCI_REF, NULL);
ref->descriptor.mediatype = g_strdup (mediatype);
ref->descriptor.digest = g_strdup (digest);
ref->descriptor.size = size;
return ref;
}
const char *
flatpak_oci_ref_get_mediatype (FlatpakOciRef *self)
{
return self->descriptor.mediatype;
}
const char *
flatpak_oci_ref_get_digest (FlatpakOciRef *self)
{
return self->descriptor.digest;
}
gint64
flatpak_oci_ref_get_size (FlatpakOciRef *self)
{
return self->descriptor.size;
}
const char **
flatpak_oci_ref_get_urls (FlatpakOciRef *self)
{
return (const char **)self->descriptor.urls;
}
void
flatpak_oci_ref_set_urls (FlatpakOciRef *self,
const char **urls)
{
g_strfreev (self->descriptor.urls);
self->descriptor.urls = g_strdupv ((char **)urls);
}
G_DEFINE_TYPE (FlatpakOciVersioned, flatpak_oci_versioned, FLATPAK_TYPE_JSON);
static void
flatpak_oci_versioned_finalize (GObject *object)
{
FlatpakOciVersioned *self = FLATPAK_OCI_VERSIONED (object);
g_free (self->mediatype);
G_OBJECT_CLASS (flatpak_oci_versioned_parent_class)->finalize (object);
}
static void
flatpak_oci_versioned_class_init (FlatpakOciVersionedClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
FlatpakJsonClass *json_class = FLATPAK_JSON_CLASS (klass);
static FlatpakJsonProp props[] = {
FLATPAK_JSON_INT64_PROP (FlatpakOciVersioned, version, "schemaVersion"),
FLATPAK_JSON_STRING_PROP (FlatpakOciVersioned, mediatype, "mediaType"),
FLATPAK_JSON_LAST_PROP
};
object_class->finalize = flatpak_oci_versioned_finalize;
json_class->props = props;
}
static void
flatpak_oci_versioned_init (FlatpakOciVersioned *self)
{
}
FlatpakOciVersioned *
flatpak_oci_versioned_from_json (GBytes *bytes, GError **error)
{
g_autoptr(JsonParser) parser = NULL;
JsonNode *root = NULL;
const gchar *mediatype;
JsonObject *object;
parser = json_parser_new ();
if (!json_parser_load_from_data (parser,
g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes),
error))
return NULL;
root = json_parser_get_root (parser);
object = json_node_get_object (root);
mediatype = json_object_get_string_member (object, "mediaType");
if (mediatype == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
"Versioned object lacks mediatype");
return NULL;
}
if (strcmp (mediatype, FLATPAK_OCI_MEDIA_TYPE_IMAGE_MANIFEST) == 0)
return (FlatpakOciVersioned *) flatpak_json_from_node (root, FLATPAK_TYPE_OCI_MANIFEST, error);
if (strcmp (mediatype, FLATPAK_OCI_MEDIA_TYPE_IMAGE_MANIFESTLIST) == 0)
return (FlatpakOciVersioned *) flatpak_json_from_node (root, FLATPAK_TYPE_OCI_MANIFEST_LIST, error);
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
"Unsupported media type %s", mediatype);
return NULL;
}
const char *
flatpak_oci_versioned_get_mediatype (FlatpakOciVersioned *self)
{
return self->mediatype;
}
gint64
flatpak_oci_versioned_get_version (FlatpakOciVersioned *self)
{
return self->version;
}
G_DEFINE_TYPE (FlatpakOciManifest, flatpak_oci_manifest, FLATPAK_TYPE_OCI_VERSIONED);
static void
flatpak_oci_manifest_finalize (GObject *object)
{
FlatpakOciManifest *self = (FlatpakOciManifest *) object;
int i;
for (i = 0; self->layers != NULL && self->layers[i] != NULL; i++)
flatpak_oci_descriptor_free (self->layers[i]);
g_free (self->layers);
flatpak_oci_descriptor_destroy (&self->config);
if (self->annotations)
g_hash_table_destroy (self->annotations);
G_OBJECT_CLASS (flatpak_oci_manifest_parent_class)->finalize (object);
}
static void
flatpak_oci_manifest_class_init (FlatpakOciManifestClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
FlatpakJsonClass *json_class = FLATPAK_JSON_CLASS (klass);
static FlatpakJsonProp props[] = {
FLATPAK_JSON_STRUCT_PROP(FlatpakOciManifest, config, "config", flatpak_oci_descriptor_props),
FLATPAK_JSON_STRUCTV_PROP(FlatpakOciManifest, layers, "layers", flatpak_oci_descriptor_props),
FLATPAK_JSON_STRMAP_PROP(FlatpakOciManifest, annotations, "annotations"),
FLATPAK_JSON_LAST_PROP
};
object_class->finalize = flatpak_oci_manifest_finalize;
json_class->props = props;
json_class->mediatype = FLATPAK_OCI_MEDIA_TYPE_IMAGE_MANIFEST;
}
static void
flatpak_oci_manifest_init (FlatpakOciManifest *self)
{
}
FlatpakOciManifest *
flatpak_oci_manifest_new (void)
{
FlatpakOciManifest *manifest;
manifest = g_object_new (FLATPAK_TYPE_OCI_MANIFEST, NULL);
manifest->parent.version = 2;
manifest->parent.mediatype = g_strdup (FLATPAK_OCI_MEDIA_TYPE_IMAGE_MANIFEST);
manifest->annotations = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
return manifest;
}
void
flatpak_oci_manifest_set_config (FlatpakOciManifest *self,
FlatpakOciRef *ref)
{
g_free (self->config.mediatype);
self->config.mediatype = g_strdup (ref->descriptor.mediatype);
g_free (self->config.digest);
self->config.digest = g_strdup (ref->descriptor.digest);
self->config.size = ref->descriptor.size;
}
static int
ptrv_count (gpointer *ptrs)
{
int count;
for (count = 0; ptrs != NULL && ptrs[count] != NULL; count++)
;
return count;
}
void
flatpak_oci_manifest_set_layer (FlatpakOciManifest *self,
FlatpakOciRef *ref)
{
FlatpakOciRef *refs[2] = { ref, NULL };
flatpak_oci_manifest_set_layers (self, refs);
}
void
flatpak_oci_manifest_set_layers (FlatpakOciManifest *self,
FlatpakOciRef **refs)
{
int i, count;
for (i = 0; self->layers != NULL && self->layers[i] != NULL; i++)
flatpak_oci_descriptor_free (self->layers[i]);
g_free (self->layers);
count = ptrv_count ((gpointer *)refs);
self->layers = g_new0 (FlatpakOciDescriptor *, count + 1);
for (i = 0; i < count; i++)
{
self->layers[i] = g_new0 (FlatpakOciDescriptor, 1);
self->layers[i]->mediatype = g_strdup (refs[i]->descriptor.mediatype);
self->layers[i]->digest = g_strdup (refs[i]->descriptor.digest);
self->layers[i]->size = refs[i]->descriptor.size;
}
}
int
flatpak_oci_manifest_get_n_layers (FlatpakOciManifest *self)
{
return ptrv_count ((gpointer *)self->layers);
}
const char *
flatpak_oci_manifest_get_layer_digest (FlatpakOciManifest *self,
int i)
{
return self->layers[i]->digest;
}
GHashTable *
flatpak_oci_manifest_get_annotations (FlatpakOciManifest *self)
{
return self->annotations;
}
G_DEFINE_TYPE (FlatpakOciManifestList, flatpak_oci_manifest_list, FLATPAK_TYPE_OCI_VERSIONED);
static void
flatpak_oci_manifest_list_finalize (GObject *object)
{
FlatpakOciManifestList *self = (FlatpakOciManifestList *) object;
int i;
for (i = 0; self->manifests != NULL && self->manifests[i] != NULL; i++)
flatpak_oci_manifest_descriptor_free (self->manifests[i]);
g_free (self->manifests);
if (self->annotations)
g_hash_table_destroy (self->annotations);
G_OBJECT_CLASS (flatpak_oci_manifest_list_parent_class)->finalize (object);
}
static void
flatpak_oci_manifest_list_class_init (FlatpakOciManifestListClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
FlatpakJsonClass *json_class = FLATPAK_JSON_CLASS (klass);
static FlatpakJsonProp props[] = {
FLATPAK_JSON_STRUCTV_PROP(FlatpakOciManifestList, manifests, "manifests", flatpak_oci_manifest_descriptor_props),
FLATPAK_JSON_STRMAP_PROP(FlatpakOciManifestList, annotations, "annotations"),
FLATPAK_JSON_LAST_PROP
};
object_class->finalize = flatpak_oci_manifest_list_finalize;
json_class->props = props;
json_class->mediatype = FLATPAK_OCI_MEDIA_TYPE_IMAGE_MANIFESTLIST;
}
static void
flatpak_oci_manifest_list_init (FlatpakOciManifestList *self)
{
}
G_DEFINE_TYPE (FlatpakOciImage, flatpak_oci_image, FLATPAK_TYPE_JSON);
static void
flatpak_oci_image_rootfs_destroy (FlatpakOciImageRootfs *self)
{
g_free (self->type);
g_strfreev (self->diff_ids);
}
static void
flatpak_oci_image_config_destroy (FlatpakOciImageConfig *self)
{
g_free (self->user);
g_free (self->working_dir);
g_strfreev (self->env);
g_strfreev (self->cmd);
g_strfreev (self->entrypoint);
g_strfreev (self->exposed_ports);
g_strfreev (self->volumes);
if (self->labels)
g_hash_table_destroy (self->labels);
}
static void
flatpak_oci_image_history_free (FlatpakOciImageHistory *self)
{
g_free (self->created);
g_free (self->created_by);
g_free (self->author);
g_free (self->comment);
g_free (self);
}
static void
flatpak_oci_image_finalize (GObject *object)
{
FlatpakOciImage *self = (FlatpakOciImage *) object;
int i;
g_free (self->created);
g_free (self->author);
g_free (self->architecture);
g_free (self->os);
flatpak_oci_image_rootfs_destroy (&self->rootfs);
flatpak_oci_image_config_destroy (&self->config);
for (i = 0; self->history != NULL && self->history[i] != NULL; i++)
flatpak_oci_image_history_free (self->history[i]);
g_free (self->history);
G_OBJECT_CLASS (flatpak_oci_image_parent_class)->finalize (object);
}
static void
flatpak_oci_image_class_init (FlatpakOciImageClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
FlatpakJsonClass *json_class = FLATPAK_JSON_CLASS (klass);
static FlatpakJsonProp config_props[] = {
FLATPAK_JSON_STRING_PROP (FlatpakOciImageConfig, user, "User"),
FLATPAK_JSON_INT64_PROP (FlatpakOciImageConfig, memory, "Memory"),
FLATPAK_JSON_INT64_PROP (FlatpakOciImageConfig, memory_swap, "MemorySwap"),
FLATPAK_JSON_INT64_PROP (FlatpakOciImageConfig, cpu_shares, "CpuShares"),
FLATPAK_JSON_BOOLMAP_PROP (FlatpakOciImageConfig, exposed_ports, "ExposedPorts"),
FLATPAK_JSON_STRV_PROP (FlatpakOciImageConfig, env, "Env"),
FLATPAK_JSON_STRV_PROP (FlatpakOciImageConfig, entrypoint, "Entrypoint"),
FLATPAK_JSON_STRV_PROP (FlatpakOciImageConfig, cmd, "Cmd"),
FLATPAK_JSON_BOOLMAP_PROP (FlatpakOciImageConfig, volumes, "Volumes"),
FLATPAK_JSON_STRING_PROP (FlatpakOciImageConfig, working_dir, "WorkingDir"),
FLATPAK_JSON_STRMAP_PROP(FlatpakOciImageConfig, labels, "Labels"),
FLATPAK_JSON_LAST_PROP
};
static FlatpakJsonProp rootfs_props[] = {
FLATPAK_JSON_STRING_PROP (FlatpakOciImageRootfs, type, "type"),
FLATPAK_JSON_STRV_PROP (FlatpakOciImageRootfs, diff_ids, "diff_ids"),
FLATPAK_JSON_LAST_PROP
};
static FlatpakJsonProp history_props[] = {
FLATPAK_JSON_STRING_PROP (FlatpakOciImageHistory, created, "created"),
FLATPAK_JSON_STRING_PROP (FlatpakOciImageHistory, created_by, "created_by"),
FLATPAK_JSON_STRING_PROP (FlatpakOciImageHistory, author, "author"),
FLATPAK_JSON_STRING_PROP (FlatpakOciImageHistory, comment, "comment"),
FLATPAK_JSON_BOOL_PROP (FlatpakOciImageHistory, empty_layer, "empty_layer"),
FLATPAK_JSON_LAST_PROP
};
static FlatpakJsonProp props[] = {
FLATPAK_JSON_STRING_PROP (FlatpakOciImage, created, "created"),
FLATPAK_JSON_STRING_PROP (FlatpakOciImage, author, "author"),
FLATPAK_JSON_STRING_PROP (FlatpakOciImage, architecture, "architecture"),
FLATPAK_JSON_STRING_PROP (FlatpakOciImage, os, "os"),
FLATPAK_JSON_STRUCT_PROP (FlatpakOciImage, config, "config", config_props),
FLATPAK_JSON_STRUCT_PROP (FlatpakOciImage, rootfs, "rootfs", rootfs_props),
FLATPAK_JSON_STRUCTV_PROP (FlatpakOciImage, history, "history", history_props),
FLATPAK_JSON_LAST_PROP
};
object_class->finalize = flatpak_oci_image_finalize;
json_class->props = props;
json_class->mediatype = FLATPAK_OCI_MEDIA_TYPE_IMAGE_CONFIG;
}
static void
flatpak_oci_image_init (FlatpakOciImage *self)
{
}
FlatpakOciImage *
flatpak_oci_image_new (void)
{
FlatpakOciImage *image;
GTimeVal stamp;
stamp.tv_sec = time (NULL);
stamp.tv_usec = 0;
image = g_object_new (FLATPAK_TYPE_OCI_IMAGE, NULL);
/* Some default values */
image->created = g_time_val_to_iso8601 (&stamp);
image->architecture = g_strdup ("arm64");
image->os = g_strdup ("linux");
image->rootfs.type = g_strdup ("layers");
image->rootfs.diff_ids = g_new0 (char *, 1);
return image;
}
void
flatpak_oci_image_set_created (FlatpakOciImage *image,
const char *created)
{
g_free (image->created);
image->created = g_strdup (created);
}
void
flatpak_oci_image_set_architecture (FlatpakOciImage *image,
const char *arch)
{
g_free (image->architecture);
image->architecture = g_strdup (arch);
}
void
flatpak_oci_image_set_os (FlatpakOciImage *image,
const char *os)
{
g_free (image->os);
image->os = g_strdup (os);
}
void
flatpak_oci_image_set_layers (FlatpakOciImage *image,
const char **layers)
{
g_strfreev (image->rootfs.diff_ids);
image->rootfs.diff_ids = g_strdupv ((char **)layers);
}
void
flatpak_oci_image_set_layer (FlatpakOciImage *image,
const char *layer)
{
const char *layers[] = {layer, NULL};
flatpak_oci_image_set_layers (image, layers);
}
static void
add_annotation (GHashTable *annotations, const char *key, const char *value)
{
g_hash_table_replace (annotations,
g_strdup (key),
g_strdup (value));
}
void
flatpak_oci_add_annotations_for_commit (GHashTable *annotations,
const char *ref,
const char *commit,
GVariant *commit_data)
{
if (ref)
add_annotation (annotations,"org.flatpak.Ostree.Ref", ref);
if (commit)
add_annotation (annotations,"org.flatpak.Ostree.Commit", commit);
if (commit_data)
{
g_autofree char *parent = NULL;
g_autofree char *subject = NULL;
g_autofree char *body = NULL;
g_autofree char *timestamp = NULL;
g_autoptr(GVariant) metadata = NULL;
int i;
parent = ostree_commit_get_parent (commit_data);
if (parent)
add_annotation (annotations, "org.flatpak.Ostree.ParentCommit", parent);
metadata = g_variant_get_child_value (commit_data, 0);
for (i = 0; i < g_variant_n_children (metadata); i++)
{
g_autoptr(GVariant) elm = g_variant_get_child_value (metadata, i);
g_autoptr(GVariant) value = g_variant_get_child_value (elm, 1);
g_autofree char *key = NULL;
g_autofree char *full_key = NULL;
g_autofree char *value_base64 = NULL;
g_variant_get_child (elm, 0, "s", &key);
full_key = g_strdup_printf ("org.flatpak.Ostree.Metadata.%s", key);
value_base64 = g_base64_encode (g_variant_get_data (value), g_variant_get_size (value));
add_annotation (annotations, full_key, value_base64);
}
timestamp = g_strdup_printf ("%"G_GUINT64_FORMAT, ostree_commit_get_timestamp (commit_data));
add_annotation (annotations, "org.flatpak.Ostree.Timestamp", timestamp);
g_variant_get_child (commit_data, 3, "s", &subject);
add_annotation (annotations, "org.flatpak.Ostree.Subject", subject);
g_variant_get_child (commit_data, 4, "s", &body);
add_annotation (annotations, "org.flatpak.Ostree.Body", body);
}
}
void
flatpak_oci_parse_commit_annotations (GHashTable *annotations,
guint64 *out_timestamp,
char **out_subject,
char **out_body,
char **out_ref,
char **out_commit,
char **out_parent_commit,
GVariantBuilder *metadata_builder)
{
const char *oci_timestamp, *oci_subject, *oci_body, *oci_parent_commit, *oci_commit, *oci_ref;
GHashTableIter iter;
gpointer _key, _value;
oci_ref = g_hash_table_lookup (annotations, "org.flatpak.Ostree.Ref");
if (oci_ref != NULL && out_ref != NULL && *out_ref == NULL)
*out_ref = g_strdup (oci_ref);
oci_commit = g_hash_table_lookup (annotations, "org.flatpak.Ostree.Commit");
if (oci_commit != NULL && out_commit != NULL && *out_commit == NULL)
*out_commit = g_strdup (oci_commit);
oci_parent_commit = g_hash_table_lookup (annotations, "org.flatpak.Ostree.ParentCommit");
if (oci_parent_commit != NULL && out_parent_commit != NULL && *out_parent_commit == NULL)
*out_parent_commit = g_strdup (oci_parent_commit);
oci_timestamp = g_hash_table_lookup (annotations, "org.flatpak.Ostree.Timestamp");
if (oci_timestamp != NULL && out_timestamp != NULL && *out_timestamp == 0)
*out_timestamp = g_ascii_strtoull (oci_timestamp, NULL, 10);
oci_subject = g_hash_table_lookup (annotations, "org.flatpak.Ostree.Subject");
if (oci_subject != NULL && out_subject != NULL && *out_subject == NULL)
*out_subject = g_strdup (oci_subject);
oci_body = g_hash_table_lookup (annotations, "org.flatpak.Ostree.Body");
if (oci_body != NULL && out_body != NULL && *out_body == NULL)
*out_body = g_strdup (oci_body);
if (metadata_builder)
{
g_hash_table_iter_init (&iter, annotations);
while (g_hash_table_iter_next (&iter, &_key, &_value))
{
const char *key = _key;
const char *value = _value;
guchar *bin;
gsize bin_len;
g_autoptr(GVariant) data = NULL;
if (!g_str_has_prefix (key, "org.flatpak.Ostree.Metadata."))
continue;
key += strlen ("org.flatpak.Ostree.Metadata.");
bin = g_base64_decode (value, &bin_len);
data = g_variant_ref_sink (g_variant_new_from_data (G_VARIANT_TYPE("v"), bin, bin_len, FALSE,
g_free, bin));
g_variant_builder_add (metadata_builder, "{s@v}", key, data);
}
}
}

View File

@ -0,0 +1,231 @@
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Alexander Larsson <alexl@redhat.com>
*/
#ifndef __FLATPAK_JSON_OCI_H__
#define __FLATPAK_JSON_OCI_H__
#include "flatpak-json.h"
G_BEGIN_DECLS
#define FLATPAK_OCI_MEDIA_TYPE_DESCRIPTOR "application/vnd.oci.descriptor.v1+json"
#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_MANIFEST "application/vnd.oci.image.manifest.v1+json"
#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_MANIFESTLIST "application/vnd.oci.image.manifest.list.v1+json"
#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_LAYER "application/vnd.oci.image.layer.v1.tar+gzip"
#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_LAYER_NONDISTRIBUTABLE "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip"
#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_CONFIG "application/vnd.oci.image.config.v1+json"
const char * flatpak_arch_to_oci_arch (const char *flatpak_arch);
typedef struct {
char *mediatype;
char *digest;
gint64 size;
char **urls;
} FlatpakOciDescriptor;
void flatpak_oci_descriptor_destroy (FlatpakOciDescriptor *self);
void flatpak_oci_descriptor_free (FlatpakOciDescriptor *self);
typedef struct
{
char *architecture;
char *os;
char *os_version;
char **os_features;
char *variant;
char **features;
} FlatpakOciManifestPlatform;
typedef struct
{
FlatpakOciDescriptor parent;
FlatpakOciManifestPlatform platform;
} FlatpakOciManifestDescriptor;
void flatpak_oci_manifest_descriptor_destroy (FlatpakOciManifestDescriptor *self);
void flatpak_oci_manifest_descriptor_free (FlatpakOciManifestDescriptor *self);
#define FLATPAK_TYPE_OCI_REF flatpak_oci_ref_get_type ()
G_DECLARE_FINAL_TYPE (FlatpakOciRef, flatpak_oci_ref, FLATPAK_OCI, REF, FlatpakJson)
struct _FlatpakOciRef {
FlatpakJson parent;
FlatpakOciDescriptor descriptor;
};
struct _FlatpakOciRefClass {
FlatpakJsonClass parent_class;
};
FlatpakOciRef *flatpak_oci_ref_new (const char *mediatype,
const char *digest,
gint64 size);
const char * flatpak_oci_ref_get_mediatype (FlatpakOciRef *self);
const char * flatpak_oci_ref_get_digest (FlatpakOciRef *self);
gint64 flatpak_oci_ref_get_size (FlatpakOciRef *self);
const char ** flatpak_oci_ref_get_urls (FlatpakOciRef *self);
void flatpak_oci_ref_set_urls (FlatpakOciRef *self,
const char **urls);
#define FLATPAK_TYPE_OCI_VERSIONED flatpak_oci_versioned_get_type ()
G_DECLARE_FINAL_TYPE (FlatpakOciVersioned, flatpak_oci_versioned, FLATPAK_OCI, VERSIONED, FlatpakJson)
struct _FlatpakOciVersioned {
FlatpakJson parent;
int version;
char *mediatype;
};
struct _FlatpakOciVersionedClass {
FlatpakJsonClass parent_class;
};
FlatpakOciVersioned *flatpak_oci_versioned_from_json (GBytes *bytes,
GError **error);
const char * flatpak_oci_versioned_get_mediatype (FlatpakOciVersioned *self);
gint64 flatpak_oci_versioned_get_version (FlatpakOciVersioned *self);
#define FLATPAK_TYPE_OCI_MANIFEST flatpak_oci_manifest_get_type ()
G_DECLARE_FINAL_TYPE (FlatpakOciManifest, flatpak_oci_manifest, FLATPAK, OCI_MANIFEST, FlatpakOciVersioned)
struct _FlatpakOciManifest
{
FlatpakOciVersioned parent;
FlatpakOciDescriptor config;
FlatpakOciDescriptor **layers;
GHashTable *annotations;
};
struct _FlatpakOciManifestClass
{
FlatpakOciVersionedClass parent_class;
};
FlatpakOciManifest *flatpak_oci_manifest_new (void);
void flatpak_oci_manifest_set_config (FlatpakOciManifest *self,
FlatpakOciRef *ref);
void flatpak_oci_manifest_set_layers (FlatpakOciManifest *self,
FlatpakOciRef **refs);
void flatpak_oci_manifest_set_layer (FlatpakOciManifest *self,
FlatpakOciRef *ref);
int flatpak_oci_manifest_get_n_layers (FlatpakOciManifest *self);
const char * flatpak_oci_manifest_get_layer_digest (FlatpakOciManifest *self,
int i);
GHashTable * flatpak_oci_manifest_get_annotations (FlatpakOciManifest *self);
#define FLATPAK_TYPE_OCI_MANIFEST_LIST flatpak_oci_manifest_list_get_type ()
G_DECLARE_FINAL_TYPE (FlatpakOciManifestList, flatpak_oci_manifest_list, FLATPAK, OCI_MANIFEST_LIST, FlatpakOciVersioned)
struct _FlatpakOciManifestList
{
FlatpakOciVersioned parent;
FlatpakOciManifestDescriptor **manifests;
GHashTable *annotations;
};
struct _FlatpakOciManifestListClass
{
FlatpakOciVersionedClass parent_class;
};
#define FLATPAK_TYPE_OCI_IMAGE flatpak_oci_image_get_type ()
G_DECLARE_FINAL_TYPE (FlatpakOciImage, flatpak_oci_image, FLATPAK, OCI_IMAGE, FlatpakJson)
typedef struct
{
char *type;
char **diff_ids;
} FlatpakOciImageRootfs;
typedef struct
{
char *user;
char *working_dir;
gint64 memory;
gint64 memory_swap;
gint64 cpu_shares;
char **env;
char **cmd;
char **entrypoint;
char **exposed_ports;
char **volumes;
GHashTable *labels;
} FlatpakOciImageConfig;
typedef struct
{
char *created;
char *created_by;
char *author;
char *comment;
gboolean empty_layer;
} FlatpakOciImageHistory;
struct _FlatpakOciImage
{
FlatpakJson parent;
char *created;
char *author;
char *architecture;
char *os;
FlatpakOciImageRootfs rootfs;
FlatpakOciImageConfig config;
FlatpakOciImageHistory **history;
};
struct _FlatpakOciImageClass
{
FlatpakJsonClass parent_class;
};
FlatpakOciImage *flatpak_oci_image_new (void);
void flatpak_oci_image_set_created (FlatpakOciImage *image,
const char *created);
void flatpak_oci_image_set_architecture (FlatpakOciImage *image,
const char *arch);
void flatpak_oci_image_set_os (FlatpakOciImage *image,
const char *os);
void flatpak_oci_image_set_layers (FlatpakOciImage *image,
const char **layers);
void flatpak_oci_image_set_layer (FlatpakOciImage *image,
const char *layer);
void flatpak_oci_add_annotations_for_commit (GHashTable *annotations,
const char *ref,
const char *commit,
GVariant *commit_data);
void flatpak_oci_parse_commit_annotations (GHashTable *annotations,
guint64 *out_timestamp,
char **out_subject,
char **out_body,
char **out_ref,
char **out_commit,
char **out_parent_commit,
GVariantBuilder *metadata_builder);
#endif /* __FLATPAK_JSON_OCI_H__ */

View File

@ -0,0 +1,597 @@
/*
* Copyright (C) 2015 Red Hat, Inc
*
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Alexander Larsson <alexl@redhat.com>
*/
#include "config.h"
#include "string.h"
#include "flatpak-json.h"
#include "flatpak-utils.h"
#include "libglnx.h"
G_DEFINE_TYPE (FlatpakJson, flatpak_json, G_TYPE_OBJECT);
static void
flatpak_json_finalize (GObject *object)
{
G_OBJECT_CLASS (flatpak_json_parent_class)->finalize (object);
}
static void
flatpak_json_class_init (FlatpakJsonClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = flatpak_json_finalize;
}
static void
flatpak_json_init (FlatpakJson *self)
{
}
static gboolean
demarshal (JsonNode *parent_node,
const char *name,
gpointer dest,
FlatpakJsonPropType type,
gpointer type_data,
gpointer type_data2,
GError **error)
{
JsonObject *parent_object;
JsonNode *node;
if (type != FLATPAK_JSON_PROP_TYPE_PARENT)
{
parent_object = json_node_get_object (parent_node);
node = json_object_get_member (parent_object, name);
}
else
node = parent_node;
if (node == NULL || JSON_NODE_TYPE (node) == JSON_NODE_NULL)
return TRUE;
switch (type)
{
case FLATPAK_JSON_PROP_TYPE_STRING:
if (!JSON_NODE_HOLDS_VALUE (node) ||
json_node_get_value_type (node) != G_TYPE_STRING)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting string for property %s", name);
return FALSE;
}
*(char **)dest = g_strdup (json_node_get_string (node));
break;
case FLATPAK_JSON_PROP_TYPE_INT64:
if (!JSON_NODE_HOLDS_VALUE (node) ||
json_node_get_value_type (node) != G_TYPE_INT64)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting int64 for property %s", name);
return FALSE;
}
*(gint64 *)dest = json_node_get_int (node);
break;
case FLATPAK_JSON_PROP_TYPE_BOOL:
if (!JSON_NODE_HOLDS_VALUE (node) ||
json_node_get_value_type (node) != G_TYPE_BOOLEAN)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting bool for property %s", name);
return FALSE;
}
*(gboolean *)dest = json_node_get_boolean (node);
break;
case FLATPAK_JSON_PROP_TYPE_STRV:
if (!JSON_NODE_HOLDS_ARRAY (node))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting array for property %s", name);
return FALSE;
}
{
JsonArray *array = json_node_get_array (node);
guint i, array_len = json_array_get_length (array);
g_autoptr(GPtrArray) str_array = g_ptr_array_sized_new (array_len + 1);
for (i = 0; i < array_len; i++)
{
JsonNode *val = json_array_get_element (array, i);
if (JSON_NODE_TYPE (val) != JSON_NODE_VALUE)
continue;
if (json_node_get_string (val) != NULL)
g_ptr_array_add (str_array, (gpointer) g_strdup (json_node_get_string (val)));
}
g_ptr_array_add (str_array, NULL);
*(char ***)dest = (char **)g_ptr_array_free (g_steal_pointer (&str_array), FALSE);
}
break;
case FLATPAK_JSON_PROP_TYPE_PARENT:
case FLATPAK_JSON_PROP_TYPE_STRUCT:
if (!JSON_NODE_HOLDS_OBJECT (node))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting object for property %s", name);
return FALSE;
}
{
FlatpakJsonProp *struct_props = type_data;
int i;
for (i = 0; struct_props[i].name != NULL; i++)
{
if (!demarshal (node, struct_props[i].name,
G_STRUCT_MEMBER_P (dest, struct_props[i].offset),
struct_props[i].type, struct_props[i].type_data, struct_props[i].type_data2,
error))
return FALSE;
}
}
break;
case FLATPAK_JSON_PROP_TYPE_STRUCTV:
if (!JSON_NODE_HOLDS_ARRAY (node))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting array for property %s", name);
return FALSE;
}
{
JsonArray *array = json_node_get_array (node);
guint array_len = json_array_get_length (array);
FlatpakJsonProp *struct_props = type_data;
g_autoptr(GPtrArray) obj_array = g_ptr_array_sized_new (array_len + 1);
int i, j;
gboolean res = TRUE;
for (j = 0; res && j < array_len; j++)
{
JsonNode *val = json_array_get_element (array, j);
gpointer new_element;
if (!JSON_NODE_HOLDS_OBJECT (val))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting object elemen for property %s", name);
res = FALSE;
break;
}
new_element = g_malloc0 ((gsize)type_data2);
g_ptr_array_add (obj_array, new_element);
for (i = 0; struct_props[i].name != NULL; i++)
{
if (!demarshal (val, struct_props[i].name,
G_STRUCT_MEMBER_P (new_element, struct_props[i].offset),
struct_props[i].type, struct_props[i].type_data, struct_props[i].type_data2,
error))
{
res = FALSE;
break;
}
}
}
/* NULL terminate */
g_ptr_array_add (obj_array, NULL);
/* We always set the array, even if it is partial, because we don't know how
to free what we demarshalled so far */
*(gpointer *)dest = (gpointer *)g_ptr_array_free (g_steal_pointer (&obj_array), FALSE);
return res;
}
break;
case FLATPAK_JSON_PROP_TYPE_STRMAP:
if (!JSON_NODE_HOLDS_OBJECT (node))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting object for property %s", name);
return FALSE;
}
{
g_autoptr(GHashTable) h = NULL;
JsonObject *object = json_node_get_object (node);
g_autoptr(GList) members = NULL;
GList *l;
h = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
members = json_object_get_members (object);
for (l = members; l != NULL; l = l->next)
{
const char *member_name = l->data;
JsonNode *val;
const char *val_str;
val = json_object_get_member (object, member_name);
val_str = json_node_get_string (val);
if (val_str == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Wrong type for string member %s", member_name);
return FALSE;
}
g_hash_table_insert (h, g_strdup (member_name), g_strdup (val_str));
}
*(GHashTable **)dest = g_steal_pointer (&h);
}
break;
case FLATPAK_JSON_PROP_TYPE_BOOLMAP:
if (!JSON_NODE_HOLDS_OBJECT (node))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting object for property %s", name);
return FALSE;
}
{
JsonObject *object = json_node_get_object (node);
g_autoptr(GPtrArray) res = g_ptr_array_new_with_free_func (g_free);
g_autoptr(GList) members = NULL;
GList *l;
members = json_object_get_members (object);
for (l = members; l != NULL; l = l->next)
{
const char *member_name = l->data;
g_ptr_array_add (res, g_strdup (member_name));
}
g_ptr_array_add (res, NULL);
*(char ***)dest = (char **)g_ptr_array_free (g_steal_pointer (&res), FALSE);
}
break;
default:
g_assert_not_reached ();
}
return TRUE;
}
FlatpakJson *
flatpak_json_from_node (JsonNode *node, GType type, GError **error)
{
g_autoptr(FlatpakJson) json = NULL;
FlatpakJsonProp *props = NULL;
gpointer class;
int i;
/* We should handle these before we get here */
g_assert (node != NULL);
g_assert (JSON_NODE_TYPE (node) != JSON_NODE_NULL);
if (JSON_NODE_TYPE (node) != JSON_NODE_OBJECT)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting a JSON object, but the node is of type `%s'",
json_node_type_name (node));
return NULL;
}
json = g_object_new (type, NULL);
class = FLATPAK_JSON_GET_CLASS (json);
while (FLATPAK_JSON_CLASS (class)->props != NULL)
{
props = FLATPAK_JSON_CLASS (class)->props;
for (i = 0; props[i].name != NULL; i++)
{
if (!demarshal (node, props[i].name,
G_STRUCT_MEMBER_P (json, props[i].offset),
props[i].type, props[i].type_data, props[i].type_data2,
error))
return NULL;
}
class = g_type_class_peek_parent (class);
}
return g_steal_pointer (&json);
}
FlatpakJson *
flatpak_json_from_bytes (GBytes *bytes,
GType type,
GError **error)
{
g_autoptr(JsonParser) parser = NULL;
JsonNode *root = NULL;
parser = json_parser_new ();
if (!json_parser_load_from_data (parser,
g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes),
error))
return NULL;
root = json_parser_get_root (parser);
return flatpak_json_from_node (root, type, error);
}
static JsonNode *
marshal (JsonObject *parent,
const char *name,
gpointer src,
FlatpakJsonPropType type,
gpointer type_data)
{
JsonNode *retval = NULL;
switch (type)
{
case FLATPAK_JSON_PROP_TYPE_STRING:
{
const char *str = *(const char **)src;
if (str != NULL)
retval = json_node_init_string (json_node_alloc (), str);
break;
}
case FLATPAK_JSON_PROP_TYPE_INT64:
{
retval = json_node_init_int (json_node_alloc (), *(gint64 *)src);
break;
}
case FLATPAK_JSON_PROP_TYPE_BOOL:
{
gboolean val = *(gboolean *)src;
if (val)
retval = json_node_init_boolean (json_node_alloc (), val);
break;
}
case FLATPAK_JSON_PROP_TYPE_STRV:
{
char **strv = *(char ***)src;
int i;
JsonArray *array;
if (strv != NULL && strv[0] != NULL)
{
array = json_array_sized_new (g_strv_length (strv));
for (i = 0; strv[i] != NULL; i++)
{
JsonNode *str = json_node_new (JSON_NODE_VALUE);
json_node_set_string (str, strv[i]);
json_array_add_element (array, str);
}
retval = json_node_init_array (json_node_alloc (), array);
json_array_unref (array);
}
break;
}
case FLATPAK_JSON_PROP_TYPE_PARENT:
case FLATPAK_JSON_PROP_TYPE_STRUCT:
{
FlatpakJsonProp *struct_props = type_data;
JsonObject *obj;
int i;
if (type == FLATPAK_JSON_PROP_TYPE_PARENT)
obj = parent;
else
obj = json_object_new ();
for (i = 0; struct_props[i].name != NULL; i++)
{
JsonNode *val = marshal (obj, struct_props[i].name,
G_STRUCT_MEMBER_P (src, struct_props[i].offset),
struct_props[i].type, struct_props[i].type_data);
if (val == NULL)
continue;
json_object_set_member (obj, struct_props[i].name, val);
}
if (type != FLATPAK_JSON_PROP_TYPE_PARENT)
{
retval = json_node_new (JSON_NODE_OBJECT);
json_node_take_object (retval, obj);
}
break;
}
case FLATPAK_JSON_PROP_TYPE_STRUCTV:
{
FlatpakJsonProp *struct_props = type_data;
gpointer *structv = *(gpointer **)src;
int i, j;
JsonArray *array;
if (structv != NULL && structv[0] != NULL)
{
array = json_array_new ();
for (j = 0; structv[j] != NULL; j++)
{
JsonObject *obj = json_object_new ();
JsonNode *node;
for (i = 0; struct_props[i].name != NULL; i++)
{
JsonNode *val = marshal (obj, struct_props[i].name,
G_STRUCT_MEMBER_P (structv[j], struct_props[i].offset),
struct_props[i].type, struct_props[i].type_data);
if (val == NULL)
continue;
json_object_set_member (obj, struct_props[i].name, val);
}
node = json_node_new (JSON_NODE_OBJECT);
json_node_take_object (node, obj);
json_array_add_element (array, node);
}
retval = json_node_init_array (json_node_alloc (), array);
json_array_unref (array);
}
break;
}
case FLATPAK_JSON_PROP_TYPE_STRMAP:
{
GHashTable *map = *(GHashTable **)src;
if (map != NULL && g_hash_table_size (map) > 0)
{
GHashTableIter iter;
gpointer _key, _value;
JsonObject *object;
object = json_object_new ();
g_hash_table_iter_init (&iter, map);
while (g_hash_table_iter_next (&iter, &_key, &_value))
{
const char *key = _key;
const char *value = _value;
JsonNode *str = json_node_new (JSON_NODE_VALUE);
json_node_set_string (str, value);
json_object_set_member (object, key, str);
}
retval = json_node_init_object (json_node_alloc (), object);
json_object_unref (object);
}
break;
}
case FLATPAK_JSON_PROP_TYPE_BOOLMAP:
{
char **map = *(char ***)src;
if (map != NULL && map[0] != NULL)
{
JsonObject *object;
int i;
object = json_object_new ();
for (i = 0; map[i] != NULL; i++)
{
const char *element = map[i];
JsonObject *empty_o = json_object_new ();
JsonNode *empty = json_node_init_object (json_node_alloc (), empty_o);
json_object_unref (empty_o);
json_object_set_member (object, element, empty);
}
retval = json_node_init_object (json_node_alloc (), object);
json_object_unref (object);
}
break;
}
default:
g_assert_not_reached ();
}
return retval;
}
static void
marshal_props_for_class (FlatpakJson *self,
FlatpakJsonClass *class,
JsonObject *obj)
{
FlatpakJsonProp *props = NULL;
int i;
gpointer parent_class;
parent_class = g_type_class_peek_parent (class);
if (FLATPAK_JSON_CLASS (parent_class)->props != NULL)
marshal_props_for_class (self,
FLATPAK_JSON_CLASS(parent_class),
obj);
props = FLATPAK_JSON_CLASS (class)->props;
for (i = 0; props[i].name != NULL; i++)
{
JsonNode *val = marshal (obj, props[i].name,
G_STRUCT_MEMBER_P (self, props[i].offset),
props[i].type, props[i].type_data);
if (val == NULL)
continue;
json_object_set_member (obj, props[i].name, val);
}
}
JsonNode *
flatpak_json_to_node (FlatpakJson *self)
{
JsonNode *retval;
JsonObject *obj;
gpointer class;
if (self == NULL)
json_node_new (JSON_NODE_NULL);
obj = json_object_new ();
class = FLATPAK_JSON_GET_CLASS (self);
marshal_props_for_class (self, FLATPAK_JSON_CLASS (class), obj);
retval = json_node_new (JSON_NODE_OBJECT);
json_node_take_object (retval, obj);
return retval;
}
GBytes *
flatpak_json_to_bytes (FlatpakJson *self)
{
g_autoptr(JsonNode) node = NULL;
char *str;
node = flatpak_json_to_node (FLATPAK_JSON (self));
str = json_to_string (node, TRUE);
return g_bytes_new_take (str, strlen (str));
}

View File

@ -0,0 +1,92 @@
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Alexander Larsson <alexl@redhat.com>
*/
#ifndef __FLATPAK_JSON_H__
#define __FLATPAK_JSON_H__
#include <json-glib/json-glib.h>
G_BEGIN_DECLS
#define FLATPAK_TYPE_JSON flatpak_json_get_type ()
typedef struct _FlatpakJsonProp FlatpakJsonProp;
typedef enum {
FLATPAK_JSON_PROP_TYPE_PARENT,
FLATPAK_JSON_PROP_TYPE_INT64,
FLATPAK_JSON_PROP_TYPE_BOOL,
FLATPAK_JSON_PROP_TYPE_STRING,
FLATPAK_JSON_PROP_TYPE_STRUCT,
FLATPAK_JSON_PROP_TYPE_STRUCTV,
FLATPAK_JSON_PROP_TYPE_STRV,
FLATPAK_JSON_PROP_TYPE_STRMAP,
FLATPAK_JSON_PROP_TYPE_BOOLMAP,
} FlatpakJsonPropType;
struct _FlatpakJsonProp {
const char *name;
gsize offset;
FlatpakJsonPropType type;
gpointer type_data;
gpointer type_data2;
} ;
#define FLATPAK_JSON_STRING_PROP(_struct, _field, _name) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRING }
#define FLATPAK_JSON_INT64_PROP(_struct, _field, _name) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_INT64 }
#define FLATPAK_JSON_BOOL_PROP(_struct, _field, _name) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_BOOL }
#define FLATPAK_JSON_STRV_PROP(_struct, _field, _name) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRV }
#define FLATPAK_JSON_STRMAP_PROP(_struct, _field, _name) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRMAP }
#define FLATPAK_JSON_BOOLMAP_PROP(_struct, _field, _name) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_BOOLMAP }
#define FLATPAK_JSON_STRUCT_PROP(_struct, _field, _name, _props) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCT, (gpointer)_props}
#define FLATPAK_JSON_PARENT_PROP(_struct, _field, _props) \
{ "parent", G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_PARENT, (gpointer)_props}
#define FLATPAK_JSON_STRUCTV_PROP(_struct, _field, _name, _props) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCTV, (gpointer)_props, (gpointer) sizeof (**((_struct *) 0)->_field) }
#define FLATPAK_JSON_LAST_PROP { NULL }
G_DECLARE_DERIVABLE_TYPE (FlatpakJson, flatpak_json, FLATPAK, JSON, GObject)
struct _FlatpakJsonClass {
GObjectClass parent_class;
FlatpakJsonProp *props;
const char *mediatype;
};
FlatpakJson *flatpak_json_from_node (JsonNode *node,
GType type,
GError **error);
JsonNode *flatpak_json_to_node (FlatpakJson *self);
FlatpakJson *flatpak_json_from_bytes (GBytes *bytes,
GType type,
GError **error);
GBytes *flatpak_json_to_bytes (FlatpakJson *self);
G_END_DECLS
#endif /* __FLATPAK_JSON_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,104 @@
/*
* Copyright © 2016 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Alexander Larsson <alexl@redhat.com>
*/
#ifndef __FLATPAK_OCI_REGISTRY_H__
#define __FLATPAK_OCI_REGISTRY_H__
#include "libglnx/libglnx.h"
#include <glib.h>
#include <gio/gio.h>
#include <archive.h>
#include "flatpak-json-oci.h"
#include "flatpak-utils.h"
#define FLATPAK_TYPE_OCI_REGISTRY flatpak_oci_registry_get_type ()
#define FLATPAK_OCI_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_OCI_REGISTRY, FlatpakOciRegistry))
#define FLATPAK_IS_OCI_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_OCI_REGISTRY))
GType flatpak_oci_registry_get_type (void);
typedef struct FlatpakOciRegistry FlatpakOciRegistry;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakOciRegistry, g_object_unref)
#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 (FlatpakOciLayerWriter, g_object_unref)
FlatpakOciRegistry * flatpak_oci_registry_new (const char *uri,
gboolean for_write,
int tmp_dfd,
GCancellable *cancellable,
GError **error);
FlatpakOciRef * flatpak_oci_registry_load_ref (FlatpakOciRegistry *self,
const char *ref,
GCancellable *cancellable,
GError **error);
gboolean flatpak_oci_registry_set_ref (FlatpakOciRegistry *self,
const char *ref,
FlatpakOciRef *data,
GCancellable *cancellable,
GError **error);
int flatpak_oci_registry_download_blob (FlatpakOciRegistry *self,
const char *digest,
FlatpakLoadUriProgress progress_cb,
gpointer user_data,
GCancellable *cancellable,
GError **error);
GBytes * flatpak_oci_registry_load_blob (FlatpakOciRegistry *self,
const char *digest,
GCancellable *cancellable,
GError **error);
char * flatpak_oci_registry_store_blob (FlatpakOciRegistry *self,
GBytes *data,
GCancellable *cancellable,
GError **error);
FlatpakOciRef * flatpak_oci_registry_store_json (FlatpakOciRegistry *self,
FlatpakJson *json,
GCancellable *cancellable,
GError **error);
FlatpakOciVersioned * flatpak_oci_registry_load_versioned (FlatpakOciRegistry *self,
const char *digest,
GCancellable *cancellable,
GError **error);
FlatpakOciLayerWriter *flatpak_oci_registry_write_layer (FlatpakOciRegistry *self,
GCancellable *cancellable,
GError **error);
FlatpakOciManifest *flatpak_oci_registry_chose_image (FlatpakOciRegistry *self,
const char *tag,
GCancellable *cancellable,
GError **error);
struct archive *flatpak_oci_layer_writer_get_archive (FlatpakOciLayerWriter *self);
gboolean flatpak_oci_layer_writer_close (FlatpakOciLayerWriter *self,
char **uncompressed_digest_out,
FlatpakOciRef **ref_out,
GCancellable *cancellable,
GError **error);
#endif /* __FLATPAK_OCI_REGISTRY_H__ */

View File

@ -89,6 +89,7 @@ libflatpak_la_LIBADD = \
$(BASE_LIBS) \
$(OSTREE_LIBS) \
$(SOUP_LIBS) \
$(JSON_LIBS) \
$(NULL)
test_libflatpak_SOURCES = \