]> git.meshlink.io Git - catta/commitdiff
Add inotify support for /ect/avahi/services and /etc/avahi/hosts. Based on a patch...
authorLennart Poettering <lennart@poettering.net>
Sun, 15 Apr 2007 00:34:30 +0000 (00:34 +0000)
committerLennart Poettering <lennart@poettering.net>
Sun, 15 Apr 2007 00:34:30 +0000 (00:34 +0000)
git-svn-id: file:///home/lennart/svn/public/avahi/trunk@1426 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe

avahi-daemon/inotify-nosys.h [new file with mode: 0644]
avahi-daemon/main.c
configure.ac

diff --git a/avahi-daemon/inotify-nosys.h b/avahi-daemon/inotify-nosys.h
new file mode 100644 (file)
index 0000000..6af44dc
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * This header is used if <sys/inotify.h> cannot be found.
+ *
+ * Inode based directory notification for Linux
+ *
+ * Copyright (C) 2005 John McCutchan
+ */
+
+#ifndef _LINUX_INOTIFY_H
+#define _LINUX_INOTIFY_H
+
+#include <stdint.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <asm/unistd.h>
+
+/*
+ * struct inotify_event - structure read from the inotify device for each event
+ *
+ * When you are watching a directory, you will receive the filename for events
+ * such as IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE, ..., relative to the wd.
+ */
+struct inotify_event {
+       int             wd;             /* watch descriptor */
+       uint32_t                mask;           /* watch mask */
+       uint32_t                cookie;         /* cookie to synchronize two events */
+       uint32_t                len;            /* length (including nulls) of name */
+       char            name __flexarr; /* stub for possible name */
+};
+
+/* the following are legal, implemented events that user-space can watch for */
+#define IN_ACCESS              0x00000001      /* File was accessed */
+#define IN_MODIFY              0x00000002      /* File was modified */
+#define IN_ATTRIB              0x00000004      /* Metadata changed */
+#define IN_CLOSE_WRITE         0x00000008      /* Writtable file was closed */
+#define IN_CLOSE_NOWRITE       0x00000010      /* Unwrittable file closed */
+#define IN_OPEN                        0x00000020      /* File was opened */
+#define IN_MOVED_FROM          0x00000040      /* File was moved from X */
+#define IN_MOVED_TO            0x00000080      /* File was moved to Y */
+#define IN_CREATE              0x00000100      /* Subfile was created */
+#define IN_DELETE              0x00000200      /* Subfile was deleted */
+#define IN_DELETE_SELF         0x00000400      /* Self was deleted */
+#define IN_MOVE_SELF           0x00000800      /* Self was moved */
+
+/* the following are legal events.  they are sent as needed to any watch */
+#define IN_UNMOUNT             0x00002000      /* Backing fs was unmounted */
+#define IN_Q_OVERFLOW          0x00004000      /* Event queued overflowed */
+#define IN_IGNORED             0x00008000      /* File was ignored */
+
+/* helper events */
+#define IN_CLOSE               (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* close */
+#define IN_MOVE                        (IN_MOVED_FROM | IN_MOVED_TO) /* moves */
+
+/* special flags */
+#define IN_ONLYDIR             0x01000000      /* only watch the path if it is a directory */
+#define IN_DONT_FOLLOW         0x02000000      /* don't follow a sym link */
+#define IN_MASK_ADD            0x20000000      /* add to the mask of an already existing watch */
+#define IN_ISDIR               0x40000000      /* event occurred against dir */
+#define IN_ONESHOT             0x80000000      /* only send event once */
+
+/*
+ * All of the events - we build the list by hand so that we can add flags in
+ * the future and not break backward compatibility.  Apps will get only the
+ * events that they originally wanted.  Be sure to add new events here!
+ */
+#define IN_ALL_EVENTS  (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \
+                        IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \
+                        IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | \
+                        IN_MOVE_SELF)
+
+#if 0
+#if defined (__alpha__)
+# define __NR_inotify_init 444
+# define __NR_inotify_add_watch 445
+# define __NR_inotify_rm_watch 446
+
+#elif defined (__arm__)
+# define __NR_inotify_init (__NR_SYSCALL_BASE+316)
+# define __NR_inotify_add_watch (__NR_SYSCALL_BASE+317)
+# define __NR_inotify_rm_watch (__NR_SYSCALL_BASE+318)
+
+#elif defined (__frv__)
+# define __NR_inotify_init 291
+# define __NR_inotify_add_watch 292
+# define __NR_inotify_rm_watch 293
+
+#elif defined(__i386__)
+# define __NR_inotify_init 291
+# define __NR_inotify_add_watch 292
+# define __NR_inotify_rm_watch 293
+
+#elif defined (__ia64__)
+# define __NR_inotify_init 1277
+# define __NR_inotify_add_watch 1278
+# define __NR_inotify_rm_watch 1279
+
+#elif defined (__mips__)
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+#  define __NR_inotify_init (__NR_Linux + 284)
+#  define __NR_inotify_add_watch (__NR_Linux + 285)
+#  define __NR_inotify_rm_watch (__NR_Linux + 286)
+# endif
+# if _MIPS_SIM == _MIPS_SIM_ABI64
+#  define __NR_inotify_init (__NR_Linux + 243)
+#  define __NR_inotify_add_watch (__NR_Linux + 243)
+#  define __NR_inotify_rm_watch (__NR_Linux + 243)
+# endif
+# if _MIPS_SIM == _MIPS_SIM_NABI32
+#  define __NR_inotify_init (__NR_Linux + 247)
+#  define __NR_inotify_add_watch (__NR_Linux + 248)
+#  define __NR_inotify_rm_watch (__NR_Linux + 249)
+# endif
+
+#elif defined(__parisc__)
+# define __NR_inotify_init (__NR_Linux + 269)
+# define __NR_inotify_add_watch (__NR_Linux + 270)
+# define __NR_inotify_rm_watch (__NR_Linux + 271)
+
+#elif defined(__powerpc__) || defined(__powerpc64__)
+# define __NR_inotify_init 275
+# define __NR_inotify_add_watch 276
+# define __NR_inotify_rm_watch 277
+
+#elif defined (__s390__)
+# define __NR_inotify_init 284
+# define __NR_inotify_add_watch 285
+# define __NR_inotify_rm_watch 286
+
+#elif defined (__sh__)
+# define __NR_inotify_init 290
+# define __NR_inotify_add_watch 291
+# define __NR_inotify_rm_watch 292
+
+#elif defined (__sh64__)
+# define __NR_inotify_init 318
+# define __NR_inotify_add_watch 319
+# define __NR_inotify_rm_watch 320
+
+#elif defined (__sparc__) || defined (__sparc64__)
+# define __NR_inotify_init 151
+# define __NR_inotify_add_watch 152
+# define __NR_inotify_rm_watch 156
+
+#elif defined(__x86_64__)
+# define __NR_inotify_init 253
+# define __NR_inotify_add_watch 254
+# define __NR_inotify_rm_watch 255
+
+#else
+# error "Unsupported architecture!"
+#endif
+#endif
+
+#ifndef __NR_inotify_init
+# error "Unsupported architecture!"
+#endif
+#ifndef __NR_inotify_add_watch
+# error "Unsupported architecture!"
+#endif
+#ifndef __NR_inotify_rm_watch
+# error "Unsupported architecture!"
+#endif
+
+
+static inline int inotify_init (void)
+{
+       return syscall (__NR_inotify_init);
+}
+
+static inline int inotify_add_watch (int fd, const char *name, uint32_t mask)
+{
+       return syscall (__NR_inotify_add_watch, fd, name, mask);
+}
+
+static inline int inotify_rm_watch (int fd, uint32_t wd)
+{
+       return syscall (__NR_inotify_rm_watch, fd, wd);
+}
+
+
+#endif /* _LINUX_INOTIFY_H */
index d0a3c85c9be96cec9abd696f8fa0e333020f0d45..0367b98d431857cdba776a303461e3c754ccb73a 100644 (file)
@@ -33,6 +33,7 @@
 #include <grp.h>
 #include <pwd.h>
 #include <sys/stat.h>
