Hi, Not really tested that well, but more for comment if upstream will be interested ... Basically add a inotify legacy support backend, disabled by default. I think however the HAVE_INOTIFY_IOCTL_MAGIC stuff might be considered if the rest is not, as it should not try to compile the new backend against system linux/inotify.h if old version. Regards, -- Martin Schlemmer
Add support for INotify Legacy backend (pre 0.24) diff -urpN gamin-0.1.2/configure.in gamin-0.1.2.az/configure.in --- gamin-0.1.2/configure.in 2005-07-13 13:10:43.000000000 +0200 +++ gamin-0.1.2.az/configure.in 2005-07-16 09:23:22.000000000 +0200 @@ -225,16 +225,41 @@ dnl check if inotify backend is enabled AM_CONDITIONAL(ENABLE_INOTIFY, test x$inotify = xtrue) if test x$inotify = xtrue; then - AC_CHECK_HEADERS(linux/inotify.h) + AC_CHECK_HEADERS(linux/inotify.h, + [AC_CHECK_DECL(INOTIFY_IOCTL_MAGIC, + [AC_DEFINE(HAVE_INOTIFY_IOCTL_MAGIC,1,[Have legacy linux/inotify.h])], + [],[#include <linux/inotify.h>])]) AC_DEFINE(ENABLE_INOTIFY,1,[Use inotify as backend]) backends="${backends}, inotify" fi +if test x$os = xlinux-gnu; then + AC_ARG_ENABLE(inotify-legacy, + [ --enable-inotify-legacy Enable the INotify Legacy backend], + [case "${enableval}" in + yes) inotify_legacy=true ;; + no) inotify_legacy=false;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-inotify-legacy) ;; + esac],[inotify_legacy=false]) +fi + +dnl check if inotify legacy backend is enabled +AM_CONDITIONAL(ENABLE_INOTIFY_LEGACY, test x$inotify_legacy = xtrue) + +if test x$inotify_legacy = xtrue; then + AC_CHECK_HEADERS(linux/inotify.h, + [AC_CHECK_DECL(INOTIFY_IOCTL_MAGIC, + [AC_DEFINE(HAVE_INOTIFY_IOCTL_MAGIC,1,[Have legacy linux/inotify.h])], + [],[#include <linux/inotify.h>])]) + AC_DEFINE(ENABLE_INOTIFY_LEGACY,1,[Use inotify legacy as backend]) + backends="${backends}, inotify_legacy" +fi + if test x$os != xBogusOS; then AC_CHECK_FUNC(kevent,[have_kevent=1],) if test x$have_kevent = x1 ; then AC_ARG_ENABLE(kqueue, - [ --disable-kqueue Disable the KQueue backend], + [ --disable-kqueue Disable the KQueue backend], [case "${enableval}" in yes) kqueue=true ;; no) kqueue=false ;; diff -urpN gamin-0.1.2/server/Makefile.am gamin-0.1.2.az/server/Makefile.am --- gamin-0.1.2/server/Makefile.am 2005-06-08 23:48:00.000000000 +0200 +++ gamin-0.1.2.az/server/Makefile.am 2005-07-16 09:26:06.000000000 +0200 @@ -38,6 +38,7 @@ gam_server_SOURCES = \ gam_excludes.c \ gam_excludes.h \ local_inotify.h \ + local_inotify_legacy.h \ gam_debug_lists.c \ server_config.h @@ -45,6 +46,10 @@ if ENABLE_INOTIFY gam_server_SOURCES += gam_inotify.c gam_inotify.h endif +if ENABLE_INOTIFY_LEGACY +gam_server_SOURCES += gam_inotify_legacy.c gam_inotify_legacy.h +endif + if ENABLE_DNOTIFY gam_server_SOURCES += gam_dnotify.c gam_dnotify.h endif diff -urpN gamin-0.1.2/server/gam_inotify.c gamin-0.1.2.az/server/gam_inotify.c --- gamin-0.1.2/server/gam_inotify.c 2005-07-12 23:15:19.000000000 +0200 +++ gamin-0.1.2.az/server/gam_inotify.c 2005-07-16 09:24:31.000000000 +0200 @@ -31,7 +31,7 @@ #include <glib.h> #include "gam_error.h" #include "gam_poll.h" -#ifdef HAVE_LINUX_INOTIFY_H +#if defined(HAVE_LINUX_INOTIFY_H) && !defined(HAVE_INOTIFY_IOCTL_MAGIC) #include <linux/inotify.h> #else #include "local_inotify.h" diff -urpN gamin-0.1.2/server/gam_inotify_legacy.c gamin-0.1.2.az/server/gam_inotify_legacy.c --- gamin-0.1.2/server/gam_inotify_legacy.c 1970-01-01 02:00:00.000000000 +0200 +++ gamin-0.1.2.az/server/gam_inotify_legacy.c 2005-07-16 09:36:47.000000000 +0200 @@ -0,0 +1,611 @@ +/* gamin inotify_legacy backend + * Copyright (C) 2005 John McCutchan + * + * Based off of code, + * Copyright (C) 2003 James Willcox, Corey Bowers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "server_config.h" +#define _GNU_SOURCE +#include <fcntl.h> +#include <signal.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <glib.h> +#include "gam_error.h" +#include "gam_poll.h" +#if defined(HAVE_LINUX_INOTIFY_H) && defined(HAVE_INOTIFY_IOCTL_MAGIC) +#include <linux/inotify.h> +#else +#include "local_inotify_legacy.h" +#endif +#include "gam_inotify_legacy.h" +#include "gam_tree.h" +#include "gam_event.h" +#include "gam_server.h" +#include "gam_event.h" +#ifdef GAMIN_DEBUG_API +#include "gam_debugging.h" +#endif + +typedef struct { + char *path; + int wd; + int refcount; + GList *subs; + int busy; + gboolean deactivated; + int events; + int deactivated_events; +} inotify_legacy_data_t; + +static GHashTable *path_hash = NULL; +static GHashTable *wd_hash = NULL; + +G_LOCK_DEFINE_STATIC(inotify_legacy); + +static GIOChannel *inotify_legacy_read_ioc = NULL; + +static gboolean have_consume_idler = FALSE; + +static int inotify_legacy_device_fd = -1; + +static guint should_poll_mask = IN_MODIFY|IN_ATTRIB|IN_CLOSE_WRITE|IN_MOVED_FROM|IN_MOVED_TO|IN_DELETE|IN_CREATE|IN_DELETE_SELF|IN_UNMOUNT; + +static void +gam_inotify_legacy_data_debug (gpointer key, gpointer value, gpointer user_data) +{ + inotify_legacy_data_t *data = (inotify_legacy_data_t *)value; + + if (!data) + return; + + int deactivated = data->deactivated; + + GAM_DEBUG(DEBUG_INFO, "isub wd %d refs %d busy %d deactivated %d events (%d:%d): %s\n", data->wd, data->refcount, data->busy, deactivated, data->events, data->deactivated_events, data->path); +} + +void +gam_inotify_legacy_debug(void) +{ + if (inotify_legacy_device_fd == -1) + { + GAM_DEBUG(DEBUG_INFO, "Inotify device not opened\n"); + return; + } + + if (path_hash == NULL) + return; + + GAM_DEBUG(DEBUG_INFO, "Inotify device fd = %d\n", inotify_legacy_device_fd); + GAM_DEBUG(DEBUG_INFO, "Dumping inotify_legacy subscriptions\n"); + g_hash_table_foreach (path_hash, gam_inotify_legacy_data_debug, NULL); +} + +static void print_mask(int mask) +{ + if (mask & IN_ACCESS) + { + GAM_DEBUG(DEBUG_INFO, "ACCESS\n"); + } + if (mask & IN_MODIFY) + { + GAM_DEBUG(DEBUG_INFO, "MODIFY\n"); + } + if (mask & IN_ATTRIB) + { + GAM_DEBUG(DEBUG_INFO, "ATTRIB\n"); + } + if (mask & IN_CLOSE_WRITE) + { + GAM_DEBUG(DEBUG_INFO, "CLOSE_WRITE\n"); + } + if (mask & IN_CLOSE_NOWRITE) + { + GAM_DEBUG(DEBUG_INFO, "CLOSE_WRITE\n"); + } + if (mask & IN_OPEN) + { + GAM_DEBUG(DEBUG_INFO, "OPEN\n"); + } + if (mask & IN_MOVED_FROM) + { + GAM_DEBUG(DEBUG_INFO, "MOVE_FROM\n"); + } + if (mask & IN_MOVED_TO) + { + GAM_DEBUG(DEBUG_INFO, "MOVE_TO\n"); + } + if (mask & IN_DELETE) + { + GAM_DEBUG(DEBUG_INFO, "DELETE\n"); + } + if (mask & IN_CREATE) + { + GAM_DEBUG(DEBUG_INFO, "CREATE_SUBDIR\n"); + } + if (mask & IN_DELETE_SELF) + { + GAM_DEBUG(DEBUG_INFO, "DELETE_SELF\n"); + } + if (mask & IN_UNMOUNT) + { + GAM_DEBUG(DEBUG_INFO, "UNMOUNT\n"); + } + if (mask & IN_Q_OVERFLOW) + { + GAM_DEBUG(DEBUG_INFO, "Q_OVERFLOW\n"); + } + if (mask & IN_IGNORED) + { + GAM_DEBUG(DEBUG_INFO, "IGNORED\n"); + } +} + +static inotify_legacy_data_t * +gam_inotify_legacy_data_new(const char *path, int wd) +{ + inotify_legacy_data_t *data; + + data = g_new0(inotify_legacy_data_t, 1); + data->path = g_strdup(path); + data->wd = wd; + data->busy = 0; + data->refcount = 1; + data->deactivated_events = 0; + data->events = 0; + + return data; +} + +static void +gam_inotify_legacy_data_free(inotify_legacy_data_t * data) +{ + if (data->refcount != 0) + GAM_DEBUG(DEBUG_INFO, "gam_inotify_legacy_data_free called with reffed data.\n"); + g_free(data->path); + g_free(data); +} + +static void +gam_inotify_legacy_directory_handler_internal(const char *path, pollHandlerMode mode) +{ + inotify_legacy_data_t *data; + int path_fd, path_wd; + struct inotify_watch_request iwr; + switch (mode) { + case GAMIN_ACTIVATE: + GAM_DEBUG(DEBUG_INFO, "Adding %s to inotify_legacy\n", path); + break; + case GAMIN_DESACTIVATE: + GAM_DEBUG(DEBUG_INFO, "Removing %s from inotify_legacy\n", path); + break; + case GAMIN_FLOWCONTROLSTART: + GAM_DEBUG(DEBUG_INFO, "inotify_legacy: Start flow control for %s\n", path); + break; + case GAMIN_FLOWCONTROLSTOP: + GAM_DEBUG(DEBUG_INFO, "inotify_legacy: Stop flow control for %s\n", path); + break; + default: + gam_error(DEBUG_INFO, "Unknown inotify_legacy operation %d for %s\n", + mode, path); + return; + } + + G_LOCK(inotify_legacy); + + if (mode == GAMIN_ACTIVATE) { + + if ((data = g_hash_table_lookup(path_hash, path)) != NULL) { + data->refcount++; + GAM_DEBUG(DEBUG_INFO, " found incremented refcount: %d\n", + data->refcount); + G_UNLOCK(inotify_legacy); +#ifdef GAMIN_DEBUG_API + gam_debug_report(GAMinotifyChange, path, data->refcount); +#endif + GAM_DEBUG(DEBUG_INFO, "inotify_legacy updated refcount\n"); + return; + } + + path_fd = open(path, O_RDONLY); + + if (path_fd < 0) { + G_UNLOCK(inotify_legacy); + return; + } + + iwr.fd = path_fd; + iwr.mask = should_poll_mask; + path_wd = ioctl (inotify_legacy_device_fd, INOTIFY_WATCH, &iwr); + close (path_fd); + + data = gam_inotify_legacy_data_new(path, path_wd); + g_hash_table_insert(wd_hash, GINT_TO_POINTER(data->wd), data); + g_hash_table_insert(path_hash, data->path, data); + + GAM_DEBUG(DEBUG_INFO, "activated inotify_legacy for %s\n", path); +#ifdef GAMIN_DEBUG_API + gam_debug_report(GAMinotifyCreate, path, 0); +#endif + } else if (mode == GAMIN_DESACTIVATE) { + data = g_hash_table_lookup(path_hash, path); + + if (!data) { + GAM_DEBUG(DEBUG_INFO, " not found !!!\n"); + + G_UNLOCK(inotify_legacy); + return; + } + + data->refcount--; + GAM_DEBUG(DEBUG_INFO, "inotify_legacy decremeneted refcount for %s\n", + path); + + if (data->refcount == 0) { + int wd = data->wd; + GAM_DEBUG(DEBUG_INFO, "removed inotify_legacy watch for %s\n", + data->path); + g_hash_table_remove(path_hash, data->path); + g_hash_table_remove(wd_hash, GINT_TO_POINTER(data->wd)); + gam_inotify_legacy_data_free(data); + if (ioctl (inotify_legacy_device_fd, INOTIFY_IGNORE, &wd) < 0) { + GAM_DEBUG (DEBUG_INFO, "INOTIFY_IGNORE failed for %s (wd = %d)\n", data->path, data->wd); + } +#ifdef GAMIN_DEBUG_API + gam_debug_report(GAMinotifyDelete, data->path, 0); +#endif + } else { + GAM_DEBUG(DEBUG_INFO, " found decremented refcount: %d\n", + data->refcount); +#ifdef GAMIN_DEBUG_API + gam_debug_report(GAMinotifyChange, data->path, data->refcount); +#endif + } + } else if ((mode == GAMIN_FLOWCONTROLSTART) || + (mode == GAMIN_FLOWCONTROLSTOP)) { + data = g_hash_table_lookup(path_hash, path); + if (!data) { + GAM_DEBUG(DEBUG_INFO, " not found !!!\n"); + + G_UNLOCK(inotify_legacy); + return; + } + if (data != NULL) { + if (mode == GAMIN_FLOWCONTROLSTART) { + GAM_DEBUG(DEBUG_INFO, "inotify_legacy: GAMIN_FLOWCONTROLSTART for %s\n", data->path); + if (data->wd >= 0) { + if (ioctl (inotify_legacy_device_fd, INOTIFY_IGNORE, &data->wd) < 0) { + GAM_DEBUG (DEBUG_INFO, "INOTIFY_IGNORE failed for %s (wd = %d)\n", data->path, data->wd); + } + data->deactivated = TRUE; + GAM_DEBUG(DEBUG_INFO, "deactivated inotify_legacy for %s\n", + data->path); +#ifdef GAMIN_DEBUG_API + gam_debug_report(GAMinotifyFlowOn, data->path, 0); +#endif + } + data->busy++; + } else { + GAM_DEBUG(DEBUG_INFO, "inotify_legacy: GAMIN_FLOWCONTROLSTOP for %s\n", data->path); + if (data->busy > 0) { + GAM_DEBUG(DEBUG_INFO, "inotify_legacy: data->busy > 0 for %s\n", data->path); + data->busy--; + if (data->busy == 0) { + GAM_DEBUG(DEBUG_INFO, "inotify_legacy: data->busy == 0 for %s\n", data->path); + path_fd = open(data->path, O_RDONLY); + if (path_fd < 0) { + G_UNLOCK(inotify_legacy); + GAM_DEBUG(DEBUG_INFO, + "failed to reactivate inotify_legacy for %s\n", + data->path); + + return; + } + + iwr.fd = path_fd; + iwr.mask = should_poll_mask; + path_wd = ioctl (inotify_legacy_device_fd, INOTIFY_WATCH, &iwr); + close (path_fd); + + /* Remove the old wd from the hash table */ + g_hash_table_remove(wd_hash, GINT_TO_POINTER(data->wd)); + + data->wd = path_wd; + data->deactivated = FALSE; + + /* Insert the new wd into the hash table */ + g_hash_table_insert(wd_hash, GINT_TO_POINTER(data->wd), + data); + GAM_DEBUG(DEBUG_INFO, "reactivated inotify_legacy for %s\n", + data->path); +#ifdef GAMIN_DEBUG_API + gam_debug_report(GAMinotifyFlowOff, path, 0); +#endif + } + } + } + } + } else { + GAM_DEBUG(DEBUG_INFO, "Unimplemented operation\n"); + } + + G_UNLOCK(inotify_legacy); +} + +static void +gam_inotify_legacy_directory_handler(const char *path, pollHandlerMode mode) +{ + GAM_DEBUG(DEBUG_INFO, "gam_inotify_legacy_directory_handler %s : %d\n", + path, mode); + + gam_inotify_legacy_directory_handler_internal(path, mode); +} + +static void +gam_inotify_legacy_file_handler(const char *path, pollHandlerMode mode) +{ + GAM_DEBUG(DEBUG_INFO, "gam_inotify_legacy_file_handler %s : %d\n", path, mode); + + if (g_file_test(path, G_FILE_TEST_IS_DIR)) { + gam_inotify_legacy_directory_handler_internal(path, mode); + } else { + GAM_DEBUG(DEBUG_INFO, " not a dir %s, FAILED!!!\n", path); + } +} + +static void +gam_inotify_legacy_q_overflow (gpointer key, gpointer value, gpointer user_data) +{ + inotify_legacy_data_t *data = (inotify_legacy_data_t *)value; + + gam_poll_scan_directory (data->path); +} + +static gboolean +gam_inotify_legacy_read_handler(gpointer user_data) +{ + char *buffer; + int buffer_size; + int events; + gsize buffer_i, read_size; + + G_LOCK(inotify_legacy); + + if (ioctl(inotify_legacy_device_fd, FIONREAD, &buffer_size) < 0) { + G_UNLOCK(inotify_legacy); + GAM_DEBUG(DEBUG_INFO, "inotify_legacy FIONREAD < 0. kaboom!\n"); + return FALSE; + } + + buffer = g_malloc(buffer_size); + + if (g_io_channel_read_chars(inotify_legacy_read_ioc, (char *)buffer, buffer_size, &read_size, NULL) != G_IO_STATUS_NORMAL) { + G_UNLOCK(inotify_legacy); + GAM_DEBUG(DEBUG_INFO, "inotify_legacy failed to read events from inotify_legacy fd.\n"); + g_free (buffer); + return FALSE; + } + + buffer_i = 0; + events = 0; + while (buffer_i < read_size) { + struct inotify_event *event; + gsize event_size; + inotify_legacy_data_t *data; + + event = (struct inotify_event *)&buffer[buffer_i]; + event_size = sizeof(struct inotify_event) + event->len; + + data = g_hash_table_lookup (wd_hash, GINT_TO_POINTER(event->wd)); + if (!data) { + GAM_DEBUG(DEBUG_INFO, "processing event: inotify_legacy can't find wd %d\n", event->wd); + } else if (data->deactivated) { + GAM_DEBUG(DEBUG_INFO, "inotify_legacy: ignoring event on temporarily deactivated watch %s\n", data->path); + data->deactivated_events++; + } else { + if (event->mask == IN_IGNORED) { + GList *l; + + GAM_DEBUG(DEBUG_INFO, "inotify_legacy: IN_IGNORE on wd=%d\n", event->wd); + GAM_DEBUG(DEBUG_INFO, "inotify_legacy: removing all subscriptions for %s\n", data->path); + + data->events++; + + l = data->subs; + data->subs = NULL; + for (l = l; l; l = l->next) { + GamSubscription *sub = l->data; + gam_inotify_legacy_remove_subscription (sub); + } + } else if (event->mask != IN_Q_OVERFLOW) { + if (event->mask & should_poll_mask) { + GAM_DEBUG(DEBUG_INFO, "inotify_legacy requesting poll for %s\n", data->path); + GAM_DEBUG(DEBUG_INFO, "poll was requested for event = "); + print_mask (event->mask); + data->events++; + gam_poll_scan_directory (data->path); + } + } else if (event->mask == IN_Q_OVERFLOW) { + GAM_DEBUG(DEBUG_INFO, "inotify_legacy queue over flowed, requesting poll on all watched paths\n"); + g_hash_table_foreach (path_hash, gam_inotify_legacy_q_overflow, NULL); + } + } + + buffer_i += event_size; + events++; + } + GAM_DEBUG(DEBUG_INFO, "inotify_legacy recieved %d events\n", events); + + g_free(buffer); + G_UNLOCK(inotify_legacy); + + return TRUE; +} + + +static gboolean +gam_inotify_legacy_consume_subscriptions_real(gpointer data) +{ + GAM_DEBUG(DEBUG_INFO, "gam_inotify_legacy_consume_subscriptions_real()\n"); + gam_poll_consume_subscriptions(); + have_consume_idler = FALSE; + return FALSE; +} + +static void +gam_inotify_legacy_consume_subscriptions(void) +{ + GSource *source; + + if (have_consume_idler) + return; + + GAM_DEBUG(DEBUG_INFO, "gam_inotify_legacy_consume_subscriptions()\n"); + have_consume_idler = TRUE; + source = g_idle_source_new(); + g_source_set_callback(source, gam_inotify_legacy_consume_subscriptions_real, + NULL, NULL); + g_source_attach(source, NULL); +} + +/** + * @defgroup inotify_legacy inotify_legacy Backend + * @ingroup Backends + * @brief inotify_legacy backend API + * + * Since version 2.6.X, Linux kernels have included the Linux Inode + * Notification system (inotify_legacy). This backend uses inotify_legacy to know when + * files are changed/created/deleted. Since inotify_legacy can't watch files/dirs that + * don't exist we still have to cache stat() information. For this, + * we can just use the code in the polling backend. + * + * @{ + */ + + +/** + * Initializes the inotify_legacy backend. This must be called before + * any other functions in this module. + * + * @returns TRUE if initialization succeeded, FALSE otherwise + */ +gboolean +gam_inotify_legacy_init(void) +{ + GSource *source; + + g_return_val_if_fail(gam_poll_init_full(FALSE), FALSE); + + inotify_legacy_device_fd = open("/dev/inotify", O_RDONLY); + + if (inotify_legacy_device_fd < 0) { + GAM_DEBUG(DEBUG_INFO, "Could not open /dev/inotify\n"); + return FALSE; + } + + inotify_legacy_read_ioc = g_io_channel_unix_new(inotify_legacy_device_fd); + + /* For binary data */ + g_io_channel_set_encoding(inotify_legacy_read_ioc, NULL, NULL); + /* Non blocking */ + g_io_channel_set_flags(inotify_legacy_read_ioc, G_IO_FLAG_NONBLOCK, NULL); + + source = g_io_create_watch(inotify_legacy_read_ioc, + G_IO_IN | G_IO_HUP | G_IO_ERR); + g_source_set_callback(source, gam_inotify_legacy_read_handler, NULL, NULL); + + g_source_attach(source, NULL); + + path_hash = g_hash_table_new(g_str_hash, g_str_equal); + wd_hash = g_hash_table_new(g_direct_hash, g_direct_equal); + gam_poll_set_kernel_handler(gam_inotify_legacy_directory_handler, + gam_inotify_legacy_file_handler, + GAMIN_K_INOTIFY); + + GAM_DEBUG(DEBUG_INFO, "inotify_legacy initialized\n"); + + gam_backend_add_subscription = gam_inotify_legacy_add_subscription; + gam_backend_remove_subscription = gam_inotify_legacy_remove_subscription; + gam_backend_remove_all_for = gam_inotify_legacy_remove_all_for; + + return TRUE; +} + +/** + * Adds a subscription to be monitored. + * + * @param sub a #GamSubscription to be polled + * @returns TRUE if adding the subscription succeeded, FALSE otherwise + */ +gboolean +gam_inotify_legacy_add_subscription(GamSubscription * sub) +{ + GAM_DEBUG(DEBUG_INFO, "gam_inotify_legacy_add_subscription\n"); + + if (!gam_poll_add_subscription(sub)) { + return FALSE; + } + + gam_inotify_legacy_consume_subscriptions(); + + GAM_DEBUG(DEBUG_INFO, "gam_inotify_legacy_add_subscription: done\n"); + return TRUE; +} + +/** + * Removes a subscription which was being monitored. + * + * @param sub a #GamSubscription to remove + * @returns TRUE if removing the subscription succeeded, FALSE otherwise + */ +gboolean +gam_inotify_legacy_remove_subscription(GamSubscription * sub) +{ + GAM_DEBUG(DEBUG_INFO, "gam_inotify_legacy_remove_subscription\n"); + + if (!gam_poll_remove_subscription(sub)) { + return FALSE; + } + + gam_inotify_legacy_consume_subscriptions(); + + GAM_DEBUG(DEBUG_INFO, "gam_inotify_legacy_remove_subscription: done\n"); + return TRUE; +} + +/** + * Stop monitoring all subscriptions for a given listener. + * + * @param listener a #GamListener + * @returns TRUE if removing the subscriptions succeeded, FALSE otherwise + */ +gboolean +gam_inotify_legacy_remove_all_for(GamListener * listener) +{ + if (!gam_poll_remove_all_for(listener)) { + return FALSE; + } + + gam_inotify_legacy_consume_subscriptions(); + + return TRUE; +} + +/** @} */ diff -urpN gamin-0.1.2/server/gam_inotify_legacy.h gamin-0.1.2.az/server/gam_inotify_legacy.h --- gamin-0.1.2/server/gam_inotify_legacy.h 1970-01-01 02:00:00.000000000 +0200 +++ gamin-0.1.2.az/server/gam_inotify_legacy.h 2005-07-16 08:41:34.000000000 +0200 @@ -0,0 +1,18 @@ +#ifndef __GAM_INOTIFY_LEGACY_H__ +#define __GAM_INOTIFY_LEGACY_H__ + +#include <glib.h> +#include "gam_poll.h" +#include "gam_subscription.h" + +G_BEGIN_DECLS + +gboolean gam_inotify_legacy_init (void); +gboolean gam_inotify_legacy_add_subscription (GamSubscription *sub); +gboolean gam_inotify_legacy_remove_subscription (GamSubscription *sub); +gboolean gam_inotify_legacy_remove_all_for (GamListener *listener); +void gam_inotify_legacy_debug (void); + +G_END_DECLS + +#endif /* __GAM_INOTIFY_LEGACY_H__ */ diff -urpN gamin-0.1.2/server/gam_server.c gamin-0.1.2.az/server/gam_server.c --- gamin-0.1.2/server/gam_server.c 2005-06-15 13:02:34.000000000 +0200 +++ gamin-0.1.2.az/server/gam_server.c 2005-07-16 08:44:19.000000000 +0200 @@ -36,6 +36,9 @@ #ifdef ENABLE_INOTIFY #include "gam_inotify.h" #endif +#ifdef ENABLE_INOTIFY_LEGACY +#include "gam_inotify_legacy.h" +#endif #ifdef ENABLE_DNOTIFY #include "gam_dnotify.h" #endif @@ -85,6 +88,9 @@ gam_show_debug(void) { #ifdef ENABLE_INOTIFY gam_inotify_debug (); #endif +#ifdef ENABLE_INOTIFY_LEGACY + gam_inotify_legacy_debug (); +#endif #ifdef ENABLE_DNOTIFY gam_dnotify_debug (); #endif @@ -110,6 +116,12 @@ gam_init_subscriptions(void) return(TRUE); } #endif +#ifdef ENABLE_INOTIFY_LEGACY + if (gam_inotify_legacy_init()) { + GAM_DEBUG(DEBUG_INFO, "Using INotify Legacy as backend\n"); + return(TRUE); + } +#endif #ifdef ENABLE_DNOTIFY if (gam_dnotify_init()) { GAM_DEBUG(DEBUG_INFO, "Using DNotify as backend\n"); diff -urpN gamin-0.1.2/server/local_inotify_legacy.h gamin-0.1.2.az/server/local_inotify_legacy.h --- gamin-0.1.2/server/local_inotify_legacy.h 1970-01-01 02:00:00.000000000 +0200 +++ gamin-0.1.2.az/server/local_inotify_legacy.h 2005-07-16 08:42:16.000000000 +0200 @@ -0,0 +1,124 @@ +/* + * Inode based directory notification for Linux + * + * Copyright (C) 2005 John McCutchan + */ + +#ifndef _LINUX_INOTIFY_LEGACY_H +#define _LINUX_INOTIFY_LEGACY_H + +#include <linux/types.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 { + __s32 wd; /* watch descriptor */ + __u32 mask; /* watch mask */ + __u32 cookie; /* cookie to synchronize two events */ + __u32 len; /* length (including nulls) of name */ + char name[0]; /* stub for possible name */ +}; + +/* + * struct inotify_watch_request - represents a watch request + * + * Pass to the inotify device via the INOTIFY_WATCH ioctl + */ +struct inotify_watch_request { + int fd; /* fd of filename to watch */ + __u32 mask; /* event mask */ +}; + +/* 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 */ + +/* 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_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) + +#define INOTIFY_IOCTL_MAGIC 'Q' +#define INOTIFY_IOCTL_MAXNR 2 + +#define INOTIFY_WATCH _IOR(INOTIFY_IOCTL_MAGIC, 1, struct inotify_watch_request) +#define INOTIFY_IGNORE _IOR(INOTIFY_IOCTL_MAGIC, 2, int) + +#ifdef __KERNEL__ + +#include <linux/dcache.h> +#include <linux/fs.h> +#include <linux/config.h> + +#ifdef CONFIG_INOTIFY + +extern void inotify_inode_queue_event(struct inode *, __u32, __u32, + const char *); +extern void inotify_dentry_parent_queue_event(struct dentry *, __u32, __u32, + const char *); +extern void inotify_unmount_inodes(struct list_head *); +extern void inotify_inode_is_dead(struct inode *); +extern u32 inotify_get_cookie(void); + +#else + +static inline void inotify_inode_queue_event(struct inode *inode, + __u32 mask, __u32 cookie, + const char *filename) +{ +} + +static inline void inotify_dentry_parent_queue_event(struct dentry *dentry, + __u32 mask, __u32 cookie, + const char *filename) +{ +} + +static inline void inotify_unmount_inodes(struct list_head *list) +{ +} + +static inline void inotify_inode_is_dead(struct inode *inode) +{ +} + +static inline u32 inotify_get_cookie(void) +{ + return 0; +} + +#endif /* CONFIG_INOTIFY */ + +#endif /* __KERNEL __ */ + +#endif /* _LINUX_INOTIFY_LEGACY_H */
Attachment:
signature.asc
Description: This is a digitally signed message part