summary refs log tree commit diff
path: root/src/systemd/nm-sd-adapt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemd/nm-sd-adapt.c')
-rw-r--r--src/systemd/nm-sd-adapt.c237
1 files changed, 237 insertions, 0 deletions
diff --git a/src/systemd/nm-sd-adapt.c b/src/systemd/nm-sd-adapt.c
new file mode 100644
index 00000000..8b29aed5
--- /dev/null
+++ b/src/systemd/nm-sd-adapt.c
@@ -0,0 +1,237 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* 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, 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2014 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "sd-event.h"
+#include "fd-util.h"
+#include "time-util.h"
+
+struct sd_event_source {
+	guint refcount;
+	guint id;
+	gpointer user_data;
+
+	GIOChannel *channel;
+
+	union {
+		struct {
+			sd_event_io_handler_t cb;
+		} io;
+		struct {
+			sd_event_time_handler_t cb;
+			uint64_t usec;
+		} time;
+	};
+};
+
+static struct sd_event_source *
+source_new (void)
+{
+	struct sd_event_source *source;
+
+	source = g_slice_new0 (struct sd_event_source);
+	source->refcount = 1;
+	return source;
+}
+
+int
+sd_event_source_set_priority (sd_event_source *s, int64_t priority)
+{
+	return 0;
+}
+
+sd_event_source*
+sd_event_source_unref (sd_event_source *s)
+{
+
+	if (!s)
+		return NULL;
+
+	g_return_val_if_fail (s->refcount, NULL);
+
+	s->refcount--;
+	if (s->refcount == 0) {
+		if (s->id)
+			g_source_remove (s->id);
+		if (s->channel) {
+			/* Don't shut down the channel since systemd will soon close
+			 * the file descriptor itself, which would cause -EBADF.
+			 */
+			g_io_channel_unref (s->channel);
+		}
+		g_slice_free (struct sd_event_source, s);
+	}
+	return NULL;
+}
+
+int
+sd_event_source_set_description(sd_event_source *s, const char *description)
+{
+	if (!s)
+		return -EINVAL;
+
+	g_source_set_name_by_id (s->id, description);
+	return 0;
+}
+
+static gboolean
+io_ready (GIOChannel *channel, GIOCondition condition, struct sd_event_source *source)
+{
+	int r, revents = 0;
+	gboolean result;
+
+	if (condition & G_IO_IN)
+		revents |= EPOLLIN;
+	if (condition & G_IO_OUT)
+		revents |= EPOLLOUT;
+	if (condition & G_IO_PRI)
+		revents |= EPOLLPRI;
+	if (condition & G_IO_ERR)
+		revents |= EPOLLERR;
+	if (condition & G_IO_HUP)
+		revents |= EPOLLHUP;
+
+	source->refcount++;
+
+	r = source->io.cb (source, g_io_channel_unix_get_fd (channel), revents, source->user_data);
+	if (r < 0 || source->refcount <= 1) {
+		source->id = 0;
+		result = G_SOURCE_REMOVE;
+	} else
+		result = G_SOURCE_CONTINUE;
+
+	sd_event_source_unref (source);
+
+	return result;
+}
+
+int
+sd_event_add_io (sd_event *e, sd_event_source **s, int fd, uint32_t events, sd_event_io_handler_t callback, void *userdata)
+{
+	struct sd_event_source *source;
+	GIOChannel *channel;
+	GIOCondition condition = 0;
+
+	/* systemd supports floating sd_event_source by omitting the @s argument.
+	 * We don't have such users and don't implement floating references. */
+	g_return_val_if_fail (s, -EINVAL);
+
+	channel = g_io_channel_unix_new (fd);
+	if (!channel)
+		return -EINVAL;
+
+	source = source_new ();
+	source->io.cb = callback;
+	source->user_data = userdata;
+	source->channel = channel;
+
+	if (events & EPOLLIN)
+		condition |= G_IO_IN;
+	if (events & EPOLLOUT)
+		condition |= G_IO_OUT;
+	if (events & EPOLLPRI)
+		condition |= G_IO_PRI;
+	if (events & EPOLLERR)
+		condition |= G_IO_ERR;
+	if (events & EPOLLHUP)
+		condition |= G_IO_HUP;
+
+	g_io_channel_set_encoding (source->channel, NULL, NULL);
+	g_io_channel_set_buffered (source->channel, FALSE);
+	source->id = g_io_add_watch (source->channel, condition, (GIOFunc) io_ready, source);
+
+	*s = source;
+	return 0;
+}
+
+static gboolean
+time_ready (struct sd_event_source *source)
+{
+	source->refcount++;
+
+	source->time.cb (source, source->time.usec, source->user_data);
+	source->id = 0;
+
+	sd_event_source_unref (source);
+
+	return G_SOURCE_REMOVE;
+}
+
+int
+sd_event_add_time(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata)
+{
+	struct sd_event_source *source;
+	uint64_t n = now (clock);
+
+	/* systemd supports floating sd_event_source by omitting the @s argument.
+	 * We don't have such users and don't implement floating references. */
+	g_return_val_if_fail (s, -EINVAL);
+
+	source = source_new ();
+	source->time.cb = callback;
+	source->user_data = userdata;
+	source->time.usec = usec;
+
+	if (usec > 1000)
+		usec = n < usec - 1000 ? usec - n : 1000;
+	source->id = g_timeout_add (usec / 1000, (GSourceFunc) time_ready, source);
+
+	*s = source;
+	return 0;
+}
+
+/* sd_event is basically a GMainContext; but since we only
+ * ever use the default context, nothing to do here.
+ */
+
+int
+sd_event_default (sd_event **e)
+{
+	*e = GUINT_TO_POINTER (1);
+	return 0;
+}
+
+sd_event*
+sd_event_ref (sd_event *e)
+{
+	return e;
+}
+
+sd_event*
+sd_event_unref (sd_event *e)
+{
+	return NULL;
+}
+
+int
+sd_event_now (sd_event *e, clockid_t clock, uint64_t *usec)
+{
+	*usec = now (clock);
+	return 0;
+}
+
+int asynchronous_close(int fd) {
+	safe_close(fd);
+	return -1;
+}
+