Index: Makefile.in
--- Makefile.in.orig	2008-11-24 16:25:07.000000000 +0100
+++ Makefile.in	2012-07-25 13:58:16.000000000 +0200
@@ -309,7 +309,7 @@
 	-rm -f libtool
 install-pkgconfigDATA: $(pkgconfig_DATA)
 	@$(NORMAL_INSTALL)
-	test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
+	test -d "$(DESTDIR)$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
 	@list='$(pkgconfig_DATA)'; for p in $$list; do \
 	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
 	  f=$(am__strip_dir) \
Index: libgamin/Makefile.in
--- libgamin/Makefile.in.orig	2008-11-24 16:25:07.000000000 +0100
+++ libgamin/Makefile.in	2012-07-25 14:05:11.000000000 +0200
@@ -239,7 +239,7 @@
 	gamin_sym.version
 
 lib_LTLIBRARIES = libgamin-1.la libfam.la
-gaminincludedir = $(includedir)/
+gaminincludedir = $(includedir)
 gamininclude_HEADERS = \
 	fam.h
 
@@ -302,7 +302,7 @@
 	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
 install-libLTLIBRARIES: $(lib_LTLIBRARIES)
 	@$(NORMAL_INSTALL)
-	test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+	test -d "$(DESTDIR)$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
 	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
 	  if test -f $$p; then \
 	    f=$(am__strip_dir) \
@@ -383,7 +383,7 @@
 	-rm -rf .libs _libs
 install-gaminincludeHEADERS: $(gamininclude_HEADERS)
 	@$(NORMAL_INSTALL)
-	test -z "$(gaminincludedir)" || $(MKDIR_P) "$(DESTDIR)$(gaminincludedir)"
+	test -d "$(DESTDIR)$(gaminincludedir)" || $(MKDIR_P) "$(DESTDIR)$(gaminincludedir)"
 	@list='$(gamininclude_HEADERS)'; for p in $$list; do \
 	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
 	  f=$(am__strip_dir) \
@@ -477,7 +477,7 @@
 all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
 installdirs:
 	for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(gaminincludedir)"; do \
-	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	  test -d "$$dir" || $(MKDIR_P) "$$dir"; \
 	done
 install: install-am
 install-exec: install-exec-am
Index: libgamin/gam_api.c
--- libgamin/gam_api.c.orig	2007-08-27 12:21:03.000000000 +0200
+++ libgamin/gam_api.c	2012-07-25 13:58:16.000000000 +0200
@@ -14,6 +14,7 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <sys/uio.h>
+#include <string.h>
 #include "fam.h"
 #include "gam_protocol.h"
 #include "gam_data.h"
