summaryrefslogtreecommitdiffstats
path: root/devel
diff options
context:
space:
mode:
authorkwm <kwm@df743ca5-7f9a-e211-a948-0013205c9059>2013-03-30 18:50:57 +0800
committerkwm <kwm@df743ca5-7f9a-e211-a948-0013205c9059>2013-03-30 18:50:57 +0800
commitb843edee6bfa64b092d8cc37c0b057c4c783ec66 (patch)
tree7be617b36e492e65a54f6739118549627a0b1b52 /devel
parent6ee2f52bca4d57d96561e5054df1385b59d6056c (diff)
downloadmarcuscom-ports-b843edee6bfa64b092d8cc37c0b057c4c783ec66.tar.gz
marcuscom-ports-b843edee6bfa64b092d8cc37c0b057c4c783ec66.tar.zst
marcuscom-ports-b843edee6bfa64b092d8cc37c0b057c4c783ec66.zip
_glib20 is removed, long live glib20
git-svn-id: svn://creme-brulee.marcuscom.com/ports/trunk@17257 df743ca5-7f9a-e211-a948-0013205c9059
Diffstat (limited to 'devel')
-rw-r--r--devel/gamin/Makefile71
-rw-r--r--devel/gamin/distinfo2
-rw-r--r--devel/gamin/files/patch-libgamin_gam_api.c159
-rw-r--r--devel/gamin/files/patch-libgamin_gam_fork.c95
-rw-r--r--devel/gamin/files/patch-libgamin_gam_fork.h12
-rw-r--r--devel/gamin/files/patch-python_Makefile.in20
-rw-r--r--devel/gamin/files/patch-server__gam_node.h11
-rw-r--r--devel/gamin/files/patch-server__gam_subscription.c11
-rw-r--r--devel/gamin/files/patch-server__gam_subscription.h11
-rw-r--r--devel/gamin/files/patch-server_gam_channel.c127
-rw-r--r--devel/gamin/files/patch-server_gam_eq.c11
-rw-r--r--devel/gamin/files/patch-server_gam_fs.c161
-rw-r--r--devel/gamin/files/patch-server_gam_kqueue.c356
-rw-r--r--devel/gamin/files/patch-server_gam_node.c19
-rw-r--r--devel/gamin/files/patch-server_gam_poll_basic.c11
-rw-r--r--devel/gamin/files/patch-server_gam_server.c40
-rw-r--r--devel/gamin/files/patch-tests_testing.c27
-rw-r--r--devel/gamin/pkg-descr8
-rw-r--r--devel/gamin/pkg-message26
-rw-r--r--devel/gamin/pkg-plist12
20 files changed, 1190 insertions, 0 deletions
diff --git a/devel/gamin/Makefile b/devel/gamin/Makefile
new file mode 100644
index 000000000..5ccc145af
--- /dev/null
+++ b/devel/gamin/Makefile
@@ -0,0 +1,71 @@
+# Created by: Joe Marcus Clarke <marcus@FreeBSD.org>
+# $FreeBSD: head/devel/gamin/Makefile 314945 2013-03-22 16:30:36Z kwm $
+# $MCom: ports/devel/gamin/Makefile,v 1.11 2012/08/04 16:55:24 kwm Exp $
+
+PORTNAME= gamin
+PORTVERSION= 0.1.10
+PORTREVISION?= 6
+CATEGORIES?= devel
+MASTER_SITES= http://people.gnome.org/~veillard/gamin/sources/
+
+MAINTAINER?= gnome@FreeBSD.org
+COMMENT?= A file and directory monitoring system
+
+USE_AUTOTOOLS= libtool
+USE_GMAKE= yes
+USE_GETTEXT= yes
+USES= pathfix
+USE_GNOME?= glib20
+USE_PKGCONFIG= build
+USE_LDCONFIG= yes
+CONFIGURE_ARGS?=--with-html-dir=${PREFIX}/share/doc \
+ --without-python
+LDFLAGS+= -L${LOCALBASE}/lib
+CPPFLAGS+= -DHAVE_LINUX -I${LOCALBASE}/include
+
+CONFLICTS= fam-[0-9]*
+
+GNU_CONFIGURE= yes
+
+.if !defined(GAMIN_SLAVE)
+OPTIONS_DEFINE= GAM_POLLER LIBINOTIFY RUN_AS_EUID
+OPTIONS_DEFAULT=RUN_AS_EUID
+GAM_POLLER_DESC=Use gamin's poller instead of kqueue's
+LIBINOTIFY_DESC=Use libinotify as the FAM backend
+RUN_AS_EUID_DESC=Drop privileges to effective user
+.endif
+
+.include <bsd.port.options.mk>
+
+.if !defined(GAMIN_SLAVE)
+.if ${PORT_OPTIONS:MGAM_POLLER}
+CPPFLAGS+= -DUSE_GAMIN_POLLER=1
+.endif
+
+.if ${PORT_OPTIONS:MLIBINOTIFY}
+CONFIGURE_ARGS+=--enable-inotify
+LDFLAGS+= -L${LOCALBASE}/lib -linotify
+LIB_DEPENDS+= inotify:${PORTSDIR}/devel/libinotify
+.else
+CONFIGURE_ARGS+=--disable-inotify
+.endif
+.endif
+
+.if ${PORT_OPTIONS:MRUN_AS_EUID}
+CPPFLAGS+= -DRUN_AS_EUID=1
+.endif
+
+post-patch:
+ @${REINPLACE_CMD} "s|/etc|${PREFIX}/etc|g" ${WRKSRC}/server/gam_conf.c
+
+.if !defined(GAMIN_SLAVE)
+regression-test: build
+ @${ECHO_MSG} "===> Running gamin regression tests"
+ @(cd ${WRKSRC}/tests && ${SETENV} ${MAKE_ENV} ${GMAKE} ${MAKE_FLAGS} \
+ Makefile ${MAKE_ARGS} tests)
+
+post-install:
+ @${CAT} ${PKGMESSAGE}
+.endif
+
+.include <bsd.port.mk>
diff --git a/devel/gamin/distinfo b/devel/gamin/distinfo
new file mode 100644
index 000000000..9e4e3874c
--- /dev/null
+++ b/devel/gamin/distinfo
@@ -0,0 +1,2 @@
+SHA256 (gamin-0.1.10.tar.gz) = 28085f0ae8be10eab582ff186af4fb0be92cc6c62b5cc19cd09b295c7c2899a1
+SIZE (gamin-0.1.10.tar.gz) = 653392
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 000000000..9f2672c1d
--- /dev/null
+++ b/devel/gamin/files/patch-libgamin_gam_api.c
@@ -0,0 +1,159 @@
+--- libgamin/gam_api.c.orig 2007-08-27 03:21:03.000000000 -0700
++++ libgamin/gam_api.c 2013-02-16 15:51:11.927100135 -0800
+@@ -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"
+@@ -117,7 +118,11 @@
+ if (user_name[0] != 0)
+ return (user_name);
+
++#ifdef RUN_AS_EUID
++ pw = getpwuid(geteuid());
++#else
+ pw = getpwuid(getuid());
++#endif
+
+ if (pw != NULL) {
+ strncpy(user_name, pw->pw_name, 99);
+@@ -224,7 +229,11 @@
+ free(dir);
+ return(0);
+ }
++#ifdef RUN_AS_EUID
++ if (st.st_uid != geteuid()) {
++#else
+ if (st.st_uid != getuid()) {
++#endif
+ gam_error(DEBUG_INFO,
+ "Socket directory %s has different owner\n",
+ dir);
+@@ -301,7 +310,11 @@
+ if (ret < 0)
+ return(0);
+
++#ifdef RUN_AS_EUID
++ if (st.st_uid != geteuid()) {
++#else
+ if (st.st_uid != getuid()) {
++#endif
+ gam_error(DEBUG_INFO,
+ "Socket %s has different owner\n",
+ path);
+@@ -428,10 +441,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 +456,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 +667,20 @@
+ 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
+
++#ifdef RUN_AS_EUID
++ s_uid = geteuid();
++#else
+ s_uid = getuid();
++#endif
+
+-#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 +701,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 +719,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 +745,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 +1307,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) {
diff --git a/devel/gamin/files/patch-libgamin_gam_fork.c b/devel/gamin/files/patch-libgamin_gam_fork.c
new file mode 100644
index 000000000..8ed0e222f
--- /dev/null
+++ b/devel/gamin/files/patch-libgamin_gam_fork.c
@@ -0,0 +1,95 @@
+--- libgamin/gam_fork.c.orig 2007-07-04 06:36:48.000000000 -0700
++++ libgamin/gam_fork.c 2013-02-16 20:37:31.298176973 -0800
+@@ -42,6 +42,78 @@
+ return NULL;
+ }
+
++#ifdef RUN_AS_EUID
++/**
++ * gamin_drop_privileges
++ *
++ * Attempt to drop privileges to another user and group before forking
++ * a copy of the gam server
++ *
++ * Return 0 in case of success or -1 in case of detected error.
++ */
++int
++gamin_drop_privileges(int to_uid, int to_gid)
++{
++ GAM_DEBUG(DEBUG_INFO, "Dropping privileges to %d:%d before forking server\n", to_uid, to_gid);
++
++ /* Get the current real user and group */
++ int from_uid = getuid();
++ int from_gid = getgid();
++
++ /* Make sure we were able to get the user and group values */
++ if ( from_uid == -1 || to_uid == -1 || from_gid == -1 || to_gid == -1 ) {
++ gam_error(DEBUG_INFO, "failed to get user or group info, unable to drop privileges\n");
++ return(-1);
++ }
++
++ /* Refuse to run setuid if it would escalate privileges */
++ if ( from_uid != 0 && to_uid == 0 )
++ {
++ gam_error(DEBUG_INFO, "refusing to escalate user privileges from=%d to=%d\n", from_uid, to_uid);
++ return(-1);
++ }
++
++ /* Refuse to run setgid if it would escalate privileges */
++ if ( from_gid != 0 && to_gid == 0 )
++ {
++ gam_error(DEBUG_INFO, "refusing to escalate group privileges from=%d to=%d\n", from_gid, to_gid);
++ return(-1);
++ }
++
++ /* Run setuid to drop privileges to the effective user */
++ if ( from_uid != to_uid ) {
++ GAM_DEBUG(DEBUG_INFO, "Attempting setuid from=%d to=%d\n", from_uid, to_uid);
++
++ /* run setuid and check for errors */
++ if (setuid(to_uid) == -1) {
++ gam_error(DEBUG_INFO, "failed to run setuid from=%d to=%d\n", from_uid, to_uid);
++ return(-1);
++ }
++ }
++ else {
++ GAM_DEBUG(DEBUG_INFO, "Already running as effective user, skipping setuid\n");
++ }
++
++ /* Run setgid to drop privileges to the effective group */
++ if ( from_gid != to_gid ) {
++ GAM_DEBUG(DEBUG_INFO, "Attempting setgid from=%d to=%d\n", from_gid, to_gid);
++
++ /* run setuid and check for errors */
++ if (setgid(to_gid) == -1) {
++ gam_error(DEBUG_INFO, "failed to run setgid from=%d to=%d\n", from_gid, to_gid);
++ return(-1);
++ }
++ }
++ else {
++ GAM_DEBUG(DEBUG_INFO, "Already running as effective group, skipping setgid\n");
++ }
++
++ GAM_DEBUG(DEBUG_INFO, "Succeeded in dropping privileges from %d:%d to %d:%d\n", from_uid, from_gid, to_uid, to_gid);
++
++ return(0);
++}
++#endif
++
+ /**
+ * gamin_fork_server:
+ * @fam_client_id: the client ID string to use
+@@ -71,6 +143,13 @@
+ long open_max;
+ long i;
+
++#ifdef RUN_AS_EUID
++ /* Drop privileges to the current effective uid/gid and return on failure */
++ if(gamin_drop_privileges( geteuid(), getegid() ) == -1) {
++ return(-1);
++ }
++#endif
++
+ /* don't hold open fd opened from the client of the library */
+ open_max = sysconf (_SC_OPEN_MAX);
+ for (i = 0; i < open_max; i++)
diff --git a/devel/gamin/files/patch-libgamin_gam_fork.h b/devel/gamin/files/patch-libgamin_gam_fork.h
new file mode 100644
index 000000000..db96b2d05
--- /dev/null
+++ b/devel/gamin/files/patch-libgamin_gam_fork.h
@@ -0,0 +1,12 @@
+--- libgamin/gam_fork.h.orig 2007-07-04 06:36:48.000000000 -0700
++++ libgamin/gam_fork.h 2013-02-16 20:38:00.328594608 -0800
+@@ -32,6 +32,9 @@
+ #endif
+
+ int gamin_fork_server (const char *fam_client_id);
++#ifdef RUN_AS_EUID
++int gamin_drop_privileges (int to_uid, int to_gid);
++#endif
+
+ #ifdef __cplusplus
+ }
diff --git a/devel/gamin/files/patch-python_Makefile.in b/devel/gamin/files/patch-python_Makefile.in
new file mode 100644
index 000000000..24bbe73c6
--- /dev/null
+++ b/devel/gamin/files/patch-python_Makefile.in
@@ -0,0 +1,20 @@
+--- python/Makefile.in.orig 2008-11-26 01:42:29.000000000 -0500
++++ python/Makefile.in 2008-11-26 01:43:26.000000000 -0500
+@@ -53,7 +53,7 @@ am__strip_dir = `echo $$p | sed -e 's|^.
+ 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 @@ INCLUDES = \
+
+ 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
diff --git a/devel/gamin/files/patch-server__gam_node.h b/devel/gamin/files/patch-server__gam_node.h
new file mode 100644
index 000000000..2490964c9
--- /dev/null
+++ b/devel/gamin/files/patch-server__gam_node.h
@@ -0,0 +1,11 @@
+--- server/gam_node.h.orig 2011-09-17 11:19:43.000000000 +0200
++++ server/gam_node.h 2011-09-17 11:20:13.000000000 +0200
+@@ -58,7 +58,7 @@ gboolean gam_node_is_dir
+ 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);
+
diff --git a/devel/gamin/files/patch-server__gam_subscription.c b/devel/gamin/files/patch-server__gam_subscription.c
new file mode 100644
index 000000000..4c14baecb
--- /dev/null
+++ b/devel/gamin/files/patch-server__gam_subscription.c
@@ -0,0 +1,11 @@
+--- server/gam_subscription.c.orig 2011-09-17 11:17:22.000000000 +0200
++++ server/gam_subscription.c 2011-09-17 11:17:44.000000000 +0200
+@@ -141,7 +141,7 @@ gam_subscription_pathlen(GamSubscription
+ * @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)
diff --git a/devel/gamin/files/patch-server__gam_subscription.h b/devel/gamin/files/patch-server__gam_subscription.h
new file mode 100644
index 000000000..b8d5c3467
--- /dev/null
+++ b/devel/gamin/files/patch-server__gam_subscription.h
@@ -0,0 +1,11 @@
+--- server/gam_subscription.h.orig 2011-09-17 11:15:00.000000000 +0200
++++ server/gam_subscription.h 2011-09-17 11:15:18.000000000 +0200
+@@ -21,7 +21,7 @@ int gam_subscription_pa
+
+ 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);
+
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 000000000..7b5fb8aee
--- /dev/null
+++ b/devel/gamin/files/patch-server_gam_channel.c
@@ -0,0 +1,127 @@
+--- server/gam_channel.c.orig Tue Aug 9 12:17:39 2005
++++ server/gam_channel.c Fri Feb 10 01:22:46 2006
+@@ -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 @@ gam_client_conn_send_cred(int fd)
+ {
+ 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 @@ gam_client_conn_send_cred(int fd)
+ 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 @@ gam_client_conn_check_cred(GIOChannel *
+ 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 @@ gam_client_conn_check_cred(GIOChannel *
+
+ #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 @@ gam_client_conn_check_cred(GIOChannel *
+ 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 @@ gam_client_conn_check_cred(GIOChannel *
+ 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 +621,7 @@ gam_listen_unix_socket(const char *path)
+ {
+ int fd;
+ struct sockaddr_un addr;
++ struct stat st;
+
+ fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+@@ -640,8 +642,18 @@ gam_listen_unix_socket(const char *path)
+ * 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);
diff --git a/devel/gamin/files/patch-server_gam_eq.c b/devel/gamin/files/patch-server_gam_eq.c
new file mode 100644
index 000000000..6dfb7c975
--- /dev/null
+++ b/devel/gamin/files/patch-server_gam_eq.c
@@ -0,0 +1,11 @@
+--- server/gam_eq.c.orig 2012-05-13 19:42:20.257794534 +0400
++++ server/gam_eq.c 2012-05-13 19:44:41.228799909 +0400
+@@ -124,7 +124,7 @@ gam_eq_flush (gam_eq_t *eq, GamConnDataP
+ {
+ gboolean done_work = FALSE;
+ if (!eq)
+- return;
++ return FALSE;
+
+ #ifdef GAM_EQ_VERBOSE
+ GAM_DEBUG(DEBUG_INFO, "gam_eq: Flushing event queue for %s\n", gam_connection_get_pidname (conn));
diff --git a/devel/gamin/files/patch-server_gam_fs.c b/devel/gamin/files/patch-server_gam_fs.c
new file mode 100644
index 000000000..2fcc24209
--- /dev/null
+++ b/devel/gamin/files/patch-server_gam_fs.c
@@ -0,0 +1,161 @@
+--- server/gam_fs.c.orig 2007-07-04 09:36:49.000000000 -0400
++++ server/gam_fs.c 2007-08-10 15:05:41.000000000 -0400
+@@ -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_properties {
+ 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 @@ gam_fs_filesystem_sort_cb (gconstpointer
+ return strlen(fsb->path) - strlen (fsa->path);
+ }
+
++#ifdef __linux__
+ static void
+ gam_fs_scan_mtab (void)
+ {
+@@ -165,10 +175,41 @@ gam_fs_scan_mtab (void)
+ 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 @@ gam_fs_init (void)
+ 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 @@ gam_fs_init (void)
+ 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 @@ gam_fs_init (void)
+
+ 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 @@ gam_fs_get_mon_type (const char *path)
+ 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;
+ }
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 000000000..89289c533
--- /dev/null
+++ b/devel/gamin/files/patch-server_gam_kqueue.c
@@ -0,0 +1,356 @@
+--- server/gam_kqueue.c.orig 2007-07-04 09:50:41.000000000 -0400
++++ server/gam_kqueue.c 2009-06-03 13:43:38.000000000 -0400
+@@ -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 @@ typedef struct
+ HashTableRemoveFunc remove;
+ HashTablePostRemoveFunc post_remove;
+ } HashTableMethods;
+-
++
+ /*
+ * A hash table which can be modified while iterating over it.
+ */
+@@ -281,8 +285,8 @@ static void
+ 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 @@ gam_kqueue_isdir (const char *pathname,
+ 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 @@ gam_kqueue_hash_table_foreach (HashTable
+ 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 @@ static gboolean
+ 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_sub_monitor_free (SubMonitor
+ 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 @@ gam_kqueue_sub_monitor_enable_notificati
+ {
+ 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 @@ gam_kqueue_sub_monitor_enable_notificati
+ {
+ 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 @@ gam_kqueue_sub_monitor_enable_notificati
+
+ return;
+ }
+-
++
+ /* then we enable kqueue notification, falling back to poll if necessary */
+
+ if (! gam_kqueue_monitor_enable_kqueue(mon))
+@@ -774,7 +797,7 @@ gam_kqueue_sub_monitor_handle_directory_
+
+ 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 @@ gam_kqueue_sub_monitor_handle_directory_
+ 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 @@ gam_kqueue_sub_monitor_handle_directory_
+ {
+ 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 @@ gam_kqueue_sub_monitor_emit_event (SubMo
+ 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 @@ gam_kqueue_file_monitor_emit_event (File
+ 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 @@ gam_kqueue_file_monitor_emit_event (File
+ 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 @@ gam_kqueue_file_monitor_emit_event (File
+ {
+ 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 @@ gam_kqueue_file_monitor_emit_event (File
+ 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 @@ gam_kqueue_kevent_cb (GIOChannel *source
+
+ 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 @@ gam_kqueue_missing_smon_poll (SubMonitor
+ {
+ 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 @@ gam_kqueue_unsupported_smon_poll (SubMon
+ 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 @@ gam_kqueue_init (void)
+ 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 @@ gam_kqueue_add_subscription (GamSubscrip
+ 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 @@ gam_kqueue_remove_all_for (GamListener *
+ success = FALSE;
+
+ g_list_free(subs);
+-
++
+ return success;
+ }
diff --git a/devel/gamin/files/patch-server_gam_node.c b/devel/gamin/files/patch-server_gam_node.c
new file mode 100644
index 000000000..4330949d0
--- /dev/null
+++ b/devel/gamin/files/patch-server_gam_node.c
@@ -0,0 +1,19 @@
+--- server/gam_node.c.orig 2007-07-04 15:36:49.000000000 +0200
++++ server/gam_node.c 2011-09-17 11:19:10.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 @@ gam_node_set_is_dir(GamNode * node, gboo
+ * 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);
diff --git a/devel/gamin/files/patch-server_gam_poll_basic.c b/devel/gamin/files/patch-server_gam_poll_basic.c
new file mode 100644
index 000000000..9a0333149
--- /dev/null
+++ b/devel/gamin/files/patch-server_gam_poll_basic.c
@@ -0,0 +1,11 @@
+--- server/gam_poll_basic.c.orig 2007-08-10 15:12:29.000000000 -0400
++++ server/gam_poll_basic.c 2007-08-10 15:16:07.000000000 -0400
+@@ -345,7 +345,7 @@ gam_poll_basic_poll_file(GamNode * node)
+ #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 */
+ }
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 000000000..77c9b75f4
--- /dev/null
+++ b/devel/gamin/files/patch-server_gam_server.c
@@ -0,0 +1,40 @@
+--- server/gam_server.c.orig 2007-07-04 09:36:49.000000000 -0400
++++ server/gam_server.c 2009-05-01 20:25:41.000000000 -0400
+@@ -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 @@ gam_add_subscription(GamSubscription * s
+ 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 @@ gam_remove_subscription(GamSubscription
+ 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 @@ gam_server_get_kernel_handler (void)
+ GamPollHandler
+ gam_server_get_poll_handler (void)
+ {
+- return __gam_kernel_handler;
++ return __gam_poll_handler;
+ }
+
+ gboolean
diff --git a/devel/gamin/files/patch-tests_testing.c b/devel/gamin/files/patch-tests_testing.c
new file mode 100644
index 000000000..35097790d
--- /dev/null
+++ b/devel/gamin/files/patch-tests_testing.c
@@ -0,0 +1,27 @@
+--- tests/testing.c.orig Thu Oct 27 10:51:03 2005
++++ tests/testing.c Tue Feb 14 17:46:01 2006
+@@ -376,11 +376,11 @@ processCommand(char *line, int no)
+ }
+ 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 @@ processCommand(char *line, int no)
+ 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); */
diff --git a/devel/gamin/pkg-descr b/devel/gamin/pkg-descr
new file mode 100644
index 000000000..7bac17f94
--- /dev/null
+++ b/devel/gamin/pkg-descr
@@ -0,0 +1,8 @@
+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.
+
+Whereas the FreeBSD port of FAM polls files every few seconds, this port
+includes a kqueue(2) backend for immediate notification of most alterations.
+
+WWW: http://www.gnome.org/~veillard/gamin/index.html
diff --git a/devel/gamin/pkg-message b/devel/gamin/pkg-message
new file mode 100644
index 000000000..28586c6c6
--- /dev/null
+++ b/devel/gamin/pkg-message
@@ -0,0 +1,26 @@
+===============================================================================
+
+Gamin will only provide realtime notification of changes for at most n files,
+where n is the minimum value between (kern.maxfiles * 0.7) and
+(kern.maxfilesperproc - 200). Beyond that limit, files will be polled.
+
+If you often open several large folders with Nautilus, you might want to
+increase the kern.maxfiles tunable (you do not need to set
+kern.maxfilesperproc, since it is computed at boot time from kern.maxfiles).
+
+For a typical desktop, add the following line to /boot/loader.conf, then
+reboot the system:
+
+ kern.maxfiles="25000"
+
+The behavior of gamin can be controlled via the various gaminrc files.
+See http://www.gnome.org/~veillard/gamin/config.html on how to create
+these files. In particular, if you find gam_server is taking up too much
+CPU time polling for changes, something like the following may help
+in one of the gaminrc files:
+
+# reduce polling frequency to once per 10 seconds
+# for UFS file systems in order to lower CPU load
+fsset ufs poll 10
+
+===============================================================================
diff --git a/devel/gamin/pkg-plist b/devel/gamin/pkg-plist
new file mode 100644
index 000000000..008f29b34
--- /dev/null
+++ b/devel/gamin/pkg-plist
@@ -0,0 +1,12 @@
+include/fam.h
+lib/libfam.a
+lib/libfam.la
+lib/libfam.so
+lib/libfam.so.0
+lib/libgamin-1.a
+lib/libgamin-1.la
+lib/libgamin-1.so
+lib/libgamin-1.so.1
+lib/libgamin_shared.a
+libdata/pkgconfig/gamin.pc
+libexec/gam_server