+#include <sys/ioctl.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <time.h>
 #include <sys/resource.h>
 #include <sys/socket.h>
 
+#ifdef HAVE_SYS_INOTIFY_H
+#include <sys/inotify.h>
+#else
+#include "inotify-nosys.h"
+#endif
+
 #include <libdaemon/dfork.h>
 #include <libdaemon/dsignal.h>
 #include <libdaemon/dlog.h>
@@ -654,6 +661,81 @@ static void dump(const char *text, AVAHI_GCC_UNUSED void* userdata) {
     avahi_log_info("%s", text);
 }
 
+#ifdef HAVE_INOTIFY
+
+static int inotify_fd = -1;
+
+static void add_inotify_watches(void) {
+    int c = 0;
+    /* We ignore the return values, because one or more of these files
+     * might not exist and we're OK with that. In addition we never
+     * want to remove these watches, hence we keep their ids? */
+
+#ifdef ENABLE_CHROOT
+    c = config.use_chroot;
+#endif
+    
+    inotify_add_watch(inotify_fd, c ? "/services" : AVAHI_SERVICE_DIR, IN_CLOSE_WRITE|IN_DELETE|IN_DELETE_SELF|IN_MOVED_FROM|IN_MOVED_TO|IN_MOVE_SELF|IN_ONLYDIR);
+    inotify_add_watch(inotify_fd, c ? "/" : AVAHI_CONFIG_DIR, IN_CLOSE_WRITE|IN_DELETE|IN_DELETE_SELF|IN_MOVED_FROM|IN_MOVED_TO|IN_MOVE_SELF|IN_ONLYDIR);
+}
+
+#endif
+
+static void reload_config(void) {
+
+#ifdef HAVE_INOTIFY
+    /* Refresh in case the config dirs have been removed */
+    add_inotify_watches();
+#endif
+
+#ifdef ENABLE_CHROOT
+    static_service_load(config.use_chroot);
+    static_hosts_load(config.use_chroot);
+#else
+    static_service_load(0);
+    static_hosts_load(0);
+#endif            
+    static_service_add_to_server();
+    static_hosts_add_to_server();
+    
+    if (resolv_conf_entry_group)
+        avahi_s_entry_group_reset(resolv_conf_entry_group);
+    
+    load_resolv_conf();
+    
+    update_wide_area_servers();
+    
+    if (config.publish_resolv_conf && resolv_conf && resolv_conf[0])
+        resolv_conf_entry_group = add_dns_servers(avahi_server, resolv_conf_entry_group, resolv_conf);
+}
+
+#ifdef HAVE_INOTIFY
+
+static void inotify_callback(AvahiWatch *watch, int fd, AVAHI_GCC_UNUSED AvahiWatchEvent event, AVAHI_GCC_UNUSED void *userdata) {
+    char* buffer;
+    int n = 0;
+
+    assert(fd == inotify_fd);
+    assert(watch);
+
+    ioctl(inotify_fd, FIONREAD, &n);
+    if (n <= 0)
+        n = 128;
+
+    buffer = avahi_malloc(n);
+    if (read(inotify_fd, buffer, n) < 0 ) {
+        avahi_free(buffer);
+        avahi_log_error("Failed to read inotify event: %s", avahi_strerror(errno));
+       return;
+    }
+    avahi_free(buffer);
+
+    avahi_log_info("Files changed, reloading.");
+    reload_config();
+}
+
+#endif
+
 static void signal_callback(AvahiWatch *watch, AVAHI_GCC_UNUSED int fd, AVAHI_GCC_UNUSED AvahiWatchEvent event, AVAHI_GCC_UNUSED void *userdata) {
     int sig;
     const AvahiPoll *poll_api;
@@ -682,26 +764,8 @@ static void signal_callback(AvahiWatch *watch, AVAHI_GCC_UNUSED int fd, AVAHI_GC
 
         case SIGHUP:
             avahi_log_info("Got SIGHUP, reloading.");
-#ifdef ENABLE_CHROOT
-            static_service_load(config.use_chroot);
-            static_hosts_load(config.use_chroot);
-#else
-            static_service_load(0);
-            static_hosts_load(0);
-#endif            
-            static_service_add_to_server();
-            static_hosts_add_to_server();
-
-            if (resolv_conf_entry_group)
-                avahi_s_entry_group_reset(resolv_conf_entry_group);
-
-            load_resolv_conf();
-
-            update_wide_area_servers();
-            
-            if (config.publish_resolv_conf && resolv_conf && resolv_conf[0])
-                resolv_conf_entry_group = add_dns_servers(avahi_server, resolv_conf_entry_group, resolv_conf);
 
+            reload_config();
             break;
 
         case SIGUSR1:
@@ -724,6 +788,9 @@ static int run_server(DaemonConfig *c) {
     const AvahiPoll *poll_api = NULL;
     AvahiWatch *sig_watch = NULL;
     int retval_is_sent = 0;
+#ifdef HAVE_INOTIFY
+    AvahiWatch *inotify_watch = NULL;
+#endif
 
     assert(c);
 
@@ -786,6 +853,19 @@ static int run_server(DaemonConfig *c) {
     
 #endif
 
+#ifdef HAVE_INOTIFY
+    if ((inotify_fd = inotify_init()) < 0)
+        avahi_log_warn( "Failed to initialize inotify: %s", strerror(errno));
+    else {
+        add_inotify_watches();
+        
+        if (!(inotify_watch = poll_api->watch_new(poll_api, inotify_fd, AVAHI_WATCH_IN, inotify_callback, NULL))) {
+            avahi_log_error( "Failed to create inotify watcher");
+            goto finish;
+        }
+    }
+#endif
+
     load_resolv_conf();
 #ifdef ENABLE_CHROOT
     static_service_load(config.use_chroot);
@@ -849,6 +929,13 @@ finish:
     if (sig_watch)
         poll_api->watch_free(sig_watch);
 
+#ifdef HAVE_INOTIFY
+    if (inotify_watch)
+        poll_api->watch_free(inotify_watch);
+    if (inotify_fd >= 0)
+        close(inotify_fd);
+#endif
+    
     if (simple_poll_api) {
         avahi_simple_poll_free(simple_poll_api);
         simple_poll_api = NULL;
index 660f138b12003f184980093d7562b0a79dc1fa13..9ca1f8930e1bad96687d12b0fd497af3b760ad50 100644 (file)
@@ -296,6 +296,16 @@ if test "x$HAVE_DLOPEN" = "xyes" ; then
 fi
 AM_CONDITIONAL(HAVE_DLOPEN, test "x$HAVE_DLOPEN" = "xyes")
 
+have_inotify=no
+AC_CHECK_HEADERS([linux/inotify.h], [have_inotify=yes])
+AC_CHECK_HEADERS([sys/inotify.h], [have_inotify=yes])
+
+AM_CONDITIONAL(HAVE_INOTIFY, test "x$have_inotify" = "xyes")
+
+if test "x$have_inotify" = "xyes" ; then
+   AC_DEFINE([HAVE_INOTIFY], 1, [Enable Linux inotify() usage])
+fi
+
 # Check for pkg-config manually first, as if its not installed the
 # PKG_PROG_PKG_CONFIG macro won't be defined.
 AC_CHECK_PROG(have_pkg_config, pkg-config, yes, no)
@@ -948,6 +958,7 @@ echo "
     User for avahi-autoipd:                    ${AVAHI_AUTOIPD_USER}
     Group for avahi-autoipd:                   ${AVAHI_AUTOIPD_GROUP}
     Enable chroot():                           ${enable_chroot}
+    Enable Linux inotify:                      ${have_inotify}
 "
 
 BUILD_DAEMON="no   (You need libdaemon and expat!)"