diff --git a/libostree/ostree-checkout.c b/libostree/ostree-checkout.c deleted file mode 100644 index 0d584986..00000000 --- a/libostree/ostree-checkout.c +++ /dev/null @@ -1,362 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2011 Colin Walters - * - * This library 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 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Colin Walters - */ - -#include "config.h" - -#include "ostree.h" -#include "otutil.h" - -enum { - PROP_0, - - PROP_REPO, - PROP_PATH -}; - -G_DEFINE_TYPE (OstreeCheckout, ostree_checkout, G_TYPE_OBJECT) - -#define GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), OSTREE_TYPE_CHECKOUT, OstreeCheckoutPrivate)) - -typedef struct _OstreeCheckoutPrivate OstreeCheckoutPrivate; - -struct _OstreeCheckoutPrivate { - OstreeRepo *repo; - char *path; -}; - -static void -ostree_checkout_finalize (GObject *object) -{ - OstreeCheckout *self = OSTREE_CHECKOUT (object); - OstreeCheckoutPrivate *priv = GET_PRIVATE (self); - - g_free (priv->path); - g_clear_object (&priv->repo); - - G_OBJECT_CLASS (ostree_checkout_parent_class)->finalize (object); -} - -static void -ostree_checkout_set_property(GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - OstreeCheckout *self = OSTREE_CHECKOUT (object); - OstreeCheckoutPrivate *priv = GET_PRIVATE (self); - - switch (prop_id) - { - case PROP_PATH: - priv->path = g_value_dup_string (value); - break; - case PROP_REPO: - priv->repo = g_value_dup_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -ostree_checkout_get_property(GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - OstreeCheckout *self = OSTREE_CHECKOUT (object); - OstreeCheckoutPrivate *priv = GET_PRIVATE (self); - - switch (prop_id) - { - case PROP_PATH: - g_value_set_string (value, priv->path); - break; - case PROP_REPO: - g_value_set_object (value, priv->repo); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GObject * -ostree_checkout_constructor (GType gtype, - guint n_properties, - GObjectConstructParam *properties) -{ - GObject *object; - GObjectClass *parent_class; - OstreeCheckoutPrivate *priv; - - parent_class = G_OBJECT_CLASS (ostree_checkout_parent_class); - object = parent_class->constructor (gtype, n_properties, properties); - - priv = GET_PRIVATE (object); - - g_assert (priv->path != NULL); - - return object; -} - -static void -ostree_checkout_class_init (OstreeCheckoutClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (OstreeCheckoutPrivate)); - - object_class->constructor = ostree_checkout_constructor; - object_class->get_property = ostree_checkout_get_property; - object_class->set_property = ostree_checkout_set_property; - object_class->finalize = ostree_checkout_finalize; - - g_object_class_install_property (object_class, - PROP_PATH, - g_param_spec_string ("path", "", "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_REPO, - g_param_spec_object ("repo", "", "", - OSTREE_TYPE_REPO, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); -} - -static void -ostree_checkout_init (OstreeCheckout *self) -{ -} - -OstreeCheckout* -ostree_checkout_new (OstreeRepo *repo, - const char *path) -{ - return g_object_new (OSTREE_TYPE_CHECKOUT, "repo", repo, "path", path, NULL); -} - -static gboolean -executable_exists_in_checkout (const char *path, - const char *executable) -{ - int i; - const char *subdirs[] = {"bin", "sbin", "usr/bin", "usr/sbin"}; - - for (i = 0; i < G_N_ELEMENTS (subdirs); i++) - { - char *possible_path = g_build_filename (path, subdirs[i], executable, NULL); - gboolean exists; - - exists = g_file_test (possible_path, G_FILE_TEST_EXISTS); - g_free (possible_path); - - if (exists) - return TRUE; - } - - return FALSE; -} - -static gboolean -run_trigger (OstreeCheckout *self, - GFile *trigger, - gboolean requires_chroot, - GError **error) -{ - OstreeCheckoutPrivate *priv = GET_PRIVATE (self); - gboolean ret = FALSE; - char *path = NULL; - char *temp_path = NULL; - char *rel_temp_path = NULL; - GFile *temp_copy = NULL; - char *basename = NULL; - GPtrArray *args = NULL; - int estatus; - - path = g_file_get_path (trigger); - basename = g_path_get_basename (path); - - args = g_ptr_array_new (); - - if (requires_chroot) - { - temp_path = g_build_filename (priv->path, basename, NULL); - rel_temp_path = g_strconcat ("./", basename, NULL); - temp_copy = ot_util_new_file_for_path (temp_path); - - if (!g_file_copy (trigger, temp_copy, 0, NULL, NULL, NULL, error)) - goto out; - - g_ptr_array_add (args, "chroot"); - g_ptr_array_add (args, "."); - g_ptr_array_add (args, rel_temp_path); - g_ptr_array_add (args, NULL); - } - else - { - g_ptr_array_add (args, path); - g_ptr_array_add (args, NULL); - } - - g_print ("Running trigger: %s\n", path); - if (!g_spawn_sync (priv->path, - (char**)args->pdata, - NULL, - G_SPAWN_SEARCH_PATH, - NULL, NULL, NULL, NULL, - &estatus, - error)) - { - g_prefix_error (error, "Failed to run trigger %s: ", basename); - goto out; - } - - ret = TRUE; - out: - if (requires_chroot && temp_path) - (void)unlink (temp_path); - - g_free (path); - g_free (basename); - g_free (temp_path); - g_free (rel_temp_path); - g_clear_object (&temp_copy); - if (args) - g_ptr_array_free (args, TRUE); - return ret; -} - -static gboolean -check_trigger (OstreeCheckout *self, - GFile *trigger, - GError **error) -{ - OstreeCheckoutPrivate *priv = GET_PRIVATE (self); - gboolean ret = FALSE; - GInputStream *instream = NULL; - GDataInputStream *datain = NULL; - GError *temp_error = NULL; - char *line; - gsize len; - gboolean requires_chroot = TRUE; - gboolean matches = FALSE; - - instream = (GInputStream*)g_file_read (trigger, NULL, error); - if (!instream) - goto out; - datain = g_data_input_stream_new (instream); - - while ((line = g_data_input_stream_read_line (datain, &len, NULL, &temp_error)) != NULL) - { - if (g_str_has_prefix (line, "# IfExecutable: ")) - { - char *executable = g_strdup (line + strlen ("# IfExecutable: ")); - g_strchomp (executable); - matches = executable_exists_in_checkout (priv->path, executable); - g_free (executable); - } - - g_free (line); - } - if (line == NULL && temp_error != NULL) - { - g_propagate_error (error, temp_error); - goto out; - } - if (matches) - { - if (!run_trigger (self, trigger, requires_chroot, error)) - goto out; - } - - ret = TRUE; - out: - g_clear_object (&instream); - g_clear_object (&datain); - return ret; -} - -gboolean -ostree_checkout_run_triggers (OstreeCheckout *self, - GError **error) -{ - gboolean ret = FALSE; - GError *temp_error = NULL; - char *triggerdir_path = NULL; - GFile *triggerdir = NULL; - GFileInfo *file_info = NULL; - GFileEnumerator *enumerator = NULL; - - triggerdir_path = g_build_filename (LIBEXECDIR, "ostree", "triggers.d", NULL); - triggerdir = ot_util_new_file_for_path (triggerdir_path); - - enumerator = g_file_enumerate_children (triggerdir, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, - error); - if (!enumerator) - goto out; - - while ((file_info = g_file_enumerator_next_file (enumerator, NULL, &temp_error)) != NULL) - { - const char *name; - guint32 type; - char *child_path = NULL; - GFile *child = NULL; - gboolean success; - - name = g_file_info_get_attribute_byte_string (file_info, "standard::name"); - type = g_file_info_get_attribute_uint32 (file_info, "standard::type"); - - if (type == G_FILE_TYPE_REGULAR && g_str_has_suffix (name, ".trigger")) - { - child_path = g_build_filename (triggerdir_path, name, NULL); - child = ot_util_new_file_for_path (child_path); - - success = check_trigger (self, child, error); - } - else - success = TRUE; - - g_object_unref (file_info); - g_free (child_path); - g_clear_object (&child); - if (!success) - goto out; - } - if (file_info == NULL && temp_error != NULL) - { - g_propagate_error (error, temp_error); - goto out; - } - - ret = TRUE; - out: - g_free (triggerdir_path); - g_clear_object (&triggerdir); - g_clear_object (&enumerator); - return ret; -} diff --git a/libostree/ostree-checkout.h b/libostree/ostree-checkout.h deleted file mode 100644 index 042cdc8b..00000000 --- a/libostree/ostree-checkout.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2011 Colin Walters - * - * This library 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 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Colin Walters - */ - -#ifndef _OSTREE_CHECKOUT -#define _OSTREE_CHECKOUT - -#include - -G_BEGIN_DECLS - -#define OSTREE_TYPE_CHECKOUT ostree_checkout_get_type() -#define OSTREE_CHECKOUT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSTREE_TYPE_CHECKOUT, OstreeCheckout)) -#define OSTREE_CHECKOUT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), OSTREE_TYPE_CHECKOUT, OstreeCheckoutClass)) -#define OSTREE_IS_CHECKOUT(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSTREE_TYPE_CHECKOUT)) -#define OSTREE_IS_CHECKOUT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), OSTREE_TYPE_CHECKOUT)) -#define OSTREE_CHECKOUT_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), OSTREE_TYPE_CHECKOUT, OstreeCheckoutClass)) - -typedef struct { - GObject parent; -} OstreeCheckout; - -typedef struct { - GObjectClass parent_class; -} OstreeCheckoutClass; - -GType ostree_checkout_get_type (void); - -OstreeCheckout* ostree_checkout_new (OstreeRepo *repo, - const char *path); - -gboolean ostree_checkout_run_triggers (OstreeCheckout *checkout, - GError **error); - -G_END_DECLS - -#endif /* _OSTREE_CHECKOUT */ diff --git a/libostree/ostree-core.c b/libostree/ostree-core.c deleted file mode 100644 index ca0fb1f5..00000000 --- a/libostree/ostree-core.c +++ /dev/null @@ -1,856 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2011 Colin Walters - * - * This library 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 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Colin Walters - */ - -#include "config.h" - -#include "ostree.h" -#include "otutil.h" - -#include -#include - -gboolean -ostree_validate_checksum_string (const char *sha256, - GError **error) -{ - if (strlen (sha256) != 64) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid rev '%s'", sha256); - return FALSE; - } - return TRUE; -} - - -void -ostree_checksum_update_stat (GChecksum *checksum, guint32 uid, guint32 gid, guint32 mode) -{ - guint32 perms = (mode & ~S_IFMT); - g_checksum_update (checksum, (guint8*) &uid, 4); - g_checksum_update (checksum, (guint8*) &gid, 4); - g_checksum_update (checksum, (guint8*) &perms, 4); -} - -static char * -canonicalize_xattrs (char *xattr_string, size_t len) -{ - char *p; - GSList *xattrs = NULL; - GSList *iter; - GString *result; - - result = g_string_new (0); - - p = xattr_string; - while (p < xattr_string+len) - { - xattrs = g_slist_prepend (xattrs, p); - p += strlen (p) + 1; - } - - xattrs = g_slist_sort (xattrs, (GCompareFunc) strcmp); - for (iter = xattrs; iter; iter = iter->next) - g_string_append (result, iter->data); - - g_slist_free (xattrs); - return g_string_free (result, FALSE); -} - -static gboolean -read_xattr_name_array (const char *path, - const char *xattrs, - size_t len, - GVariantBuilder *builder, - GError **error) -{ - gboolean ret = FALSE; - const char *p; - - p = xattrs; - while (p < xattrs+len) - { - ssize_t bytes_read; - char *buf; - - bytes_read = lgetxattr (path, p, NULL, 0); - if (bytes_read < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - if (bytes_read == 0) - continue; - - buf = g_malloc (bytes_read); - if (lgetxattr (path, p, buf, bytes_read) < 0) - { - ot_util_set_error_from_errno (error, errno); - g_free (buf); - goto out; - } - - g_variant_builder_add (builder, "(@ay@ay)", - g_variant_new_bytestring (p), - g_variant_new_from_data (G_VARIANT_TYPE ("ay"), - buf, bytes_read, FALSE, g_free, buf)); - - p = p + strlen (p) + 1; - } - - ret = TRUE; - out: - return ret; -} - -GVariant * -ostree_get_xattrs_for_path (const char *path, - GError **error) -{ - GVariant *ret = NULL; - GVariantBuilder builder; - char *xattr_names = NULL; - char *xattr_names_canonical = NULL; - ssize_t bytes_read; - - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ayay)")); - - bytes_read = llistxattr (path, NULL, 0); - - if (bytes_read < 0) - { - if (errno != ENOTSUP) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - } - else if (bytes_read > 0) - { - xattr_names = g_malloc (bytes_read); - if (llistxattr (path, xattr_names, bytes_read) < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - xattr_names_canonical = canonicalize_xattrs (xattr_names, bytes_read); - - if (!read_xattr_name_array (path, xattr_names_canonical, bytes_read, &builder, error)) - goto out; - } - - ret = g_variant_builder_end (&builder); - g_variant_ref_sink (ret); - out: - if (!ret) - g_variant_builder_clear (&builder); - g_free (xattr_names); - g_free (xattr_names_canonical); - return ret; -} - -gboolean -ostree_stat_and_checksum_file (int dir_fd, const char *path, - OstreeObjectType objtype, - GChecksum **out_checksum, - struct stat *out_stbuf, - GError **error) -{ - GChecksum *content_sha256 = NULL; - GChecksum *content_and_meta_sha256 = NULL; - char *stat_string = NULL; - ssize_t bytes_read; - GVariant *xattrs = NULL; - int fd = -1; - DIR *temp_dir = NULL; - char *basename = NULL; - gboolean ret = FALSE; - char *symlink_target = NULL; - char *device_id = NULL; - struct stat stbuf; - - basename = g_path_get_basename (path); - - if (dir_fd == -1) - { - char *dirname = g_path_get_dirname (path); - temp_dir = opendir (dirname); - if (temp_dir == NULL) - { - ot_util_set_error_from_errno (error, errno); - g_free (dirname); - } - g_free (dirname); - dir_fd = dirfd (temp_dir); - } - - if (fstatat (dir_fd, basename, &stbuf, AT_SYMLINK_NOFOLLOW) < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - - if (S_ISREG(stbuf.st_mode)) - { - fd = ot_util_open_file_read_at (dir_fd, basename, error); - if (fd < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - } - - if (objtype == OSTREE_OBJECT_TYPE_FILE) - { - xattrs = ostree_get_xattrs_for_path (path, error); - if (!xattrs) - goto out; - } - - content_sha256 = g_checksum_new (G_CHECKSUM_SHA256); - - if (S_ISREG(stbuf.st_mode)) - { - guint8 buf[8192]; - - while ((bytes_read = read (fd, buf, sizeof (buf))) > 0) - g_checksum_update (content_sha256, buf, bytes_read); - if (bytes_read < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - } - else if (S_ISLNK(stbuf.st_mode)) - { - symlink_target = g_malloc (PATH_MAX); - - g_assert (objtype == OSTREE_OBJECT_TYPE_FILE); - - bytes_read = readlinkat (dir_fd, basename, symlink_target, PATH_MAX); - if (bytes_read < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - g_checksum_update (content_sha256, (guint8*)symlink_target, bytes_read); - } - else if (S_ISCHR(stbuf.st_mode) || S_ISBLK(stbuf.st_mode)) - { - g_assert (objtype == OSTREE_OBJECT_TYPE_FILE); - device_id = g_strdup_printf ("%u", (guint)stbuf.st_rdev); - g_checksum_update (content_sha256, (guint8*)device_id, strlen (device_id)); - } - else if (S_ISFIFO(stbuf.st_mode)) - { - g_assert (objtype == OSTREE_OBJECT_TYPE_FILE); - } - else - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Unsupported file '%s' (must be regular, symbolic link, fifo, or character/block device)", - path); - goto out; - } - - content_and_meta_sha256 = g_checksum_copy (content_sha256); - - if (objtype == OSTREE_OBJECT_TYPE_FILE) - { - ostree_checksum_update_stat (content_and_meta_sha256, stbuf.st_uid, - stbuf.st_gid, stbuf.st_mode); - g_checksum_update (content_and_meta_sha256, (guint8*)g_variant_get_data (xattrs), g_variant_get_size (xattrs)); - } - - *out_stbuf = stbuf; - *out_checksum = content_and_meta_sha256; - ret = TRUE; - out: - if (fd >= 0) - close (fd); - if (temp_dir != NULL) - closedir (temp_dir); - g_free (symlink_target); - g_free (basename); - g_free (stat_string); - if (xattrs) - g_variant_unref (xattrs); - if (content_sha256) - g_checksum_free (content_sha256); - return ret; -} - -gboolean -ostree_set_xattrs (const char *path, GVariant *xattrs, GCancellable *cancellable, GError **error) -{ - gboolean ret = FALSE; - int i, n; - - n = g_variant_n_children (xattrs); - for (i = 0; i < n; i++) - { - const guint8* name; - GVariant *value; - const guint8* value_data; - gsize value_len; - gboolean loop_err; - - g_variant_get_child (xattrs, i, "(^&ay@ay)", - &name, &value); - value_data = g_variant_get_fixed_array (value, &value_len, 1); - - loop_err = lsetxattr (path, (char*)name, (char*)value_data, value_len, XATTR_REPLACE) < 0; - - g_variant_unref (value); - if (loop_err) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - } - - ret = TRUE; - out: - return ret; -} - -gboolean -ostree_parse_metadata_file (const char *path, - OstreeSerializedVariantType *out_type, - GVariant **out_variant, - GError **error) -{ - GFile *pathf = NULL; - gboolean ret = FALSE; - GVariant *ret_variant = NULL; - GVariant *container = NULL; - guint32 ret_type; - - pathf = ot_util_new_file_for_path (path); - if (!ot_util_variant_map (pathf, G_VARIANT_TYPE (OSTREE_SERIALIZED_VARIANT_FORMAT), - &container, error)) - goto out; - - g_variant_get (container, "(uv)", - &ret_type, &ret_variant); - ret_type = GUINT32_FROM_BE (ret_type); - if (ret_type <= 0 || ret_type > OSTREE_SERIALIZED_VARIANT_LAST) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Corrupted metadata object '%s'; invalid type %d", path, ret_type); - goto out; - } - - ret = TRUE; - *out_type = ret_type; - *out_variant = ot_util_variant_take_ref (ret_variant); - ret_variant = NULL; - out: - if (ret_variant) - g_variant_unref (ret_variant); - if (container != NULL) - g_variant_unref (container); - g_clear_object (&pathf); - return ret; -} - -char * -ostree_get_relative_object_path (const char *checksum, - OstreeObjectType type, - gboolean archive) -{ - GString *path; - const char *type_string; - - g_assert (strlen (checksum) == 64); - - path = g_string_new ("objects/"); - - g_string_append_len (path, checksum, 2); - g_string_append_c (path, '/'); - g_string_append (path, checksum + 2); - switch (type) - { - case OSTREE_OBJECT_TYPE_FILE: - if (archive) - type_string = ".packfile"; - else - type_string = ".file"; - break; - case OSTREE_OBJECT_TYPE_META: - type_string = ".meta"; - break; - default: - g_assert_not_reached (); - } - g_string_append (path, type_string); - return g_string_free (path, FALSE); -} - -gboolean -ostree_pack_object (GOutputStream *output, - GFile *file, - OstreeObjectType objtype, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - char *path = NULL; - GFileInfo *finfo = NULL; - GFileInputStream *instream = NULL; - gboolean pack_builder_initialized = FALSE; - GVariantBuilder pack_builder; - GVariant *pack_variant = NULL; - GVariant *xattrs = NULL; - gsize bytes_written; - - path = g_file_get_path (file); - - finfo = g_file_query_info (file, "standard::type,standard::size,standard::is-symlink,standard::symlink-target,unix::*", - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, error); - if (!finfo) - goto out; - - if (objtype == OSTREE_OBJECT_TYPE_META) - { - guint64 object_size_be = GUINT64_TO_BE ((guint64)g_file_info_get_size (finfo)); - if (!g_output_stream_write_all (output, &object_size_be, 8, &bytes_written, cancellable, error)) - goto out; - - instream = g_file_read (file, NULL, error); - if (!instream) - goto out; - - if (g_output_stream_splice (output, (GInputStream*)instream, 0, cancellable, error) < 0) - goto out; - } - else - { - guint32 uid, gid, mode; - guint32 device = 0; - guint32 metadata_size_be; - const char *target = NULL; - guint64 object_size; - - uid = g_file_info_get_attribute_uint32 (finfo, G_FILE_ATTRIBUTE_UNIX_UID); - gid = g_file_info_get_attribute_uint32 (finfo, G_FILE_ATTRIBUTE_UNIX_GID); - mode = g_file_info_get_attribute_uint32 (finfo, G_FILE_ATTRIBUTE_UNIX_MODE); - - g_variant_builder_init (&pack_builder, G_VARIANT_TYPE (OSTREE_PACK_FILE_VARIANT_FORMAT)); - pack_builder_initialized = TRUE; - g_variant_builder_add (&pack_builder, "u", GUINT32_TO_BE (0)); - g_variant_builder_add (&pack_builder, "u", GUINT32_TO_BE (uid)); - g_variant_builder_add (&pack_builder, "u", GUINT32_TO_BE (gid)); - g_variant_builder_add (&pack_builder, "u", GUINT32_TO_BE (mode)); - - xattrs = ostree_get_xattrs_for_path (path, error); - if (!xattrs) - goto out; - g_variant_builder_add (&pack_builder, "@a(ayay)", xattrs); - - if (S_ISREG (mode)) - { - object_size = (guint64)g_file_info_get_size (finfo); - } - else if (S_ISLNK (mode)) - { - target = g_file_info_get_attribute_byte_string (finfo, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET); - object_size = strlen (target); - } - else if (S_ISBLK (mode) || S_ISCHR (mode)) - { - device = g_file_info_get_attribute_uint32 (finfo, G_FILE_ATTRIBUTE_UNIX_DEVICE); - object_size = 4; - } - else if (S_ISFIFO (mode)) - { - object_size = 0; - } - else - g_assert_not_reached (); - - g_variant_builder_add (&pack_builder, "t", GUINT64_TO_BE (object_size)); - pack_variant = g_variant_builder_end (&pack_builder); - pack_builder_initialized = FALSE; - - metadata_size_be = GUINT32_TO_BE (g_variant_get_size (pack_variant)); - - if (!g_output_stream_write_all (output, &metadata_size_be, 4, - &bytes_written, cancellable, error)) - goto out; - g_assert (bytes_written == 4); - - if (!g_output_stream_write_all (output, g_variant_get_data (pack_variant), g_variant_get_size (pack_variant), - &bytes_written, cancellable, error)) - goto out; - - if (S_ISREG (mode)) - { - instream = g_file_read (file, NULL, error); - if (!instream) - goto out; - bytes_written = g_output_stream_splice (output, (GInputStream*)instream, 0, cancellable, error); - if (bytes_written < 0) - goto out; - if (bytes_written != object_size) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "File size changed unexpectedly"); - goto out; - } - } - else if (S_ISLNK (mode)) - { - if (!g_output_stream_write_all (output, target, object_size, - &bytes_written, cancellable, error)) - goto out; - } - else if (S_ISBLK (mode) || S_ISCHR (mode)) - { - guint32 device_be = GUINT32_TO_BE (device); - g_assert (object_size == 4); - if (!g_output_stream_write_all (output, &device_be, object_size, - &bytes_written, cancellable, error)) - goto out; - g_assert (bytes_written == 4); - } - else if (S_ISFIFO (mode)) - { - } - else - g_assert_not_reached (); - } - - ret = TRUE; - out: - g_free (path); - g_clear_object (&finfo); - g_clear_object (&instream); - if (xattrs) - g_variant_unref (xattrs); - if (pack_builder_initialized) - g_variant_builder_clear (&pack_builder); - if (pack_variant) - g_variant_unref (pack_variant); - return ret; -} - -static gboolean -splice_and_checksum (GOutputStream *out, - GInputStream *in, - GChecksum *checksum, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - - if (checksum != NULL) - { - gsize bytes_read, bytes_written; - char buf[4096]; - do - { - if (!g_input_stream_read_all (in, buf, sizeof(buf), &bytes_read, cancellable, error)) - goto out; - if (checksum) - g_checksum_update (checksum, (guint8*)buf, bytes_read); - if (!g_output_stream_write_all (out, buf, bytes_read, &bytes_written, cancellable, error)) - goto out; - } - while (bytes_read > 0); - } - else - { - if (g_output_stream_splice (out, in, 0, cancellable, error) < 0) - goto out; - } - - ret = TRUE; - out: - return ret; -} - -static gboolean -unpack_meta (const char *path, - const char *dest_path, - GChecksum **out_checksum, - GError **error) -{ - gboolean ret = FALSE; - GFile *file = NULL; - GFile *dest_file = NULL; - GFileInputStream *in = NULL; - GChecksum *ret_checksum = NULL; - GFileOutputStream *out = NULL; - - file = ot_util_new_file_for_path (path); - dest_file = ot_util_new_file_for_path (dest_path); - - if (out_checksum) - ret_checksum = g_checksum_new (G_CHECKSUM_SHA256); - - in = g_file_read (file, NULL, error); - if (!in) - goto out; - - out = g_file_replace (dest_file, NULL, FALSE, 0, NULL, error); - if (!out) - goto out; - - if (!splice_and_checksum ((GOutputStream*)out, (GInputStream*)in, ret_checksum, NULL, error)) - goto out; - - if (!g_output_stream_close ((GOutputStream*)out, NULL, error)) - goto out; - - ret = TRUE; - if (out_checksum) - *out_checksum = ret_checksum; - ret_checksum = NULL; - out: - if (!ret) - (void) unlink (dest_path); - if (ret_checksum) - g_checksum_free (ret_checksum); - g_clear_object (&file); - g_clear_object (&dest_file); - g_clear_object (&in); - return ret; -} - -gboolean -ostree_parse_packed_file (GFile *file, - GVariant **out_metadata, - GInputStream **out_content, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - char *metadata_buf = NULL; - GVariant *ret_metadata = NULL; - GFileInputStream *in = NULL; - guint32 metadata_len; - gsize bytes_read; - - in = g_file_read (file, NULL, error); - if (!in) - goto out; - - if (!g_input_stream_read_all ((GInputStream*)in, &metadata_len, 4, &bytes_read, NULL, error)) - goto out; - if (bytes_read != 4) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Corrupted packfile; too short while reading metadata length"); - goto out; - } - - metadata_len = GUINT32_FROM_BE (metadata_len); - if (metadata_len > OSTREE_MAX_METADATA_SIZE) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Corrupted packfile; metadata length %u is larger than maximum %u", - metadata_len, OSTREE_MAX_METADATA_SIZE); - goto out; - } - metadata_buf = g_malloc (metadata_len); - - if (!g_input_stream_read_all ((GInputStream*)in, metadata_buf, metadata_len, &bytes_read, NULL, error)) - goto out; - if (bytes_read != metadata_len) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Corrupted packfile; too short while reading metadata"); - goto out; - } - - ret_metadata = g_variant_new_from_data (G_VARIANT_TYPE (OSTREE_PACK_FILE_VARIANT_FORMAT), - metadata_buf, metadata_len, FALSE, - (GDestroyNotify)g_free, - metadata_buf); - metadata_buf = NULL; - - ret = TRUE; - *out_metadata = ret_metadata; - ret_metadata = NULL; - *out_content = (GInputStream*)in; - in = NULL; - out: - g_clear_object (&in); - if (ret_metadata) - g_variant_unref (ret_metadata); - return ret; -} - -static gboolean -unpack_file (const char *path, - const char *dest_path, - GChecksum **out_checksum, - GError **error) -{ - gboolean ret = FALSE; - GFile *file = NULL; - GFile *dest_file = NULL; - GVariant *metadata = NULL; - GVariant *xattrs = NULL; - GInputStream *in = NULL; - GFileOutputStream *out = NULL; - GChecksum *ret_checksum = NULL; - guint32 version, uid, gid, mode; - guint64 content_len; - gsize bytes_read; - - file = ot_util_new_file_for_path (path); - - if (!ostree_parse_packed_file (file, &metadata, &in, NULL, error)) - goto out; - - g_variant_get (metadata, "(uuuu@a(ayay)t)", - &version, &uid, &gid, &mode, - &xattrs, &content_len); - uid = GUINT32_FROM_BE (uid); - gid = GUINT32_FROM_BE (gid); - mode = GUINT32_FROM_BE (mode); - content_len = GUINT64_FROM_BE (content_len); - - dest_file = ot_util_new_file_for_path (dest_path); - - if (out_checksum) - ret_checksum = g_checksum_new (G_CHECKSUM_SHA256); - - if (S_ISREG (mode)) - { - out = g_file_replace (dest_file, NULL, FALSE, 0, NULL, error); - if (!out) - goto out; - - if (!splice_and_checksum ((GOutputStream*)out, in, ret_checksum, NULL, error)) - goto out; - - if (!g_output_stream_close ((GOutputStream*)out, NULL, error)) - goto out; - } - else if (S_ISLNK (mode)) - { - char target[PATH_MAX+1]; - - if (!g_input_stream_read_all (in, target, sizeof(target)-1, &bytes_read, NULL, error)) - goto out; - target[bytes_read] = '\0'; - if (ret_checksum) - g_checksum_update (ret_checksum, (guint8*)target, bytes_read); - if (symlink (target, dest_path) < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - } - else if (S_ISCHR (mode) || S_ISBLK (mode)) - { - guint32 dev; - - if (!g_input_stream_read_all (in, &dev, 4, &bytes_read, NULL, error)) - goto out; - if (bytes_read != 4) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Corrupted packfile; too short while reading device id"); - goto out; - } - dev = GUINT32_FROM_BE (dev); - if (ret_checksum) - g_checksum_update (ret_checksum, (guint8*)&dev, 4); - if (mknod (dest_path, mode, dev) < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - } - else if (S_ISFIFO (mode)) - { - if (mkfifo (dest_path, mode) < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - } - else - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Corrupted packfile; invalid mode %u", mode); - goto out; - } - - if (!S_ISLNK (mode)) - { - if (chmod (dest_path, mode) < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - } - - if (!ostree_set_xattrs (dest_path, xattrs, NULL, error)) - goto out; - - if (ret_checksum) - { - ostree_checksum_update_stat (ret_checksum, uid, gid, mode); - g_checksum_update (ret_checksum, (guint8*)g_variant_get_data (xattrs), g_variant_get_size (xattrs)); - } - - ret = TRUE; - if (out_checksum) - *out_checksum = ret_checksum; - ret_checksum = NULL; - out: - if (!ret) - (void) unlink (dest_path); - if (ret_checksum) - g_checksum_free (ret_checksum); - g_clear_object (&file); - g_clear_object (&dest_file); - g_clear_object (&in); - g_clear_object (&out); - if (metadata) - g_variant_unref (metadata); - if (xattrs) - g_variant_unref (xattrs); - return ret; -} - -gboolean -ostree_unpack_object (const char *path, - OstreeObjectType objtype, - const char *dest_path, - GChecksum **out_checksum, - GError **error) -{ - if (objtype == OSTREE_OBJECT_TYPE_META) - return unpack_meta (path, dest_path, out_checksum, error); - else - return unpack_file (path, dest_path, out_checksum, error); -} - - - diff --git a/libostree/ostree-core.h b/libostree/ostree-core.h deleted file mode 100644 index d67f42f9..00000000 --- a/libostree/ostree-core.h +++ /dev/null @@ -1,155 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2011 Colin Walters - * - * This library 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 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Colin Walters - */ - -#ifndef _OSTREE_CORE -#define _OSTREE_CORE - -#include - -G_BEGIN_DECLS - -#define OSTREE_MAX_METADATA_SIZE (1 << 26) - -#define OSTREE_GIO_FAST_QUERYINFO "standard::name,standard::type,standard::is-symlink,standard::symlink-target,standard::is-hidden,unix::*" - -#define OSTREE_EMPTY_STRING_SHA256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; - -typedef enum { - OSTREE_OBJECT_TYPE_FILE = 1, - OSTREE_OBJECT_TYPE_META = 2, -} OstreeObjectType; - -typedef enum { - OSTREE_SERIALIZED_TREE_VARIANT = 1, - OSTREE_SERIALIZED_COMMIT_VARIANT = 2, - OSTREE_SERIALIZED_DIRMETA_VARIANT = 3, - OSTREE_SERIALIZED_XATTR_VARIANT = 4 -} OstreeSerializedVariantType; -#define OSTREE_SERIALIZED_VARIANT_LAST 4 - -#define OSTREE_SERIALIZED_VARIANT_FORMAT "(uv)" - -/* - * xattr objects: - * a(ayay) - array of (name, value) pairs, both binary data, though name is a bytestring - */ -#define OSTREE_XATTR_GVARIANT_FORMAT "a(ayay)" - -#define OSTREE_DIR_META_VERSION 0 -/* - * dirmeta objects: - * u - Version - * u - uid - * u - gid - * u - mode - * a(ayay) - xattrs - */ -#define OSTREE_DIRMETA_GVARIANT_FORMAT "(uuuua(ayay))" - -#define OSTREE_TREE_VERSION 0 -/* - * Tree objects: - * u - Version - * a{sv} - Metadata - * a(ss) - array of (filename, checksum) for files - * a(sss) - array of (dirname, tree_checksum, meta_checksum) for directories - */ -#define OSTREE_TREE_GVARIANT_FORMAT "(ua{sv}a(ss)a(sss)" - -#define OSTREE_COMMIT_VERSION 0 -/* - * Commit objects: - * u - Version - * a{sv} - Metadata - * s - parent checksum (empty string for initial) - * s - subject - * s - body - * t - Timestamp in seconds since the epoch (UTC) - * s - Root tree contents - * s - Root tree metadata - */ -#define OSTREE_COMMIT_GVARIANT_FORMAT "(ua{sv}ssstss)" - -gboolean ostree_validate_checksum_string (const char *sha256, - GError **error); - -char *ostree_get_relative_object_path (const char *checksum, - OstreeObjectType type, - gboolean archive); - -GVariant *ostree_get_xattrs_for_path (const char *path, - GError **error); - -gboolean ostree_set_xattrs (const char *path, GVariant *xattrs, - GCancellable *cancellable, GError **error); - -gboolean ostree_parse_metadata_file (const char *path, - OstreeSerializedVariantType *out_type, - GVariant **out_variant, - GError **error); - -gboolean ostree_stat_and_checksum_file (int dirfd, const char *path, - OstreeObjectType type, - GChecksum **out_checksum, - struct stat *out_stbuf, - GError **error); - -/* Packed files: - * - * guint32 metadata_length [metadata gvariant] [content] - * - * metadata variant: - * u - Version - * u - uid - * u - gid - * u - mode - * a(ayay) - xattrs - * t - content length - * - * And then following the end of the variant is the content. If - * symlink, then this is the target; if device, then device ID as - * network byte order uint32. - */ -#define OSTREE_PACK_FILE_VARIANT_FORMAT "(uuuua(ayay)t)" - -gboolean ostree_pack_object (GOutputStream *output, - GFile *file, - OstreeObjectType objtype, - GCancellable *cancellable, - GError **error); - -gboolean ostree_parse_packed_file (GFile *file, - GVariant **out_metadata, - GInputStream **out_content, - GCancellable *cancellable, - GError **error); - -gboolean ostree_unpack_object (const char *path, - OstreeObjectType objtype, - const char *dest_path, - GChecksum **out_checksum, - GError **error); - -void ostree_checksum_update_stat (GChecksum *checksum, guint32 uid, guint32 gid, guint32 mode); - - -#endif /* _OSTREE_REPO */ diff --git a/libostree/ostree-repo-file-enumerator.c b/libostree/ostree-repo-file-enumerator.c deleted file mode 100644 index 7858bde9..00000000 --- a/libostree/ostree-repo-file-enumerator.c +++ /dev/null @@ -1,143 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2011 Colin Walters - * - * This library 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 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Colin Walters - */ - -#include "config.h" - -#include "ostree-repo-file-enumerator.h" -#include - -struct _OstreeRepoFileEnumerator -{ - GFileEnumerator parent; - - OstreeRepoFile *dir; - char *attributes; - GFileQueryInfoFlags flags; - - int index; -}; - -#define ostree_repo_file_enumerator_get_type _ostree_repo_file_enumerator_get_type -G_DEFINE_TYPE (OstreeRepoFileEnumerator, ostree_repo_file_enumerator, G_TYPE_FILE_ENUMERATOR); - -static GFileInfo *ostree_repo_file_enumerator_next_file (GFileEnumerator *enumerator, - GCancellable *cancellable, - GError **error); -static gboolean ostree_repo_file_enumerator_close (GFileEnumerator *enumerator, - GCancellable *cancellable, - GError **error); - - -static void -ostree_repo_file_enumerator_dispose (GObject *object) -{ - OstreeRepoFileEnumerator *self; - - self = OSTREE_REPO_FILE_ENUMERATOR (object); - - g_clear_object (&self->dir); - g_free (self->attributes); - - if (G_OBJECT_CLASS (ostree_repo_file_enumerator_parent_class)->dispose) - G_OBJECT_CLASS (ostree_repo_file_enumerator_parent_class)->dispose (object); -} - -static void -ostree_repo_file_enumerator_finalize (GObject *object) -{ - OstreeRepoFileEnumerator *self; - - self = OSTREE_REPO_FILE_ENUMERATOR (object); - (void)self; - - G_OBJECT_CLASS (ostree_repo_file_enumerator_parent_class)->finalize (object); -} - - -static void -ostree_repo_file_enumerator_class_init (OstreeRepoFileEnumeratorClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GFileEnumeratorClass *enumerator_class = G_FILE_ENUMERATOR_CLASS (klass); - - gobject_class->finalize = ostree_repo_file_enumerator_finalize; - gobject_class->dispose = ostree_repo_file_enumerator_dispose; - - enumerator_class->next_file = ostree_repo_file_enumerator_next_file; - enumerator_class->close_fn = ostree_repo_file_enumerator_close; -} - -static void -ostree_repo_file_enumerator_init (OstreeRepoFileEnumerator *self) -{ -} - -GFileEnumerator * -_ostree_repo_file_enumerator_new (OstreeRepoFile *dir, - const char *attributes, - GFileQueryInfoFlags flags, - GCancellable *cancellable, - GError **error) -{ - OstreeRepoFileEnumerator *self; - - self = g_object_new (OSTREE_TYPE_REPO_FILE_ENUMERATOR, - "container", dir, - NULL); - - self->dir = g_object_ref (dir); - self->attributes = g_strdup (attributes); - self->flags = flags; - - return G_FILE_ENUMERATOR (self); -} - -static GFileInfo * -ostree_repo_file_enumerator_next_file (GFileEnumerator *enumerator, - GCancellable *cancellable, - GError **error) -{ - OstreeRepoFileEnumerator *self = OSTREE_REPO_FILE_ENUMERATOR (enumerator); - gboolean ret = FALSE; - GFileInfo *info = NULL; - - if (!_ostree_repo_file_tree_query_child (self->dir, self->index, - self->attributes, self->flags, - &info, cancellable, error)) - goto out; - - self->index++; - - ret = TRUE; - out: - if (!ret) - g_clear_object (&info); - return info; -} - -static gboolean -ostree_repo_file_enumerator_close (GFileEnumerator *enumerator, - GCancellable *cancellable, - GError **error) -{ - return TRUE; -} diff --git a/libostree/ostree-repo-file-enumerator.h b/libostree/ostree-repo-file-enumerator.h deleted file mode 100644 index 499a01be..00000000 --- a/libostree/ostree-repo-file-enumerator.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2011 Colin Walters - * - * This library 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 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Colin Walters - */ - -#ifndef _OSTREE_REPO_FILE_ENUMERATOR -#define _OSTREE_REPO_FILE_ENUMERATOR - -#include "ostree-repo-file.h" - -G_BEGIN_DECLS - -#define OSTREE_TYPE_REPO_FILE_ENUMERATOR (_ostree_repo_file_enumerator_get_type ()) -#define OSTREE_REPO_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OSTREE_TYPE_REPO_FILE_ENUMERATOR, OstreeRepoFileEnumerator)) -#define OSTREE_REPO_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), OSTREE_TYPE_REPO_FILE_ENUMERATOR, OstreeRepoFileEnumeratorClass)) -#define OSTREE_IS_REPO_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OSTREE_TYPE_REPO_FILE_ENUMERATOR)) -#define OSTREE_IS_REPO_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OSTREE_TYPE_REPO_FILE_ENUMERATOR)) -#define OSTREE_REPO_FILE_ENUMERATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OSTREE_TYPE_REPO_FILE_ENUMERATOR, OstreeRepoFileEnumeratorClass)) - -typedef struct _OstreeRepoFileEnumerator OstreeRepoFileEnumerator; -typedef struct _OstreeRepoFileEnumeratorClass OstreeRepoFileEnumeratorClass; - -struct _OstreeRepoFileEnumeratorClass -{ - GFileEnumeratorClass parent_class; -}; - -GType _ostree_repo_file_enumerator_get_type (void) G_GNUC_CONST; - -GFileEnumerator * _ostree_repo_file_enumerator_new (OstreeRepoFile *dir, - const char *attributes, - GFileQueryInfoFlags flags, - GCancellable *cancellable, - GError **error); - -G_END_DECLS - -#endif diff --git a/libostree/ostree-repo-file.c b/libostree/ostree-repo-file.c deleted file mode 100644 index a3d5e79c..00000000 --- a/libostree/ostree-repo-file.c +++ /dev/null @@ -1,1428 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2011 Colin Walters - * - * This library 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 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Colin Walters - */ - -#include "config.h" - -#include "ostree-repo-file-enumerator.h" - -static void ostree_repo_file_file_iface_init (GFileIface *iface); - -static void -tree_replace_contents (OstreeRepoFile *self, - GVariant *new_files, - GVariant *new_dirs); - -struct _OstreeRepoFile -{ - GObject parent_instance; - - OstreeRepo *repo; - - char *commit; - GError *commit_resolve_error; - - OstreeRepoFile *parent; - int index; - char *name; - - char *tree_contents_checksum; - GVariant *tree_contents; - char *tree_metadata_checksum; - GVariant *tree_metadata; -}; - -#define ostree_repo_file_get_type _ostree_repo_file_get_type -G_DEFINE_TYPE_WITH_CODE (OstreeRepoFile, ostree_repo_file, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (G_TYPE_FILE, - ostree_repo_file_file_iface_init)) - -static void -ostree_repo_file_finalize (GObject *object) -{ - OstreeRepoFile *self; - - self = OSTREE_REPO_FILE (object); - - if (self->tree_contents) - g_variant_unref (self->tree_contents); - if (self->tree_metadata) - g_variant_unref (self->tree_metadata); - g_free (self->tree_contents_checksum); - g_free (self->tree_metadata_checksum); - g_free (self->commit); - g_free (self->name); - - G_OBJECT_CLASS (ostree_repo_file_parent_class)->finalize (object); -} - -static void -ostree_repo_file_dispose (GObject *object) -{ - OstreeRepoFile *self; - - self = OSTREE_REPO_FILE (object); - - g_clear_object (&self->repo); - g_clear_object (&self->parent); - - if (G_OBJECT_CLASS (ostree_repo_file_parent_class)->dispose) - G_OBJECT_CLASS (ostree_repo_file_parent_class)->dispose (object); -} - -static void -ostree_repo_file_class_init (OstreeRepoFileClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->finalize = ostree_repo_file_finalize; - gobject_class->dispose = ostree_repo_file_dispose; -} - -static void -ostree_repo_file_init (OstreeRepoFile *self) -{ - self->index = -1; -} - -static gboolean -set_error_noent (GFile *self, GError **error) -{ - char *path = g_file_get_path (self); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, - "No such file or directory: %s", path); - g_free (path); - return FALSE; -} - -GFile * -_ostree_repo_file_new_root (OstreeRepo *repo, - const char *commit) -{ - OstreeRepoFile *self; - - g_return_val_if_fail (repo != NULL, NULL); - g_return_val_if_fail (commit != NULL, NULL); - g_return_val_if_fail (strlen (commit) == 64, NULL); - - self = g_object_new (OSTREE_TYPE_REPO_FILE, NULL); - self->repo = g_object_ref (repo); - self->commit = g_strdup (commit); - - return G_FILE (self); -} - - -GFile * -_ostree_repo_file_new_child (OstreeRepoFile *parent, - const char *name) -{ - OstreeRepoFile *self; - - self = g_object_new (OSTREE_TYPE_REPO_FILE, NULL); - self->repo = g_object_ref (parent->repo); - self->parent = g_object_ref (parent); - self->name = g_strdup (name); - - return G_FILE (self); -} - -OstreeRepoFile * -_ostree_repo_file_new_empty_tree (OstreeRepo *repo) -{ - OstreeRepoFile *self; - - self = g_object_new (OSTREE_TYPE_REPO_FILE, NULL); - self->repo = g_object_ref (repo); - - tree_replace_contents (self, NULL, NULL); - - return self; -} - -static gboolean -do_resolve_commit (OstreeRepoFile *self, - GError **error) -{ - gboolean ret = FALSE; - GVariant *commit = NULL; - GVariant *root_contents = NULL; - GVariant *root_metadata = NULL; - const char *tree_contents_checksum; - const char *tree_meta_checksum; - - g_assert (self->parent == NULL); - - if (!ostree_repo_load_variant_checked (self->repo, OSTREE_SERIALIZED_COMMIT_VARIANT, - self->commit, &commit, error)) - goto out; - - /* PARSE OSTREE_SERIALIZED_COMMIT_VARIANT */ - g_variant_get_child (commit, 6, "&s", &tree_contents_checksum); - g_variant_get_child (commit, 7, "&s", &tree_meta_checksum); - - if (!ostree_repo_load_variant_checked (self->repo, OSTREE_SERIALIZED_TREE_VARIANT, - tree_contents_checksum, &root_contents, - error)) - goto out; - - if (!ostree_repo_load_variant_checked (self->repo, OSTREE_SERIALIZED_DIRMETA_VARIANT, - tree_meta_checksum, &root_metadata, - error)) - goto out; - - self->tree_metadata = root_metadata; - root_metadata = NULL; - self->tree_contents = root_contents; - root_contents = NULL; - - out: - if (commit) - g_variant_unref (commit); - if (root_metadata) - g_variant_unref (root_metadata); - if (root_contents) - g_variant_unref (root_contents); - return ret; -} - -static gboolean -do_resolve_nonroot (OstreeRepoFile *self, - GError **error) -{ - gboolean ret = FALSE; - GVariant *container = NULL; - GVariant *tree_contents = NULL; - GVariant *tree_metadata = NULL; - gboolean is_dir; - int i; - - i = _ostree_repo_file_tree_find_child (self->parent, self->name, &is_dir, &container); - - if (i < 0) - { - set_error_noent ((GFile*)self, error); - goto out; - } - - if (is_dir) - { - const char *name; - const char *content_checksum; - const char *metadata_checksum; - GVariant *files_variant; - - files_variant = g_variant_get_child_value (self->parent->tree_contents, 2); - self->index = g_variant_n_children (files_variant) + i; - g_variant_unref (files_variant); - - g_variant_get_child (container, i, "(&s&s&s)", - &name, &content_checksum, &metadata_checksum); - - if (!ostree_repo_load_variant_checked (self->repo, OSTREE_SERIALIZED_TREE_VARIANT, - content_checksum, &tree_contents, - error)) - goto out; - - if (!ostree_repo_load_variant_checked (self->repo, OSTREE_SERIALIZED_DIRMETA_VARIANT, - metadata_checksum, &tree_metadata, - error)) - goto out; - - self->tree_contents = tree_contents; - tree_contents = NULL; - self->tree_metadata = tree_metadata; - tree_metadata = NULL; - } - else - self->index = i; - - ret = TRUE; - out: - if (container) - g_variant_unref (container); - if (tree_metadata) - g_variant_unref (tree_metadata); - if (tree_contents) - g_variant_unref (tree_contents); - return ret; -} - -gboolean -_ostree_repo_file_ensure_resolved (OstreeRepoFile *self, - GError **error) -{ - if (self->commit_resolve_error != NULL) - goto out; - - if (self->parent == NULL) - { - if (self->tree_contents == NULL) - (void)do_resolve_commit (self, &(self->commit_resolve_error)); - } - else if (self->index == -1) - { - (void)do_resolve_nonroot (self, &(self->commit_resolve_error)); - } - - out: - if (self->commit_resolve_error) - { - if (error) - *error = g_error_copy (self->commit_resolve_error); - return FALSE; - } - else - return TRUE; -} - -gboolean -_ostree_repo_file_get_xattrs (OstreeRepoFile *self, - GVariant **out_xattrs, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - GVariant *ret_xattrs = NULL; - GVariant *metadata = NULL; - GInputStream *input = NULL; - GFile *local_file = NULL; - - if (!_ostree_repo_file_ensure_resolved (self, error)) - goto out; - - if (self->tree_metadata) - ret_xattrs = g_variant_get_child_value (self->tree_metadata, 4); - else if (ostree_repo_is_archive (self->repo)) - { - local_file = _ostree_repo_file_nontree_get_local (self); - if (!ostree_parse_packed_file (local_file, &metadata, &input, cancellable, error)) - goto out; - ret_xattrs = g_variant_get_child_value (metadata, 4); - } - else - { - local_file = _ostree_repo_file_nontree_get_local (self); - ret_xattrs = ostree_get_xattrs_for_path (ot_gfile_get_path_cached (local_file), error); - } - - ret = TRUE; - *out_xattrs = ret_xattrs; - ret_xattrs = NULL; - out: - if (ret_xattrs) - g_variant_unref (ret_xattrs); - if (metadata) - g_variant_unref (metadata); - g_clear_object (&input); - g_clear_object (&local_file); - return ret; -} - -GVariant * -_ostree_repo_file_tree_get_contents (OstreeRepoFile *self) -{ - return self->tree_contents; -} - -GVariant * -_ostree_repo_file_tree_get_metadata (OstreeRepoFile *self) -{ - return self->tree_metadata; -} - -void -_ostree_repo_file_tree_set_metadata (OstreeRepoFile *self, - const char *checksum, - GVariant *metadata) -{ - if (self->tree_metadata) - g_variant_unref (self->tree_metadata); - self->tree_metadata = g_variant_ref (metadata); - g_free (self->tree_metadata_checksum); - self->tree_metadata_checksum = g_strdup (checksum); -} - -void -_ostree_repo_file_make_empty_tree (OstreeRepoFile *self) -{ - tree_replace_contents (self, NULL, NULL); -} - -void -_ostree_repo_file_tree_set_content_checksum (OstreeRepoFile *self, - const char *checksum) -{ - g_assert (self->parent == NULL); - g_free (self->tree_contents_checksum); - self->tree_contents_checksum = g_strdup (checksum); -} - -const char * -_ostree_repo_file_tree_get_content_checksum (OstreeRepoFile *self) -{ - g_assert (self->parent == NULL); - return self->tree_contents_checksum; -} - -GFile * -_ostree_repo_file_nontree_get_local (OstreeRepoFile *self) -{ - const char *checksum; - char *path; - GFile *ret; - - g_assert (!ostree_repo_is_archive (self->repo)); - - checksum = _ostree_repo_file_nontree_get_checksum (self); - path = ostree_repo_get_object_path (self->repo, checksum, OSTREE_OBJECT_TYPE_FILE); - ret = ot_util_new_file_for_path (path); - g_free (path); - - return ret; -} - -OstreeRepo * -_ostree_repo_file_get_repo (OstreeRepoFile *self) -{ - return self->repo; -} - -OstreeRepoFile * -_ostree_repo_file_get_root (OstreeRepoFile *self) -{ - OstreeRepoFile *parent = self; - - while (parent->parent) - parent = parent->parent; - return parent; -} - -const char * -_ostree_repo_file_nontree_get_checksum (OstreeRepoFile *self) -{ - int n; - gboolean is_dir; - - g_assert (self->parent); - - n = _ostree_repo_file_tree_find_child (self->parent, self->name, &is_dir, NULL); - g_assert (n >= 0 && !is_dir); - - return _ostree_repo_file_tree_get_child_checksum (self->parent, n); -} - -const char * -_ostree_repo_file_tree_get_child_checksum (OstreeRepoFile *self, - int n) -{ - GVariant *files_variant; - const char *checksum; - - g_assert (self->tree_contents); - - files_variant = g_variant_get_child_value (self->tree_contents, 2); - - g_variant_get_child (files_variant, n, "(@s&s)", NULL, &checksum); - - g_variant_unref (files_variant); - - return checksum; -} - -static gboolean -ostree_repo_file_is_native (GFile *file) -{ - return FALSE; -} - -static gboolean -ostree_repo_file_has_uri_scheme (GFile *file, - const char *uri_scheme) -{ - return g_ascii_strcasecmp (uri_scheme, "ostree") == 0; -} - -static char * -ostree_repo_file_get_uri_scheme (GFile *file) -{ - return g_strdup ("ostree"); -} - -static char * -ostree_repo_file_get_basename (GFile *file) -{ - OstreeRepoFile *self = OSTREE_REPO_FILE (file); - return g_strdup (self->name); -} - -static char * -ostree_repo_file_get_path (GFile *file) -{ - OstreeRepoFile *self = OSTREE_REPO_FILE (file); - OstreeRepoFile *parent; - GString *buf; - GSList *parents; - GSList *iter; - - buf = g_string_new (""); - parents = NULL; - - for (parent = self->parent; parent; parent = parent->parent) - parents = g_slist_prepend (parents, parent); - - if (parents->next) - { - for (iter = parents->next; iter; iter = iter->next) - { - parent = iter->data; - g_string_append_c (buf, '/'); - g_string_append (buf, parent->name); - } - } - g_string_append_c (buf, '/'); - g_string_append (buf, self->name); - - g_slist_free (parents); - - return g_string_free (buf, FALSE); -} - -static char * -ostree_repo_file_get_uri (GFile *file) -{ - OstreeRepoFile *self = OSTREE_REPO_FILE (file); - char *path; - char *uri_path; - char *ret; - - path = g_file_get_path (file); - uri_path = g_filename_to_uri (path, NULL, NULL); - g_free (path); - g_assert (g_str_has_prefix (uri_path, "file://")); - ret = g_strconcat ("ostree://", self->commit, uri_path+strlen("file://"), NULL); - g_free (uri_path); - - return ret; -} - -static char * -ostree_repo_file_get_parse_name (GFile *file) -{ - return ostree_repo_file_get_uri (file); -} - -static GFile * -ostree_repo_file_get_parent (GFile *file) -{ - OstreeRepoFile *self = OSTREE_REPO_FILE (file); - - return g_object_ref (self->parent); -} - -static GFile * -ostree_repo_file_dup (GFile *file) -{ - OstreeRepoFile *self = OSTREE_REPO_FILE (file); - - if (self->parent) - return _ostree_repo_file_new_child (self->parent, self->name); - else - return _ostree_repo_file_new_root (self->repo, self->commit); -} - -static guint -ostree_repo_file_hash (GFile *file) -{ - OstreeRepoFile *self = OSTREE_REPO_FILE (file); - - if (self->parent) - return g_file_hash (self->parent) + g_str_hash (self->name); - else - return g_str_hash (self->commit); -} - -static gboolean -ostree_repo_file_equal (GFile *file1, - GFile *file2) -{ - OstreeRepoFile *self1 = OSTREE_REPO_FILE (file1); - OstreeRepoFile *self2 = OSTREE_REPO_FILE (file2); - - if (self1->parent && self2->parent) - { - return g_str_equal (self1->name, self2->name) - && g_file_equal ((GFile*)self1->parent, (GFile*)self2->parent); - } - else if (!self1->parent && !self2->parent) - { - return g_str_equal (self1->commit, self2->commit); - } - else - return FALSE; -} - -static const char * -match_prefix (const char *path, - const char *prefix) -{ - int prefix_len; - - prefix_len = strlen (prefix); - if (strncmp (path, prefix, prefix_len) != 0) - return NULL; - - /* Handle the case where prefix is the root, so that - * the IS_DIR_SEPRARATOR check below works */ - if (prefix_len > 0 && - G_IS_DIR_SEPARATOR (prefix[prefix_len-1])) - prefix_len--; - - return path + prefix_len; -} - -static gboolean -ostree_repo_file_prefix_matches (GFile *parent, - GFile *descendant) -{ - const char *remainder; - char *parent_path; - char *descendant_path; - - parent_path = g_file_get_path (parent); - descendant_path = g_file_get_path (descendant); - remainder = match_prefix (descendant_path, parent_path); - g_free (parent_path); - g_free (descendant_path); - if (remainder != NULL && G_IS_DIR_SEPARATOR (*remainder)) - return TRUE; - return FALSE; -} - -static char * -ostree_repo_file_get_relative_path (GFile *parent, - GFile *descendant) -{ - const char *remainder; - char *parent_path; - char *descendant_path; - - parent_path = g_file_get_path (parent); - descendant_path = g_file_get_path (descendant); - remainder = match_prefix (descendant_path, parent_path); - g_free (parent_path); - g_free (descendant_path); - - if (remainder != NULL && G_IS_DIR_SEPARATOR (*remainder)) - return g_strdup (remainder + 1); - return NULL; -} - -static GFile * -ostree_repo_file_resolve_relative_path (GFile *file, - const char *relative_path) -{ - OstreeRepoFile *self = OSTREE_REPO_FILE (file); - OstreeRepoFile *parent; - char *filename; - const char *rest; - GFile *ret; - - if (g_path_is_absolute (relative_path) && self->parent) - { - g_assert (*relative_path == '/'); - return ostree_repo_file_resolve_relative_path ((GFile*)_ostree_repo_file_get_root (self), - relative_path+1); - } - - rest = strchr (relative_path, '/'); - if (rest) - { - rest += 1; - filename = g_strndup (relative_path, rest - relative_path); - } - else - filename = g_strdup (relative_path); - - parent = (OstreeRepoFile*)_ostree_repo_file_new_child (self, filename); - g_free (filename); - - if (!rest) - ret = (GFile*)parent; - else - { - ret = ostree_repo_file_resolve_relative_path ((GFile*)parent, rest); - g_clear_object (&parent); - } - return ret; -} - -static GFileEnumerator * -ostree_repo_file_enumerate_children (GFile *file, - const char *attributes, - GFileQueryInfoFlags flags, - GCancellable *cancellable, - GError **error) -{ - OstreeRepoFile *self = OSTREE_REPO_FILE (file); - return _ostree_repo_file_enumerator_new (self, - attributes, flags, - cancellable, error); -} - -static GFile * -ostree_repo_file_get_child_for_display_name (GFile *file, - const char *display_name, - GError **error) -{ - return g_file_get_child (file, display_name); -} - -static GFile * -get_child_local_file (OstreeRepo *repo, - const char *checksum) -{ - char *path; - GFile *ret; - - path = ostree_repo_get_object_path (repo, checksum, OSTREE_OBJECT_TYPE_FILE); - ret = ot_util_new_file_for_path (path); - g_free (path); - - return ret; -} - -static gboolean -query_child_info_file_nonarchive (OstreeRepo *repo, - const char *checksum, - GFileAttributeMatcher *matcher, - GFileInfo *info, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - GFileInfo *local_info = NULL; - GFile *local_file = NULL; - int i ; - const char *mapped_boolean[] = { - "standard::is-symlink" - }; - const char *mapped_string[] = { - }; - const char *mapped_byte_string[] = { - "standard::symlink-target" - }; - const char *mapped_uint32[] = { - "standard::type", - "unix::device", - "unix::mode", - "unix::nlink", - "unix::uid", - "unix::gid", - "unix::rdev" - }; - const char *mapped_uint64[] = { - "standard::size", - "standard::allocated-size", - "unix::inode" - }; - - if (!(g_file_attribute_matcher_matches (matcher, "unix::mode") - || g_file_attribute_matcher_matches (matcher, "standard::type"))) - { - ret = TRUE; - goto out; - } - - local_file = get_child_local_file (repo, checksum); - local_info = g_file_query_info (local_file, - OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, - error); - if (!local_info) - goto out; - - for (i = 0; i < G_N_ELEMENTS (mapped_boolean); i++) - g_file_info_set_attribute_boolean (info, mapped_boolean[i], g_file_info_get_attribute_boolean (local_info, mapped_boolean[i])); - - for (i = 0; i < G_N_ELEMENTS (mapped_string); i++) - { - const char *string = g_file_info_get_attribute_string (local_info, mapped_string[i]); - if (string) - g_file_info_set_attribute_string (info, mapped_string[i], string); - } - - for (i = 0; i < G_N_ELEMENTS (mapped_byte_string); i++) - { - const char *byte_string = g_file_info_get_attribute_byte_string (local_info, mapped_byte_string[i]); - if (byte_string) - g_file_info_set_attribute_byte_string (info, mapped_byte_string[i], byte_string); - } - - for (i = 0; i < G_N_ELEMENTS (mapped_uint32); i++) - g_file_info_set_attribute_uint32 (info, mapped_uint32[i], g_file_info_get_attribute_uint32 (local_info, mapped_uint32[i])); - - for (i = 0; i < G_N_ELEMENTS (mapped_uint64); i++) - g_file_info_set_attribute_uint64 (info, mapped_uint64[i], g_file_info_get_attribute_uint64 (local_info, mapped_uint64[i])); - - ret = TRUE; - out: - g_clear_object (&local_info); - g_clear_object (&local_file); - return ret; -} - -static gboolean -query_child_info_file_archive (OstreeRepo *repo, - const char *checksum, - GFileAttributeMatcher *matcher, - GFileInfo *info, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - GFile *local_file = NULL; - GVariant *metadata = NULL; - GInputStream *input = NULL; - guint32 version, uid, gid, mode; - guint64 content_len; - guint32 file_type; - gsize bytes_read; - char *buf = NULL; - - local_file = get_child_local_file (repo, checksum); - - if (!ostree_parse_packed_file (local_file, &metadata, &input, cancellable, error)) - goto out; - - g_variant_get (metadata, "(uuuu@a(ayay)t)", - &version, &uid, &gid, &mode, - NULL, &content_len); - uid = GUINT32_FROM_BE (uid); - gid = GUINT32_FROM_BE (gid); - mode = GUINT32_FROM_BE (mode); - content_len = GUINT64_FROM_BE (content_len); - - g_file_info_set_attribute_boolean (info, "standard::is-symlink", - S_ISLNK (mode)); - if (S_ISLNK (mode)) - file_type = G_FILE_TYPE_SYMBOLIC_LINK; - else if (S_ISREG (mode)) - file_type = G_FILE_TYPE_REGULAR; - else if (S_ISBLK (mode) || S_ISCHR(mode) || S_ISFIFO(mode)) - file_type = G_FILE_TYPE_SPECIAL; - else - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Corrupted packfile %s: Invalid mode", checksum); - goto out; - } - g_file_info_set_attribute_uint32 (info, "standard::type", file_type); - - g_file_info_set_attribute_uint32 (info, "unix::uid", uid); - g_file_info_set_attribute_uint32 (info, "unix::gid", gid); - g_file_info_set_attribute_uint32 (info, "unix::mode", mode); - - if (file_type == G_FILE_TYPE_REGULAR) - { - g_file_info_set_attribute_uint64 (info, "standard::size", content_len); - } - else if (file_type == G_FILE_TYPE_SYMBOLIC_LINK) - { - gsize len = MIN (PATH_MAX, content_len) + 1; - buf = g_malloc (len); - - if (!g_input_stream_read_all (input, buf, len, &bytes_read, cancellable, error)) - goto out; - buf[bytes_read] = '\0'; - - g_file_info_set_attribute_byte_string (info, "standard::symlink-target", buf); - } - else if (file_type == G_FILE_TYPE_SPECIAL) - { - guint32 device; - - if (!g_input_stream_read_all (input, &device, 4, &bytes_read, cancellable, error)) - goto out; - - device = GUINT32_FROM_BE (device); - g_file_info_set_attribute_uint32 (info, "unix::device", device); - } - - ret = TRUE; - out: - g_free (buf); - if (metadata) - g_variant_unref (metadata); - g_clear_object (&local_file); - g_clear_object (&input); - return ret; -} - -static void -set_info_from_dirmeta (GFileInfo *info, - GVariant *metadata) -{ - guint32 version, uid, gid, mode; - - g_file_info_set_attribute_uint32 (info, "standard::type", G_FILE_TYPE_DIRECTORY); - - /* PARSE OSTREE_SERIALIZED_DIRMETA_VARIANT */ - g_variant_get (metadata, "(uuuu@a(ayay))", - &version, &uid, &gid, &mode, - NULL); - version = GUINT32_FROM_BE (version); - uid = GUINT32_FROM_BE (uid); - gid = GUINT32_FROM_BE (gid); - mode = GUINT32_FROM_BE (mode); - - g_file_info_set_attribute_uint32 (info, "unix::uid", uid); - g_file_info_set_attribute_uint32 (info, "unix::gid", gid); - g_file_info_set_attribute_uint32 (info, "unix::mode", mode); -} - -static gboolean -query_child_info_dir (OstreeRepo *repo, - const char *metadata_checksum, - GFileAttributeMatcher *matcher, - GFileQueryInfoFlags flags, - GFileInfo *info, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - GVariant *metadata = NULL; - - if (!g_file_attribute_matcher_matches (matcher, "unix::mode")) - { - ret = TRUE; - goto out; - } - - if (!ostree_repo_load_variant_checked (repo, OSTREE_SERIALIZED_DIRMETA_VARIANT, - metadata_checksum, &metadata, error)) - goto out; - - set_info_from_dirmeta (info, metadata); - - ret = TRUE; - out: - if (metadata) - g_variant_unref (metadata); - return ret; -} - -static gboolean -bsearch_in_file_variant (GVariant *variant, - const char *name, - int *out_pos) -{ - int i, n; - int m; - - i = 0; - n = g_variant_n_children (variant) - 1; - m = 0; - - while (i <= n) - { - GVariant *child; - const char *cur; - int cmp; - - m = i + ((n - i) / 2); - - child = g_variant_get_child_value (variant, m); - g_variant_get_child (child, 0, "&s", &cur, NULL); - - cmp = strcmp (cur, name); - if (cmp < 0) - i = m + 1; - else if (cmp > 0) - n = m - 1; - else - { - g_variant_unref (child); - *out_pos = m; - return TRUE; - } - g_variant_unref (child); - } - - *out_pos = m; - return FALSE; -} - -static GVariant * -remove_variant_child (GVariant *variant, - int n) -{ - GVariantBuilder builder; - GVariantIter *iter; - int i; - GVariant *child; - - g_variant_builder_init (&builder, g_variant_get_type (variant)); - iter = g_variant_iter_new (variant); - - i = 0; - while ((child = g_variant_iter_next_value (iter)) != NULL) - { - if (i != n) - g_variant_builder_add_value (&builder, child); - g_variant_unref (child); - } - g_variant_iter_free (iter); - - return g_variant_builder_end (&builder); -} - -static GVariant * -insert_variant_child (GVariant *variant, - int n, - GVariant *item) -{ - GVariantBuilder builder; - GVariantIter *iter; - int i; - GVariant *child; - - g_variant_builder_init (&builder, g_variant_get_type (variant)); - iter = g_variant_iter_new (variant); - - i = 0; - while ((child = g_variant_iter_next_value (iter)) != NULL) - { - if (i == n) - g_variant_builder_add_value (&builder, item); - g_variant_builder_add_value (&builder, child); - g_variant_unref (child); - } - g_variant_iter_free (iter); - - return g_variant_builder_end (&builder); -} - -static void -tree_replace_contents (OstreeRepoFile *self, - GVariant *new_files, - GVariant *new_dirs) -{ - guint version; - GVariant *metadata; - GVariant *tmp_files = NULL; - GVariant *tmp_dirs = NULL; - - if (!(new_files || new_dirs) && self->tree_contents) - return; - else if (!self->tree_contents) - { - version = GUINT32_TO_BE (0); - metadata = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0); - tmp_dirs = g_variant_new_array (G_VARIANT_TYPE ("(ss)"), NULL, 0); - tmp_files = g_variant_new_array (G_VARIANT_TYPE ("(ss)"), NULL, 0); - } - else - { - g_variant_get_child (self->tree_contents, 0, "u", &version); - metadata = g_variant_get_child_value (self->tree_contents, 1); - if (!new_files) - tmp_files = g_variant_get_child_value (self->tree_contents, 2); - if (!new_dirs) - tmp_dirs = g_variant_get_child_value (self->tree_contents, 3); - } - - if (self->tree_contents) - g_variant_unref (self->tree_contents); - self->tree_contents = g_variant_new ("(u@a{sv}@a(ss)@a(sss))", version, metadata, - new_files ? new_files : tmp_files, - new_dirs ? new_dirs : tmp_dirs); - - g_variant_unref (metadata); - if (tmp_files) - g_variant_unref (tmp_files); - if (tmp_dirs) - g_variant_unref (tmp_dirs); -} - -void -_ostree_repo_file_tree_remove_child (OstreeRepoFile *self, - const char *name) -{ - int i; - GVariant *files_variant; - GVariant *new_files_variant = NULL; - GVariant *dirs_variant; - GVariant *new_dirs_variant = NULL; - - files_variant = g_variant_get_child_value (self->tree_contents, 2); - dirs_variant = g_variant_get_child_value (self->tree_contents, 3); - - if (bsearch_in_file_variant (files_variant, name, &i)) - { - new_files_variant = remove_variant_child (files_variant, i); - } - else - { - if (bsearch_in_file_variant (dirs_variant, name, &i)) - { - new_dirs_variant = remove_variant_child (dirs_variant, i); - } - } - - tree_replace_contents (self, new_files_variant, new_dirs_variant); - - g_variant_unref (files_variant); - g_variant_unref (dirs_variant); -} - -void -_ostree_repo_file_tree_add_file (OstreeRepoFile *self, - const char *name, - const char *checksum) -{ - int n; - GVariant *files_variant; - GVariant *new_files_variant; - - files_variant = g_variant_get_child_value (self->tree_contents, 2); - - if (!bsearch_in_file_variant (files_variant, name, &n)) - { - new_files_variant = insert_variant_child (files_variant, n, - g_variant_new ("(ss)", name, checksum)); - g_variant_ref_sink (new_files_variant); - tree_replace_contents (self, new_files_variant, NULL); - g_variant_unref (new_files_variant); - } - g_variant_unref (files_variant); -} - -void -_ostree_repo_file_tree_add_dir (OstreeRepoFile *self, - const char *name, - const char *content_checksum, - const char *metadata_checksum) -{ - int n; - GVariant *dirs_variant; - GVariant *new_dirs_variant; - - dirs_variant = g_variant_get_child_value (self->tree_contents, 3); - - if (!bsearch_in_file_variant (dirs_variant, name, &n)) - { - new_dirs_variant = insert_variant_child (dirs_variant, n, - g_variant_new ("(sss)", name, content_checksum, - metadata_checksum)); - g_variant_ref_sink (new_dirs_variant); - tree_replace_contents (self, NULL, new_dirs_variant); - g_variant_unref (new_dirs_variant); - } - g_variant_unref (dirs_variant); -} - -int -_ostree_repo_file_tree_find_child (OstreeRepoFile *self, - const char *name, - gboolean *is_dir, - GVariant **out_container) -{ - int i; - GVariant *files_variant = NULL; - GVariant *dirs_variant = NULL; - GVariant *ret_container = NULL; - - files_variant = g_variant_get_child_value (self->tree_contents, 2); - dirs_variant = g_variant_get_child_value (self->tree_contents, 3); - - i = -1; - if (bsearch_in_file_variant (files_variant, name, &i)) - { - *is_dir = FALSE; - ret_container = files_variant; - files_variant = NULL; - } - else - { - if (bsearch_in_file_variant (dirs_variant, name, &i)) - { - *is_dir = TRUE; - ret_container = dirs_variant; - dirs_variant = NULL; - } - else - { - i = -1; - } - } - if (ret_container && out_container) - { - *out_container = ret_container; - ret_container = NULL; - } - if (ret_container) - g_variant_unref (ret_container); - if (files_variant) - g_variant_unref (files_variant); - if (dirs_variant) - g_variant_unref (dirs_variant); - return i; -} - -gboolean -_ostree_repo_file_tree_query_child (OstreeRepoFile *self, - int n, - const char *attributes, - GFileQueryInfoFlags flags, - GFileInfo **out_info, - GCancellable *cancellable, - GError **error) -{ - const char *name = NULL; - gboolean ret = FALSE; - GFileInfo *ret_info = NULL; - GVariant *files_variant = NULL; - GVariant *dirs_variant = NULL; - GVariant *tree_child_metadata = NULL; - GFileAttributeMatcher *matcher = NULL; - int c; - - if (!_ostree_repo_file_ensure_resolved (self, error)) - goto out; - - matcher = g_file_attribute_matcher_new (attributes); - - ret_info = g_file_info_new (); - - g_assert (self->tree_contents); - - files_variant = g_variant_get_child_value (self->tree_contents, 2); - dirs_variant = g_variant_get_child_value (self->tree_contents, 3); - - c = g_variant_n_children (files_variant); - if (n < c) - { - const char *checksum; - - g_variant_get_child (files_variant, n, "(&s&s)", &name, &checksum); - - if (ostree_repo_is_archive (self->repo)) - { - if (!query_child_info_file_archive (self->repo, checksum, matcher, ret_info, - cancellable, error)) - goto out; - } - else - { - if (!query_child_info_file_nonarchive (self->repo, checksum, matcher, ret_info, - cancellable, error)) - goto out; - } - } - else - { - const char *tree_checksum; - const char *meta_checksum; - - n -= c; - - c = g_variant_n_children (dirs_variant); - - if (n < c) - { - g_variant_get_child (dirs_variant, n, "(&s&s&s)", - &name, &tree_checksum, &meta_checksum); - - if (!query_child_info_dir (self->repo, meta_checksum, - matcher, flags, ret_info, - cancellable, error)) - goto out; - } - else - n -= c; - } - - if (name) - { - g_file_info_set_attribute_byte_string (ret_info, "standard::name", - name); - g_file_info_set_attribute_string (ret_info, "standard::display-name", - name); - if (*name == '.') - g_file_info_set_is_hidden (ret_info, TRUE); - } - else - { - g_clear_object (&ret_info); - } - - ret = TRUE; - *out_info = ret_info; - ret_info = NULL; - out: - g_clear_object (&ret_info); - if (matcher) - g_file_attribute_matcher_unref (matcher); - if (tree_child_metadata) - g_variant_unref (tree_child_metadata); - g_variant_unref (files_variant); - g_variant_unref (dirs_variant); - return ret; -} - -static GFileInfo * -ostree_repo_file_query_info (GFile *file, - const char *attributes, - GFileQueryInfoFlags flags, - GCancellable *cancellable, - GError **error) -{ - OstreeRepoFile *self = OSTREE_REPO_FILE (file); - gboolean ret = FALSE; - GFileInfo *info = NULL; - - if (!_ostree_repo_file_ensure_resolved (self, error)) - goto out; - - if (!self->parent) - { - info = g_file_info_new (); - set_info_from_dirmeta (info, self->tree_metadata); - } - else - { - if (!_ostree_repo_file_tree_query_child (self->parent, self->index, - attributes, flags, - &info, cancellable, error)) - goto out; - } - - ret = TRUE; - out: - if (!ret) - g_clear_object (&info); - return info; -} - -static GFileAttributeInfoList * -ostree_repo_file_query_settable_attributes (GFile *file, - GCancellable *cancellable, - GError **error) -{ - return g_file_attribute_info_list_new (); -} - -static GFileAttributeInfoList * -ostree_repo_file_query_writable_namespaces (GFile *file, - GCancellable *cancellable, - GError **error) -{ - return g_file_attribute_info_list_new (); -} - -static GFileInputStream * -ostree_repo_file_read (GFile *file, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - GFile *local_file = NULL; - GFileInputStream *ret_stream = NULL; - OstreeRepoFile *self = OSTREE_REPO_FILE (file); - - if (self->tree_contents) - { - g_set_error_literal (error, G_IO_ERROR, - G_IO_ERROR_IS_DIRECTORY, - "Can't open directory"); - goto out; - } - - if (ostree_repo_is_archive (self->repo)) - { - g_set_error_literal (error, G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - "Can't open archived file (yet)"); - goto out; - } - else - { - local_file = _ostree_repo_file_nontree_get_local (self); - ret_stream = g_file_read (local_file, cancellable, error); - if (!ret_stream) - goto out; - } - - ret = TRUE; - out: - g_clear_object (&local_file); - if (!ret) - g_clear_object (&ret_stream); - return ret_stream; -} - -static void -ostree_repo_file_file_iface_init (GFileIface *iface) -{ - iface->dup = ostree_repo_file_dup; - iface->hash = ostree_repo_file_hash; - iface->equal = ostree_repo_file_equal; - iface->is_native = ostree_repo_file_is_native; - iface->has_uri_scheme = ostree_repo_file_has_uri_scheme; - iface->get_uri_scheme = ostree_repo_file_get_uri_scheme; - iface->get_basename = ostree_repo_file_get_basename; - iface->get_path = ostree_repo_file_get_path; - iface->get_uri = ostree_repo_file_get_uri; - iface->get_parse_name = ostree_repo_file_get_parse_name; - iface->get_parent = ostree_repo_file_get_parent; - iface->prefix_matches = ostree_repo_file_prefix_matches; - iface->get_relative_path = ostree_repo_file_get_relative_path; - iface->resolve_relative_path = ostree_repo_file_resolve_relative_path; - iface->get_child_for_display_name = ostree_repo_file_get_child_for_display_name; - iface->set_display_name = NULL; - iface->enumerate_children = ostree_repo_file_enumerate_children; - iface->query_info = ostree_repo_file_query_info; - iface->query_filesystem_info = NULL; - iface->find_enclosing_mount = NULL; - iface->query_settable_attributes = ostree_repo_file_query_settable_attributes; - iface->query_writable_namespaces = ostree_repo_file_query_writable_namespaces; - iface->set_attribute = NULL; - iface->set_attributes_from_info = NULL; - iface->read_fn = ostree_repo_file_read; - iface->append_to = NULL; - iface->create = NULL; - iface->replace = NULL; - iface->open_readwrite = NULL; - iface->create_readwrite = NULL; - iface->replace_readwrite = NULL; - iface->delete_file = NULL; - iface->trash = NULL; - iface->make_directory = NULL; - iface->make_symbolic_link = NULL; - iface->copy = NULL; - iface->move = NULL; - iface->monitor_dir = NULL; - iface->monitor_file = NULL; - - iface->supports_thread_contexts = TRUE; -} diff --git a/libostree/ostree-repo-file.h b/libostree/ostree-repo-file.h deleted file mode 100644 index 20749655..00000000 --- a/libostree/ostree-repo-file.h +++ /dev/null @@ -1,115 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2011 Colin Walters - * - * This library 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 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Colin Walters - */ - -#ifndef _OSTREE_REPO_FILE -#define _OSTREE_REPO_FILE - -#include "ostree-repo.h" - -G_BEGIN_DECLS - -#define OSTREE_TYPE_REPO_FILE (_ostree_repo_file_get_type ()) -#define OSTREE_REPO_FILE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OSTREE_TYPE_REPO_FILE, OstreeRepoFile)) -#define OSTREE_REPO_FILE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), OSTREE_TYPE_REPO_FILE, OstreeRepoFileClass)) -#define OSTREE_IS_LOCAL_FILE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OSTREE_TYPE_REPO_FILE)) -#define OSTREE_IS_LOCAL_FILE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OSTREE_TYPE_REPO_FILE)) -#define OSTREE_REPO_FILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OSTREE_TYPE_REPO_FILE, OstreeRepoFileClass)) - -typedef struct _OstreeRepoFile OstreeRepoFile; -typedef struct _OstreeRepoFileClass OstreeRepoFileClass; - -struct _OstreeRepoFileClass -{ - GObjectClass parent_class; -}; - -GType _ostree_repo_file_get_type (void) G_GNUC_CONST; - -GFile * _ostree_repo_file_new_root (OstreeRepo *repo, - const char *commit); - -OstreeRepoFile * _ostree_repo_file_new_empty_tree (OstreeRepo *repo); - -GFile * _ostree_repo_file_new_child (OstreeRepoFile *parent, - const char *name); - -gboolean _ostree_repo_file_ensure_resolved (OstreeRepoFile *self, - GError **error); - -gboolean _ostree_repo_file_get_xattrs (OstreeRepoFile *self, - GVariant **out_xattrs, - GCancellable *cancellable, - GError **error); - -OstreeRepo * _ostree_repo_file_get_repo (OstreeRepoFile *self); -OstreeRepoFile * _ostree_repo_file_get_root (OstreeRepoFile *self); - -void _ostree_repo_file_make_empty_tree (OstreeRepoFile *self); - -void _ostree_repo_file_tree_set_metadata (OstreeRepoFile *self, - const char *checksum, - GVariant *metadata); - -void _ostree_repo_file_tree_set_content_checksum (OstreeRepoFile *self, - const char *checksum); -const char *_ostree_repo_file_tree_get_content_checksum (OstreeRepoFile *self); - -gboolean _ostree_repo_file_is_tree (OstreeRepoFile *self); - -const char * _ostree_repo_file_nontree_get_checksum (OstreeRepoFile *self); - -GFile *_ostree_repo_file_nontree_get_local (OstreeRepoFile *self); - -void _ostree_repo_file_tree_remove_child (OstreeRepoFile *self, - const char *name); - -void _ostree_repo_file_tree_add_file (OstreeRepoFile *self, - const char *name, - const char *checksum); - -void _ostree_repo_file_tree_add_dir (OstreeRepoFile *self, - const char *name, - const char *content_checksum, - const char *metadata_checksum); - -int _ostree_repo_file_tree_find_child (OstreeRepoFile *self, - const char *name, - gboolean *is_dir, - GVariant **out_container); - -const char *_ostree_repo_file_tree_get_child_checksum (OstreeRepoFile *self, - int n); - -gboolean _ostree_repo_file_tree_query_child (OstreeRepoFile *self, - int n, - const char *attributes, - GFileQueryInfoFlags flags, - GFileInfo **out_info, - GCancellable *cancellable, - GError **error); - -GVariant *_ostree_repo_file_tree_get_contents (OstreeRepoFile *self); -GVariant *_ostree_repo_file_tree_get_metadata (OstreeRepoFile *self); - -G_END_DECLS - -#endif diff --git a/libostree/ostree-repo.c b/libostree/ostree-repo.c deleted file mode 100644 index 2bdb56dc..00000000 --- a/libostree/ostree-repo.c +++ /dev/null @@ -1,1877 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2011 Colin Walters - * - * This library 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 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Colin Walters - */ - -#define _GNU_SOURCE - -#include "config.h" - -#include "ostree.h" -#include "otutil.h" -#include "ostree-repo-file-enumerator.h" - -#include -#include - -enum { - PROP_0, - - PROP_PATH -}; - -G_DEFINE_TYPE (OstreeRepo, ostree_repo, G_TYPE_OBJECT) - -#define GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), OSTREE_TYPE_REPO, OstreeRepoPrivate)) - -typedef struct _OstreeRepoPrivate OstreeRepoPrivate; - -struct _OstreeRepoPrivate { - char *path; - GFile *repo_file; - GFile *tmp_dir; - GFile *local_heads_dir; - GFile *remote_heads_dir; - char *objects_path; - char *config_path; - - gboolean inited; - - GKeyFile *config; - gboolean archive; -}; - -static void -ostree_repo_finalize (GObject *object) -{ - OstreeRepo *self = OSTREE_REPO (object); - OstreeRepoPrivate *priv = GET_PRIVATE (self); - - g_free (priv->path); - g_clear_object (&priv->repo_file); - g_clear_object (&priv->tmp_dir); - g_clear_object (&priv->local_heads_dir); - g_clear_object (&priv->remote_heads_dir); - g_free (priv->objects_path); - g_free (priv->config_path); - if (priv->config) - g_key_file_free (priv->config); - - G_OBJECT_CLASS (ostree_repo_parent_class)->finalize (object); -} - -static void -ostree_repo_set_property(GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - OstreeRepo *self = OSTREE_REPO (object); - OstreeRepoPrivate *priv = GET_PRIVATE (self); - - switch (prop_id) - { - case PROP_PATH: - priv->path = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -ostree_repo_get_property(GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - OstreeRepo *self = OSTREE_REPO (object); - OstreeRepoPrivate *priv = GET_PRIVATE (self); - - switch (prop_id) - { - case PROP_PATH: - g_value_set_string (value, priv->path); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GObject * -ostree_repo_constructor (GType gtype, - guint n_properties, - GObjectConstructParam *properties) -{ - GObject *object; - GObjectClass *parent_class; - OstreeRepoPrivate *priv; - - parent_class = G_OBJECT_CLASS (ostree_repo_parent_class); - object = parent_class->constructor (gtype, n_properties, properties); - - priv = GET_PRIVATE (object); - - g_assert (priv->path != NULL); - - priv->repo_file = ot_util_new_file_for_path (priv->path); - priv->tmp_dir = g_file_resolve_relative_path (priv->repo_file, "tmp"); - priv->local_heads_dir = g_file_resolve_relative_path (priv->repo_file, "refs/heads"); - priv->remote_heads_dir = g_file_resolve_relative_path (priv->repo_file, "refs/remotes"); - - priv->objects_path = g_build_filename (priv->path, "objects", NULL); - priv->config_path = g_build_filename (priv->path, "config", NULL); - - return object; -} - -static void -ostree_repo_class_init (OstreeRepoClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (OstreeRepoPrivate)); - - object_class->constructor = ostree_repo_constructor; - object_class->get_property = ostree_repo_get_property; - object_class->set_property = ostree_repo_set_property; - object_class->finalize = ostree_repo_finalize; - - g_object_class_install_property (object_class, - PROP_PATH, - g_param_spec_string ("path", - "", - "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); -} - -static void -ostree_repo_init (OstreeRepo *self) -{ -} - -OstreeRepo* -ostree_repo_new (const char *path) -{ - return g_object_new (OSTREE_TYPE_REPO, "path", path, NULL); -} - -static gboolean -parse_rev_file (OstreeRepo *self, - const char *path, - char **sha256, - GError **error) G_GNUC_UNUSED; - -static gboolean -parse_rev_file (OstreeRepo *self, - const char *path, - char **sha256, - GError **error) -{ - OstreeRepoPrivate *priv = GET_PRIVATE (self); - GError *temp_error = NULL; - gboolean ret = FALSE; - char *rev = NULL; - - rev = ot_util_get_file_contents_utf8 (path, &temp_error); - if (rev == NULL) - { - if (g_error_matches (temp_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) - { - g_clear_error (&temp_error); - } - else - { - g_propagate_error (error, temp_error); - goto out; - } - } - else - { - g_strchomp (rev); - } - - if (g_str_has_prefix (rev, "ref: ")) - { - GFile *ref; - char *ref_path; - char *ref_sha256; - gboolean subret; - - ref = g_file_resolve_relative_path (priv->local_heads_dir, rev + 5); - ref_path = g_file_get_path (ref); - - subret = parse_rev_file (self, ref_path, &ref_sha256, error); - g_clear_object (&ref); - g_free (ref_path); - - if (!subret) - { - g_free (ref_sha256); - goto out; - } - - g_free (rev); - rev = ref_sha256; - } - else - { - if (!ostree_validate_checksum_string (rev, error)) - goto out; - } - - *sha256 = rev; - rev = NULL; - ret = TRUE; - out: - g_free (rev); - return ret; -} - -static gboolean -resolve_rev (OstreeRepo *self, - const char *rev, - gboolean allow_noent, - char **sha256, - GError **error) -{ - OstreeRepoPrivate *priv = GET_PRIVATE (self); - gboolean ret = FALSE; - char *tmp = NULL; - char *tmp2 = NULL; - char *ret_rev = NULL; - GFile *child = NULL; - char *child_path = NULL; - GError *temp_error = NULL; - GVariant *commit = NULL; - - if (strlen (rev) == 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid empty rev"); - goto out; - } - else if (strlen (rev) == 64) - { - ret_rev = g_strdup (rev); - } - else if (g_str_has_suffix (rev, "^")) - { - tmp = g_strdup (rev); - tmp[strlen(tmp) - 1] = '\0'; - - if (!resolve_rev (self, tmp, allow_noent, &tmp2, error)) - goto out; - - if (!ostree_repo_load_variant_checked (self, OSTREE_SERIALIZED_COMMIT_VARIANT, tmp2, &commit, error)) - goto out; - - g_variant_get_child (commit, 2, "s", &ret_rev); - if (strlen (ret_rev) == 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Commit %s has no parent", tmp2); - goto out; - - } - } - else - { - child = g_file_get_child (priv->local_heads_dir, rev); - child_path = g_file_get_path (child); - if (!ot_util_gfile_load_contents_utf8 (child, NULL, &ret_rev, NULL, &temp_error)) - { - if (allow_noent && g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) - { - g_free (ret_rev); - ret_rev = NULL; - } - else - { - g_propagate_error (error, temp_error); - g_prefix_error (error, "Couldn't open ref '%s': ", child_path); - goto out; - } - } - else - { - g_strchomp (ret_rev); - - if (!ostree_validate_checksum_string (ret_rev, error)) - goto out; - } - } - - *sha256 = ret_rev; - ret_rev = NULL; - ret = TRUE; - out: - if (commit) - g_variant_unref (commit); - g_free (tmp); - g_free (tmp2); - g_clear_object (&child); - g_free (child_path); - g_free (ret_rev); - return ret; -} - -gboolean -ostree_repo_resolve_rev (OstreeRepo *self, - const char *rev, - char **sha256, - GError **error) -{ - g_return_val_if_fail (rev != NULL, FALSE); - return resolve_rev (self, rev, FALSE, sha256, error); -} - -static gboolean -write_checksum_file (GFile *parentdir, - const char *name, - const char *sha256, - GError **error) -{ - gboolean ret = FALSE; - GFile *child = NULL; - GOutputStream *out = NULL; - gsize bytes_written; - - child = g_file_get_child (parentdir, name); - - if ((out = (GOutputStream*)g_file_replace (child, NULL, FALSE, 0, NULL, error)) == NULL) - goto out; - if (!g_output_stream_write_all (out, sha256, strlen (sha256), &bytes_written, NULL, error)) - goto out; - if (!g_output_stream_write_all (out, "\n", 1, &bytes_written, NULL, error)) - goto out; - if (!g_output_stream_close (out, NULL, error)) - goto out; - - ret = TRUE; - out: - g_clear_object (&child); - g_clear_object (&out); - return ret; -} - -/** - * ostree_repo_get_config: - * @self: - * - * Returns: (transfer none): The repository configuration; do not modify - */ -GKeyFile * -ostree_repo_get_config (OstreeRepo *self) -{ - OstreeRepoPrivate *priv = GET_PRIVATE (self); - - g_return_val_if_fail (priv->inited, NULL); - - return priv->config; -} - -/** - * ostree_repo_copy_config: - * @self: - * - * Returns: (transfer full): A newly-allocated copy of the repository config - */ -GKeyFile * -ostree_repo_copy_config (OstreeRepo *self) -{ - OstreeRepoPrivate *priv = GET_PRIVATE (self); - GKeyFile *copy; - char *data; - gsize len; - - g_return_val_if_fail (priv->inited, NULL); - - copy = g_key_file_new (); - data = g_key_file_to_data (priv->config, &len, NULL); - if (!g_key_file_load_from_data (copy, data, len, 0, NULL)) - g_assert_not_reached (); - g_free (data); - return copy; -} - -/** - * ostree_repo_write_config: - * @self: - * @new_config: Overwrite the config file with this data. Do not change later! - * @error: a #GError - * - * Save @new_config in place of this repository's config file. Note - * that @new_config should not be modified after - this function - * simply adds a reference. - */ -gboolean -ostree_repo_write_config (OstreeRepo *self, - GKeyFile *new_config, - GError **error) -{ - OstreeRepoPrivate *priv = GET_PRIVATE (self); - char *data = NULL; - gsize len; - gboolean ret = FALSE; - - g_return_val_if_fail (priv->inited, FALSE); - - data = g_key_file_to_data (new_config, &len, error); - if (!g_file_set_contents (priv->config_path, data, len, error)) - goto out; - - g_key_file_free (priv->config); - priv->config = g_key_file_new (); - if (!g_key_file_load_from_data (priv->config, data, len, 0, error)) - goto out; - - ret = TRUE; - out: - g_free (data); - return ret; -} - -gboolean -ostree_repo_check (OstreeRepo *self, GError **error) -{ - OstreeRepoPrivate *priv = GET_PRIVATE (self); - gboolean ret = FALSE; - char *version = NULL;; - GError *temp_error = NULL; - - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - if (priv->inited) - return TRUE; - - if (!g_file_test (priv->objects_path, G_FILE_TEST_IS_DIR)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Couldn't find objects directory '%s'", priv->objects_path); - goto out; - } - - priv->config = g_key_file_new (); - if (!g_key_file_load_from_file (priv->config, priv->config_path, 0, error)) - { - g_prefix_error (error, "Couldn't parse config file: "); - goto out; - } - - version = g_key_file_get_value (priv->config, "core", "repo_version", &temp_error); - if (temp_error) - { - g_propagate_error (error, temp_error); - goto out; - } - - if (strcmp (version, "0") != 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid repository version '%s'", version); - goto out; - } - - priv->archive = g_key_file_get_boolean (priv->config, "core", "archive", &temp_error); - if (temp_error) - { - if (g_error_matches (temp_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) - { - g_clear_error (&temp_error); - } - else - { - g_propagate_error (error, temp_error); - goto out; - } - } - - priv->inited = TRUE; - - ret = TRUE; - out: - g_free (version); - return ret; -} - -const char * -ostree_repo_get_path (OstreeRepo *self) -{ - OstreeRepoPrivate *priv = GET_PRIVATE (self); - return priv->path; -} - -gboolean -ostree_repo_is_archive (OstreeRepo *self) -{ - OstreeRepoPrivate *priv = GET_PRIVATE (self); - - g_return_val_if_fail (priv->inited, FALSE); - - return priv->archive; -} - -static gboolean -write_gvariant_to_tmp (OstreeRepo *self, - OstreeSerializedVariantType type, - GVariant *variant, - GChecksum **out_checksum, - GError **error) -{ - OstreeRepoPrivate *priv = GET_PRIVATE (self); - GVariant *serialized = NULL; - gboolean ret = FALSE; - gsize bytes_written; - char *tmp_name = NULL; - char *dest_name = NULL; - int fd = -1; - GUnixOutputStream *stream = NULL; - GChecksum *checksum = NULL; - - serialized = g_variant_new ("(uv)", GUINT32_TO_BE ((guint32)type), variant); - - tmp_name = g_build_filename (ot_gfile_get_path_cached (priv->tmp_dir), "variant-tmp-XXXXXX", NULL); - fd = g_mkstemp (tmp_name); - if (fd < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - - checksum = g_checksum_new (G_CHECKSUM_SHA256); - - stream = (GUnixOutputStream*)g_unix_output_stream_new (fd, FALSE); - if (!g_output_stream_write_all ((GOutputStream*)stream, - g_variant_get_data (serialized), - g_variant_get_size (serialized), - &bytes_written, - NULL, - error)) - goto out; - - g_checksum_update (checksum, (guint8*)g_variant_get_data (serialized), g_variant_get_size (serialized)); - - if (!g_output_stream_close ((GOutputStream*)stream, - NULL, error)) - goto out; - - dest_name = g_build_filename (ot_gfile_get_path_cached (priv->tmp_dir), g_checksum_get_string (checksum), NULL); - if (rename (tmp_name, dest_name) < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - - ret = TRUE; - *out_checksum = checksum; - checksum = NULL; - out: - /* Unconditionally unlink; if we suceeded, there's a new link, if not, clean up. */ - (void) unlink (tmp_name); - if (fd != -1) - close (fd); - if (checksum) - g_checksum_free (checksum); - if (serialized != NULL) - g_variant_unref (serialized); - g_free (tmp_name); - g_free (dest_name); - g_clear_object (&stream); - return ret; -} - -static gboolean -import_gvariant_object (OstreeRepo *self, - OstreeSerializedVariantType type, - GVariant *variant, - GChecksum **out_checksum, - GError **error) -{ - gboolean ret = FALSE; - OstreeRepoPrivate *priv = GET_PRIVATE (self); - char *tmp_name = NULL; - GChecksum *ret_checksum = NULL; - gboolean did_exist; - - if (!write_gvariant_to_tmp (self, type, variant, &ret_checksum, error)) - goto out; - - tmp_name = g_build_filename (ot_gfile_get_path_cached (priv->tmp_dir), - g_checksum_get_string (ret_checksum), NULL); - - if (!ostree_repo_store_object_trusted (self, tmp_name, - g_checksum_get_string (ret_checksum), - OSTREE_OBJECT_TYPE_META, - TRUE, FALSE, &did_exist, error)) - goto out; - - ret = TRUE; - *out_checksum = ret_checksum; - ret_checksum = NULL; - out: - (void) unlink (tmp_name); - g_free (tmp_name); - if (ret_checksum) - g_checksum_free (ret_checksum); - return ret; -} - -gboolean -ostree_repo_load_variant_checked (OstreeRepo *self, - OstreeSerializedVariantType expected_type, - const char *sha256, - GVariant **out_variant, - GError **error) -{ - gboolean ret = FALSE; - OstreeSerializedVariantType type; - GVariant *ret_variant = NULL; - - if (!ostree_repo_load_variant (self, sha256, &type, &ret_variant, error)) - goto out; - - if (type != expected_type) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Corrupted metadata object '%s'; found type %u, expected %u", sha256, - type, (guint32)expected_type); - goto out; - } - - ret = TRUE; - *out_variant = ret_variant; - ret_variant = NULL; - out: - if (ret_variant) - g_variant_unref (ret_variant); - return ret; -} - -static gboolean -import_directory_meta (OstreeRepo *self, - const char *path, - GVariant **out_variant, - GChecksum **out_checksum, - GError **error) -{ - gboolean ret = FALSE; - struct stat stbuf; - GChecksum *ret_checksum = NULL; - GVariant *dirmeta = NULL; - GVariant *xattrs = NULL; - - if (lstat (path, &stbuf) < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - - if (!S_ISDIR(stbuf.st_mode)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Not a directory: '%s'", path); - goto out; - } - - xattrs = ostree_get_xattrs_for_path (path, error); - if (!xattrs) - goto out; - - dirmeta = g_variant_new ("(uuuu@a(ayay))", - OSTREE_DIR_META_VERSION, - GUINT32_TO_BE ((guint32)stbuf.st_uid), - GUINT32_TO_BE ((guint32)stbuf.st_gid), - GUINT32_TO_BE ((guint32)stbuf.st_mode), - xattrs); - g_variant_ref_sink (dirmeta); - - if (!import_gvariant_object (self, OSTREE_SERIALIZED_DIRMETA_VARIANT, - dirmeta, &ret_checksum, error)) - goto out; - - ret = TRUE; - out: - if (!ret) - { - if (ret_checksum) - g_checksum_free (ret_checksum); - if (dirmeta != NULL) - g_variant_unref (dirmeta); - } - else - { - *out_checksum = ret_checksum; - *out_variant = dirmeta; - } - if (xattrs) - g_variant_unref (xattrs); - return ret; -} - -char * -ostree_repo_get_object_path (OstreeRepo *self, - const char *checksum, - OstreeObjectType type) -{ - OstreeRepoPrivate *priv = GET_PRIVATE (self); - char *ret; - char *relpath; - - relpath = ostree_get_relative_object_path (checksum, type, priv->archive); - ret = g_build_filename (priv->path, relpath, NULL); - g_free (relpath); - - return ret; -} - -static char * -prepare_dir_for_checksum_get_object_path (OstreeRepo *self, - const char *checksum, - OstreeObjectType type, - GError **error) -{ - char *checksum_dir = NULL; - char *object_path = NULL; - - object_path = ostree_repo_get_object_path (self, checksum, type); - checksum_dir = g_path_get_dirname (object_path); - - if (!ot_util_ensure_directory (checksum_dir, FALSE, error)) - goto out; - - out: - g_free (checksum_dir); - return object_path; -} - -static gboolean -link_object_trusted (OstreeRepo *self, - const char *path, - const char *checksum, - OstreeObjectType objtype, - gboolean ignore_exists, - gboolean force, - gboolean *did_exist, - GError **error) -{ - char *src_basename = NULL; - char *src_dirname = NULL; - char *dest_basename = NULL; - char *tmp_dest_basename = NULL; - char *dest_dirname = NULL; - DIR *src_dir = NULL; - DIR *dest_dir = NULL; - gboolean ret = FALSE; - char *dest_path = NULL; - - src_basename = g_path_get_basename (path); - src_dirname = g_path_get_dirname (path); - - src_dir = opendir (src_dirname); - if (src_dir == NULL) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - - dest_path = prepare_dir_for_checksum_get_object_path (self, checksum, objtype, error); - if (!dest_path) - goto out; - - dest_basename = g_path_get_basename (dest_path); - dest_dirname = g_path_get_dirname (dest_path); - dest_dir = opendir (dest_dirname); - if (dest_dir == NULL) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - - if (force) - { - tmp_dest_basename = g_strconcat (dest_basename, ".tmp", NULL); - (void) unlinkat (dirfd (dest_dir), tmp_dest_basename, 0); - } - else - tmp_dest_basename = g_strdup (dest_basename); - - if (linkat (dirfd (src_dir), src_basename, dirfd (dest_dir), tmp_dest_basename, 0) < 0) - { - if (errno != EEXIST || !ignore_exists) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - else - *did_exist = TRUE; - } - else - *did_exist = FALSE; - - if (force) - { - if (renameat (dirfd (dest_dir), tmp_dest_basename, - dirfd (dest_dir), dest_basename) < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - (void) unlinkat (dirfd (dest_dir), tmp_dest_basename, 0); - } - - ret = TRUE; - out: - if (src_dir != NULL) - closedir (src_dir); - if (dest_dir != NULL) - closedir (dest_dir); - g_free (src_basename); - g_free (src_dirname); - g_free (dest_basename); - g_free (tmp_dest_basename); - g_free (dest_dirname); - g_free (dest_path); - return ret; -} - -static gboolean -archive_file_trusted (OstreeRepo *self, - const char *path, - const char *checksum, - OstreeObjectType objtype, - gboolean ignore_exists, - gboolean force, - gboolean *did_exist, - GError **error) -{ - GFile *infile = NULL; - GFile *outfile = NULL; - GFileOutputStream *out = NULL; - gboolean ret = FALSE; - char *dest_path = NULL; - char *dest_tmp_path = NULL; - - infile = ot_util_new_file_for_path (path); - - dest_path = prepare_dir_for_checksum_get_object_path (self, checksum, objtype, error); - if (!dest_path) - goto out; - - dest_tmp_path = g_strconcat (dest_path, ".tmp", NULL); - - outfile = ot_util_new_file_for_path (dest_tmp_path); - out = g_file_replace (outfile, NULL, FALSE, 0, NULL, error); - if (!out) - goto out; - - if (!ostree_pack_object ((GOutputStream*)out, infile, objtype, NULL, error)) - goto out; - - if (!g_output_stream_close ((GOutputStream*)out, NULL, error)) - goto out; - - if (rename (dest_tmp_path, dest_path) < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - - ret = TRUE; - out: - g_free (dest_path); - g_free (dest_tmp_path); - g_clear_object (&infile); - g_clear_object (&outfile); - g_clear_object (&out); - return ret; -} - -gboolean -ostree_repo_store_object_trusted (OstreeRepo *self, - const char *path, - const char *checksum, - OstreeObjectType objtype, - gboolean ignore_exists, - gboolean force, - gboolean *did_exist, - GError **error) -{ - OstreeRepoPrivate *priv = GET_PRIVATE (self); - if (priv->archive && objtype == OSTREE_OBJECT_TYPE_FILE) - return archive_file_trusted (self, path, checksum, objtype, ignore_exists, force, did_exist, error); - else - return link_object_trusted (self, path, checksum, objtype, ignore_exists, force, did_exist, error); -} - -gboolean -ostree_repo_store_packfile (OstreeRepo *self, - const char *expected_checksum, - const char *path, - OstreeObjectType objtype, - GError **error) -{ - OstreeRepoPrivate *priv = GET_PRIVATE (self); - gboolean ret = FALSE; - GString *tempfile_path = NULL; - GChecksum *checksum = NULL; - gboolean did_exist; - - tempfile_path = g_string_new (priv->path); - g_string_append_printf (tempfile_path, "/tmp-unpack-%s", expected_checksum); - - if (!ostree_unpack_object (path, objtype, tempfile_path->str, &checksum, error)) - goto out; - - if (strcmp (g_checksum_get_string (checksum), expected_checksum) != 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Corrupted object %s (actual checksum is %s)", - expected_checksum, g_checksum_get_string (checksum)); - goto out; - } - - if (!ostree_repo_store_object_trusted (self, tempfile_path ? tempfile_path->str : path, - expected_checksum, - objtype, - TRUE, FALSE, &did_exist, error)) - goto out; - - ret = TRUE; - out: - if (tempfile_path) - { - (void) unlink (tempfile_path->str); - g_string_free (tempfile_path, TRUE); - } - if (checksum) - g_checksum_free (checksum); - return ret; -} - -typedef struct _ParsedTreeData ParsedTreeData; -typedef struct _ParsedDirectoryData ParsedDirectoryData; - -static void parsed_tree_data_free (ParsedTreeData *pdata); - -struct _ParsedDirectoryData { - ParsedTreeData *tree_data; - char *metadata_sha256; - GVariant *meta_data; -}; - -static void -parsed_directory_data_free (ParsedDirectoryData *pdata) -{ - if (pdata == NULL) - return; - parsed_tree_data_free (pdata->tree_data); - g_free (pdata->metadata_sha256); - g_variant_unref (pdata->meta_data); - g_free (pdata); -} - -struct _ParsedTreeData { - GHashTable *files; /* char* filename -> char* checksum */ - GHashTable *directories; /* char* dirname -> ParsedDirectoryData* */ -}; - -static ParsedTreeData * -parsed_tree_data_new (void) -{ - ParsedTreeData *ret = g_new0 (ParsedTreeData, 1); - ret->files = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify)g_free, - (GDestroyNotify)g_free); - ret->directories = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify)g_free, - (GDestroyNotify)parsed_directory_data_free); - return ret; -} - -static void -parsed_tree_data_free (ParsedTreeData *pdata) -{ - if (pdata == NULL) - return; - g_hash_table_destroy (pdata->files); - g_hash_table_destroy (pdata->directories); - g_free (pdata); -} - -static GVariant * -create_empty_gvariant_dict (void) -{ - GVariantBuilder builder; - g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sv}")); - return g_variant_builder_end (&builder); -} - -static gboolean -import_parsed_tree (OstreeRepo *self, - ParsedTreeData *tree, - GChecksum **out_checksum, - GError **error) -{ - gboolean ret = FALSE; - GVariant *serialized_tree = NULL; - gboolean builders_initialized = FALSE; - GVariantBuilder files_builder; - GVariantBuilder dirs_builder; - GHashTableIter hash_iter; - GSList *sorted_filenames = NULL; - GSList *iter; - gpointer key, value; - - g_variant_builder_init (&files_builder, G_VARIANT_TYPE ("a(ss)")); - g_variant_builder_init (&dirs_builder, G_VARIANT_TYPE ("a(sss)")); - builders_initialized = TRUE; - - g_hash_table_iter_init (&hash_iter, tree->files); - while (g_hash_table_iter_next (&hash_iter, &key, &value)) - { - const char *name = key; - sorted_filenames = g_slist_prepend (sorted_filenames, (char*)name); - } - - sorted_filenames = g_slist_sort (sorted_filenames, (GCompareFunc)strcmp); - - for (iter = sorted_filenames; iter; iter = iter->next) - { - const char *name = iter->data; - const char *value; - - value = g_hash_table_lookup (tree->files, name); - g_variant_builder_add (&files_builder, "(ss)", name, value); - } - - g_slist_free (sorted_filenames); - sorted_filenames = NULL; - - g_hash_table_iter_init (&hash_iter, tree->directories); - while (g_hash_table_iter_next (&hash_iter, &key, &value)) - { - const char *name = key; - sorted_filenames = g_slist_prepend (sorted_filenames, (char*)name); - } - - sorted_filenames = g_slist_sort (sorted_filenames, (GCompareFunc)strcmp); - - for (iter = sorted_filenames; iter; iter = iter->next) - { - const char *name = iter->data; - GChecksum *dir_checksum = NULL; - ParsedDirectoryData *dir; - - dir = g_hash_table_lookup (tree->directories, name); - - if (!import_parsed_tree (self, dir->tree_data, &dir_checksum, error)) - goto out; - - g_variant_builder_add (&dirs_builder, "(sss)", - name, g_checksum_get_string (dir_checksum), dir->metadata_sha256); - g_checksum_free (dir_checksum); - } - - g_slist_free (sorted_filenames); - sorted_filenames = NULL; - - serialized_tree = g_variant_new ("(u@a{sv}@a(ss)@a(sss))", - GUINT32_TO_BE (0), - create_empty_gvariant_dict (), - g_variant_builder_end (&files_builder), - g_variant_builder_end (&dirs_builder)); - builders_initialized = FALSE; - g_variant_ref_sink (serialized_tree); - if (!import_gvariant_object (self, OSTREE_SERIALIZED_TREE_VARIANT, serialized_tree, out_checksum, error)) - goto out; - - ret = TRUE; - out: - g_slist_free (sorted_filenames); - if (builders_initialized) - { - g_variant_builder_clear (&files_builder); - g_variant_builder_clear (&dirs_builder); - } - if (serialized_tree) - g_variant_unref (serialized_tree); - return ret; -} - -static gboolean -check_path (const char *filename, - GError **error) -{ - gboolean ret = FALSE; - - if (!*filename) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid empty filename"); - goto out; - } - - if (strcmp (filename, ".") == 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Self-reference '.' in filename '%s' not allowed (yet)", filename); - goto out; - } - - if (ot_util_filename_has_dotdot (filename)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Path uplink '..' in filename '%s' not allowed (yet)", filename); - goto out; - } - - if (g_path_is_absolute (filename)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Absolute filename '%s' not allowed (yet)", filename); - goto out; - } - - ret = TRUE; - out: - return ret; -} - -static gboolean -add_one_directory_to_tree_and_import (OstreeRepo *self, - const char *basename, - const char *abspath, - ParsedTreeData *tree, - ParsedDirectoryData **dir, /*inout*/ - GError **error) -{ - gboolean ret = FALSE; - GVariant *dirmeta = NULL; - GChecksum *dir_meta_checksum = NULL; - ParsedDirectoryData *dir_value = *dir; - - g_assert (tree != NULL); - - if (!import_directory_meta (self, abspath, &dirmeta, &dir_meta_checksum, error)) - goto out; - - if (dir_value) - { - g_variant_unref (dir_value->meta_data); - dir_value->meta_data = dirmeta; - } - else - { - dir_value = g_new0 (ParsedDirectoryData, 1); - dir_value->tree_data = parsed_tree_data_new (); - dir_value->metadata_sha256 = g_strdup (g_checksum_get_string (dir_meta_checksum)); - dir_value->meta_data = dirmeta; - g_hash_table_insert (tree->directories, g_strdup (basename), dir_value); - } - - ret = TRUE; - *dir = dir_value; - out: - if (dir_meta_checksum) - g_checksum_free (dir_meta_checksum); - return ret; -} - -static gboolean -add_one_file_to_tree_and_import (OstreeRepo *self, - const char *basename, - const char *abspath, - ParsedTreeData *tree, - GError **error) -{ - gboolean ret = FALSE; - GChecksum *checksum = NULL; - struct stat stbuf; - gboolean did_exist; - - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - g_assert (tree != NULL); - - if (!ostree_stat_and_checksum_file (-1, abspath, OSTREE_OBJECT_TYPE_FILE, &checksum, &stbuf, error)) - goto out; - - if (!ostree_repo_store_object_trusted (self, abspath, g_checksum_get_string (checksum), - OSTREE_OBJECT_TYPE_FILE, TRUE, FALSE, &did_exist, error)) - goto out; - - g_hash_table_replace (tree->files, g_strdup (basename), - g_strdup (g_checksum_get_string (checksum))); - - ret = TRUE; - out: - if (checksum) - g_checksum_free (checksum); - return ret; -} - -static gboolean -add_one_path_to_tree_and_import (OstreeRepo *self, - const char *base, - const char *filename, - ParsedTreeData *tree, - GError **error) -{ - gboolean ret = FALSE; - GPtrArray *components = NULL; - struct stat stbuf; - char *component_abspath = NULL; - ParsedTreeData *current_tree = tree; - const char *component = NULL; - const char *file_sha1; - char *abspath = NULL; - ParsedDirectoryData *dir; - int i; - gboolean is_directory; - - if (!check_path (filename, error)) - goto out; - - abspath = g_build_filename (base, filename, NULL); - - if (lstat (abspath, &stbuf) < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - is_directory = S_ISDIR(stbuf.st_mode); - - if (components) - g_ptr_array_free (components, TRUE); - components = ot_util_path_split (filename); - g_assert (components->len > 0); - - current_tree = tree; - for (i = 0; i < components->len; i++) - { - component = components->pdata[i]; - g_free (component_abspath); - component_abspath = ot_util_path_join_n (base, components, i); - file_sha1 = g_hash_table_lookup (current_tree->files, component); - dir = g_hash_table_lookup (current_tree->directories, component); - - g_assert_cmpstr (component, !=, "."); - - if (i < components->len - 1) - { - if (file_sha1 != NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Encountered non-directory '%s' in '%s'", - component, - filename); - goto out; - } - /* Implicitly add intermediate directories */ - if (!add_one_directory_to_tree_and_import (self, component, - component_abspath, current_tree, &dir, - error)) - goto out; - g_assert (dir != NULL); - current_tree = dir->tree_data; - } - else if (is_directory) - { - if (file_sha1 != NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "File '%s' can't be overwritten by directory", - filename); - goto out; - } - if (!add_one_directory_to_tree_and_import (self, component, - abspath, current_tree, &dir, - error)) - goto out; - } - else - { - g_assert (!is_directory); - if (dir != NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "File '%s' can't be overwritten by directory", - filename); - goto out; - } - if (!add_one_file_to_tree_and_import (self, component, abspath, - current_tree, error)) - goto out; - } - } - - ret = TRUE; - out: - if (components) - g_ptr_array_unref (components); - g_free (component_abspath); - g_free (abspath); - return ret; -} - -gboolean -ostree_repo_write_ref (OstreeRepo *self, - gboolean is_local, - const char *name, - const char *rev, - GError **error) -{ - OstreeRepoPrivate *priv = GET_PRIVATE (self); - return write_checksum_file (is_local ? priv->local_heads_dir : priv->remote_heads_dir, - name, rev, error); -} - -static gboolean -commit_parsed_tree (OstreeRepo *self, - const char *branch, - const char *parent, - const char *subject, - const char *body, - GVariant *metadata, - ParsedDirectoryData *root, - GChecksum **out_commit, - GError **error) -{ - gboolean ret = FALSE; - GChecksum *root_checksum = NULL; - GChecksum *ret_commit = NULL; - GVariant *commit = NULL; - GDateTime *now = NULL; - - g_assert (branch != NULL); - g_assert (subject != NULL); - - if (!import_parsed_tree (self, root->tree_data, &root_checksum, error)) - goto out; - - now = g_date_time_new_now_utc (); - commit = g_variant_new ("(u@a{sv}ssstss)", - GUINT32_TO_BE (OSTREE_COMMIT_VERSION), - metadata ? metadata : create_empty_gvariant_dict (), - parent ? parent : "", - subject, body ? body : "", - GUINT64_TO_BE (g_date_time_to_unix (now)), - g_checksum_get_string (root_checksum), - root->metadata_sha256); - g_variant_ref_sink (commit); - if (!import_gvariant_object (self, OSTREE_SERIALIZED_COMMIT_VARIANT, - commit, &ret_commit, error)) - goto out; - - if (!ostree_repo_write_ref (self, TRUE, branch, g_checksum_get_string (ret_commit), error)) - goto out; - - ret = TRUE; - *out_commit = ret_commit; - out: - if (root_checksum) - g_checksum_free (root_checksum); - if (commit) - g_variant_unref (commit); - if (now) - g_date_time_unref (now); - return ret; -} - -static gboolean -import_root (OstreeRepo *self, - const char *base, - ParsedDirectoryData **out_root, - GError **error) -{ - gboolean ret = FALSE; - ParsedDirectoryData *ret_root = NULL; - GVariant *root_metadata = NULL; - GChecksum *root_meta_checksum = NULL; - - if (!import_directory_meta (self, base, &root_metadata, &root_meta_checksum, error)) - goto out; - - ret_root = g_new0 (ParsedDirectoryData, 1); - ret_root->tree_data = parsed_tree_data_new (); - ret_root->meta_data = root_metadata; - root_metadata = NULL; - ret_root->metadata_sha256 = g_strdup (g_checksum_get_string (root_meta_checksum)); - - ret = TRUE; - *out_root = ret_root; - ret_root = NULL; - out: - if (root_metadata) - g_variant_unref (root_metadata); - if (root_meta_checksum) - g_checksum_free (root_meta_checksum); - parsed_directory_data_free (ret_root); - return ret; -} - -gboolean -ostree_repo_commit_from_filelist_fd (OstreeRepo *self, - const char *branch, - const char *parent, - const char *subject, - const char *body, - GVariant *metadata, - const char *base, - int fd, - char separator, - GChecksum **out_commit, - GError **error) -{ - OstreeRepoPrivate *priv = GET_PRIVATE (self); - gboolean ret = FALSE; - ParsedDirectoryData *root = NULL; - GChecksum *ret_commit_checksum = NULL; - GUnixInputStream *in = NULL; - GDataInputStream *datain = NULL; - char *filename = NULL; - gsize filename_len; - GError *temp_error = NULL; - GVariant *root_metadata = NULL; - GChecksum *root_meta_checksum = NULL; - char *current_head = NULL; - - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - g_return_val_if_fail (priv->inited, FALSE); - g_return_val_if_fail (branch != NULL, FALSE); - g_return_val_if_fail (subject != NULL, FALSE); - g_return_val_if_fail (metadata == NULL || g_variant_is_of_type (metadata, G_VARIANT_TYPE ("a{sv}")), FALSE); - - if (parent == NULL) - parent = branch; - - /* We're overwriting the tree */ - if (!import_root (self, base, &root, error)) - goto out; - - if (!resolve_rev (self, parent, TRUE, ¤t_head, error)) - goto out; - - in = (GUnixInputStream*)g_unix_input_stream_new (fd, FALSE); - datain = g_data_input_stream_new ((GInputStream*)in); - - while ((filename = g_data_input_stream_read_upto (datain, &separator, 1, - &filename_len, NULL, &temp_error)) != NULL) - { - if (!g_data_input_stream_read_byte (datain, NULL, &temp_error)) - { - if (temp_error != NULL) - { - g_propagate_prefixed_error (error, temp_error, "%s", "While reading filelist: "); - goto out; - } - } - if (!add_one_path_to_tree_and_import (self, base, filename, root->tree_data, error)) - goto out; - g_free (filename); - filename = NULL; - } - if (filename == NULL && temp_error != NULL) - { - g_propagate_prefixed_error (error, temp_error, "%s", "While reading filelist: "); - goto out; - } - if (!commit_parsed_tree (self, branch, current_head, subject, body, metadata, - root, &ret_commit_checksum, error)) - goto out; - - ret = TRUE; - *out_commit = ret_commit_checksum; - ret_commit_checksum = NULL; - out: - if (ret_commit_checksum) - g_checksum_free (ret_commit_checksum); - g_free (current_head); - if (root_metadata) - g_variant_unref (root_metadata); - if (root_meta_checksum) - g_checksum_free (root_meta_checksum); - g_clear_object (&datain); - g_clear_object (&in); - g_free (filename); - parsed_directory_data_free (root); - return ret; - -} - -static gboolean -iter_object_dir (OstreeRepo *self, - GFile *dir, - OstreeRepoObjectIter callback, - gpointer user_data, - GError **error) -{ - gboolean ret = FALSE; - GError *temp_error = NULL; - GFileEnumerator *enumerator = NULL; - GFileInfo *file_info = NULL; - char *dirpath = NULL; - - dirpath = g_file_get_path (dir); - - enumerator = g_file_enumerate_children (dir, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, - error); - if (!enumerator) - goto out; - - while ((file_info = g_file_enumerator_next_file (enumerator, NULL, &temp_error)) != NULL) - { - const char *name; - guint32 type; - name = g_file_info_get_attribute_byte_string (file_info, "standard::name"); - type = g_file_info_get_attribute_uint32 (file_info, "standard::type"); - - if (type != G_FILE_TYPE_DIRECTORY - && (g_str_has_suffix (name, ".meta") - || g_str_has_suffix (name, ".file") - || g_str_has_suffix (name, ".packfile"))) - { - char *dot; - char *path; - - dot = strrchr (name, '.'); - g_assert (dot); - - if ((dot - name) == 62) - { - path = g_build_filename (dirpath, name, NULL); - callback (self, path, file_info, user_data); - g_free (path); - } - } - - g_object_unref (file_info); - } - if (file_info == NULL && temp_error != NULL) - { - g_propagate_error (error, temp_error); - goto out; - } - if (!g_file_enumerator_close (enumerator, NULL, error)) - goto out; - - ret = TRUE; - out: - g_free (dirpath); - return ret; -} - -gboolean -ostree_repo_iter_objects (OstreeRepo *self, - OstreeRepoObjectIter callback, - gpointer user_data, - GError **error) -{ - OstreeRepoPrivate *priv = GET_PRIVATE (self); - GFile *objectdir = NULL; - GFileEnumerator *enumerator = NULL; - gboolean ret = FALSE; - GFileInfo *file_info = NULL; - GError *temp_error = NULL; - - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - g_return_val_if_fail (priv->inited, FALSE); - - objectdir = ot_util_new_file_for_path (priv->objects_path); - enumerator = g_file_enumerate_children (objectdir, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, - error); - if (!enumerator) - goto out; - - while ((file_info = g_file_enumerator_next_file (enumerator, NULL, &temp_error)) != NULL) - { - const char *name; - guint32 type; - - name = g_file_info_get_attribute_byte_string (file_info, "standard::name"); - type = g_file_info_get_attribute_uint32 (file_info, "standard::type"); - - if (strlen (name) == 2 && type == G_FILE_TYPE_DIRECTORY) - { - GFile *objdir = g_file_get_child (objectdir, name); - if (!iter_object_dir (self, objdir, callback, user_data, error)) - { - g_object_unref (objdir); - goto out; - } - g_object_unref (objdir); - } - g_object_unref (file_info); - } - if (file_info == NULL && temp_error != NULL) - { - g_propagate_error (error, temp_error); - goto out; - } - if (!g_file_enumerator_close (enumerator, NULL, error)) - goto out; - - ret = TRUE; - out: - g_clear_object (&file_info); - g_clear_object (&enumerator); - g_clear_object (&objectdir); - return ret; -} - -gboolean -ostree_repo_load_variant (OstreeRepo *self, - const char *sha256, - OstreeSerializedVariantType *out_type, - GVariant **out_variant, - GError **error) -{ - gboolean ret = FALSE; - OstreeSerializedVariantType ret_type; - GVariant *ret_variant = NULL; - char *path = NULL; - - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - path = ostree_repo_get_object_path (self, sha256, OSTREE_OBJECT_TYPE_META); - if (!ostree_parse_metadata_file (path, &ret_type, &ret_variant, error)) - goto out; - - ret = TRUE; - *out_type = ret_type; - *out_variant = ret_variant; - ret_variant = NULL; - out: - if (ret_variant) - g_variant_unref (ret_variant); - g_free (path); - return ret; -} - -static gboolean -checkout_tree (OstreeRepo *self, - OstreeRepoFile *dir, - const char *destination, - GCancellable *cancellable, - GError **error); - -static gboolean -checkout_one_directory (OstreeRepo *self, - const char *destination, - const char *dirname, - OstreeRepoFile *dir, - GFileInfo *dir_info, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - char *dest_path = NULL; - GVariant *xattr_variant = NULL; - - dest_path = g_build_filename (destination, dirname, NULL); - - if (!_ostree_repo_file_get_xattrs (dir, &xattr_variant, NULL, error)) - goto out; - - if (mkdir (dest_path, (mode_t)g_file_info_get_attribute_uint32 (dir_info, "unix::mode")) < 0) - { - ot_util_set_error_from_errno (error, errno); - g_prefix_error (error, "Failed to create directory '%s': ", dest_path); - goto out; - } - - if (!ostree_set_xattrs (dest_path, xattr_variant, cancellable, error)) - goto out; - - if (!checkout_tree (self, dir, dest_path, cancellable, error)) - goto out; - - ret = TRUE; - out: - g_free (dest_path); - if (xattr_variant) - g_variant_unref (xattr_variant); - return ret; -} - -static gboolean -checkout_tree (OstreeRepo *self, - OstreeRepoFile *dir, - const char *destination, - GCancellable *cancellable, - GError **error) -{ - OstreeRepoPrivate *priv = GET_PRIVATE (self); - gboolean ret = FALSE; - GError *temp_error = NULL; - GFileInfo *file_info = NULL; - GFileEnumerator *dir_enum = NULL; - GFile *child = NULL; - char *object_path = NULL; - char *dest_path = NULL; - - dir_enum = g_file_enumerate_children ((GFile*)dir, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, - error); - if (!dir_enum) - goto out; - - while ((file_info = g_file_enumerator_next_file (dir_enum, cancellable, &temp_error)) != NULL) - { - const char *name; - guint32 type; - - name = g_file_info_get_attribute_byte_string (file_info, "standard::name"); - type = g_file_info_get_attribute_uint32 (file_info, "standard::type"); - - child = g_file_get_child ((GFile*)dir, name); - - if (type == G_FILE_TYPE_DIRECTORY) - { - if (!checkout_one_directory (self, destination, name, (OstreeRepoFile*)child, file_info, cancellable, error)) - goto out; - } - else - { - const char *checksum = _ostree_repo_file_nontree_get_checksum ((OstreeRepoFile*)child); - - dest_path = g_build_filename (destination, name, NULL); - object_path = ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE); - - if (priv->archive) - { - if (!ostree_unpack_object (object_path, OSTREE_OBJECT_TYPE_FILE, dest_path, NULL, error)) - goto out; - } - else - { - if (link (object_path, dest_path) < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - } - } - - g_free (object_path); - object_path = NULL; - g_free (dest_path); - dest_path = NULL; - g_clear_object (&file_info); - g_clear_object (&child); - } - if (file_info == NULL && temp_error != NULL) - { - g_propagate_error (error, temp_error); - goto out; - } - - ret = TRUE; - out: - g_clear_object (&dir_enum); - g_clear_object (&file_info); - g_clear_object (&child); - g_free (object_path); - g_free (dest_path); - return ret; -} - -gboolean -ostree_repo_checkout (OstreeRepo *self, - const char *rev, - const char *destination, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - char *resolved = NULL; - OstreeRepoFile *root = NULL; - GFileInfo *root_info = NULL; - - if (g_file_test (destination, G_FILE_TEST_EXISTS)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Destination path '%s' already exists", - destination); - goto out; - } - - if (!resolve_rev (self, rev, FALSE, &resolved, error)) - goto out; - - root = (OstreeRepoFile*)_ostree_repo_file_new_root (self, resolved); - if (!_ostree_repo_file_ensure_resolved (root, error)) - goto out; - - root_info = g_file_query_info ((GFile*)root, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, error); - if (!root_info) - goto out; - - if (!checkout_one_directory (self, destination, NULL, root, root_info, cancellable, error)) - goto out; - - ret = TRUE; - out: - g_free (resolved); - g_clear_object (&root); - g_clear_object (&root_info); - return ret; -} - -gboolean -ostree_repo_diff (OstreeRepo *self, - const char *ref, - GFile *target, - GPtrArray **out_modified, - GPtrArray **out_removed, - GPtrArray **out_added, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - GPtrArray *ret_modified = NULL; - GPtrArray *ret_removed = NULL; - GPtrArray *ret_added = NULL; - - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Not implemented yet"); - goto out; - - ret = TRUE; - out: - if (ret_modified) - g_ptr_array_free (ret_modified, TRUE); - if (ret_removed) - g_ptr_array_free (ret_removed, TRUE); - if (ret_added) - g_ptr_array_free (ret_added, TRUE); - return ret; -} diff --git a/libostree/ostree-repo.h b/libostree/ostree-repo.h deleted file mode 100644 index 47a896e1..00000000 --- a/libostree/ostree-repo.h +++ /dev/null @@ -1,162 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2011 Colin Walters - * - * This library 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 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Colin Walters - */ - -#ifndef _OSTREE_REPO -#define _OSTREE_REPO - -#include "ostree-core.h" - -G_BEGIN_DECLS - -#define OSTREE_TYPE_REPO ostree_repo_get_type() -#define OSTREE_REPO(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSTREE_TYPE_REPO, OstreeRepo)) -#define OSTREE_REPO_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), OSTREE_TYPE_REPO, OstreeRepoClass)) -#define OSTREE_IS_REPO(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSTREE_TYPE_REPO)) -#define OSTREE_IS_REPO_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), OSTREE_TYPE_REPO)) -#define OSTREE_REPO_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), OSTREE_TYPE_REPO, OstreeRepoClass)) - -typedef struct { - GObject parent; -} OstreeRepo; - -typedef struct { - GObjectClass parent_class; -} OstreeRepoClass; - -GType ostree_repo_get_type (void); - -OstreeRepo* ostree_repo_new (const char *path); - -gboolean ostree_repo_check (OstreeRepo *self, GError **error); - -const char * ostree_repo_get_path (OstreeRepo *self); - -gboolean ostree_repo_is_archive (OstreeRepo *self); - -GKeyFile * ostree_repo_get_config (OstreeRepo *self); - -GKeyFile * ostree_repo_copy_config (OstreeRepo *self); - -gboolean ostree_repo_write_config (OstreeRepo *self, - GKeyFile *new_config, - GError **error); - -char * ostree_repo_get_object_path (OstreeRepo *self, - const char *object, - OstreeObjectType type); - -gboolean ostree_repo_store_packfile (OstreeRepo *self, - const char *expected_checksum, - const char *path, - OstreeObjectType objtype, - GError **error); - -gboolean ostree_repo_store_object_trusted (OstreeRepo *self, - const char *path, - const char *checksum, - OstreeObjectType objtype, - gboolean ignore_exists, - gboolean force, - gboolean *did_exist, - GError **error); - -gboolean ostree_repo_resolve_rev (OstreeRepo *self, - const char *rev, - char **out_resolved, - GError **error); - -gboolean ostree_repo_write_ref (OstreeRepo *self, - gboolean is_local, - const char *name, - const char *rev, - GError **error); - -gboolean ostree_repo_load_variant (OstreeRepo *self, - const char *sha256, - OstreeSerializedVariantType *out_type, - GVariant **out_variant, - GError **error); - -gboolean ostree_repo_load_variant_checked (OstreeRepo *self, - OstreeSerializedVariantType expected_type, - const char *sha256, - GVariant **out_variant, - GError **error); - -gboolean ostree_repo_commit_from_filelist_fd (OstreeRepo *self, - const char *branch, - const char *parent, - const char *subject, - const char *body, - GVariant *metadata, - const char *base, - int fd, - char separator, - GChecksum **out_commit, - GError **error); - -gboolean ostree_repo_checkout (OstreeRepo *self, - const char *ref, - const char *destination, - GCancellable *cancellable, - GError **error); - -typedef struct { - guint content_differs : 1; - guint xattrs_differs : 1; - guint unused : 30; - - GFileInfo *src_info; - GFileInfo *target_info; - - char *src_file_checksum; - char *target_file_checksum; - - GVariant *src_xattrs; - GVariant *target_xattrs; -} OstreeRepoDiffItem; - -gboolean ostree_repo_diff (OstreeRepo *self, - const char *ref, - GFile *target, - GPtrArray **out_modified, /* OstreeRepoDiffItem */ - GPtrArray **out_removed, /* OstreeRepoDiffItem */ - GPtrArray **out_added, /* OstreeRepoDiffItem */ - GCancellable *cancellable, - GError **error); - -typedef void (*OstreeRepoObjectIter) (OstreeRepo *self, const char *path, - GFileInfo *fileinfo, gpointer user_data); - -gboolean ostree_repo_iter_objects (OstreeRepo *self, - OstreeRepoObjectIter callback, - gpointer user_data, - GError **error); - -G_END_DECLS - -#endif /* _OSTREE_REPO */ diff --git a/libostree/ostree.h b/libostree/ostree.h deleted file mode 100644 index d683080b..00000000 --- a/libostree/ostree.h +++ /dev/null @@ -1,29 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2011 Colin Walters . - * - * This library 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 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Colin Walters - */ - -#ifndef __OSTREE_H__ - -#include -#include -#include - -#endif