@@ -428,10 +429,10 @@
 {
     char data[2] = { 0, 0 };
     int written;
-#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
-    struct {
+#if defined(HAVE_CMSGCRED) && (!defined(LOCAL_CREDS) || defined(__FreeBSD__))
+    union {
 	    struct cmsghdr hdr;
-	    struct cmsgcred cred;
+	    char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
     } cmsg;
     struct iovec iov;
     struct msghdr msg;
@@ -443,16 +444,16 @@
     msg.msg_iov = &iov;
     msg.msg_iovlen = 1;
 
-    msg.msg_control = &cmsg;
-    msg.msg_controllen = sizeof (cmsg);
+    msg.msg_control = (caddr_t) &cmsg;
+    msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
     memset (&cmsg, 0, sizeof (cmsg));
-    cmsg.hdr.cmsg_len = sizeof (cmsg);
+    cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
     cmsg.hdr.cmsg_level = SOL_SOCKET;
     cmsg.hdr.cmsg_type = SCM_CREDS;
 #endif
 
 retry:
-#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
+#if defined(HAVE_CMSGCRED) && (!defined(LOCAL_CREDS) || defined(__FreeBSD__))
     written = sendmsg(fd, &msg, 0);
 #else
     written = write(fd, &data[0], 1);
@@ -654,15 +655,16 @@
     gid_t c_gid;
 
 #ifdef HAVE_CMSGCRED
-    struct {
+    struct cmsgcred *cred;
+    union {
 	    struct cmsghdr hdr;
-	    struct cmsgcred cred;
+	    char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
     } cmsg;
 #endif
 
     s_uid = getuid();
 
-#if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
+#if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED) && !defined(__FreeBSD__)
     /* Set the socket to receive credentials on the next message */
     {
         int on = 1;
@@ -683,8 +685,8 @@
 
 #ifdef HAVE_CMSGCRED
     memset(&cmsg, 0, sizeof(cmsg));
-    msg.msg_control = &cmsg;
-    msg.msg_controllen = sizeof(cmsg);
+    msg.msg_control = (caddr_t) &cmsg;
+    msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
 #endif
 
 retry:
@@ -701,7 +703,7 @@
         goto failed;
     }
 #ifdef HAVE_CMSGCRED
-    if (cmsg.hdr.cmsg_len < sizeof(cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS) {
+    if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred)) || cmsg.hdr.cmsg_type != SCM_CREDS) {
         GAM_DEBUG(DEBUG_INFO,
                   "Message from recvmsg() was not SCM_CREDS\n");
         goto failed;
@@ -727,9 +729,10 @@
             goto failed;
         }
 #elif defined(HAVE_CMSGCRED)
-        c_pid = cmsg.cred.cmcred_pid;
-        c_uid = cmsg.cred.cmcred_euid;
-        c_gid = cmsg.cred.cmcred_groups[0];
+        cred = (struct cmsgcred *) CMSG_DATA (&cmsg);
+        c_pid = cred->cmcred_pid;
+        c_uid = cred->cmcred_euid;
+        c_gid = cred->cmcred_groups[0];
 #else /* !SO_PEERCRED && !HAVE_CMSGCRED */
         GAM_DEBUG(DEBUG_INFO,
                   "Socket credentials not supported on this OS\n");
@@ -1288,14 +1291,17 @@
 
     // FIXME: drop and reacquire lock while blocked?
     gamin_data_lock(conn);
-    if (!gamin_data_event_ready(conn)) {
+    while ((ret = gamin_data_event_ready(conn)) == 0) {
         if (gamin_read_data(conn, fc->fd, 1) < 0) {
 	    gamin_try_reconnect(conn, fc->fd);
 	    FAMErrno = FAM_CONNECT;
 	    return (-1);
 	}
     }
-    ret = gamin_data_read_event(conn, fe);
+
+    if (ret > 0)
+        ret = gamin_data_read_event(conn, fe);
+
     gamin_data_unlock(conn);
 
     if (ret < 0) {
Index: python/Makefile.in
--- python/Makefile.in.orig	2008-11-24 16:25:07.000000000 +0100
+++ python/Makefile.in	2012-07-25 13:58:16.000000000 +0200
@@ -53,7 +53,7 @@
 am__installdirs = "$(DESTDIR)$(pythondir)" "$(DESTDIR)$(pythondir)"
 pythonLTLIBRARIES_INSTALL = $(INSTALL)
 LTLIBRARIES = $(python_LTLIBRARIES)
-_gamin_la_DEPENDENCIES = $(top_builddir)/libgamin/libgamin-1.la
+_gamin_la_DEPENDENCIES = -lgamin-1
 am__gamin_la_OBJECTS = gamin.lo
 _gamin_la_OBJECTS = $(am__gamin_la_OBJECTS)
 _gamin_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -228,7 +228,7 @@
 
 python_LTLIBRARIES = _gamin.la
 _gamin_la_SOURCES = gamin.c
-_gamin_la_LIBADD = $(top_builddir)/libgamin/libgamin-1.la
+_gamin_la_LIBADD = -lgamin-1
 _gamin_la_LDFLAGS = -module -avoid-version
 python_PYTHON = gamin.py
 all: all-recursive
Index: server/gam_channel.c
--- server/gam_channel.c.orig	2007-07-04 15:36:49.000000000 +0200
+++ server/gam_channel.c	2012-07-25 13:58:16.000000000 +0200
@@ -7,6 +7,7 @@
 #include <sys/stat.h>
 #include <sys/un.h>
 #include <sys/uio.h>
+#include <string.h>
 #include "gam_error.h"
 #include "gam_connection.h"
 #include "gam_channel.h"
@@ -30,10 +31,10 @@
 {
     char data[2] = { 0, 0 };
     int written;
-#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
-    struct {
+#if defined(HAVE_CMSGCRED) && (!defined(LOCAL_CREDS) || defined(__FreeBSD__))
+    union {
 	    struct cmsghdr hdr;
-	    struct cmsgcred cred;
+	    char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
     } cmsg;
     struct iovec iov;
     struct msghdr msg;
@@ -45,16 +46,16 @@
     msg.msg_iov = &iov;
     msg.msg_iovlen = 1;
 
-    msg.msg_control = &cmsg;
-    msg.msg_controllen = sizeof (cmsg);
+    msg.msg_control = (caddr_t) &cmsg;
+    msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
     memset (&cmsg, 0, sizeof (cmsg));
-    cmsg.hdr.cmsg_len = sizeof (cmsg);
+    cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
     cmsg.hdr.cmsg_level = SOL_SOCKET;
     cmsg.hdr.cmsg_type = SCM_CREDS;
 #endif
 
 retry:
-#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
+#if defined(HAVE_CMSGCRED) && (!defined(LOCAL_CREDS) || defined(__FreeBSD__))
     written = sendmsg(fd, &msg, 0);
 #else
     written = write(fd, &data[0], 1);
@@ -95,15 +96,16 @@
     gid_t c_gid;
 
 #ifdef HAVE_CMSGCRED
-    struct {
+    struct cmsgcred *cred;
+    union {
 	    struct cmsghdr hdr;
-	    struct cmsgcred cred;
+	    char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
     } cmsg;
 #endif
 
     s_uid = getuid();
 
-#if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
+#if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED) && !defined(__FreeBSD__)
     /* Set the socket to receive credentials on the next message */
     {
         int on = 1;
@@ -124,8 +126,8 @@
 
 #ifdef HAVE_CMSGCRED
     memset(&cmsg, 0, sizeof(cmsg));
-    msg.msg_control = &cmsg;
-    msg.msg_controllen = sizeof(cmsg);
+    msg.msg_control = (caddr_t) &cmsg;
+    msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
 #endif
 
   retry:
@@ -142,7 +144,7 @@
         goto failed;
     }
 #ifdef HAVE_CMSGCRED
-    if (cmsg.hdr.cmsg_len < sizeof(cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS) {
+    if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred)) || cmsg.hdr.cmsg_type != SCM_CREDS) {
         GAM_DEBUG(DEBUG_INFO,
                   "Message from recvmsg() was not SCM_CREDS\n");
         goto failed;
@@ -168,9 +170,10 @@
             goto failed;
         }
 #elif defined(HAVE_CMSGCRED)
-	c_pid = cmsg.cred.cmcred_pid;
-	c_uid = cmsg.cred.cmcred_euid;
-	c_gid = cmsg.cred.cmcred_groups[0];
+	cred = (struct cmsgcred *) CMSG_DATA (&cmsg);
+	c_pid = cred->cmcred_pid;
+	c_uid = cred->cmcred_euid;
+	c_gid = cred->cmcred_groups[0];
 #else /* !SO_PEERCRED && !HAVE_CMSGCRED */
         GAM_DEBUG(DEBUG_INFO,
                   "Socket credentials not supported on this OS\n");
@@ -620,6 +623,7 @@
 {
     int fd;
     struct sockaddr_un addr;
+    struct stat st;
 
     fd = socket(PF_UNIX, SOCK_STREAM, 0);
     if (fd < 0) {
@@ -640,9 +644,19 @@
      * some extra protection checks. Also make sure the socket is created
      * with restricted mode
      */
-    if (!gam_check_secure_path(path)) {
+    if (!gam_check_secure_dir()) {
+	close(fd);
 	return (-1);
     }
+
+    if (stat(path, &st) == 0) {
+        /* bind() will fail if the socket already exists */
+        if (unlink(path) < 0) {
+            GAM_DEBUG(DEBUG_INFO, "Failed to remove %s\n", path);
+            close(fd);
+            return (-1);
+        }
+    }
     strncpy(&addr.sun_path[0], path, (sizeof(addr) - 4) - 1);
     umask(0077);
 #endif
Index: server/gam_fs.c
--- server/gam_fs.c.orig	2008-11-12 21:45:28.000000000 +0100
+++ server/gam_fs.c	2012-07-25 13:58:16.000000000 +0200
@@ -7,6 +7,11 @@
 #include <string.h>
 #include <errno.h>
 #include <glib.h>
+#ifdef __FreeBSD__
+#include <sys/param.h>
+#include <sys/ucred.h>
+#include <sys/mount.h>
+#endif
 #include "gam_error.h"
 #include "gam_fs.h"
 
@@ -21,9 +26,13 @@
 typedef struct _gam_fs {
 	char *path;
 	char *fsname;
+	guint64 flags;
 } gam_fs;
 
 static gboolean initialized = FALSE;
+#ifdef __FreeBSD__
+static gboolean initializing = FALSE;
+#endif
 static GList *filesystems = NULL;
 static GList *fs_props = NULL;
 static struct stat mtab_sbuf;
@@ -110,6 +119,7 @@
 	return strlen(fsb->path) - strlen (fsa->path);
 }
 
+#ifdef __linux__
 static void
 gam_fs_scan_mtab (void)
 {
@@ -165,10 +175,41 @@
 	gam_fs_free_filesystems ();
 	filesystems = g_list_sort (new_filesystems, gam_fs_filesystem_sort_cb);
 }
+#endif
+
+#ifdef __FreeBSD__
+static void
+gam_fs_getmntinfo (void)
+{
+	struct statfs *stat;
+	GList *new_filesystems = NULL;
+	gam_fs *fs = NULL;
+        int i, n;
+
+	n = getmntinfo(&stat, MNT_NOWAIT);
+	if (n == -1)
+		return;
+
+	for (i = 0; i < n; i++)
+	{
+		fs = g_new0 (gam_fs, 1);
+		fs->path = g_strdup (stat[i].f_mntonname);
+		fs->fsname = g_strdup (stat[i].f_fstypename);
+		fs->flags = stat[i].f_flags;
+
+		new_filesystems = g_list_prepend (new_filesystems, fs);
+	}
+
+        /* Replace the old file systems list with the new one */
+        gam_fs_free_filesystems ();
+        filesystems = g_list_sort (new_filesystems, gam_fs_filesystem_sort_cb);
+}
+#endif
 
 void
 gam_fs_init (void)
 {
+#if defined(__linux__)
 	if (initialized == FALSE)
 	{
 		initialized = TRUE;
@@ -181,6 +222,7 @@
 		if (stat("/etc/mtab", &mtab_sbuf) != 0)
 		{
 			GAM_DEBUG(DEBUG_INFO, "Could not stat /etc/mtab\n");
+                        return;
 		}
 		gam_fs_scan_mtab ();
 	} else {
@@ -189,6 +231,7 @@
 		if (stat("/etc/mtab", &sbuf) != 0)
 		{
 			GAM_DEBUG(DEBUG_INFO, "Could not stat /etc/mtab\n");
+                        return;
 		}
 
 		/* /etc/mtab has changed */
@@ -199,6 +242,54 @@
 
 		mtab_sbuf = sbuf;
 	}
+#elif defined(__FreeBSD__)
+	if (initialized == FALSE && initializing == FALSE)
+	{
+		GList *iterator = NULL;
+		GHashTable *fs_hash = NULL;
+		gam_fs *fs = NULL;
+
+		initialized = TRUE;
+		initializing = TRUE;
+
+		gam_fs_getmntinfo ();
+
+		iterator = filesystems;
+		fs_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+		while (iterator) {
+			fs = iterator->data;
+
+			if (!g_hash_table_lookup (fs_hash, fs->fsname)) {
+				if (fs->flags & MNT_LOCAL)
+					gam_fs_set (fs->fsname, GFS_MT_DEFAULT, 0);
+				else
+					gam_fs_set (fs->fsname, GFS_MT_POLL, 5);
+
+				g_hash_table_insert (fs_hash, g_strdup (fs->fsname), GINT_TO_POINTER (1));
+			}
+
+			iterator = g_list_next (iterator);
+		}
+
+		g_hash_table_destroy (fs_hash);
+		initializing = FALSE;
+	} else if (initializing == FALSE) {
+		struct stat sbuf;
+
+		if (stat ("/etc/fstab", &sbuf) != 0) {
+			GAM_DEBUG(DEBUG_INFO, "Could not stat /etc/fstab\n");
+			return;
+		}
+
+		if (sbuf.st_mtime != mtab_sbuf.st_mtime) {
+			GAM_DEBUG(DEBUG_INFO, "Updating list of mounted filesystems\n");
+			gam_fs_getmntinfo ();
+		}
+
+		mtab_sbuf = sbuf;
+	}
+#endif
 }
 
 gam_fs_mon_type
@@ -210,7 +301,11 @@
 	props = gam_fs_find_fs_props (path);
 
 	if (!props)
+#ifdef USE_GAMIN_POLLER
+		return GFS_MT_POLL;
+#else
 		return GFS_MT_DEFAULT;
+#endif
 
 	return props->mon_type;
 }
Index: server/gam_kqueue.c
--- server/gam_kqueue.c.orig	2007-07-04 15:50:41.000000000 +0200
+++ server/gam_kqueue.c	2012-07-25 13:58:16.000000000 +0200
@@ -5,7 +5,8 @@
  *
  *     * http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=0650&db=bks&fname=/SGI_Developer/books/IIDsktp_IG/sgi_html/ch08.html
  *       states that FAM does not follow monitored symbolic links: we
- *       do the same (note that regarding
+ *       do NOT do the same to preserve compatibility with SGI FAM (note
+ *       that regarding
  *       http://oss.sgi.com/bugzilla/show_bug.cgi?id=405, we do what
  *       FAM should do: we do not call g_dir_open() if the file is a
  *       symbolic link).
@@ -28,10 +29,9 @@
  *           - kqueue needs to be augmented with a filename-based
  *             monitoring facility;
  *
- *           - kqueue needs to be moved out the UFS code.
- *
  * Copyright (C) 2005 Joe Marcus Clarke <marcus@FreeBSD.org>
- * Copyright (C) 2005 Jean-Yves Lefort <jylefort@FreeBSD.org>
+ * Copyright (C) 2005, 2006 Jean-Yves Lefort <jylefort@FreeBSD.org>
+ * Copyright (C) 2006 Alex Dupre <ale@FreeBSD.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -53,6 +53,9 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/param.h>
+#ifndef USE_GAMIN_POLLER
+#include <sys/mount.h>
+#endif
 #include <sys/types.h>
 #include <sys/sysctl.h>
 #include <sys/stat.h>
@@ -62,6 +65,7 @@
 #include "gam_error.h"
 #include "gam_kqueue.h"
 #include "gam_event.h"
+#include "gam_excludes.h"
 #include "gam_server.h"
 #include "gam_poll_basic.h"
 
@@ -130,7 +134,7 @@
   HashTableRemoveFunc		remove;
   HashTablePostRemoveFunc	post_remove;
 } HashTableMethods;
-  
+
 /*
  * A hash table which can be modified while iterating over it.
  */
@@ -281,8 +285,8 @@
 gam_kqueue_mini_lstat (const char *pathname, MiniStat *mini_sb)
 {
   struct stat sb;
-  
-  if (lstat(pathname, &sb) < 0)
+
+  if (stat(pathname, &sb) < 0)
     memset(mini_sb, 0, sizeof(*mini_sb));
   else
     {
@@ -319,14 +323,14 @@
   else
     {
       struct stat sb;
-      return lstat(pathname, &sb) >= 0 && (sb.st_mode & S_IFDIR) != 0;
+      return stat(pathname, &sb) >= 0 && (sb.st_mode & S_IFDIR) != 0;
     }
 }
 
 static gboolean
 gam_kqueue_get_uint_sysctl (const char *name, unsigned int *value)
 {
-  unsigned int value_len = sizeof(*value);
+  size_t value_len = sizeof(*value);
 
   if (sysctlbyname(name, value, &value_len, (void *)NULL, 0) < 0)
     {
@@ -406,7 +410,7 @@
   table->iterating = TRUE;
   g_hash_table_foreach(table->main, func, user_data);
   table->iterating = FALSE;
-  
+
   if (table->pending_additions)
     {
       GSList *l;
@@ -509,33 +513,52 @@
 gam_kqueue_monitor_enable_kqueue (Monitor *mon)
 {
   struct kevent ev[1];
+#ifndef USE_GAMIN_POLLER
+  struct statfs sb;
+#endif
 
   if (open_files == max_open_files)
     {
       GAM_DEBUG(DEBUG_INFO, "cannot open %s (max_open_files limit reached), falling back to poll\n", mon->pathname);
       return FALSE;
     }
-  
-  mon->fd = open(mon->pathname, O_RDONLY | O_NOFOLLOW);
+
+  if (gam_exclude_check(mon->pathname))
+    {
+      GAM_DEBUG(DEBUG_INFO, "not using kqueue for %s since it is excluded, falling back to poll\n", mon->pathname);
+      return FALSE;
+    }
+
+  mon->fd = open(mon->pathname, O_RDONLY | O_NONBLOCK | O_NOFOLLOW);
   if (mon->fd < 0)
     {
       GAM_DEBUG(DEBUG_INFO, "cannot open %s (%s), falling back to poll\n", mon->pathname, g_strerror(errno));
       return FALSE;
     }
 
+#ifndef USE_GAMIN_POLLER
+  if (fstatfs(mon->fd, &sb) == 0 && (sb.f_flags & MNT_LOCAL) == 0)
+    {
+      GAM_DEBUG(DEBUG_INFO, "%s resides on a remote file system, falling back to poll\n", mon->pathname);
+      goto poll;
+    }
+#endif
+
   EV_SET(ev, mon->fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, VN_NOTE_ALL, 0, mon);
   if (kevent(kq, ev, G_N_ELEMENTS(ev), NULL, 0, NULL) < 0)
     {
       GAM_DEBUG(DEBUG_INFO, "cannot enable kqueue notification for %s (%s), falling back to poll\n", mon->pathname, g_strerror(errno));
-
-      close(mon->fd);
-      mon->fd = -1;
-
-      return FALSE;
+      goto poll;
     }
 
   open_files++;
   return TRUE;
+
+ poll:
+  close(mon->fd);
+  mon->fd = -1;
+
+  return FALSE;
 }
 
 static void
@@ -612,7 +635,7 @@
   gam_kqueue_poller_remove_sub_monitor(&missing_smon_poller, smon);
   gam_kqueue_poller_remove_sub_monitor(&unsupported_smon_poller, smon);
   /* unsupported_dirs_poller is handled by _clear_fmons() below */
-  
+
   gam_kqueue_sub_monitor_clear_fmons(smon);
   gam_kqueue_monitor_free(MONITOR(smon));
 }
@@ -700,7 +723,7 @@
     {
       struct stat sb;
 
-      exists = lstat(mon->pathname, &sb) >= 0;
+      exists = stat(mon->pathname, &sb) >= 0;
       flags |= (exists && (sb.st_mode & S_IFDIR) != 0) ? MONITOR_ISDIR : MONITOR_ISNOTDIR;
     }
 
@@ -715,21 +738,21 @@
 	{
 	  GDir *dir;
 	  GError *err = NULL;
-	  
+
 	  dir = g_dir_open(mon->pathname, 0, &err);
 	  if (dir)
 	    {
 	      const char *filename;
-	      
+
 	      while ((filename = g_dir_read_name(dir)))
 		{
 		  FileMonitor *fmon;
 		  FileMonitorFlags fmon_flags;
-		  
+
 		  fmon = gam_kqueue_file_monitor_new(smon, filename, &fmon_flags);
 		  gam_kqueue_file_monitor_emit_event(fmon, gevent, fmon_flags);
 		}
-	      
+
 	      g_dir_close(dir);
 	    }
 	  else
@@ -749,7 +772,7 @@
 
       return;
     }
-    
+
   /* then we enable kqueue notification, falling back to poll if necessary */
 
   if (! gam_kqueue_monitor_enable_kqueue(mon))
@@ -774,7 +797,7 @@
 
   filenames = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
 
-  if (isdir)			/* do not follow symbolic links */
+  if (isdir)
     {
       GDir *dir;
       GError *err = NULL;
@@ -783,7 +806,7 @@
       if (dir)
 	{
 	  const char *filename;
-	  
+
 	  while ((filename = g_dir_read_name(dir)))
 	    {
 	      g_hash_table_insert(filenames, g_strdup(filename), GINT_TO_POINTER(TRUE));
@@ -793,12 +816,12 @@
 		{
 		  FileMonitor *fmon;
 		  FileMonitorFlags fmon_flags;
-		  
+
 		  fmon = gam_kqueue_file_monitor_new(smon, filename, &fmon_flags);
 		  gam_kqueue_file_monitor_emit_event(fmon, GAMIN_EVENT_CREATED, fmon_flags);
 		}
 	    }
-	  
+
 	  g_dir_close(dir);
 	}
       else
@@ -840,6 +863,8 @@
     case GAMIN_EVENT_MOVED:
       gam_kqueue_sub_monitor_set_missing(smon);
       break;
+    default:
+      break;
     }
 
   gam_server_emit_event(mon->pathname, isdir, event, smon->subs, 1);
@@ -931,11 +956,11 @@
   gboolean isdir;
   gboolean stat_done;
   gboolean stat_succeeded;
-  
+
   if ((flags & MONITOR_ISDIR) == 0 && (flags & MONITOR_ISNOTDIR) == 0)
     {
       stat_done = TRUE;
-      stat_succeeded = lstat(mon->pathname, &sb) >= 0;
+      stat_succeeded = stat(mon->pathname, &sb) >= 0;
       isdir = stat_succeeded && (sb.st_mode & S_IFDIR) != 0;
     }
   else
@@ -943,7 +968,7 @@
       stat_done = FALSE;
       isdir = (flags & MONITOR_ISDIR) != 0;
     }
-  
+
   gam_server_emit_event(mon->pathname, isdir, event, fmon->smon->subs, 1);
 
   switch (event)
@@ -962,7 +987,7 @@
 	    {
 	      FileMonitor *new_fmon;
 	      FileMonitorFlags new_fmon_flags;
-	      
+
 	      /*
 	       * The file exists again. It means that kqueue has
 	       * aggregated a removal+creation into a single event. We
@@ -978,9 +1003,11 @@
 	      break;		/* do not remove the fmon we've just created */
 	    }
 	}
-	
+
       gam_kqueue_hash_table_remove(fmon->smon->fmons, fmon);
       break;
+    default:
+      break;
     }
 }
 
@@ -1033,7 +1060,7 @@
 
   for (i = 0; i < nevents; i++)
     MONITOR(ev[i].udata)->handle_kevent(MONITOR(ev[i].udata), &ev[i]);
-  
+
   return TRUE;			/* keep source */
 }
 
@@ -1042,7 +1069,7 @@
 {
   struct stat sb;
 
-  if (lstat(MONITOR(smon)->pathname, &sb) >= 0)
+  if (stat(MONITOR(smon)->pathname, &sb) >= 0)
     {
       gam_kqueue_poller_remove_sub_monitor(&missing_smon_poller, smon);
       gam_kqueue_sub_monitor_enable_notification(smon, SUB_MONITOR_WAS_MISSING | ((sb.st_mode & S_IFDIR) != 0 ? MONITOR_ISDIR : MONITOR_ISNOTDIR));
@@ -1062,16 +1089,16 @@
       if (gam_kqueue_monitor_enable_kqueue(mon))
 	gam_kqueue_poller_remove_sub_monitor(&missing_smon_poller, smon);
     }
-  
+
   gam_kqueue_mini_lstat(mon->pathname, &sb);
-  
+
   if (! sb.exists && mon->sb.exists)
     event = GAMIN_EVENT_DELETED;
   else if (gam_kqueue_differs(&sb, &mon->sb))
     event = GAMIN_EVENT_CHANGED;
   else
     return;
-	
+
   memcpy(&mon->sb, &sb, sizeof(sb));
   gam_kqueue_sub_monitor_emit_event(smon, event, (sb.mode & S_IFDIR) != 0 ? MONITOR_ISDIR : MONITOR_ISNOTDIR);
 }
@@ -1167,7 +1194,10 @@
   channel = g_io_channel_unix_new(kq);
   g_io_add_watch(channel, G_IO_IN, gam_kqueue_kevent_cb, NULL);
 
-  
+#ifdef USE_GAMIN_POLLER
+  gam_poll_basic_init ();
+#endif
+
   gam_server_install_kernel_hooks(GAMIN_K_KQUEUE,
   				  gam_kqueue_add_subscription,
 				  gam_kqueue_remove_subscription,
@@ -1200,7 +1230,7 @@
       smon->subs = g_list_append(smon->subs, sub);
       return TRUE;
     }
-  
+
   smon = gam_kqueue_sub_monitor_new(sub);
   smon->subs = g_list_append(smon->subs, sub);
 
@@ -1260,6 +1290,6 @@
       success = FALSE;
 
   g_list_free(subs);
-  
+
   return success;
 }
Index: server/gam_node.c
--- server/gam_node.c.orig	2007-07-04 15:36:49.000000000 +0200
+++ server/gam_node.c	2012-07-25 13:58:16.000000000 +0200
@@ -23,6 +23,7 @@
 #include "gam_event.h"
 #include "gam_node.h"
 #include "gam_error.h"
+#include "gam_server.h"
 
 /**
  * Create a new node
@@ -122,7 +123,7 @@
  * it has finished with the string.  If it must keep it longer, it
  * should makes its own copy.  The returned string must not be freed.
  */
-G_CONST_RETURN char *
+const char *
 gam_node_get_path(GamNode * node)
 {
     g_assert(node);
Index: server/gam_node.h
--- server/gam_node.h.orig	2007-07-04 15:36:49.000000000 +0200
+++ server/gam_node.h	2012-07-25 13:58:16.000000000 +0200
@@ -58,7 +58,7 @@
 void                  gam_node_set_is_dir          (GamNode         *node,
 						   gboolean        is_dir);
 	
-G_CONST_RETURN char  *gam_node_get_path            (GamNode         *node);
+const          char  *gam_node_get_path            (GamNode         *node);
 
 GList                *gam_node_get_subscriptions   (GamNode         *node);
 
Index: server/gam_poll_basic.c
--- server/gam_poll_basic.c.orig	2007-07-04 15:46:29.000000000 +0200
+++ server/gam_poll_basic.c	2012-07-25 13:58:16.000000000 +0200
@@ -345,7 +345,7 @@
 #ifdef ST_MTIM_NSEC
 		GAM_DEBUG(DEBUG_INFO, "%d %d : %d %d\n", node->sbuf.st_mtim.tv_sec, node->sbuf.st_mtim.tv_nsec, sbuf.st_mtim.tv_sec, sbuf.st_mtim.tv_nsec);
 #else
-		GAM_DEBUG(DEBUG_INFO, "%d : %d\n", node->sbuf.st_mtime, sbuf.st_mtim.tv_nsec);
+		GAM_DEBUG(DEBUG_INFO, "%d : %d\n", node->sbuf.st_mtime, sbuf.st_mtime);
 #endif /* ST_MTIM_NSEC */
 #endif /* VERBOSE_POLL */
 	}
Index: server/gam_server.c
--- server/gam_server.c.orig	2007-07-04 15:36:49.000000000 +0200
+++ server/gam_server.c	2012-07-25 13:58:16.000000000 +0200
@@ -32,7 +32,7 @@
 #include "gam_server.h"
 #include "gam_channel.h"
 #include "gam_subscription.h"
-#include "gam_poll_generic.h"
+#include "gam_poll_basic.h"
 #ifdef ENABLE_INOTIFY
 #include "gam_inotify.h"
 #endif
@@ -200,7 +200,8 @@
 			return gam_poll_add_subscription (sub);
 		else
 #endif
-			return gam_kernel_add_subscription (sub);
+			/*return gam_kernel_add_subscription (sub);*/
+			return gam_poll_add_subscription (sub);
 	} else {
 		gam_fs_mon_type type;
 		type = gam_fs_get_mon_type (path);
@@ -243,7 +244,8 @@
 			return gam_poll_remove_subscription (sub);
 		else
 #endif
-			return gam_kernel_remove_subscription(sub);
+			/*return gam_kernel_remove_subscription(sub);*/
+			return gam_poll_remove_subscription (sub);
 	} else {
 		gam_fs_mon_type type;
 		type = gam_fs_get_mon_type (path);
@@ -438,7 +440,7 @@
 GamPollHandler
 gam_server_get_poll_handler (void)
 {
-	return __gam_kernel_handler;
+	return __gam_poll_handler;
 }
 
 gboolean
Index: server/gam_subscription.c
--- server/gam_subscription.c.orig	2007-07-04 15:36:49.000000000 +0200
+++ server/gam_subscription.c	2012-07-25 13:58:16.000000000 +0200
@@ -141,7 +141,7 @@
  * @param sub the GamSubscription
  * @returns The path being monitored.  It should not be freed.
  */
-G_CONST_RETURN char *
+const char *
 gam_subscription_get_path(GamSubscription * sub)
 {
     if (sub == NULL)
Index: server/gam_subscription.h
--- server/gam_subscription.h.orig	2007-07-04 15:36:49.000000000 +0200
+++ server/gam_subscription.h	2012-07-25 13:58:16.000000000 +0200
@@ -21,7 +21,7 @@
 
 int                  gam_subscription_get_reqno    (GamSubscription *sub);
 
-G_CONST_RETURN char *gam_subscription_get_path     (GamSubscription *sub);
+const          char *gam_subscription_get_path     (GamSubscription *sub);
 
 GamListener         *gam_subscription_get_listener (GamSubscription *sub);
 
Index: tests/testing.c
--- tests/testing.c.orig	2007-07-04 15:36:49.000000000 +0200
+++ tests/testing.c	2012-07-25 13:58:16.000000000 +0200
@@ -376,11 +376,11 @@
         }
         printf("chmod %s to %s\n", arg, arg2);
     } else if (!strcmp(command, "chown")) {
+	struct stat sb;
         if (args != 3) {
             fprintf(stderr, "chown line %d: lacks path and owner\n", no);
             return (-1);
         }
-		struct stat sb;
 		if (!lstat (arg, &sb)) {
 			ret = (S_ISLNK (sb.st_mode)) ?
 				lchown(arg, strtol(arg2, NULL, 10), -1) :
@@ -486,9 +486,9 @@
             return (-1);
         }
         /*
-         * wait at most 3 secs before declaring failure
+         * wait at most 7 secs before declaring failure
          */
-        while ((delay < 30) && (testState.nb_events < nb_events + count)) {
+        while ((delay < 70) && (testState.nb_events < nb_events + count)) {
             debugLoop(100);
 
 /*	    printf("+"); fflush(stdout); */
