diff --git a/Makefile-daemon.am b/Makefile-daemon.am index 2bd851bf..366551ee 100644 --- a/Makefile-daemon.am +++ b/Makefile-daemon.am @@ -22,6 +22,16 @@ librpmostreed_la_SOURCES = \ src/daemon/daemon.c \ src/daemon/utils.h \ src/daemon/utils.c \ + src/daemon/sysroot.h \ + src/daemon/sysroot.c \ + src/daemon/errors.h \ + src/daemon/errors.c \ + src/daemon/auth.h \ + src/daemon/auth.c \ + src/daemon/deployment-utils.h \ + src/daemon/deployment-utils.c \ + src/daemon/os.h \ + src/daemon/os.c \ $(NULL) librpmostreed_la_CFLAGS = \ diff --git a/libglnx b/libglnx index fbdb15cd..0cf50c67 160000 --- a/libglnx +++ b/libglnx @@ -1 +1 @@ -Subproject commit fbdb15cd958c007dc14f6e7cfe314b14c042ce3c +Subproject commit 0cf50c6735246147d0a231d45f730724de0841e8 diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index a86f0c7f..09672a54 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c @@ -19,7 +19,9 @@ #include "config.h" #include "daemon.h" +#include "sysroot.h" #include "types.h" +#include "utils.h" #include "libgsystem.h" @@ -59,6 +61,7 @@ struct _Daemon GMutex mutex; gint num_tasks; + Sysroot *sysroot; gchar *sysroot_path; GDBusConnection *connection; @@ -99,6 +102,8 @@ daemon_finalize (GObject *object) g_clear_object (&self->object_manager); self->object_manager = NULL; + g_clear_object (&self->sysroot); + g_object_unref (self->connection); if (self->ticker_id > 0) @@ -171,6 +176,7 @@ daemon_init (Daemon *self) self->num_tasks = 0; self->last_message = g_get_monotonic_time (); self->sysroot_path = NULL; + self->sysroot = NULL; g_mutex_init (&self->mutex); } @@ -192,7 +198,21 @@ daemon_constructed (GObject *_object) g_dbus_connection_start_message_processing (self->connection); + path = utils_generate_object_path(BASE_DBUS_PATH, "Sysroot", NULL); + self->sysroot = g_object_new (TYPE_SYSROOT, + "sysroot-path", self->sysroot_path, + NULL); + + if (!sysroot_populate (sysroot_get (), &error)) + { + g_error ("Error setting up sysroot: %s", error->message); + goto out; + } + + daemon_publish (self, path, FALSE, self->sysroot); g_debug ("daemon constructed"); + +out: g_clear_error (&error); } diff --git a/src/daemon/os.c b/src/daemon/os.c new file mode 100644 index 00000000..3b570257 --- /dev/null +++ b/src/daemon/os.c @@ -0,0 +1,65 @@ +/* +* Copyright (C) 2015 Red Hat, Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "config.h" +#include "ostree.h" + +#include "types.h" +#include "os.h" + +typedef struct _OSStubClass OSStubClass; + +struct _OSStub +{ + RPMOSTreeOSSkeleton parent_instance; +}; + +struct _OSStubClass +{ + RPMOSTreeOSSkeletonClass parent_class; +}; + +static void osstub_iface_init (RPMOSTreeOSIface *iface); + + +G_DEFINE_TYPE_WITH_CODE (OSStub, osstub, RPMOSTREE_TYPE_OS_SKELETON, + G_IMPLEMENT_INTERFACE (RPMOSTREE_TYPE_OS, + osstub_iface_init)); + +static void +osstub_init (OSStub *self) +{ +} + +static void +osstub_class_init (OSStubClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static void +osstub_iface_init (RPMOSTreeOSIface *iface) +{ +} + + +/* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/daemon/os.h b/src/daemon/os.h new file mode 100644 index 00000000..f2036d8a --- /dev/null +++ b/src/daemon/os.h @@ -0,0 +1,34 @@ +/* +* Copyright (C) 2015 Red Hat, Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef RPM_OSTREED_OSSTUB_H__ +#define RPM_OSTREED_OSSTUB_H__ + +#include "types.h" + +G_BEGIN_DECLS + +#define TYPE_OSSTUB (osstub_get_type ()) +#define OSSTUB(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_OSSTUB, OSSTUB)) +#define IS_OSSTUB(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_OSSTUB)) + +GType osstub_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* RPM_OSTREED_OS_H__ */ diff --git a/src/daemon/sysroot.c b/src/daemon/sysroot.c new file mode 100644 index 00000000..68129f95 --- /dev/null +++ b/src/daemon/sysroot.c @@ -0,0 +1,677 @@ +/* +* Copyright (C) 2015 Red Hat, Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "config.h" +#include "ostree.h" + +#include "types.h" +#include "daemon.h" +#include "sysroot.h" +#include "os.h" +#include "utils.h" +#include "deployment-utils.h" +#include "auth.h" +#include "errors.h" + +#include "libgsystem.h" +#include + +/** + * SECTION:daemon + * @title: Sysroot + * @short_description: Implementation of #RPMOSTreeSysroot + * + * This type provides an implementation of the #RPMOSTreeSysroot interface. + */ + +typedef struct _SysrootClass SysrootClass; + +/** + * Sysroot: + * + * The #Sysroot structure contains only private data and should + * only be accessed using the provided API. + */ +struct _Sysroot +{ + RPMOSTreeSysrootSkeleton parent_instance; + + GCancellable *cancellable; + + gchar *sysroot_path; + + GHashTable *os_interfaces; + GRWLock children_lock; + + GFileMonitor *monitor; + guint sig_changed; + guint64 last_monitor_event; +}; + +struct _SysrootClass +{ + RPMOSTreeSysrootSkeletonClass parent_class; +}; + +enum +{ + PROP_0, + PROP_PATH, +}; + +enum { + UPDATED, + NUM_SIGNALS +}; + +static guint64 UPDATED_THROTTLE_SECONDS = 2; +static guint sysroot_signals[NUM_SIGNALS] = { 0, }; + +static void sysroot_iface_init (RPMOSTreeSysrootIface *iface); + + +G_DEFINE_TYPE_WITH_CODE (Sysroot, sysroot, RPMOSTREE_TYPE_SYSROOT_SKELETON, + G_IMPLEMENT_INTERFACE (RPMOSTREE_TYPE_SYSROOT, + sysroot_iface_init)); + +static Sysroot *_sysroot_instance; + +/* ---------------------------------------------------------------------------------------------------- */ + +static GFile * +_build_file (const char *first, ...) +{ + va_list args; + const gchar *arg; + gs_free gchar *path = NULL; + g_autoptr(GPtrArray) parts = NULL; + + va_start (args, first); + parts = g_ptr_array_new (); + arg = first; + while (arg != NULL) + { + g_ptr_array_add (parts, (char*)arg); + arg = va_arg (args, const char *); + } + va_end (args); + + g_ptr_array_add (parts, NULL); + path = g_build_filenamev ((gchar**)parts->pdata); + return g_file_new_for_path (path); +} + +static gboolean +handle_create_osname (RPMOSTreeSysroot *object, + GDBusMethodInvocation *invocation, + const gchar *osname) +{ + gs_unref_object OstreeSysroot *ot_sysroot = NULL; + g_autoptr(GFile) dir = NULL; + gs_free gchar *deploy_dir = NULL; + + GError *error = NULL; + gs_free gchar *dbus_path = NULL; + + Sysroot *self = SYSROOT (object); + + if (!utils_load_sysroot_and_repo (self->sysroot_path, + self->cancellable, + &ot_sysroot, + NULL, + &error)) + goto out; + + if (!ostree_sysroot_ensure_initialized (ot_sysroot, + self->cancellable, + &error)) + goto out; + + // TODO: The operations here are copied from ostree init-os + // command, should be refactored into shared code + deploy_dir = g_build_filename (self->sysroot_path, + "ostree", "deploy", osname, NULL); + + /* Ensure core subdirectories of /var exist, since we need them for + * dracut generation, and the host will want them too. + */ + g_clear_object (&dir); + dir = _build_file (deploy_dir, "var", "tmp", NULL); + if (!gs_file_ensure_directory (dir, TRUE, self->cancellable, &error)) + goto out; + if (chmod (gs_file_get_path_cached (dir), 01777) < 0) + { + gs_set_error_from_errno (&error, errno); + goto out; + } + + g_clear_object (&dir); + dir = _build_file (deploy_dir, "var", "lib", NULL); + if (!gs_file_ensure_directory (dir, TRUE, self->cancellable, &error)) + goto out; + + g_clear_object (&dir); + dir = _build_file (deploy_dir, "var", "run", NULL); + if (!g_file_test (gs_file_get_path_cached (dir), G_FILE_TEST_IS_SYMLINK)) + { + if (symlink ("../run", gs_file_get_path_cached (dir)) < 0) + { + gs_set_error_from_errno (&error, errno); + goto out; + } + } + + dir = _build_file (deploy_dir, "var", "lock", NULL); + if (!g_file_test (gs_file_get_path_cached (dir), G_FILE_TEST_IS_SYMLINK)) + { + if (symlink ("../run/lock", gs_file_get_path_cached (dir)) < 0) + { + gs_set_error_from_errno (&error, errno); + goto out; + } + } + + dbus_path = utils_generate_object_path (BASE_DBUS_PATH, + osname, NULL); + sysroot_ensure_refresh (SYSROOT (self)); + rpmostree_sysroot_complete_create_osname (RPMOSTREE_SYSROOT (self), + invocation, + g_strdup (dbus_path)); +out: + if (error) + g_dbus_method_invocation_take_error (invocation, error); + + return TRUE; +} + +/* ---------------------------------------------------------------------------------------------------- */ +static void +sysroot_dispose (GObject *object) +{ + Sysroot *self = SYSROOT (object); + GHashTableIter iter; + gpointer value; + gint tries; + + g_cancellable_cancel (self->cancellable); + + if (self->monitor) + { + if (self->sig_changed) + g_signal_handler_disconnect (self->monitor, self->sig_changed); + self->sig_changed = 0; + + // HACK - It is not generally safe to just unref a GFileMonitor. + // Some events might be on their way to the main loop from its + // worker thread and if they arrive after the GFileMonitor has + // been destroyed, bad things will happen. + // + // As a workaround, we cancel the monitor and then spin the main + // loop a bit until nothing is pending anymore. + // + // https://bugzilla.gnome.org/show_bug.cgi?id=740491 + + g_file_monitor_cancel (self->monitor); + for (tries = 0; tries < 10; tries ++) + { + if (!g_main_context_iteration (NULL, FALSE)) + break; + } + } + + g_rw_lock_writer_lock (&self->children_lock); + + /* Tracked os paths are responsible to unpublish themselves */ + g_hash_table_iter_init (&iter, self->os_interfaces); + while (g_hash_table_iter_next (&iter, NULL, &value)) + g_object_run_dispose (value); + g_hash_table_remove_all (self->os_interfaces); + + g_rw_lock_writer_unlock (&self->children_lock); + + G_OBJECT_CLASS (sysroot_parent_class)->dispose (object); +} + +static void +sysroot_finalize (GObject *object) +{ + Sysroot *self = SYSROOT (object); + _sysroot_instance = NULL; + + g_free (self->sysroot_path); + + g_hash_table_unref (self->os_interfaces); + + g_rw_lock_clear (&self->children_lock); + + g_clear_object (&self->cancellable); + g_clear_object (&self->monitor); + + G_OBJECT_CLASS (sysroot_parent_class)->finalize (object); +} + +static void +sysroot_init (Sysroot *self) +{ + g_assert (_sysroot_instance == NULL); + _sysroot_instance = self; + + self->cancellable = g_cancellable_new (); + + self->os_interfaces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, + (GDestroyNotify) g_object_unref); + + g_rw_lock_init (&self->children_lock); + + self->monitor = NULL; + self->sig_changed = 0; + self->last_monitor_event = 0; +} + +static void +sysroot_constructed (GObject *object) +{ + Sysroot *self = SYSROOT (object); + g_signal_connect (RPMOSTREE_SYSROOT(self), "g-authorize-method", + G_CALLBACK (auth_check_root_or_access_denied), NULL); + G_OBJECT_CLASS (sysroot_parent_class)->constructed (object); +} + +static void +sysroot_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + Sysroot *self = SYSROOT (object); + + switch (prop_id) + { + case PROP_PATH: + g_assert (self->sysroot_path == NULL); + self->sysroot_path = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void +sysroot_class_init (SysrootClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->dispose = sysroot_dispose; + gobject_class->finalize = sysroot_finalize; + gobject_class->constructed = sysroot_constructed; + gobject_class->set_property = sysroot_set_property; + + /** + * Sysroot:sysroot_path: + * + * The Sysroot path + */ + g_object_class_install_property (gobject_class, + PROP_PATH, + g_param_spec_string ("sysroot-path", + NULL, + NULL, + NULL, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + sysroot_signals[UPDATED] = g_signal_new ("sysroot-updated", + TYPE_SYSROOT, + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, 0); +} + + +static gboolean +sysroot_populate_deployments (Sysroot *self, + OstreeSysroot *ot_sysroot, + OstreeRepo *ot_repo) +{ + gs_unref_object OstreeDeployment *booted = NULL; + g_autoptr (GPtrArray) deployments = NULL; + + GVariantBuilder builder; + guint i; + gboolean ret = FALSE; + + g_debug ("loading deployments"); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ssisstsav)")); + + // Add deployment interfaces + deployments = ostree_sysroot_get_deployments (ot_sysroot); + + if (deployments == NULL) + goto out; + + for (i=0; ilen; i++) + { + g_variant_builder_add_value (&builder, + deployment_generate_variant (deployments->pdata[i], + ot_repo)); + } + + booted = ostree_sysroot_get_booted_deployment (ot_sysroot); + if (booted) + { + const gchar *os = ostree_deployment_get_osname (booted); + gs_free gchar *path = utils_generate_object_path (BASE_DBUS_PATH, + os, NULL); + rpmostree_sysroot_set_booted (RPMOSTREE_SYSROOT (self), path); + } + else + { + rpmostree_sysroot_set_booted (RPMOSTREE_SYSROOT (self), "/"); + } + + g_debug ("we think we are here"); + rpmostree_sysroot_set_deployments (RPMOSTREE_SYSROOT (self), + g_variant_builder_end (&builder)); + g_debug ("finished deployments"); + +out: + return ret; +} +static gboolean +sysroot_load_internals (Sysroot *self, + OstreeSysroot **out_sysroot, + OstreeRepo **out_repo, + GError **error) +{ + gboolean ret = FALSE; + gs_unref_object OstreeSysroot *ot_sysroot = NULL; + gs_unref_object OstreeRepo *ot_repo = NULL; + g_autoptr (GHashTable) seen = NULL; + gs_free gchar *os_path = NULL; + GDir *os_dir = NULL; + + GHashTableIter iter; + gpointer hashkey; + gpointer value; + + g_rw_lock_writer_lock (&self->children_lock); + if (!utils_load_sysroot_and_repo (self->sysroot_path, + self->cancellable, + &ot_sysroot, + &ot_repo, + error)) + goto out; + + os_path = g_build_filename (self->sysroot_path, "ostree", + "deploy", NULL); + seen = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + os_dir = g_dir_open (os_path, 0, error); + if (!os_dir) + goto out; + + while (TRUE) + { + const gchar *os = g_dir_read_name (os_dir); + gs_free gchar *full_path = NULL; + + if (os == NULL) { + if (errno && errno != ENOENT) + { + glnx_set_error_from_errno (error); + goto out; + } + break; + } + + g_hash_table_add (seen, g_strdup (os)); + // If we've already seen it, continue + if (g_hash_table_contains (self->os_interfaces, os)) + continue; + + full_path = g_build_filename(os_path, os, NULL); + if (g_file_test (full_path, G_FILE_TEST_IS_DIR)) + { + gs_free gchar *path = utils_generate_object_path (BASE_DBUS_PATH, + os, NULL); + //TODO: stub for real OS implementation + RPMOSTreeOS *obj = RPMOSTREE_OS (g_object_new (TYPE_OSSTUB, NULL)); + g_hash_table_insert(self->os_interfaces, + g_strdup (os), + obj); + daemon_publish (daemon_get (), path, FALSE, obj); + } + } + + // Remove dead os paths + g_hash_table_iter_init (&iter, self->os_interfaces); + while (g_hash_table_iter_next (&iter, &hashkey, &value)) + { + if (!g_hash_table_contains (seen, hashkey)) + { + //TODO: stub for real implementation + gs_free gchar *path = utils_generate_object_path (BASE_DBUS_PATH, + hashkey, NULL); + daemon_unpublish (daemon_get (), + path, + G_OBJECT (value)); + g_object_run_dispose (G_OBJECT (value)); + g_hash_table_iter_remove (&iter); + } + } + + // update deployments + sysroot_populate_deployments (self, ot_sysroot, ot_repo); + + gs_transfer_out_value (out_sysroot, &ot_sysroot); + if (out_repo != NULL) + *out_repo = g_object_ref (ot_repo); + + ret = TRUE; + +out: + g_rw_lock_writer_unlock (&self->children_lock); + + if (os_dir) + g_dir_close(os_dir); + + return ret; +} + + +static gboolean _throttle_refresh (gpointer user_data); + +static void +_do_reload_data (GTask *task, + gpointer object, + gpointer data_ptr, + GCancellable *cancellable) +{ + GError *error = NULL; + Sysroot *self = SYSROOT (object); + + g_debug ("reloading"); + + // this was valid once, make sure it is tried again + // TODO, should we bail at some point? + if (!sysroot_load_internals (self, NULL, NULL, &error)) { + g_message ("Error refreshing sysroot data: %s", error->message); + g_timeout_add_seconds (UPDATED_THROTTLE_SECONDS, + _throttle_refresh, + self); + } + g_clear_error (&error); +} + + +static void +_reload_callback (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + Sysroot *self = SYSROOT (user_data); + GTask *task = G_TASK (res); + + g_signal_emit (self, sysroot_signals[UPDATED], 0); + g_object_unref (task); +} + + +static gboolean +_throttle_refresh (gpointer user_data) +{ + Sysroot *self = SYSROOT (user_data); + gboolean ret = TRUE; + + // Only run the update if there isn't another one pending. + g_rw_lock_writer_lock (&self->children_lock); + if ((g_get_monotonic_time () - self->last_monitor_event) > + UPDATED_THROTTLE_SECONDS * G_USEC_PER_SEC) + { + GTask *task = g_task_new (self, self->cancellable, + _reload_callback, self); + g_task_set_return_on_cancel (task, TRUE); + self->last_monitor_event = 0; + g_task_run_in_thread (task, _do_reload_data); + ret = FALSE; + } + g_rw_lock_writer_unlock (&self->children_lock); + + return ret; +} + +static void +on_repo_file (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + gpointer user_data) +{ + Sysroot *self = SYSROOT (user_data); + if (event_type == G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED) + { + g_rw_lock_writer_lock (&self->children_lock); + if (self->last_monitor_event == 0) + g_timeout_add_seconds (UPDATED_THROTTLE_SECONDS, + _throttle_refresh, + user_data); + + self->last_monitor_event = g_get_monotonic_time (); + g_rw_lock_writer_unlock (&self->children_lock); + } +} + + + +static void +sysroot_iface_init (RPMOSTreeSysrootIface *iface) +{ + iface->handle_create_osname = handle_create_osname; +} + + +/** + * sysroot_ensure_refresh: + * + * Ensures that the sysroot will reload it's + * internal data. + */ + +void +sysroot_ensure_refresh (Sysroot *self) +{ + gboolean needs_run; + g_rw_lock_reader_lock (&self->children_lock); + needs_run = self->last_monitor_event == 0; + g_rw_lock_reader_unlock (&self->children_lock); + + if (needs_run) + _throttle_refresh (self); +} + +/** + * sysroot_populate : + * + * loads internals and starts monitoring + * + * Returns: True on success + */ +gboolean +sysroot_populate (Sysroot *self, + GError **error) +{ + gboolean ret = FALSE; + gs_unref_object OstreeRepo *ot_repo = NULL; + g_return_val_if_fail (self != NULL, FALSE); + + if (!sysroot_load_internals (self, NULL, &ot_repo, error)) + goto out; + + if (self->monitor == NULL) + { + GFile *repo_file = ostree_repo_get_path (ot_repo); // owned by ot_repo + self->monitor = g_file_monitor (repo_file, 0, NULL, error); + + if (self->monitor == NULL) + goto out; + + self->sig_changed = g_signal_connect (self->monitor, + "changed", + G_CALLBACK (on_repo_file), + self); + } + + ret = TRUE; + +out: + return ret; +} + +/** + * sysroot_get_sysroot_path : + * + * Returns: The filesystem path for sysroot. + * Do not free owned by sysroot + */ +gchar * +sysroot_get_sysroot_path (Sysroot *self) +{ + return self->sysroot_path; +} + + +/** + * sysroot_get: + * + * Returns: (transfer none): The singleton #Sysroot instance + */ +Sysroot * +sysroot_get (void) +{ + g_assert (_sysroot_instance); + return _sysroot_instance; +} + + + +/* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/daemon/sysroot.h b/src/daemon/sysroot.h new file mode 100644 index 00000000..1fe7a661 --- /dev/null +++ b/src/daemon/sysroot.h @@ -0,0 +1,44 @@ +/* +* Copyright (C) 2015 Red Hat, Inc. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef RPM_OSTREED_SYSROOT_H__ +#define RPM_OSTREED_SYSROOT_H__ + +#include "types.h" + +G_BEGIN_DECLS + +#define TYPE_SYSROOT (sysroot_get_type ()) +#define SYSROOT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_SYSROOT, Sysroot)) +#define IS_SYSROOT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_SYSROOT)) + +#define SYSROOT_DEFAULT_PATH "/" + +GType sysroot_get_type (void) G_GNUC_CONST; + +Sysroot * sysroot_get (void); + +gchar * sysroot_get_sysroot_path (Sysroot *self); + +gboolean sysroot_populate (Sysroot *self, + GError **error); + +void sysroot_ensure_refresh (Sysroot *self); +G_END_DECLS + +#endif /* RPM_OSTREED_SYSROOT_H__ */ diff --git a/src/daemon/types.h b/src/daemon/types.h index 07b49136..c7107fa6 100644 --- a/src/daemon/types.h +++ b/src/daemon/types.h @@ -30,4 +30,10 @@ struct _Daemon; typedef struct _Daemon Daemon; +struct _Sysroot; +typedef struct _Sysroot Sysroot; + +struct _OSStub; +typedef struct _OSStub OSStub; + #endif /* RPM_OSTREED_TYPES_H__ */