aboutsummaryrefslogtreecommitdiff
path: root/devel/gamin
diff options
context:
space:
mode:
authorJoe Marcus Clarke <marcus@FreeBSD.org>2005-04-02 09:08:47 +0000
committerJoe Marcus Clarke <marcus@FreeBSD.org>2005-04-02 09:08:47 +0000
commitc87a13d10067ef06b630ae8bdfe8828173cf4dcc (patch)
tree07ec2ea01bf6a1dba2629923750086898b3889a9 /devel/gamin
parent56599c12994ef6cc2be0db32aa8dfc5bf23e5aa8 (diff)
downloadports-c87a13d10067ef06b630ae8bdfe8828173cf4dcc.tar.gz
ports-c87a13d10067ef06b630ae8bdfe8828173cf4dcc.zip
Notes
Diffstat (limited to 'devel/gamin')
-rw-r--r--devel/gamin/Makefile45
-rw-r--r--devel/gamin/distinfo2
-rw-r--r--devel/gamin/files/patch-config.h.in12
-rw-r--r--devel/gamin/files/patch-configure76
-rw-r--r--devel/gamin/files/patch-configure.in31
-rw-r--r--devel/gamin/files/patch-libgamin_gam_api.c98
-rw-r--r--devel/gamin/files/patch-python_Makefile.in32
-rw-r--r--devel/gamin/files/patch-server_Makefile.in47
-rw-r--r--devel/gamin/files/patch-server_gam_channel.c127
-rw-r--r--devel/gamin/files/patch-server_gam_kqueue.c639
-rw-r--r--devel/gamin/files/patch-server_gam_kqueue.h27
-rw-r--r--devel/gamin/files/patch-server_gam_server.c56
-rw-r--r--devel/gamin/pkg-descr5
-rw-r--r--devel/gamin/pkg-plist10
14 files changed, 1207 insertions, 0 deletions
diff --git a/devel/gamin/Makefile b/devel/gamin/Makefile
new file mode 100644
index 000000000000..1bf34abb76b0
--- /dev/null
+++ b/devel/gamin/Makefile
@@ -0,0 +1,45 @@
+# ports collection makefile for: gamin
+# Date created: 24 March 2005
+# Whom: Joe Marcus Clarke <marcus@FreeBSD.org>
+#
+# $FreeBSD$
+#
+
+PORTNAME= gamin
+PORTVERSION= 0.0.26
+PORTREVISION?= 8
+CATEGORIES?= devel
+MASTER_SITES= http://www.gnome.org/~veillard/gamin/sources/
+
+MAINTAINER?= gnome@FreeBSD.org
+COMMENT?= A file and directory monitoring system
+
+USE_GMAKE= yes
+USE_LIBTOOL_VER=15
+USE_GNOME?= gnomehack glib20
+INSTALLS_SHLIB= yes
+CONFIGURE_ARGS?=--disable-gtk-doc --with-html-dir=${PREFIX}/share/doc \
+ --without-python
+CONFIGURE_ENV= CPPFLAGS="-I${LOCALBASE}/include" \
+ LDFLAGS="-L${LOCALBASE}/lib"
+
+CONFLICTS= fam-[0-9]*
+
+.if !defined(GAMIN_SLAVE)
+OPTIONS= KQUEUE "Enable the KQueue backend (UFS only)" on
+.endif
+
+.include <bsd.port.pre.mk>
+
+.if !defined(GAMIN_SLAVE)
+.if defined(WITHOUT_KQUEUE)
+CONFIGURE_ARGS+= --disable-kqueue
+.else
+CONFIGURE_ARGS+= --enable-kqueue
+.endif
+.endif
+
+post-patch:
+ @${FIND} ${WRKSRC} -type f | ${XARGS} ${TOUCH} -f
+
+.include <bsd.port.post.mk>
diff --git a/devel/gamin/distinfo b/devel/gamin/distinfo
new file mode 100644
index 000000000000..498f60829967
--- /dev/null
+++ b/devel/gamin/distinfo
@@ -0,0 +1,2 @@
+MD5 (gamin-0.0.26.tar.gz) = 3d716b6533466f9ca69df13c58009981
+SIZE (gamin-0.0.26.tar.gz) = 484070
diff --git a/devel/gamin/files/patch-config.h.in b/devel/gamin/files/patch-config.h.in
new file mode 100644
index 000000000000..095ee06375ee
--- /dev/null
+++ b/devel/gamin/files/patch-config.h.in
@@ -0,0 +1,12 @@
+--- config.h.in.orig Thu Mar 24 23:41:54 2005
++++ config.h.in Thu Mar 24 23:42:12 2005
+@@ -6,6 +6,9 @@
+ /* Use inotify as backend */
+ #undef ENABLE_INOTIFY
+
++/* Use kqueue as backend */
++#undef ENABLE_KQUEUE
++
+ /* Use polling as backend */
+ #undef ENABLE_POLLING
+
diff --git a/devel/gamin/files/patch-configure b/devel/gamin/files/patch-configure
new file mode 100644
index 000000000000..c26ef854cf2e
--- /dev/null
+++ b/devel/gamin/files/patch-configure
@@ -0,0 +1,76 @@
+--- configure.orig Fri Mar 25 01:48:07 2005
++++ configure Fri Mar 25 02:17:01 2005
+@@ -463,7 +463,7 @@
+ # include <unistd.h>
+ #endif"
+
+-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os GAMIN_MAJOR_VERSION GAMIN_MINOR_VERSION GAMIN_MICRO_VERSION GAMIN_VERSION GAMIN_VERSION_INFO FAM_VERSION_INFO INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CPP CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL RELDATE HTML_DIR ENABLE_GTK_DOC_TRUE ENABLE_GTK_DOC_FALSE PKG_CONFIG DAEMON_CFLAGS DAEMON_LIBS LIBGAMIN_CFLAGS LIBGAMIN_LIBS TEST_CFLAGS TEST_LIBS GAMIN_DEBUG_TRUE GAMIN_DEBUG_FALSE BUILD_DOCS_TRUE BUILD_DOCS_FALSE HAVE_LINUX_TRUE HAVE_LINUX_FALSE ENABLE_DNOTIFY_TRUE ENABLE_DNOTIFY_FALSE ENABLE_INOTIFY_TRUE ENABLE_INOTIFY_FALSE PYTHON WITH_PYTHON_TRUE WITH_PYTHON_FALSE pythondir PYTHON_VERSION PYTHON_SUBDIR PYTHON_INCLUDES PYTHON_PYTHON_SITE_PACKAGES LIBOBJS LTLIBOBJS'
++ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os GAMIN_MAJOR_VERSION GAMIN_MINOR_VERSION GAMIN_MICRO_VERSION GAMIN_VERSION GAMIN_VERSION_INFO FAM_VERSION_INFO INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CPP CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL RELDATE HTML_DIR ENABLE_GTK_DOC_TRUE ENABLE_GTK_DOC_FALSE PKG_CONFIG DAEMON_CFLAGS DAEMON_LIBS LIBGAMIN_CFLAGS LIBGAMIN_LIBS TEST_CFLAGS TEST_LIBS GAMIN_DEBUG_TRUE GAMIN_DEBUG_FALSE BUILD_DOCS_TRUE BUILD_DOCS_FALSE HAVE_LINUX_TRUE HAVE_LINUX_FALSE ENABLE_DNOTIFY_TRUE ENABLE_DNOTIFY_FALSE ENABLE_KQUEUE_TRUE ENABLE_KQUEUE_FALSE ENABLE_INOTIFY_TRUE ENABLE_INOTIFY_FALSE PYTHON WITH_PYTHON_TRUE WITH_PYTHON_FALSE pythondir PYTHON_VERSION PYTHON_SUBDIR PYTHON_INCLUDES PYTHON_SITE_PACKAGES LIBOBJS LTLIBOBJS'
+ ac_subst_files=''
+
+ # Initialize some variables set by options.
+@@ -21926,7 +21926,7 @@
+
+
+ debug_api=no
+-if test "`hostname`" == "paphio" -a "`pwd`" == "/u/veillard/gamin"
++if test "`hostname`" = "paphio" -a "`pwd`" = "/u/veillard/gamin"
+ then
+ debug_api=yes
+ fi
+@@ -22051,6 +22051,37 @@
+ backends="${backends}, dnotify"
+ fi
+
++if test "${enable_kqueue+set}" = set; then
++ enableval="$enable_kqueue"
++ case "${enableval}" in
++ yes) kqueue=true ;;
++ no) kqueue=false ;;
++ *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --disable-kqueue" >&5
++echo "$as_me: error: bad value ${enableval} for --disable-kqueue" >&2;}
++ { (exit 1); exit 1; }; } ;;
++ esac
++else
++ kqueue=true
++fi
++
++if test x$kqueue = xtrue; then
++ ENABLE_KQUEUE_TRUE=
++ ENABLE_KQUEUE_FALSE='#'
++else
++ ENABLE_KQUEUE_TRUE='#'
++ ENABLE_KQUEUE_FALSE=
++fi
++
++
++if test x$kqueue = xtrue; then
++
++cat >>confdefs.h <<\_ACEOF
++#define ENABLE_KQUEUE 1
++_ACEOF
++
++ backends="${backends}, kqueue"
++fi
++
+ if test x$os = xlinux-gnu; then
+ # Check whether --enable-inotify or --disable-inotify was given.
+ if test "${enable_inotify+set}" = set; then
+@@ -23472,6 +23503,8 @@
+ s,@HAVE_LINUX_FALSE@,$HAVE_LINUX_FALSE,;t t
+ s,@ENABLE_DNOTIFY_TRUE@,$ENABLE_DNOTIFY_TRUE,;t t
+ s,@ENABLE_DNOTIFY_FALSE@,$ENABLE_DNOTIFY_FALSE,;t t
++s,@ENABLE_KQUEUE_TRUE@,$ENABLE_KQUEUE_TRUE,;t t
++s,@ENABLE_KQUEUE_FALSE@,$ENABLE_KQUEUE_FALSE,;t t
+ s,@ENABLE_INOTIFY_TRUE@,$ENABLE_INOTIFY_TRUE,;t t
+ s,@ENABLE_INOTIFY_FALSE@,$ENABLE_INOTIFY_FALSE,;t t
+ s,@PYTHON@,$PYTHON,;t t
+@@ -23481,7 +23514,7 @@
+ s,@PYTHON_VERSION@,$PYTHON_VERSION,;t t
+ s,@PYTHON_SUBDIR@,$PYTHON_SUBDIR,;t t
+ s,@PYTHON_INCLUDES@,$PYTHON_INCLUDES,;t t
+-s,@PYTHON_PYTHON_SITE_PACKAGES@,$PYTHON_PYTHON_SITE_PACKAGES,;t t
++s,@PYTHON_SITE_PACKAGES@,$PYTHON_SITE_PACKAGES,;t t
+ s,@LIBOBJS@,$LIBOBJS,;t t
+ s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+ CEOF
diff --git a/devel/gamin/files/patch-configure.in b/devel/gamin/files/patch-configure.in
new file mode 100644
index 000000000000..b1e2cdebc85a
--- /dev/null
+++ b/devel/gamin/files/patch-configure.in
@@ -0,0 +1,31 @@
+--- configure.in.orig Wed Mar 30 15:19:06 2005
++++ configure.in Wed Mar 30 15:38:58 2005
+@@ -230,6 +230,28 @@
+ backends="${backends}, inotify"
+ 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],
++ [case "${enableval}" in
++ yes) kqueue=true ;;
++ no) kqueue=false ;;
++ *) AC_MSG_ERROR(bad value ${enableval} for --disable-kqueue) ;;
++ esac],[kqueue=true])
++ fi
++fi
++
++dnl check if kqueue backend is enabled
++AM_CONDITIONAL(ENABLE_KQUEUE, test x$kqueue = xtrue)
++
++if test x$kqueue = xtrue; then
++ AC_CHECK_HEADERS(sys/event.h)
++ AC_DEFINE(ENABLE_KQUEUE,1,[Use kqueue as backend])
++ backends="${backends}, kqueue"
++fi
++
+ dnl check for flavours of varargs macros (test from GLib)
+ AC_MSG_CHECKING(for ISO C99 varargs macros in C)
+ AC_TRY_COMPILE([],[
diff --git a/devel/gamin/files/patch-libgamin_gam_api.c b/devel/gamin/files/patch-libgamin_gam_api.c
new file mode 100644
index 000000000000..c5cedfce6801
--- /dev/null
+++ b/devel/gamin/files/patch-libgamin_gam_api.c
@@ -0,0 +1,98 @@
+--- libgamin/gam_api.c.orig Thu Mar 24 19:07:08 2005
++++ libgamin/gam_api.c Thu Mar 24 19:26:39 2005
+@@ -181,7 +181,6 @@ gamin_get_socket_dir(void)
+ snprintf(path, MAXPATHLEN, "/tmp/fam-%s", user);
+ path[MAXPATHLEN] = 0;
+ ret = strdup(path);
+- free(user);
+ return (ret);
+ }
+
+@@ -421,9 +420,35 @@ gamin_write_credential_byte(int fd)
+ {
+ char data[2] = { 0, 0 };
+ int written;
++#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
++ struct {
++ struct cmsghdr hdr;
++ struct cmsgcred cred;
++ } cmsg;
++ struct iovec iov;
++ struct msghdr msg;
++
++ iov.iov_base = &data[0];
++ iov.iov_len = 1;
++
++ memset (&msg, 0, sizeof (msg));
++ msg.msg_iov = &iov;
++ msg.msg_iovlen = 1;
++
++ msg.msg_control = &cmsg;
++ msg.msg_controllen = sizeof (cmsg);
++ memset (&cmsg, 0, sizeof (cmsg));
++ cmsg.hdr.cmsg_len = sizeof (cmsg);
++ cmsg.hdr.cmsg_level = SOL_SOCKET;
++ cmsg.hdr.cmsg_type = SCM_CREDS;
++#endif
+
+ retry:
++#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
++ written = sendmsg(fd, &msg, 0);
++#else
+ written = write(fd, &data[0], 1);
++#endif
+ if (written < 0) {
+ if (errno == EINTR)
+ goto retry;
+@@ -616,8 +641,10 @@ gamin_check_cred(GAMDataPtr conn, int fd
+ gid_t c_gid;
+
+ #ifdef HAVE_CMSGCRED
+- char cmsgmem[CMSG_SPACE(sizeof(struct cmsgcred))];
+- struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
++ struct {
++ struct cmsghdr hdr;
++ struct cmsgcred cred;
++ } cmsg;
+ #endif
+
+ s_uid = getuid();
+@@ -642,9 +669,9 @@ gamin_check_cred(GAMDataPtr conn, int fd
+ msg.msg_iovlen = 1;
+
+ #ifdef HAVE_CMSGCRED
+- memset(cmsgmem, 0, sizeof(cmsgmem));
+- msg.msg_control = cmsgmem;
+- msg.msg_controllen = sizeof(cmsgmem);
++ memset(&cmsg, 0, sizeof(cmsg));
++ msg.msg_control = &cmsg;
++ msg.msg_controllen = sizeof(cmsg);
+ #endif
+
+ retry:
+@@ -661,7 +688,7 @@ retry:
+ goto failed;
+ }
+ #ifdef HAVE_CMSGCRED
+- if (cmsg->cmsg_len < sizeof(cmsgmem) || cmsg->cmsg_type != SCM_CREDS) {
++ if (cmsg.hdr.cmsg_len < sizeof(cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS) {
+ GAM_DEBUG(DEBUG_INFO,
+ "Message from recvmsg() was not SCM_CREDS\n");
+ goto failed;
+@@ -687,13 +714,9 @@ retry:
+ goto failed;
+ }
+ #elif defined(HAVE_CMSGCRED)
+- struct cmsgcred *cred;
+-
+- cred = (struct cmsgcred *) CMSG_DATA(cmsg);
+-
+- c_pid = cred->cmcred_pid;
+- c_uid = cred->cmcred_euid;
+- c_gid = cred->cmcred_groups[0];
++ c_pid = cmsg.cred.cmcred_pid;
++ c_uid = cmsg.cred.cmcred_euid;
++ c_gid = cmsg.cred.cmcred_groups[0];
+ #else /* !SO_PEERCRED && !HAVE_CMSGCRED */
+ GAM_DEBUG(DEBUG_INFO,
+ "Socket credentials not supported on this OS\n");
diff --git a/devel/gamin/files/patch-python_Makefile.in b/devel/gamin/files/patch-python_Makefile.in
new file mode 100644
index 000000000000..13580076c7f3
--- /dev/null
+++ b/devel/gamin/files/patch-python_Makefile.in
@@ -0,0 +1,32 @@
+--- python/Makefile.in.orig Thu Mar 24 19:56:18 2005
++++ python/Makefile.in Thu Mar 24 19:58:01 2005
+@@ -59,7 +59,7 @@
+ pythonLTLIBRARIES_INSTALL = $(INSTALL)
+ LTLIBRARIES = $(python_LTLIBRARIES)
+ @WITH_PYTHON_TRUE@am__DEPENDENCIES_1 = \
+-@WITH_PYTHON_TRUE@ $(top_builddir)/libgamin/libgamin-1.la
++@WITH_PYTHON_TRUE@ -lgamin-1
+ @WITH_PYTHON_TRUE@_gamin_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+ am___gamin_la_SOURCES_DIST = gamin.c
+ @WITH_PYTHON_TRUE@am__gamin_la_OBJECTS = gamin.lo
+@@ -162,7 +162,7 @@
+ PKG_CONFIG = @PKG_CONFIG@
+ PYTHON = @PYTHON@
+ PYTHON_INCLUDES = @PYTHON_INCLUDES@
+-PYTHON_PYTHON_SITE_PACKAGES = @PYTHON_PYTHON_SITE_PACKAGES@
++PYTHON_SITE_PACKAGES = @PYTHON_SITE_PACKAGES@
+ PYTHON_SUBDIR = @PYTHON_SUBDIR@
+ PYTHON_VERSION = @PYTHON_VERSION@
+ RANLIB = @RANLIB@
+@@ -233,9 +233,9 @@
+ gamin.c \
+ gamin.py
+
+-_gamin_la_LDFLAGS = -module -avoid-version -L$(top_builddir)/libgamin/.libs
++_gamin_la_LDFLAGS = -module -avoid-version
+ @WITH_PYTHON_TRUE@mylibs = \
+-@WITH_PYTHON_TRUE@ $(top_builddir)/libgamin/libgamin-1.la
++@WITH_PYTHON_TRUE@ -lgamin-1
+
+ @WITH_PYTHON_TRUE@python_LTLIBRARIES = _gamin.la
+ @WITH_PYTHON_TRUE@_gamin_la_SOURCES = gamin.c
diff --git a/devel/gamin/files/patch-server_Makefile.in b/devel/gamin/files/patch-server_Makefile.in
new file mode 100644
index 000000000000..233298647382
--- /dev/null
+++ b/devel/gamin/files/patch-server_Makefile.in
@@ -0,0 +1,47 @@
+--- server/Makefile.in.orig Thu Mar 24 23:04:39 2005
++++ server/Makefile.in Thu Mar 24 23:07:52 2005
+@@ -43,6 +43,7 @@
+ libexec_PROGRAMS = gam_server$(EXEEXT)
+ @ENABLE_INOTIFY_TRUE@am__append_2 = gam_inotify.c gam_inotify.h
+ @ENABLE_DNOTIFY_TRUE@am__append_3 = gam_dnotify.c gam_dnotify.h
++@ENABLE_KQUEUE_TRUE@am__append_4 = gam_kqueue.c gam_kqueue.h
+ subdir = server
+ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+@@ -63,15 +64,16 @@
+ gam_connection.h gam_debugging.h gam_debugging.c \
+ gam_excludes.c gam_excludes.h local_inotify.h \
+ gam_debug_lists.c gam_inotify.c gam_inotify.h gam_dnotify.c \
+- gam_dnotify.h
++ gam_dnotify.h gam_kqueue.c gam_kqueue.h
+ @ENABLE_INOTIFY_TRUE@am__objects_1 = gam_inotify.$(OBJEXT)
+ @ENABLE_DNOTIFY_TRUE@am__objects_2 = gam_dnotify.$(OBJEXT)
++@ENABLE_KQUEUE_TRUE@am__objects_3 = gam_kqueue.$(OBJEXT)
+ am_gam_server_OBJECTS = gam_subscription.$(OBJEXT) \
+ gam_listener.$(OBJEXT) gam_server.$(OBJEXT) gam_node.$(OBJEXT) \
+ gam_tree.$(OBJEXT) gam_poll.$(OBJEXT) gam_channel.$(OBJEXT) \
+ gam_connection.$(OBJEXT) gam_debugging.$(OBJEXT) \
+ gam_excludes.$(OBJEXT) gam_debug_lists.$(OBJEXT) \
+- $(am__objects_1) $(am__objects_2)
++ $(am__objects_1) $(am__objects_2) $(am__objects_3)
+ gam_server_OBJECTS = $(am_gam_server_OBJECTS)
+ am__DEPENDENCIES_1 =
+ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+@@ -236,7 +238,8 @@
+ gam_poll.h gam_channel.c gam_channel.h gam_connection.c \
+ gam_connection.h gam_debugging.h gam_debugging.c \
+ gam_excludes.c gam_excludes.h local_inotify.h \
+- gam_debug_lists.c $(am__append_2) $(am__append_3)
++ gam_debug_lists.c $(am__append_2) $(am__append_3) \
++ $(am__append_4)
+ gam_server_LDFLAGS =
+ gam_server_DEPENDENCIES = $(DEPS)
+ gam_server_LDADD = $(top_builddir)/lib/libgamin_shared.a $(LDADDS) $(LIBGAMIN_LIBS)
+@@ -316,6 +319,7 @@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gam_debug_lists.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gam_debugging.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gam_dnotify.Po@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gam_kqueue.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gam_excludes.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gam_inotify.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gam_listener.Po@am__quote@
diff --git a/devel/gamin/files/patch-server_gam_channel.c b/devel/gamin/files/patch-server_gam_channel.c
new file mode 100644
index 000000000000..7e51df41fd9a
--- /dev/null
+++ b/devel/gamin/files/patch-server_gam_channel.c
@@ -0,0 +1,127 @@
+--- server/gam_channel.c.orig Fri Jan 28 10:54:42 2005
++++ server/gam_channel.c Sat Mar 26 16:15:55 2005
+@@ -24,11 +24,53 @@
+ * to check the server credentials early on.
+ */
+ static gboolean
+-gam_client_conn_send_cred(GIOChannel * source, int fd)
++gam_client_conn_send_cred(int fd)
+ {
+ char data[2] = { 0, 0 };
++ int written;
++#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
++ struct {
++ struct cmsghdr hdr;
++ struct cmsgcred cred;
++ } cmsg;
++ struct iovec iov;
++ struct msghdr msg;
++
++ iov.iov_base = &data[0];
++ iov.iov_len = 1;
++
++ memset (&msg, 0, sizeof (msg));
++ msg.msg_iov = &iov;
++ msg.msg_iovlen = 1;
++
++ msg.msg_control = &cmsg;
++ msg.msg_controllen = sizeof (cmsg);
++ memset (&cmsg, 0, sizeof (cmsg));
++ cmsg.hdr.cmsg_len = sizeof (cmsg);
++ cmsg.hdr.cmsg_level = SOL_SOCKET;
++ cmsg.hdr.cmsg_type = SCM_CREDS;
++#endif
+
+- return(gam_client_conn_write(source, fd, &data[0], 1));
++retry:
++#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
++ written = sendmsg(fd, &msg, 0);
++#else
++ written = write(fd, &data[0], 1);
++#endif
++ if (written < 0) {
++ if (errno == EINTR)
++ goto retry;
++ gam_error(DEBUG_INFO,
++ "Failed to write credential bytes to socket %d\n", fd);
++ return (-1);
++ }
++ if (written != 1) {
++ gam_error(DEBUG_INFO, "Wrote %d credential bytes to socket %d\n",
++ written, fd);
++ return (-1);
++ }
++ GAM_DEBUG(DEBUG_INFO, "Wrote credential bytes to socket %d\n", fd);
++ return (written);
+ }
+
+ /**
+@@ -49,8 +91,10 @@ gam_client_conn_check_cred(GIOChannel *
+ gid_t c_gid;
+
+ #ifdef HAVE_CMSGCRED
+- char cmsgmem[CMSG_SPACE(sizeof(struct cmsgcred))];
+- struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
++ struct {
++ struct cmsghdr hdr;
++ struct cmsgcred cred;
++ } cmsg;
+ #endif
+
+ s_uid = getuid();
+@@ -75,9 +119,9 @@ gam_client_conn_check_cred(GIOChannel *
+ msg.msg_iovlen = 1;
+
+ #ifdef HAVE_CMSGCRED
+- memset(cmsgmem, 0, sizeof(cmsgmem));
+- msg.msg_control = cmsgmem;
+- msg.msg_controllen = sizeof(cmsgmem);
++ memset(&cmsg, 0, sizeof(cmsg));
++ msg.msg_control = &cmsg;
++ msg.msg_controllen = sizeof(cmsg);
+ #endif
+
+ retry:
+@@ -94,7 +138,7 @@ gam_client_conn_check_cred(GIOChannel *
+ goto failed;
+ }
+ #ifdef HAVE_CMSGCRED
+- if (cmsg->cmsg_len < sizeof(cmsgmem) || cmsg->cmsg_type != SCM_CREDS) {
++ if (cmsg.hdr.cmsg_len < sizeof(cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS) {
+ GAM_DEBUG(DEBUG_INFO,
+ "Message from recvmsg() was not SCM_CREDS\n");
+ goto failed;
+@@ -120,13 +164,9 @@ gam_client_conn_check_cred(GIOChannel *
+ goto failed;
+ }
+ #elif defined(HAVE_CMSGCRED)
+- struct cmsgcred *cred;
+-
+- cred = (struct cmsgcred *) CMSG_DATA(cmsg);
+-
+- c_pid = cred->cmcred_pid;
+- c_uid = cred->cmcred_euid;
+- c_gid = cred->cmcred_groups[0];
++ c_pid = cmsg.cred.cmcred_pid;
++ c_uid = cmsg.cred.cmcred_euid;
++ c_gid = cmsg.cred.cmcred_groups[0];
+ #else /* !SO_PEERCRED && !HAVE_CMSGCRED */
+ GAM_DEBUG(DEBUG_INFO,
+ "Socket credentials not supported on this OS\n");
+@@ -149,7 +189,7 @@ gam_client_conn_check_cred(GIOChannel *
+ goto failed;
+ }
+
+- if (!gam_client_conn_send_cred(source, fd)) {
++ if (!gam_client_conn_send_cred(fd)) {
+ GAM_DEBUG(DEBUG_INFO, "Failed to send credential byte to client\n");
+ goto failed;
+ }
+@@ -305,6 +345,7 @@ gam_get_socket_path(const char *session)
+ gam_client_id = g_getenv("GAM_CLIENT_ID");
+ if (gam_client_id == NULL) {
+ GAM_DEBUG(DEBUG_INFO, "Error getting GAM_CLIENT_ID\n");
++ gam_client_id = "";
+ }
+ } else {
+ gam_client_id = session;
diff --git a/devel/gamin/files/patch-server_gam_kqueue.c b/devel/gamin/files/patch-server_gam_kqueue.c
new file mode 100644
index 000000000000..3e5fe770e78d
--- /dev/null
+++ b/devel/gamin/files/patch-server_gam_kqueue.c
@@ -0,0 +1,639 @@
+--- server/gam_kqueue.c.orig Thu Mar 31 20:39:54 2005
++++ server/gam_kqueue.c Fri Apr 1 01:09:11 2005
+@@ -0,0 +1,636 @@
++/*
++ * Copyright (C) 2005 Joe Marcus Clarke <marcus@FreeBSD.org>
++ *
++ * 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 <config.h>
++#include <sys/types.h>
++#include <sys/event.h>
++#include <sys/time.h>
++#include <fcntl.h>
++#include <sys/ioctl.h>
++#include <signal.h>
++#include <unistd.h>
++#include <stdio.h>
++#include <string.h>
++#include <glib.h>
++#include "gam_error.h"
++#include "gam_kqueue.h"
++#include "gam_tree.h"
++#include "gam_event.h"
++#include "gam_server.h"
++#include "gam_event.h"
++
++typedef struct {
++ char *path;
++ int fd;
++ int refcount;
++ gboolean isdir;
++ GList *subs;
++ GSList *dirlist;
++} KQueueData;
++
++static GHashTable *dir_path_hash = NULL;
++static GHashTable *file_path_hash = NULL;
++static GHashTable *fd_hash = NULL;
++
++static GSList *exist_list = NULL;
++
++static GList *new_subs = NULL;
++G_LOCK_DEFINE_STATIC(new_subs);
++static GList *removed_subs = NULL;
++G_LOCK_DEFINE_STATIC(removed_subs);
++
++G_LOCK_DEFINE_STATIC(kqueue);
++
++static gboolean have_consume_idler = FALSE;
++
++int kq = -1;
++
++static KQueueData *
++gam_kqueue_data_new(const char *path, int fd)
++{
++ KQueueData *data;
++
++ data = g_new0(KQueueData, 1);
++ data->path = g_strdup(path);
++ data->fd = fd;
++ data->refcount = 1;
++ data->isdir = FALSE;
++ data->subs = NULL;
++ data->dirlist = NULL;
++
++ return data;
++}
++
++static GSList *
++gam_kqueue_lsdir(const char *path)
++{
++ GDir *dir;
++ GSList *lst = NULL;
++ const gchar *entry;
++
++ if (!path)
++ return NULL;
++
++ dir = g_dir_open(path, 0, NULL);
++ if (!dir)
++ return NULL;
++
++ entry = g_dir_read_name(dir);
++
++ while (entry) {
++ lst = g_slist_prepend(lst, g_strdup(entry));
++ entry = g_dir_read_name(dir);
++ }
++
++ g_dir_close(dir);
++
++ return lst;
++}
++
++static void
++gam_kqueue_cmplst(GSList *lst1, GSList *lst2, GSList **added, GSList **deleted)
++{
++ int found;
++ GSList *l;
++
++ if (!lst1 && !lst2)
++ return;
++
++ if (!lst1) {
++ *added = g_slist_copy(lst2);
++ return;
++ }
++
++ if (!lst2) {
++ *deleted = g_slist_copy(lst1);
++ return;
++ }
++
++ for (l = lst1; l; l = l->next) {
++ found = 0;
++ if (g_slist_find_custom(lst2, l->data, (GCompareFunc)strcmp)) {
++ found = 1;
++ }
++ if (found == 0) {
++ *deleted = g_slist_prepend(*deleted, l->data);
++ }
++ }
++
++ for (l = lst2; l; l = l->next) {
++ found = 0;
++ if (g_slist_find_custom(lst1, l->data, (GCompareFunc)strcmp)) {
++ found = 1;
++ }
++ if (found == 0) {
++ *added = g_slist_prepend(*added, l->data);
++ }
++ }
++}
++
++static void
++gam_kqueue_data_free(KQueueData * data)
++{
++ g_free(data->path);
++ if (data->dirlist) {
++ g_slist_foreach(data->dirlist, (GFunc)g_free, NULL);
++ g_slist_free(data->dirlist);
++ }
++ if (data->subs) {
++ g_list_free(data->subs);
++ }
++ g_free(data);
++}
++
++static void
++gam_kqueue_add_rm_handler(const char *path, GamSubscription *sub, gboolean added, gboolean was_missing)
++{
++ KQueueData *data;
++ struct kevent ev[1];
++ int isdir = 0;
++ int fd;
++
++ G_LOCK(kqueue);
++
++ isdir = g_file_test(path, G_FILE_TEST_IS_DIR);
++ if (gam_subscription_is_dir(sub)) {
++ data = g_hash_table_lookup(dir_path_hash, path);
++ }
++ else {
++ data = g_hash_table_lookup(file_path_hash, path);
++ }
++
++ if (added) {
++ GList *subs;
++
++ subs = NULL;
++ subs = g_list_append(subs, sub);
++
++ if (data != NULL) {
++ data->refcount++;
++ data->subs = g_list_prepend(data->subs, sub);
++ G_UNLOCK(kqueue);
++ GAM_DEBUG(DEBUG_INFO, "kqueue updated refcount\n");
++ if (!was_missing) {
++ gam_server_emit_event (path, isdir, GAMIN_EVENT_EXISTS, subs, 1);
++ gam_server_emit_event (path, isdir, GAMIN_EVENT_ENDEXISTS, subs, 1);
++ }
++ else {
++ gam_server_emit_event (path, isdir, GAMIN_EVENT_CREATED, subs, 1);
++ }
++ return;
++ }
++
++ if (!g_file_test(path, G_FILE_TEST_EXISTS)) {
++ data = gam_kqueue_data_new(path, -1);
++ data->subs = g_list_prepend(data->subs, sub);
++ exist_list = g_slist_append(exist_list, data);
++ gam_server_emit_event (path, isdir, GAMIN_EVENT_DELETED, subs, 1);
++ gam_server_emit_event (path, isdir, GAMIN_EVENT_ENDEXISTS, subs, 1);
++ G_UNLOCK(kqueue);
++ return;
++ }
++
++ fd = open(path, O_RDONLY);
++
++ if (fd < 0) {
++ G_UNLOCK(kqueue);
++ return;
++ }
++
++ EV_SET(ev, fd, EVFILT_VNODE,
++ EV_ADD | EV_ENABLE | EV_CLEAR, VN_NOTE_ALL, 0, 0);
++ kevent(kq, ev, 1, NULL, 0, NULL);
++
++ data = gam_kqueue_data_new(path, fd);
++ data->subs = g_list_prepend(data->subs, sub);
++
++ if (!was_missing) {
++ gam_server_emit_event (path, isdir, GAMIN_EVENT_EXISTS, subs, 1);
++ }
++ else {
++ gam_server_emit_event (path, isdir, GAMIN_EVENT_CREATED, subs, 1);
++ }
++ if (gam_subscription_is_dir(sub) && isdir) {
++ GSList *l;
++
++ data->isdir = TRUE;
++ data->dirlist = gam_kqueue_lsdir(path);
++
++ for (l = data->dirlist; l; l = l->next) {
++ char *tmpentry;
++
++ tmpentry = g_build_filename(path, l->data, NULL);
++ if (!was_missing) {
++ gam_server_emit_event (tmpentry,
++ g_file_test(tmpentry, G_FILE_TEST_IS_DIR),
++ GAMIN_EVENT_EXISTS, subs, 1);
++ }
++ g_free(tmpentry);
++ }
++ }
++
++ if (!was_missing) {
++ gam_server_emit_event (path, isdir, GAMIN_EVENT_ENDEXISTS, subs, 1);
++ }
++
++ g_hash_table_insert(fd_hash, GINT_TO_POINTER(data->fd), data);
++ if (data->isdir) {
++ g_hash_table_insert(dir_path_hash, data->path, data);
++ }
++ else {
++ g_hash_table_insert(file_path_hash, data->path, data);
++ }
++
++ if (subs)
++ g_list_free(subs);
++
++ GAM_DEBUG(DEBUG_INFO, "added kqueue watch for %s\n", path);
++ } else {
++
++ if (!data) {
++ G_UNLOCK(kqueue);
++ return;
++ }
++
++ if (g_list_find (data->subs, sub)) {
++ data->subs = g_list_remove_all (data->subs, sub);
++ }
++ data->refcount--;
++ GAM_DEBUG(DEBUG_INFO, "kqueue decremeneted refcount for %s\n", path);
++
++ if (data->refcount == 0) {
++ GList *l;
++
++ close(data->fd);
++ l = data->subs;
++ for (l = l; l; l = l->next) {
++ GamSubscription *sub = l->data;
++ gam_kqueue_remove_subscription (sub);
++ }
++ GAM_DEBUG(DEBUG_INFO, "removed kqueue watch for %s\n", data->path);
++ if (data->isdir) {
++ g_hash_table_remove(dir_path_hash, data->path);
++ }
++ else {
++ g_hash_table_remove(file_path_hash, data->path);
++ }
++ g_hash_table_remove(fd_hash, GINT_TO_POINTER(data->fd));
++ gam_kqueue_data_free(data);
++ }
++ }
++ G_UNLOCK(kqueue);
++}
++
++static GaminEventType kqueue_event_to_gamin_event (int mask)
++{
++ if ((mask & VN_NOTE_CHANGED) != 0)
++ return GAMIN_EVENT_CHANGED;
++ else if ((mask & NOTE_DELETE) != 0)
++ return GAMIN_EVENT_DELETED;
++ else if ((mask & NOTE_REVOKE) != 0)
++ return GAMIN_EVENT_ENDEXISTS;
++ else if ((mask & NOTE_RENAME) != 0)
++ return GAMIN_EVENT_MOVED;
++ else
++ return GAMIN_EVENT_UNKNOWN;
++}
++
++static void gam_kqueue_emit_event (KQueueData *data, struct kevent *event)
++{
++ GaminEventType gevent;
++ int isdir = 0;
++ char *event_path;
++
++ if (!data||!event)
++ return;
++
++ gevent = kqueue_event_to_gamin_event (event->fflags);
++
++ if (gevent == GAMIN_EVENT_UNKNOWN) {
++ return;
++ }
++
++ isdir = g_file_test(data->path, G_FILE_TEST_IS_DIR);
++
++ if (gevent == GAMIN_EVENT_CHANGED && data->isdir) {
++ GSList *dirlist = NULL, *added = NULL, *deleted = NULL;
++ GSList *l;
++
++ dirlist = gam_kqueue_lsdir(data->path);
++ gam_kqueue_cmplst(data->dirlist, dirlist, &added, &deleted);
++ if (added || deleted) {
++ for (l = deleted; l; l = l->next) {
++ data->dirlist = g_slist_remove(data->dirlist, l->data);
++ event_path = g_build_filename(data->path, l->data, NULL);
++ g_free(l->data);
++ isdir = g_file_test(event_path, G_FILE_TEST_IS_DIR);
++
++ GAM_DEBUG(DEBUG_INFO, "kqueue emitting event %s for %s\n", gam_event_to_string(GAMIN_EVENT_DELETED) , event_path);
++
++ gam_server_emit_event (event_path, isdir,
++ GAMIN_EVENT_DELETED, data->subs, 1);
++ g_free(event_path);
++ }
++
++ for (l = added; l; l = l->next) {
++ dirlist = g_slist_remove(dirlist, l->data);
++ data->dirlist = g_slist_prepend(data->dirlist,
++ g_strdup(l->data));
++ event_path = g_build_filename(data->path, l->data, NULL);
++ g_free(l->data);
++ isdir = g_file_test(event_path, G_FILE_TEST_IS_DIR);
++
++ GAM_DEBUG(DEBUG_INFO, "kqueue emitting event %s for %s\n", gam_event_to_string(GAMIN_EVENT_CREATED) , event_path);
++
++ gam_server_emit_event (event_path, isdir,
++ GAMIN_EVENT_CREATED, data->subs, 1);
++ g_free(event_path);
++ }
++
++ if (added)
++ g_slist_free(added);
++ if (deleted)
++ g_slist_free(deleted);
++ }
++
++ if (dirlist) {
++ g_slist_foreach(dirlist, (GFunc)g_free, NULL);
++ g_slist_free(dirlist);
++ }
++ return;
++ }
++ else {
++ event_path = g_strdup (data->path);
++ }
++
++ isdir = g_file_test(event_path, G_FILE_TEST_IS_DIR);
++
++ GAM_DEBUG(DEBUG_INFO, "kqueue emitting event %s for %s\n", gam_event_to_string(gevent) , event_path);
++
++ gam_server_emit_event (event_path, isdir, gevent, data->subs, 1);
++
++ g_free (event_path);
++}
++
++static gboolean
++gam_kqueue_exist_check (gpointer user_data)
++{
++ GSList *l, *tmplst;
++ KQueueData *data;
++
++ tmplst = g_slist_copy(exist_list);
++
++ for (l = tmplst; l; l = l->next) {
++ data = l->data;
++
++ if (g_file_test(data->path, G_FILE_TEST_EXISTS)) {
++ /* The subs list is guaranteed to have only one entry. */
++ GamSubscription *sub = data->subs->data;
++
++ exist_list = g_slist_remove(exist_list, data);
++ gam_kqueue_add_rm_handler(data->path, sub, TRUE, TRUE);
++ gam_kqueue_data_free(data);
++ }
++ }
++
++ if (tmplst)
++ g_slist_free(tmplst);
++
++ return TRUE;
++}
++
++static gboolean
++gam_kqueue_event_handler (gpointer user_data)
++{
++ KQueueData *data;
++ struct kevent ev[1];
++ struct timespec timeout = { 0, 0 };
++ int fd, i, nevents;
++
++ G_LOCK(kqueue);
++
++ GAM_DEBUG(DEBUG_INFO, "gam_kqueue_event_handler()\n");
++
++ nevents = kevent(kq, NULL, 0, ev, 1, &timeout);
++ if (nevents == -1)
++ return FALSE;
++ for (i = 0; i < nevents; i++) {
++ fd = ev[i].ident;
++
++ data = g_hash_table_lookup (fd_hash, GINT_TO_POINTER(fd));
++ if (!data) {
++ GAM_DEBUG(DEBUG_INFO, "kqueue can't find fd %d\n", fd);
++ GAM_DEBUG(DEBUG_INFO, "weird things have happened to kqueue.\n");
++ } else {
++ gam_kqueue_emit_event (data, &ev[i]);
++ }
++
++ }
++
++ G_UNLOCK(kqueue);
++
++ return TRUE;
++}
++
++static gboolean
++gam_kqueue_consume_subscriptions_real(gpointer data)
++{
++ GList *subs, *l;
++
++ G_LOCK(new_subs);
++ if (new_subs) {
++ subs = new_subs;
++ new_subs = NULL;
++ G_UNLOCK(new_subs);
++
++ for (l = subs; l; l = l->next) {
++ GamSubscription *sub = l->data;
++ GAM_DEBUG(DEBUG_INFO, "called gam_kqueue_add_handler()\n");
++ gam_kqueue_add_rm_handler (gam_subscription_get_path (sub), sub, TRUE, FALSE);
++ }
++
++ } else {
++ G_UNLOCK(new_subs);
++ }
++
++ G_LOCK(removed_subs);
++ if (removed_subs) {
++ subs = removed_subs;
++ removed_subs = NULL;
++ G_UNLOCK(removed_subs);
++
++ for (l = subs; l; l = l->next) {
++ GamSubscription *sub = l->data;
++ GAM_DEBUG(DEBUG_INFO, "called gam_kqueue_rm_handler()\n");
++ gam_kqueue_add_rm_handler (gam_subscription_get_path (sub), sub, FALSE, FALSE);
++ }
++ } else {
++ G_UNLOCK(removed_subs);
++ }
++
++ GAM_DEBUG(DEBUG_INFO, "gam_kqueue_consume_subscriptions()\n");
++
++ have_consume_idler = FALSE;
++ return FALSE;
++}
++
++static void
++gam_kqueue_consume_subscriptions(void)
++{
++ GSource *source;
++
++ if (have_consume_idler)
++ return;
++
++ have_consume_idler = TRUE;
++
++ source = g_idle_source_new ();
++ g_source_set_callback (source, gam_kqueue_consume_subscriptions_real, NULL, NULL);
++
++ g_source_attach (source, NULL);
++}
++
++/**
++ * @defgroup kqueue kqueue backend
++ * @ingroup Backends
++ * @brief kqueue backend API
++ *
++ * Since 4.1, FreeBSD kernels have included the kernel event notification
++ * machanism (kqueue). This backend uses kqueue to know when
++ * files are changed/created/deleted.
++ *
++ * @{
++ */
++
++
++/**
++ * Initializes the kqueue system. This must be called before
++ * any other functions in this module.
++ *
++ * @returns TRUE if initialization succeeded, FALSE otherwise
++ */
++gboolean
++gam_kqueue_init(void)
++{
++ kq = kqueue();
++ if (kq == -1) {
++ GAM_DEBUG(DEBUG_INFO, "Could not initialize a new kqueue\n");
++ return FALSE;
++ }
++
++ g_timeout_add(1000, gam_kqueue_exist_check, NULL);
++ g_timeout_add(1000, gam_kqueue_event_handler, NULL);
++
++ dir_path_hash = g_hash_table_new(g_str_hash, g_str_equal);
++ file_path_hash = g_hash_table_new(g_str_hash, g_str_equal);
++ fd_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
++
++ GAM_DEBUG(DEBUG_INFO, "kqueue initialized\n");
++
++ gam_backend_add_subscription = gam_kqueue_add_subscription;
++ gam_backend_remove_subscription = gam_kqueue_remove_subscription;
++ gam_backend_remove_all_for = gam_kqueue_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_kqueue_add_subscription(GamSubscription * sub)
++{
++ gam_listener_add_subscription(gam_subscription_get_listener(sub), sub);
++
++ G_LOCK(new_subs);
++ new_subs = g_list_prepend(new_subs, sub);
++ G_UNLOCK(new_subs);
++
++ GAM_DEBUG(DEBUG_INFO, "kqueue_add_sub\n");
++
++ gam_kqueue_consume_subscriptions();
++ 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_kqueue_remove_subscription(GamSubscription * sub)
++{
++ G_LOCK(new_subs);
++ if (g_list_find(new_subs, sub)) {
++ GAM_DEBUG(DEBUG_INFO, "removed sub found on new_subs\n");
++ new_subs = g_list_remove_all (new_subs, sub);
++ G_UNLOCK(new_subs);
++ return TRUE;
++ }
++ G_UNLOCK(new_subs);
++
++ gam_subscription_cancel (sub);
++ gam_listener_remove_subscription(gam_subscription_get_listener(sub), sub);
++
++ G_LOCK(removed_subs);
++ removed_subs = g_list_prepend (removed_subs, sub);
++ G_UNLOCK(removed_subs);
++
++ GAM_DEBUG(DEBUG_INFO, "kqueue_remove_sub\n");
++ gam_kqueue_consume_subscriptions();
++
++ 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_kqueue_remove_all_for(GamListener * listener)
++{
++ GList *subs, *l = NULL;
++
++ subs = gam_listener_get_subscriptions (listener);
++
++ for (l = subs; l; l = l->next) {
++ GamSubscription *sub = l->data;
++
++ g_assert (sub != NULL);
++
++ gam_kqueue_remove_subscription (sub);
++
++ }
++
++ if (subs) {
++ g_list_free (subs);
++ gam_kqueue_consume_subscriptions();
++ return TRUE;
++ } else {
++ return FALSE;
++ }
++}
++
++/** @} */
diff --git a/devel/gamin/files/patch-server_gam_kqueue.h b/devel/gamin/files/patch-server_gam_kqueue.h
new file mode 100644
index 000000000000..c99f5e3ee380
--- /dev/null
+++ b/devel/gamin/files/patch-server_gam_kqueue.h
@@ -0,0 +1,27 @@
+--- server/gam_kqueue.h.orig Sat Mar 26 18:32:19 2005
++++ server/gam_kqueue.h Sat Mar 26 18:36:11 2005
+@@ -0,0 +1,24 @@
++
++#ifndef __MD_KQUEUE_H__
++#define __MD_KQUEUE_H__
++
++#include <glib.h>
++#include "gam_poll.h"
++#include "gam_subscription.h"
++
++#define VN_NOTE_MOST (NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | \
++ NOTE_ATTRIB | NOTE_LINK | NOTE_RENAME | \
++ NOTE_REVOKE)
++#define VN_NOTE_ALL VN_NOTE_MOST
++#define VN_NOTE_CHANGED (NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_LINK)
++
++G_BEGIN_DECLS
++
++gboolean gam_kqueue_init (void);
++gboolean gam_kqueue_add_subscription (GamSubscription *sub);
++gboolean gam_kqueue_remove_subscription (GamSubscription *sub);
++gboolean gam_kqueue_remove_all_for (GamListener *listener);
++
++G_END_DECLS
++
++#endif /* __MD_KQUEUE_H__ */
diff --git a/devel/gamin/files/patch-server_gam_server.c b/devel/gamin/files/patch-server_gam_server.c
new file mode 100644
index 000000000000..de62120f6ff6
--- /dev/null
+++ b/devel/gamin/files/patch-server_gam_server.c
@@ -0,0 +1,56 @@
+--- server/gam_server.c.orig Thu Dec 2 12:42:56 2004
++++ server/gam_server.c Sun Mar 27 02:34:19 2005
+@@ -39,12 +39,29 @@
+ #ifdef ENABLE_DNOTIFY
+ #include "gam_dnotify.h"
+ #endif
++#ifdef ENABLE_KQUEUE
++#include "gam_kqueue.h"
++#endif
+ #include "gam_excludes.h"
+
+ static int poll_only = 0;
+ static const char *session;
+
+ /**
++ * gam_exit:
++ *
++ * Call the shutdown routine, then just exit.
++ * This function is designed to be called from a
++ * signal handler.
++ */
++void
++gam_exit(int signo) {
++ gam_shutdown();
++
++ exit(0);
++}
++
++/**
+ * gam_shutdown:
+ *
+ * Shutdown routine called when the server exits
+@@ -90,6 +107,12 @@ gam_init_subscriptions(void)
+ return(TRUE);
+ }
+ #endif
++#ifdef ENABLE_KQUEUE
++ if (gam_kqueue_init()) {
++ GAM_DEBUG(DEBUG_INFO, "Using KQueue as backend\n");
++ return(TRUE);
++ }
++#endif
+ }
+ if (gam_poll_init()) {
+ GAM_DEBUG(DEBUG_INFO, "Using Poll as backend\n");
+@@ -332,6 +355,10 @@ main(int argc, const char *argv[])
+ }
+
+ gam_error_init();
++ signal(SIGHUP, gam_exit);
++ signal(SIGINT, gam_exit);
++ signal(SIGQUIT, gam_exit);
++ signal(SIGTERM, gam_exit);
+ signal(SIGPIPE, SIG_IGN);
+
+ if (!gam_init_subscriptions()) {
diff --git a/devel/gamin/pkg-descr b/devel/gamin/pkg-descr
new file mode 100644
index 000000000000..ac16e95d121f
--- /dev/null
+++ b/devel/gamin/pkg-descr
@@ -0,0 +1,5 @@
+Gamin is a file and directory monitoring system defined to be a subset of the
+FAM (File Alteration Monitor) system. This is a service provided by a library
+which allows to detect when a file or a directory has been modified.
+
+WWW: http://www.gnome.org/~veillard/gamin/index.html
diff --git a/devel/gamin/pkg-plist b/devel/gamin/pkg-plist
new file mode 100644
index 000000000000..d318e2257d82
--- /dev/null
+++ b/devel/gamin/pkg-plist
@@ -0,0 +1,10 @@
+include/fam.h
+lib/libfam.a
+lib/libfam.so
+lib/libfam.so.0
+lib/libgamin-1.a
+lib/libgamin-1.so
+lib/libgamin-1.so.0
+lib/libgamin_shared.a
+libdata/pkgconfig/gamin.pc
+libexec/gam_server