Add gamin, a file and directory monitoring server and API. Gamin can be

used as a drop-in replacement for FAM.  Gamin is designed to be more secure
than FAM as itdoes not require RPC, and runs a separate instance for each
user.  While it is API and ABI compatible with FAM, it does not [yet]
support all of FAM's features.

This version of gamin comes with an optional (defaults to on) kqueue
backend for FreeBSD.  This backend can only be used with UFS file
systems.  If you need FAM-like support on non-UFS file systems, you
must build without the kqueue backend.
This commit is contained in:
Joe Marcus Clarke 2005-04-02 09:08:47 +00:00
parent 56599c1299
commit c87a13d100
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=132163
15 changed files with 1208 additions and 0 deletions

View File

@ -271,6 +271,7 @@
SUBDIR += g-wrap
SUBDIR += g2c
SUBDIR += gaa
SUBDIR += gamin
SUBDIR += gaphor
SUBDIR += gauche-gaunit
SUBDIR += gauche-readline

45
devel/gamin/Makefile Normal file
View File

@ -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>

2
devel/gamin/distinfo Normal file
View File

@ -0,0 +1,2 @@
MD5 (gamin-0.0.26.tar.gz) = 3d716b6533466f9ca69df13c58009981
SIZE (gamin-0.0.26.tar.gz) = 484070

View File

@ -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

View File

@ -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

View File

@ -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([],[

View File

@ -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");

View File

@ -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

View File

@ -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@

View File

@ -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;

View File

@ -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;
+ }
+}
+
+/** @} */

View File

@ -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__ */

View File

@ -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()) {

5
devel/gamin/pkg-descr Normal file
View File

@ -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

10
devel/gamin/pkg-plist Normal file
View File

@ -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