From c0d15a66ad3f35872e7dc6a29e4473246da1e843 Mon Sep 17 00:00:00 2001 From: petervo Date: Mon, 27 Apr 2015 18:22:58 -0700 Subject: [PATCH] daemon: Start of work on daemon --- .gitignore | 7 + Makefile-daemon.am | 84 ++++ Makefile-rpm-ostree.am | 2 + Makefile.am | 7 +- configure.ac | 13 + packaging/rpm-ostree.spec.in | 4 + src/daemon/daemon.c | 313 ++++++++++++++ src/daemon/daemon.h | 63 +++ src/daemon/main.c | 385 ++++++++++++++++++ src/daemon/org.projectatomic.rpmostree1.conf | 15 + .../org.projectatomic.rpmostree1.service.in | 4 + src/daemon/org.projectatomic.rpmostree1.xml | 11 + src/daemon/rpm-ostreed.service.in | 7 + src/daemon/types.h | 33 ++ 14 files changed, 947 insertions(+), 1 deletion(-) create mode 100644 Makefile-daemon.am create mode 100644 src/daemon/daemon.c create mode 100644 src/daemon/daemon.h create mode 100644 src/daemon/main.c create mode 100644 src/daemon/org.projectatomic.rpmostree1.conf create mode 100644 src/daemon/org.projectatomic.rpmostree1.service.in create mode 100644 src/daemon/org.projectatomic.rpmostree1.xml create mode 100644 src/daemon/rpm-ostreed.service.in create mode 100644 src/daemon/types.h diff --git a/.gitignore b/.gitignore index b2db5663..e6b24987 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,10 @@ rpm-ostree-*.tar.xz rpm-ostree-*.rpm rpm-ostree.1 + +rpm-ostreed +rpm-ostreed.1 +org.projectatomic.rpmostree1.service +rpm-ostreed.service +rpm-ostreed-generated.c +rpm-ostreed-generated.h diff --git a/Makefile-daemon.am b/Makefile-daemon.am new file mode 100644 index 00000000..756fb03b --- /dev/null +++ b/Makefile-daemon.am @@ -0,0 +1,84 @@ +libexec_PROGRAMS += rpm-ostreed + +dbus_built_sources = rpm-ostreed-generated.h rpm-ostreed-generated.c + +rpm-ostreed-generated.h: rpm-ostreed-generated.c +rpm-ostreed-generated.c: Makefile.am $(top_srcdir)/src/daemon/org.projectatomic.rpmostree1.xml + $(AM_V_GEN) gdbus-codegen \ + --interface-prefix org.projectatomic.rpmostree1 \ + --c-namespace RPMOSTree \ + --c-generate-object-manager \ + --generate-c-code rpm-ostreed-generated \ + $(top_srcdir)/src/daemon/org.projectatomic.rpmostree1.xml \ + $(NULL) +BUILT_SOURCES += $(dbus_built_sources) +CLEANFILES += rpm-ostreed-generated* + +noinst_LTLIBRARIES += librpmostreed.la +nodist_librpmostreed_la_SOURCES = $(dbus_built_sources) + +librpmostreed_la_SOURCES = \ + src/daemon/daemon.h \ + src/daemon/daemon.c \ + $(NULL) + +librpmostreed_la_CFLAGS = \ + $(AM_CFLAGS) \ + $(PKGDEP_RPMOSTREE_CFLAGS) \ + -DG_LOG_DOMAIN=\"rpm-ostreed\" \ + -I$(srcdir)/src/daemon \ + -I$(srcdir)/libglnx \ + -I$(srcdir)/src/lib \ + $(NULL) + +librpmostreed_la_LIBADD = \ + $(AM_LDFLAGS) \ + $(PKGDEP_RPMOSTREE_LIBS) \ + librpmostree-1.la \ + $(CAP_LIBS) + $(NULL) + +rpm_ostreed_SOURCES = \ + src/daemon/main.c \ + $(NULL) + +rpm_ostreed_CFLAGS = \ + $(AM_CFLAGS) \ + -DPKGLIBDIR=\"$(pkglibdir)\" \ + $(PKGDEP_RPMOSTREE_CFLAGS) \ + -I$(srcdir)/src/daemon \ + -I$(srcdir)/libglnx \ + -DG_LOG_DOMAIN=\"rpm-ostreed\" \ + $(NULL) + +rpm_ostreed_LDADD = \ + librpmostreed.la \ + $(AM_LDFLAGS) \ + $(PKGDEP_RPMOSTREE_LIBS) \ + $(NULL) + +dbusconf_DATA = $(srcdir)/src/daemon/org.projectatomic.rpmostree1.conf +dbusconfdir = ${sysconfdir}/dbus-1/system.d + +systemdunit_in_files = $(srcdir)/src/daemon/rpm-ostreed.service.in +systemdunit_DATA = $(systemdunit_in_files:.service.in=.service) +systemdunitdir = $(prefix)/lib/systemd/system/ +$(systemdunit_DATA): + $(SED_SUBST) $@.in > $@ + +service_in_files = $(srcdir)/src/daemon/org.projectatomic.rpmostree1.service.in +service_DATA = $(service_in_files:.service.in=.service) +servicedir = $(dbusservicedir) +$(service_DATA): + $(SED_SUBST) $@.in > $@ + +EXTRA_DIST += \ + $(dbusservice_DATA) \ + $(service_in_files) \ + $(systemdunit_in_files) \ + $(NULL) + +CLEANFILES += \ + $(service_DATA) \ + $(systemdunit_DATA) \ + $(NULL) diff --git a/Makefile-rpm-ostree.am b/Makefile-rpm-ostree.am index ceb97ead..824e908a 100644 --- a/Makefile-rpm-ostree.am +++ b/Makefile-rpm-ostree.am @@ -18,6 +18,8 @@ bin_PROGRAMS += rpm-ostree rpm_ostree_SOURCES = src/app/main.c \ + rpm-ostreed-generated.h \ + rpm-ostreed-generated.c \ src/app/rpmostree-builtins.h \ src/app/rpmostree-db-builtins.h \ src/app/rpmostree-compose-builtins.h \ diff --git a/Makefile.am b/Makefile.am index 82d690d2..1b65900a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -35,9 +35,13 @@ AM_CFLAGS += $(WARN_CFLAGS) EXTRA_DIST += autogen.sh COPYING +SED_SUBST = sed \ + -e 's,[@]libexecdir[@],$(libexecdir),g' \ + $(NULL) + libglnx_srcpath := $(srcdir)/libglnx libglnx_cflags := $(PKGDEP_GIO_UNIX_CFLAGS) -I$(libglnx_srcpath) -fvisibility=hidden -libglnx_ldflags := +libglnx_ldflags := libglnx_libs := $(PKGDEP_GIO_UNIX_LIBS) include $(INTROSPECTION_MAKEFILE) @@ -48,6 +52,7 @@ include libglnx/Makefile-libglnx.am noinst_LTLIBRARIES += libglnx.la include Makefile-libpriv.am include Makefile-lib.am +include Makefile-daemon.am include Makefile-rpm-ostree.am include Makefile-tests.am include Makefile-man.am diff --git a/configure.ac b/configure.ac index 8fe58abc..f950e714 100644 --- a/configure.ac +++ b/configure.ac @@ -13,6 +13,19 @@ AC_SYS_LARGEFILE AC_PROG_CC AM_PROG_CC_C_O +# dbus system dir +AC_MSG_CHECKING(for dbus system services directory) +if test "$enable_prefix_only" = "yes"; then + dbusservicedir='${datadir}/dbus-1/system-services' +else + dbusservicedir='${datadir}/dbus-1/system-services' + if test "$dbusservicedir" = ""; then + AC_MSG_ERROR(Couldn't find dbus services directory. Try installing dbus-devel) + fi +fi +AC_SUBST([dbusservicedir], [$dbusservicedir]) +AC_MSG_RESULT(dbusservicedir) + changequote(,)dnl if test "x$GCC" = "xyes"; then WARN_CFLAGS="-Wall -Wstrict-prototypes -Werror=missing-prototypes \ diff --git a/packaging/rpm-ostree.spec.in b/packaging/rpm-ostree.spec.in index 16555777..55897eda 100644 --- a/packaging/rpm-ostree.spec.in +++ b/packaging/rpm-ostree.spec.in @@ -52,6 +52,10 @@ find $RPM_BUILD_ROOT -name '*.la' -delete %{_mandir}/man1/* %{_libdir}/*.so.1* %{_libdir}/girepository-1.0/*.typelib +%{_libexecdir}/rpm-ostreed +%{_datadir}/dbus-1/system-services/org.projectatomic.rpmostree1.service +%{_prefix}/lib/systemd/system/rpm-ostreed.service +%{_sysconfdir}/dbus-1/system.d/org.projectatomic.rpmostree1.conf %files devel %{_libdir}/lib*.so diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c new file mode 100644 index 00000000..a5c2e0bf --- /dev/null +++ b/src/daemon/daemon.c @@ -0,0 +1,313 @@ +/* +* 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 "daemon.h" +#include "types.h" + +#include "libgsystem.h" + +/** + * SECTION:daemon + * @title: Daemon + * @short_description: Main daemon object + * + * Object holding all global state. + */ + +enum { + FINISHED, + NUM_SIGNALS +}; + +static guint signals[NUM_SIGNALS] = { 0, }; + +typedef struct _DaemonClass DaemonClass; + +/** + * Daemon: + * + * The #Daemon structure contains only private data and should only be + * accessed using the provided API. + */ +struct _Daemon +{ + GObject parent_instance; + + gint name_owner_id; + gboolean name_owned; + gboolean on_message_bus; + + gint64 last_message; + guint ticker_id; + + GMutex mutex; + gint num_tasks; + + gchar *sysroot_path; + + GDBusConnection *connection; + GDBusObjectManagerServer *object_manager; +}; + + +struct _DaemonClass +{ + GObjectClass parent_class; +}; + +static Daemon *_daemon_instance; + +enum +{ + PROP_0, + PROP_CONNECTION, + PROP_OBJECT_MANAGER, + PROP_SYSROOT_PATH, + PROP_ON_MESSAGE_BUS, +}; + +G_DEFINE_TYPE (Daemon, daemon, G_TYPE_OBJECT); + +typedef struct { + GAsyncReadyCallback callback; + gpointer callback_data; + gpointer proxy_source; +} DaemonTaskData; + + +static void +daemon_finalize (GObject *object) +{ + Daemon *self = DAEMON (object); + if (self->name_owner_id) + g_bus_unown_name (self->name_owner_id); + + g_clear_object (&self->object_manager); + self->object_manager = NULL; + + g_object_unref (self->connection); + + if (self->ticker_id > 0) + g_source_remove (self->ticker_id); + + g_mutex_clear (&self->mutex); + + g_free (self->sysroot_path); + G_OBJECT_CLASS (daemon_parent_class)->finalize (object); + + _daemon_instance = NULL; +} + + +static void +daemon_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + Daemon *self = DAEMON (object); + + switch (prop_id) + { + case PROP_OBJECT_MANAGER: + g_value_set_object (value, self->object_manager); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void +daemon_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + Daemon *self = DAEMON (object); + + switch (prop_id) + { + case PROP_CONNECTION: + g_assert (self->connection == NULL); + self->connection = g_value_dup_object (value); + break; + case PROP_SYSROOT_PATH: + g_assert (self->sysroot_path == NULL); + self->sysroot_path = g_value_dup_string (value); + break; + case PROP_ON_MESSAGE_BUS: + self->on_message_bus = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void +daemon_init (Daemon *self) +{ + g_assert (_daemon_instance == NULL); + _daemon_instance = self; + + self->num_tasks = 0; + self->last_message = g_get_monotonic_time (); + self->sysroot_path = NULL; + + g_mutex_init (&self->mutex); +} + +static void +on_name_lost (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + Daemon *self = user_data; + self->name_owned = FALSE; +} + +static void +on_name_acquired (GDBusConnection *connection, + const gchar *bus_name, + gpointer user_data) +{ + Daemon *self = user_data; + self->name_owned = TRUE; +} + +static void +daemon_constructed (GObject *_object) +{ + Daemon *self; + GError *error = NULL; + gs_free gchar *path = NULL; + + self = DAEMON (_object); + self->object_manager = g_dbus_object_manager_server_new (BASE_DBUS_PATH); + /* Export the ObjectManager */ + g_dbus_object_manager_server_set_connection (self->object_manager, self->connection); + g_debug ("exported object manager"); + + if (self->on_message_bus) + { + self->name_owner_id = g_bus_own_name_on_connection (self->connection, + DBUS_NAME, + G_BUS_NAME_OWNER_FLAGS_NONE, + on_name_acquired, + on_name_lost, + self, + NULL); + } + + G_OBJECT_CLASS (daemon_parent_class)->constructed (_object); + + g_dbus_connection_start_message_processing (self->connection); + + g_debug ("daemon constructed"); + g_clear_error (&error); +} + +static void +daemon_class_init (DaemonClass *klass) +{ + GObjectClass *gobject_class; + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = daemon_finalize; + gobject_class->constructed = daemon_constructed; + gobject_class->set_property = daemon_set_property; + gobject_class->get_property = daemon_get_property; + + /** + * Daemon:connection: + * + * The #GDBusConnection the daemon is for. + */ + g_object_class_install_property (gobject_class, + PROP_CONNECTION, + g_param_spec_object ("connection", + "Connection", + "The D-Bus connection the daemon is for", + G_TYPE_DBUS_CONNECTION, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + /** + * Daemon:object-manager: + * + * The #GDBusObjectManager used by the daemon + */ + g_object_class_install_property (gobject_class, + PROP_OBJECT_MANAGER, + g_param_spec_object ("object-manager", + "Object Manager", + "The D-Bus Object Manager server used by the daemon", + G_TYPE_DBUS_OBJECT_MANAGER_SERVER, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, + PROP_SYSROOT_PATH, + g_param_spec_string ("sysroot-path", + "Sysroot Path", + "Sysroot location on the filesystem", + FALSE, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, + PROP_ON_MESSAGE_BUS, + g_param_spec_boolean ("on-message-bus", + "On Message Bus", + "Are we listining on the message bus", + TRUE, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + signals[FINISHED] = g_signal_new ("finished", + TYPE_DAEMON, + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, 0); +} + +/** + * daemon_get: + * + * Returns: (transfer none): The singleton #Daemon instance + */ +Daemon * +daemon_get (void) +{ + g_assert (_daemon_instance); + return _daemon_instance; +} + +gboolean +daemon_on_message_bus (Daemon *self) +{ + return self->on_message_bus; +} diff --git a/src/daemon/daemon.h b/src/daemon/daemon.h new file mode 100644 index 00000000..007b6165 --- /dev/null +++ b/src/daemon/daemon.h @@ -0,0 +1,63 @@ +/* +* 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_DAEMON_H__ +#define RPM_OSTREED_DAEMON_H__ + +#include "types.h" + +G_BEGIN_DECLS + +#define TYPE_DAEMON (daemon_get_type ()) +#define DAEMON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_DAEMON, Daemon)) +#define IS_DAEMON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_DAEMON)) + +#define DBUS_NAME "org.projectatomic.rpmostree1" +#define BASE_DBUS_PATH "/org/projectatomic/rpmostree1" + +GType daemon_get_type (void) G_GNUC_CONST; + +Daemon * daemon_get (void); + +gboolean daemon_on_message_bus (Daemon *self); + +Daemon * daemon_new (GDBusConnection *connection, + gboolean persist); + +void daemon_publish (Daemon *self, + const gchar *path, + gboolean uniquely, + gpointer thing); + +void daemon_unpublish (Daemon *self, + const gchar *path, + gpointer thing); + +GTask * daemon_get_new_task (Daemon *self, + gpointer source_object, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer callback_data); + +GDBusInterface * daemon_get_interface (Daemon *self, + const gchar *object_path, + const gchar *interface_name); + +G_END_DECLS + +#endif /* RPM_OSTREED_DAEMON_H__ */ diff --git a/src/daemon/main.c b/src/daemon/main.c new file mode 100644 index 00000000..8af6d810 --- /dev/null +++ b/src/daemon/main.c @@ -0,0 +1,385 @@ +/* +* Copyright (C) 2007-2010 David Zeuthen +* Copyright (C) 2013-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 "daemon.h" +#include +#include +#include +#include +#include "libgsystem.h" + +/* ---------------------------------------------------------------------------------------------------- */ +static GMainLoop *loop = NULL; +static gboolean opt_debug = FALSE; +static char *opt_sysroot = "/"; +static gint service_dbus_fd = -1; +static GOptionEntry opt_entries[] = +{ + {"debug", 'd', 0, G_OPTION_ARG_NONE, &opt_debug, "Print debug information on stderr", NULL}, + { "sysroot", 0, 0, G_OPTION_ARG_STRING, &opt_sysroot, "Use system root SYSROOT (default: /)", "SYSROOT" }, + { "dbus-peer", 0, 0, G_OPTION_ARG_INT, &service_dbus_fd, "Use a peer to peer dbus connection on this fd", NULL }, + {NULL } +}; + + +static void +on_close (Daemon *daemon, gpointer data) +{ + g_object_unref (daemon); + g_main_loop_quit (loop); +} + +static void +start_daemon (GDBusConnection *connection, + gboolean on_messsage_bus, + gpointer user_data) +{ + Daemon **daemon = user_data; + *daemon = g_object_new (TYPE_DAEMON, + "connection", connection, + "sysroot-path", opt_sysroot, + "on-message-bus", on_messsage_bus, + NULL); + g_signal_connect (*daemon, "finished", + G_CALLBACK (on_close), NULL); +} + + +static void +on_bus_acquired (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + GDBusConnection *connection; + GError *error = NULL; + connection = g_bus_get_finish (res, &error); + if (error != NULL) + { + g_warning ("Couldn't connect to system bus: %s", error->message); + g_error_free (error); + g_main_loop_quit (loop); + } + else + { + g_debug ("Connected to the system bus"); + start_daemon (connection, TRUE, user_data); + } +} + + +static void +on_peer_acquired (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GDBusConnection *connection; + GError *error = NULL; + + connection = g_dbus_connection_new_finish (result, &error); + if (error != NULL) + { + g_warning ("Couldn't connect to peer: %s", error->message); + g_main_loop_quit (loop); + g_error_free (error); + } + else + { + g_debug ("connected to peer"); + start_daemon (connection, FALSE, user_data); + } +} + + +static gboolean +on_sigint (gpointer user_data) +{ + Daemon **daemon = user_data; + g_info ("Caught signal. Initiating shutdown"); + on_close (*daemon, NULL); + return FALSE; +} + + +static gboolean +on_stdin_close (GIOChannel *channel, + GIOCondition condition, + gpointer data) +{ + /* Nowhere to log */ + syslog (LOG_INFO, "%s", "output closed"); + g_main_loop_quit (loop); + return FALSE; +} + + +static void +on_log_debug (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + GString *string; + const gchar *progname; + const gchar *level; + + string = g_string_new (NULL); + switch (log_level & G_LOG_LEVEL_MASK) + { + case G_LOG_LEVEL_DEBUG: + level = "DEBUG"; + break; + case G_LOG_LEVEL_INFO: + level = "INFO"; + break; + default: + level = ""; + break; + } + + + progname = g_get_prgname (); + if (progname == NULL) + progname = "process"; + + if (message == NULL) + message = "(NULL) message"; + + g_string_append_printf (string, "(%s:%lu): ", progname, (gulong) getpid ()); + + if (log_domain != NULL) + g_string_append_printf (string, "%s-", log_domain); + + g_string_append_printf (string, "%s: %s", level, message); + + g_printerr ("%s\n", string->str); + + g_string_free (string, TRUE); +} + + +static void +on_log_handler (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + static gboolean have_called_openlog = FALSE; + const gchar *domains; + int priority; + + if (!have_called_openlog) + { + have_called_openlog = TRUE; + openlog (G_LOG_DOMAIN, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); + } + + /* + * Note: we should not call GLib fucntions here. + * + * Mapping glib log levels to syslog priorities + * is not at all obvious. + */ + switch (log_level & G_LOG_LEVEL_MASK) + { + /* + * In GLib this is always fatal, caller of this + * function aborts() + */ + + case G_LOG_LEVEL_ERROR: + priority = LOG_CRIT; + break; + + /* + * By convention in GLib applications, critical warnings + * are usually internal programmer error (ie: precondition + * failures). This maps well to LOG_CRIT. + */ + case G_LOG_LEVEL_CRITICAL: + priority = LOG_CRIT; + break; + + /* + * By convention in GLib apps, g_warning() is used for + * non-fatal problems, but ones that should be corrected + * or not be encountered in normal system behavior. + */ + case G_LOG_LEVEL_WARNING: + priority = LOG_WARNING; + break; + + /* + * These are related to bad input, or other hosts behaving + * badly. Map well to syslog warnings. + */ + case G_LOG_LEVEL_MESSAGE: + default: + priority = LOG_WARNING; + break; + + /* Informational messages, startup, shutdown etc. */ + case G_LOG_LEVEL_INFO: + priority = LOG_INFO; + break; + + /* Debug messages. */ + case G_LOG_LEVEL_DEBUG: + domains = g_getenv ("G_MESSAGES_DEBUG"); + if (domains == NULL || + (strcmp (domains, "all") != 0 && (!log_domain || !strstr (domains, log_domain)))) + return; + + priority = LOG_INFO; + break; + } + + syslog (priority, "%s", message); +} + + +static gboolean +connect_to_bus_or_peer (gpointer daemon_p) +{ + gs_unref_object GSocketConnection *stream = NULL; + gs_unref_object GSocket *socket = NULL; + GError *error = NULL; + gs_free gchar *guid = NULL; + gboolean ret = FALSE; + + if (service_dbus_fd == -1) + { + g_bus_get (G_BUS_TYPE_SYSTEM, NULL, &on_bus_acquired, daemon_p); + ret = TRUE; + goto out; + } + + socket = g_socket_new_from_fd (service_dbus_fd, &error); + if (error != NULL) + { + g_warning ("Couldn't create socket: %s", error->message); + goto out; + } + + stream = g_socket_connection_factory_create_connection (socket); + if (!stream) + { + g_warning ("Couldn't create socket stream"); + goto out; + } + + guid = g_dbus_generate_guid (); + g_dbus_connection_new (G_IO_STREAM (stream), guid, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER | + G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING, + NULL, NULL, on_peer_acquired, daemon_p); + ret = TRUE; + +out: + g_clear_error (&error); + return ret; +} + + +int +main (int argc, + char **argv) +{ + GError *error; + GOptionContext *opt_context; + GIOChannel *channel; + Daemon *daemon = NULL; + gint ret; + + ret = 1; + loop = NULL; + opt_context = NULL; + + #if !GLIB_CHECK_VERSION(2,36,0) + g_type_init (); + #endif + + /* See glib/gio/gsocket.c */ + signal (SIGPIPE, SIG_IGN); + + /* avoid gvfs (http://bugzilla.gnome.org/show_bug.cgi?id=526454) */ + if (!g_setenv ("GIO_USE_VFS", "local", TRUE)) + { + g_printerr ("Error setting GIO_USE_GVFS\n"); + goto out; + } + + opt_context = g_option_context_new ("rpm-ostreed -- rpm-ostree daemon"); + g_option_context_add_main_entries (opt_context, opt_entries, NULL); + error = NULL; + if (!g_option_context_parse (opt_context, &argc, &argv, &error)) + { + g_printerr ("Error parsing options: %s\n", error->message); + g_error_free (error); + goto out; + } + + if (opt_debug) + { + g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO, on_log_debug, NULL); + g_log_set_always_fatal (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING); + + /* When in debug mode (often testing) we exit when stdin closes */ + channel = g_io_channel_unix_new (0); + g_io_add_watch (channel, G_IO_HUP, on_stdin_close, NULL); + g_io_channel_unref (channel); + } + else + { + /* When not in debug mode, send all logging to syslog */ + g_log_set_default_handler (on_log_handler, NULL); + } + + if (g_getenv ("PATH") == NULL) + g_setenv ("PATH", "/usr/bin:/bin:/usr/sbin:/sbin", TRUE); + + g_info ("rpm-ostreed starting"); + + loop = g_main_loop_new (NULL, FALSE); + + g_unix_signal_add (SIGINT, on_sigint, &daemon); + g_unix_signal_add (SIGTERM, on_sigint, &daemon); + + if (!connect_to_bus_or_peer (&daemon)) + { + ret = 1; + goto out; + } + + g_debug ("Entering main event loop"); + + g_main_loop_run (loop); + + ret = 0; + +out: + if (loop != NULL) + g_main_loop_unref (loop); + + if (opt_context != NULL) + g_option_context_free (opt_context); + + g_info ("rpm-ostreed exiting"); + + return ret; +} diff --git a/src/daemon/org.projectatomic.rpmostree1.conf b/src/daemon/org.projectatomic.rpmostree1.conf new file mode 100644 index 00000000..58c22058 --- /dev/null +++ b/src/daemon/org.projectatomic.rpmostree1.conf @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/src/daemon/org.projectatomic.rpmostree1.service.in b/src/daemon/org.projectatomic.rpmostree1.service.in new file mode 100644 index 00000000..47a5d2c4 --- /dev/null +++ b/src/daemon/org.projectatomic.rpmostree1.service.in @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.projectatomic.rpmostree1 +Exec=@libexecdir@/rpm-ostreed +User=root diff --git a/src/daemon/org.projectatomic.rpmostree1.xml b/src/daemon/org.projectatomic.rpmostree1.xml new file mode 100644 index 00000000..c7abe6c0 --- /dev/null +++ b/src/daemon/org.projectatomic.rpmostree1.xml @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/src/daemon/rpm-ostreed.service.in b/src/daemon/rpm-ostreed.service.in new file mode 100644 index 00000000..358f4dcf --- /dev/null +++ b/src/daemon/rpm-ostreed.service.in @@ -0,0 +1,7 @@ +[Unit] +Description=RPM OSTree Manager + +[Service] +Type=dbus +BusName=org.projectatomic.rpmostree1 +ExecStart=@libexecdir@/rpm-ostreed diff --git a/src/daemon/types.h b/src/daemon/types.h new file mode 100644 index 00000000..07b49136 --- /dev/null +++ b/src/daemon/types.h @@ -0,0 +1,33 @@ +/* +* 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_TYPES_H__ +#define RPM_OSTREED_TYPES_H__ + +#include +#include + +#include "rpm-ostreed-generated.h" + +#include +#include + +struct _Daemon; +typedef struct _Daemon Daemon; + +#endif /* RPM_OSTREED_TYPES_H__ */