[systemd-devel] [PATCH 2/5] hostnamed: watch for transient hostname changes

Michal Sekletar msekleta at redhat.com
Mon Feb 24 06:59:28 PST 2014


hostnamed parses its state information at the startup time and doesn't update
it. This might lead to the situation when we are presenting administrator with
inaccurate information. We should watch for changes in the system and update our
state information accordingly.
---
 src/hostname/hostnamed.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)

diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index e57891b..045f24d 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -24,6 +24,10 @@
 #include <unistd.h>
 #include <dlfcn.h>
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
 #include "util.h"
 #include "strv.h"
 #include "def.h"
@@ -46,8 +50,12 @@ enum {
 typedef struct Context {
         char *data[_PROP_MAX];
         Hashmap *polkit_registry;
+        int hostnamefd;
+        sd_event_source *hostname_fd_event_source;
 } Context;
 
+static const char *proc_hostname = "/proc/sys/kernel/hostname";
+
 static void context_reset(Context *c) {
         int p;
 
@@ -59,11 +67,21 @@ static void context_reset(Context *c) {
         }
 }
 
+static void context_init(Context *c) {
+        assert(c);
+
+        memzero(c, sizeof(*c));
+
+        c->hostnamefd = -1;
+}
+
 static void context_free(Context *c, sd_bus *bus) {
         assert(c);
 
         context_reset(c);
         bus_verify_polkit_async_registry_free(bus, c->polkit_registry);
+        sd_event_source_unref(c->hostname_fd_event_source);
+        close_nointr_nofail(c->hostnamefd);
 }
 
 static int context_read_data(Context *c) {
@@ -592,6 +610,70 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
         return 0;
 }
 
+static int dispatch_hostname_change(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        int r = 0;
+        char hostname[HOST_NAME_MAX + 1] = {}, *t;
+        Context *context = (Context *) userdata;
+
+        r = lseek(fd, 0, SEEK_SET);
+        if (r < 0) {
+                log_error("Failed to seek to begining of the file : %m");
+                return -errno;
+        }
+
+        r = read(fd, hostname, HOST_NAME_MAX);
+        if (r < 0) {
+                log_error("Failed to read hostname : %m");
+                return -errno;
+        }
+
+        strstrip(hostname);
+
+        t = strdup(hostname);
+        if (!t)
+                return log_oom();
+        free(context->data[PROP_HOSTNAME]);
+        context->data[PROP_HOSTNAME] = t;
+
+        return r;
+}
+
+static int open_hostname(sd_event *event, Context *context) {
+        int r = 0, fd;
+
+        assert(event);
+        assert(context);
+
+        fd = open(proc_hostname, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
+        if (fd < 0) {
+                log_error("Failed to open %s : %m", proc_hostname);
+                return -errno;
+        }
+
+        context->hostnamefd = fd;
+
+        r = sd_event_add_io(event, &context->hostname_fd_event_source, fd, EPOLLHUP, dispatch_hostname_change, context);
+        if (r < 0) {
+                /* poll on /proc/sys/kernel/hostname not supported by kernel */
+                if (r == -EPERM) {
+                        log_warning("Failed to register hostname fd in event loop: %m. Ignoring.");
+                        close_nointr_nofail(fd);
+                        return 0;
+                }
+
+                log_error("Failed to register hostname fd in event loop : %m");
+                return r;
+        }
+
+        r = sd_event_source_set_priority(context->hostname_fd_event_source, SD_EVENT_PRIORITY_IMPORTANT);
+        if (r < 0) {
+                log_error("Failed to set priority for hostname fd event source : %m");
+                return r;
+        }
+
+        return r;
+}
+
 int main(int argc, char *argv[]) {
         Context context = {};
 
@@ -621,6 +703,8 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
+        context_init(&context);
+
         r = sd_event_default(&event);
         if (r < 0) {
                 log_error("Failed to allocate event loop: %s", strerror(-r));
@@ -639,6 +723,10 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
+        r = open_hostname(event, &context);
+        if (r < 0)
+                goto finish;
+
         r = bus_event_loop_with_idle(event, bus, "org.freedesktop.hostname1", DEFAULT_EXIT_USEC, NULL, NULL);
         if (r < 0) {
                 log_error("Failed to run event loop: %s", strerror(-r));
-- 
1.8.4.2



More information about the systemd-devel mailing list