Author: ranger
Date: Tue Jan 2 20:42:38 2007
New Revision: 551
URL:
<http://svn.finkproject.org/websvn/listing.php?sc=1&rev=551&repname=user%3a+ranger>
Log:
libfam builds, time to test it
Added:
trunk/experimental/common/main/finkinfo/libs/fam.info
trunk/experimental/common/main/finkinfo/libs/fam.patch
Added: trunk/experimental/common/main/finkinfo/libs/fam.info
URL:
<http://svn.finkproject.org/websvn/filedetails.php?path=/trunk/experimental/common/main/finkinfo/libs/fam.info&rev=551&repname=user%3a+ranger>
==============================================================================
--- trunk/experimental/common/main/finkinfo/libs/fam.info (added)
+++ trunk/experimental/common/main/finkinfo/libs/fam.info Tue Jan 2 20:42:38
2007
@@ -1,0 +1,55 @@
+Package: fam
+Version: 2.7.0
+Revision: 1
+Depends: %N-shlibs (>= %v-%r)
+BuildDepends: libtool14, autoconf (>= 2.60-1), automake1.9
+
+Source: ftp://oss.sgi.com/projects/%n/download/stable/%n-%v.tar.gz
+Source-MD5: 1bf3ae6c0c58d3201afc97c6a4834e39
+Patch: %n.patch
+
+SetCPPFLAGS: -DHAVE_KQUEUE=1 -DNDEBUG
+SetCFLAGS: -Os
+CompileScript: <<
+#!/bin/sh -ev
+
+ autoreconf -f -v -i
+ ./configure --prefix=%p/lib/%N --mandir=%p/share/man
--sysconfdir=%p/etc --bindir=%p/bin --sbindir=%p/sbin --libexecdir=%p/sbin
+ make
+<<
+
+InstallScript: <<
+ make -j1 install DESTDIR=%d
+ perl -pi -e 's,local_only = false,local_only = true,' %i/etc/fam.conf
+<<
+SplitOff: <<
+ Package: %N-shlibs
+ Description: Shared libraries for FAM
+ Files: lib/%N/lib/libfam.*.dylib
+ Shlibs: %p/lib/%N/lib/libfam.0.dylib 1.0.0 libfam-shlibs (>= 2.7.0-1)
+<<
+SplitOff2: <<
+ Package: %N-dev
+ Depends: %N-shlibs (= %v-%r)
+ Replaces: %N
+ Description: Development headers and libraries for FAM
+ Files: lib share/man/man3
+<<
+
+ConfFiles: %p/etc/fam.conf
+DocFiles: AUTHORS COPYING ChangeLog INSTALL NEWS README TODO
+Description: File Alteration Monitor
+Maintainer: Benjamin Reed <[EMAIL PROTECTED]>
+Homepage: http://oss.sgi.com/projects/fam/
+License: GPL
+DescPackaging: <<
+Includes patches from NetBSD pkgsrc to use the BSD kqueue APIs instead
+of the (linux- and SGI-only) imon support.
+<<
+DescDetail: <<
+GUI tools should not mislead the user; they should display the current
+state of the system, even when changes to the system originate from
+outside of the tools themselves. FAM helps make GUI tools more usable
+by notifying them when the files they're interested in are created,
+modified, executed, and removed.
+<<
Added: trunk/experimental/common/main/finkinfo/libs/fam.patch
URL:
<http://svn.finkproject.org/websvn/filedetails.php?path=/trunk/experimental/common/main/finkinfo/libs/fam.patch&rev=551&repname=user%3a+ranger>
==============================================================================
--- trunk/experimental/common/main/finkinfo/libs/fam.patch (added)
+++ trunk/experimental/common/main/finkinfo/libs/fam.patch Tue Jan 2 20:42:38
2007
@@ -1,0 +1,1482 @@
+diff -uNr fam-2.7.0/configure.ac fam-2.7.0-patched/configure.ac
+--- fam-2.7.0/configure.ac 2003-11-26 14:47:59.000000000 -0500
++++ fam-2.7.0-patched/configure.ac 2007-01-02 13:22:13.000000000 -0500
+@@ -31,7 +31,7 @@
+ # Checks for header files.
+ AC_HEADER_STDC
+ AC_HEADER_DIRENT
+-AC_CHECK_HEADERS([fcntl.h limits.h linux/imon.h netinet/in.h rpc/rpc.h
rpcsvc/mount.h stddef.h stdlib.h string.h syslog.h sys/imon.h sys/param.h
sys/select.h sys/statvfs.h sys/syssgi.h sys/time.h sys/types.h sys/un.h
unistd.h])
++AC_CHECK_HEADERS([fcntl.h limits.h linux/imon.h netinet/in.h rpc/rpc.h
rpc/rpcent.h rpcsvc/mount.h stddef.h stdlib.h string.h syslog.h sys/filio.h
sys/imon.h sys/param.h sys/select.h sys/statvfs.h sys/syssgi.h sys/time.h
sys/types.h sys/un.h unistd.h mntent.h sys/mnttab.h sys/sysmacros.h])
+
+ if test "$have_sys_imon_h"; then
+ MONITOR_FUNCS=IMonIRIX
+@@ -51,12 +51,14 @@
+ AC_TYPE_PID_T
+ AC_TYPE_SIZE_T
+ AC_HEADER_TIME
+-AC_CHECK_MEMBERS(struct sockaddr.sa_len, struct sockaddr_un.sun_len)
++AC_CHECK_MEMBERS(struct sockaddr.sa_len,,,[#include <sys/socket.h>])
++AC_CHECK_MEMBERS(struct sockaddr_un.sun_len,,,[#include <sys/types.h>
++#include <sys/un.h>])
+
+ # Checks for library functions.
+ AC_FUNC_ERROR_AT_LINE
+ AC_FUNC_SELECT_ARGTYPES
+-AC_CHECK_FUNCS([bindresvport _daemonize daemon getgrmember select])
++AC_CHECK_FUNCS([bindresvport _daemonize daemon getgrmember select unsetenv])
+
+ AC_CONFIG_FILES([Makefile
+ src/Makefile
+diff -uNr fam-2.7.0/include/BTree.h fam-2.7.0-patched/include/BTree.h
+--- fam-2.7.0/include/BTree.h 2003-01-19 23:22:30.000000000 -0500
++++ fam-2.7.0-patched/include/BTree.h 2007-01-02 13:22:14.000000000 -0500
+@@ -76,8 +76,6 @@
+
+ static unsigned sizeofnode() { return sizeof (Node); }
+
+-private:
+-
+ enum { fanout = 32 };
+ enum Status { OK, NO, OVER, UNDER };
+
+diff -uNr fam-2.7.0/lib/Client.c++ fam-2.7.0-patched/lib/Client.c++
+--- fam-2.7.0/lib/Client.c++ 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/lib/Client.c++ 2007-01-02 13:22:14.000000000 -0500
+@@ -24,6 +24,7 @@
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <netinet/in.h>
++#include <arpa/inet.h>
+ #include <sys/un.h>
+ #include <sys/socket.h>
+ #include <rpc/rpc.h>
+diff -uNr fam-2.7.0/lib/fam.c++ fam-2.7.0-patched/lib/fam.c++
+--- fam-2.7.0/lib/fam.c++ 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/lib/fam.c++ 2007-01-02 13:22:14.000000000 -0500
+@@ -20,8 +20,12 @@
+ // with this program; if not, write the Free Software Foundation, Inc., 59
+ // Temple Place - Suite 330, Boston MA 02111-1307, USA.
+
++#include "config.h"
+ #include <sys/types.h>
+ #include <rpc/rpc.h>
++#ifdef HAVE_RPC_RPCENT_H
++#include <rpc/rpcent.h>
++#endif
+ #include <sys/time.h>
+ #include <unistd.h>
+ #include <stdlib.h>
+diff -uNr fam-2.7.0/src/Client.h fam-2.7.0-patched/src/Client.h
+--- fam-2.7.0/src/Client.h 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/src/Client.h 2007-01-02 13:22:14.000000000 -0500
+@@ -25,6 +25,7 @@
+
+ #include <sys/types.h>
+ #include <netinet/in.h> // for in_addr
++#include <arpa/inet.h>
+
+ #include "Activity.h"
+ #include "Boolean.h"
+diff -uNr fam-2.7.0/src/FileSystem.c++ fam-2.7.0-patched/src/FileSystem.c++
+--- fam-2.7.0/src/FileSystem.c++ 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/src/FileSystem.c++ 2007-01-02 13:22:13.000000000
-0500
+@@ -22,14 +22,20 @@
+
+ #include "FileSystem.h"
+
+-#include <mntent.h>
++#include "fam-mntent.h"
+ #include <string.h>
+
+ #include "Event.h"
+
++#if defined(HAVE_SYS_MNTTAB_H)
++FileSystem::FileSystem(const mnttab& mnt)
++ : mydir (strcpy(new char[strlen(mnt.mnt_mountp) + 1], mnt.mnt_mountp)),
++ myfsname(strcpy(new char[strlen(mnt.mnt_special) + 1], mnt.mnt_special))
++#else
+ FileSystem::FileSystem(const mntent& mnt)
+ : mydir (strcpy(new char[strlen(mnt.mnt_dir ) + 1], mnt.mnt_dir )),
+ myfsname(strcpy(new char[strlen(mnt.mnt_fsname) + 1], mnt.mnt_fsname))
++#endif
+ { }
+
+ FileSystem::~FileSystem()
+@@ -40,9 +46,15 @@
+ }
+
+ bool
++#if defined(HAVE_SYS_MNTTAB_H)
++FileSystem::matches(const mnttab& mnt) const
++{
++ return !strcmp(mydir, mnt.mnt_mountp) && !strcmp(myfsname,
mnt.mnt_special);
++#else
+ FileSystem::matches(const mntent& mnt) const
+ {
+ return !strcmp(mydir, mnt.mnt_dir) && !strcmp(myfsname, mnt.mnt_fsname);
++#endif
+ }
+
+ void
+diff -uNr fam-2.7.0/src/FileSystem.h fam-2.7.0-patched/src/FileSystem.h
+--- fam-2.7.0/src/FileSystem.h 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/src/FileSystem.h 2007-01-02 13:22:14.000000000 -0500
+@@ -27,7 +27,13 @@
+ #include "Request.h"
+ #include "Set.h"
+
++#include "fam-mntent.h"
++
++#if defined(HAVE_SYS_MNTTAB_H)
++struct mnttab;
++#else
+ struct mntent;
++#endif
+ struct stat;
+
+ // FileSystem is the abstract base class for a per-filesystem object.
+@@ -91,12 +97,20 @@
+
+ typedef Set<ClientInterest *> Interests;
+
++#if defined(HAVE_SYS_MNTTAB_H)
++ FileSystem(const mnttab&);
++#else
+ FileSystem(const mntent&);
++#endif
+ virtual ~FileSystem();
+
+ // Miscellaneous routines
+
++#if defined(HAVE_SYS_MNTTAB_H)
++ bool matches(const mnttab& m) const;
++#else
+ bool matches(const mntent& m) const;
++#endif
+ const char *dir() const { return mydir; }
+ const char *fsname() const { return myfsname; }
+ const Interests& interests() { return myinterests; }
+diff -uNr fam-2.7.0/src/FileSystemTable.c++
fam-2.7.0-patched/src/FileSystemTable.c++
+--- fam-2.7.0/src/FileSystemTable.c++ 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/src/FileSystemTable.c++ 2007-01-02 13:22:13.000000000
-0500
+@@ -21,11 +21,13 @@
+ // Temple Place - Suite 330, Boston MA 02111-1307, USA.
+
+ #include <stddef.h>
++#include <stdio.h>
+ #include "FileSystemTable.h"
+
+-#include <mntent.h>
++#include "fam-mntent.h"
+ #include <stdlib.h>
+ #include <string.h>
++#include <sys/param.h>
+
+ #if HAVE_STATVFS
+ #include <sys/statvfs.h>
+@@ -106,7 +108,11 @@
+
+ // Read /etc/mtab.
+ Cred::SuperUser.become_user();
++#if defined(HAVE_SYS_MNTTAB_H)
++ FILE *mtab = fopen(mtab_name, "r");
++#else
+ FILE *mtab = setmntent(mtab_name, "r");
++#endif
+ if(mtab == NULL)
+ {
+ Log::error("couldn't open %s for reading", mtab_name);
+@@ -114,40 +120,86 @@
+ return;
+ }
+ root = NULL;
++#if defined(HAVE_SYS_MNTTAB_H)
++ resetmnttab(mtab);
++ int ret = 0;
++ do
++#else
+ for (mntent *mp; ((mp = getmntent(mtab)) != NULL); )
++#endif
+ {
++#if defined(HAVE_SYS_MNTTAB_H)
++ struct mnttab ment, *mp;
++ mp = &ment;
++ ret = getmntent(mtab, mp);
++ FileSystem *fs = fs_by_name ? fs_by_name->find(mp->mnt_mountp) : NULL;
++#else
+ FileSystem *fs = fs_by_name ? fs_by_name->find(mp->mnt_dir) : NULL;
++#endif
+ if (fs && fs->matches(*mp))
+ {
+ Log::debug("mtab: MATCH \"%s\" on \"%s\" using type <%s>",
++#if defined(HAVE_SYS_MNTTAB_H)
++ mp->mnt_special, mp->mnt_mountp, mp->mnt_fstype);
++
++ new_fs_by_name->insert(mp->mnt_mountp, fs);
++ if (dismounted_fses.find(mp->mnt_mountp))
++ dismounted_fses.remove(mp->mnt_mountp);
++#else
+ mp->mnt_fsname, mp->mnt_dir, mp->mnt_type);
+
+ new_fs_by_name->insert(mp->mnt_dir, fs);
+ if (dismounted_fses.find(mp->mnt_dir))
+ dismounted_fses.remove(mp->mnt_dir);
++#endif
+ }
+ else
+ {
+
++#if defined(HAVE_SYS_MNTTAB_H)
++ if ((!strcmp(mp->mnt_fstype, MNTTYPE_NFS)
++#else
+ if ((!strcmp(mp->mnt_type, MNTTYPE_NFS)
++#endif
+ #if HAVE_MNTTYPE_NFS2
++#if defined(HAVE_SYS_MNTTAB_H)
++ || !strcmp(mp->mnt_fstype, MNTTYPE_NFS2)
++#else
+ || !strcmp(mp->mnt_type, MNTTYPE_NFS2)
+ #endif
++#endif
+ #if HAVE_MNTTYPE_NFS3
++#if defined(HAVE_SYS_MNTTAB_H)
++ || !strcmp(mp->mnt_fstype, MNTTYPE_NFS3)
++#else
+ || !strcmp(mp->mnt_type, MNTTYPE_NFS3)
+ #endif
++#endif
+ #if HAVE_MNTTYPE_CACHEFS
++#if defined(HAVE_SYS_MNTTAB_H)
++ || !strcmp(mp->mnt_fstype, MNTTYPE_CACHEFS)
++#else
+ || !strcmp(mp->mnt_type, MNTTYPE_CACHEFS)
+ #endif
++#endif
++#if defined(HAVE_SYS_MNTTAB_H)
++ ) && strchr(mp->mnt_special, ':'))
++#else
+ ) && strchr(mp->mnt_fsname, ':'))
++#endif
+ {
+ if(Log::get_level() == Log::DEBUG)
+ {
+ const char *mntopt = hasmntopt(mp, "dev");
+ if(mntopt == NULL) mntopt = "";
+ Log::debug("mtab: new NFS \"%s\" on \"%s\" %s using <%s>",
++#if defined(HAVE_SYS_MNTTAB_H)
++ mp->mnt_special, mp->mnt_mountp, mntopt,
++ mp->mnt_fstype);
++#else
+ mp->mnt_fsname, mp->mnt_dir, mntopt,
+ mp->mnt_type);
++#endif
+ }
+
+ fs = new NFSFileSystem(*mp);
+@@ -155,24 +207,45 @@
+ else
+ {
+ Log::debug("mtab: new local \"%s\" on \"%s\"",
++#if defined(HAVE_SYS_MNTTAB_H)
++ mp->mnt_special, mp->mnt_mountp);
++#else
+ mp->mnt_fsname, mp->mnt_dir);
++#endif
+
+ fs = new LocalFileSystem(*mp);
+ }
++#if defined(HAVE_SYS_MNTTAB_H)
++ new_fs_by_name->insert(mp->mnt_mountp, fs);
++#else
+ new_fs_by_name->insert(mp->mnt_dir, fs);
++#endif
+ if (fs_by_name)
+ {
+ // Find parent filesystem.
+
++#if defined(HAVE_SYS_MNTTAB_H)
++ FileSystem *parent = longest_prefix(mp->mnt_mountp);
++#else
+ FileSystem *parent = longest_prefix(mp->mnt_dir);
++#endif
+ assert(parent);
+ mount_parents.insert(parent->dir(), parent);
+ }
+ }
++#if defined(HAVE_SYS_MNTTAB_H)
++ if (!strcmp(mp->mnt_mountp, "/"))
++#else
+ if (!strcmp(mp->mnt_dir, "/"))
++#endif
+ root = fs;
+ }
++#if defined(HAVE_SYS_MNTTAB_H)
++ while (ret != -1);
++ fclose(mtab);
++#else
+ endmntent(mtab);
++#endif
+
+ if(root == NULL)
+ {
+@@ -255,7 +328,10 @@
+ // create_fs_by_name initializes our "root" member variable.
+ if (!fs_by_name)
+ { create_fs_by_name();
++#if !defined(BSD)
++ /* there is no mtab "file" in BSD */
+ mtab_watcher = new InternalClient(mtab_name, mtab_event_handler, NULL);
++#endif
+ }
+
+ cr.become_user();
+diff -uNr fam-2.7.0/src/IMon.c++ fam-2.7.0-patched/src/IMon.c++
+--- fam-2.7.0/src/IMon.c++ 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/src/IMon.c++ 2007-01-02 13:22:13.000000000 -0500
+@@ -25,6 +25,7 @@
+ #include <assert.h>
+ #include <errno.h>
+ #include <fcntl.h>
++#include <sys/param.h>
+
+ #if HAVE_IMON
+ #ifdef __sgi
+@@ -32,15 +33,18 @@
+ #else
+ #include <linux/imon.h>
+ #endif
++#else // HAVE_IMON
++#include "imon-compat.h"
+ #endif
+
++#if HAVE_SYS_SYSMACROS_H
+ #include <sys/sysmacros.h>
++#endif
+ #include <unistd.h>
+
+ #include "Interest.h"
+ #include "Log.h"
+ #include "Scheduler.h"
+-#include "alloc.h"
+
+ int IMon::imonfd = -2;
+ IMon::EventHandler IMon::ehandler = NULL;
+diff -uNr fam-2.7.0/src/IMonKQueue.c++ fam-2.7.0-patched/src/IMonKQueue.c++
+--- fam-2.7.0/src/IMonKQueue.c++ 1969-12-31 19:00:00.000000000 -0500
++++ fam-2.7.0-patched/src/IMonKQueue.c++ 2007-01-02 13:23:06.000000000
-0500
+@@ -0,0 +1,453 @@
++// $NetBSD: IMonKQueue.c++,v 1.3 2005/01/05 16:21:06 jmmv Exp $
++//
++// Copyright (c) 2004, 2005 Julio M. Merino Vidal.
++//
++// This program is free software; you can redistribute it and/or modify it
++// under the terms of version 2 of the GNU General Public License as
++// published by the Free Software Foundation.
++//
++// This program is distributed in the hope that it would be useful, but
++// WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any
++// license provided herein, whether implied or otherwise, is limited to
++// this program in accordance with the express provisions of the GNU
++// General Public License. Patent licenses, if any, provided herein do not
++// apply to combinations of this program with other product or programs, or
++// any other product whatsoever. This program is distributed without any
++// warranty that the program is delivered free of the rightful claim of any
++// third person by way of infringement or the like. See the GNU General
++// Public License for more details.
++//
++// You should have received a copy of the GNU General Public License along
++// with this program; if not, write the Free Software Foundation, Inc., 59
++// Temple Place - Suite 330, Boston MA 02111-1307, USA.
++
++// ------------------------------------------------------------------------
++
++// imon emulation through kqueue
++// -----------------------------
++//
++// The code in this file provides an imon-like interface to FAM using kqueue,
++// the kernel event notification mechanism found in FreeBSD, NetBSD and
++// OpenBSD.
++//
++// The idea is the following: a thread, kqueue_monitor, simulates the kernel
++// part of imon. This thread can receive commands (ioctl(2)s) and produces
++// notifications when there is something to notify. The thread is constantly
++// running in the background, calling kevent(2) to see if there are new
++// events in the monitored files since the last call.
++//
++// Communication with kqueue_monitor is accomplished by using two pipes.
++// pipe_out is used by the monitor to provide notifications; i.e., it is the
++// same as the read end of the regular /dev/imon device, and produces
++// compatible messages. On the other hand we have pipe_in, which is used
++// to give commands to the monitor (express and revoke); we can't emulate
++// ioctl(2)s from user space, so we have to go this route.
++//
++// Why we use pipe_in to provide commands to the thread, instead of some
++// mutexes? If we used mutexes, we'd have to give kevent(2) a timeout, to
++// let it "reload" the list of changes to be monitored in case it was
++// externally modified. By using a pipe, we can tell kqueue(2) to monitor
++// it for us, and let kevent(2) immediately return when there is a command
++// to process.
++//
++// However, there is a little problem when using kqueue instead of imon or
++// polling. kqueue(2) works by monitoring open file descriptors, instead
++// of inodes on the disk. Therefore we must keep all files being monitored
++// open, and the number of open files can quickly raise in some environments.
++// This is why the code unlimits the number of open files in imon_open and
++// sets a reasonable maximum based on kern.maxfiles (to avoid overflowing
++// it quickly). If we overflow this limit, the poller will enter the game
++// (because we will return an error).
++//
++// Known problem: if we receive *lots* of events quickly, famd may end up
++// locked. To reproduce, run the test program provided by fam against a
++// local directory, say /tmp/foo, and do the following:
++// cd /tmp/foo; for f in $(jot 1000); do touch $(jot 100); rm *; done
++// You should receive some messages like:
++// famd[21058]: kqueue can't revoke "75", dev = 0, ino = 1113421
++// while the test is running (not a lot), and it will eventually lock up.
++//
++// Having said all this, let's go to the code...
++
++// ------------------------------------------------------------------------
++
++#include "IMon.h"
++#include "Log.h"
++
++#include "config.h"
++#include "imon-compat.h"
++
++#include <sys/event.h>
++#include <sys/param.h>
++#include <sys/resource.h>
++#include <sys/sysctl.h>
++#include <sys/time.h>
++
++#include <assert.h>
++#include <fcntl.h>
++#include <pthread.h>
++#include <string.h>
++#include <unistd.h>
++
++#include <map>
++
++// ------------------------------------------------------------------------
++
++// devino is a structure that holds a device/inode pair. It is used as an
++// indentifier of files managed by imon.
++struct devino {
++ dev_t di_dev;
++ ino_t di_ino;
++
++ bool operator<(const struct devino& di) const
++ { return (di_dev < di.di_dev) or
++ (di_dev == di.di_dev and di_ino < di.di_ino); }
++};
++
++// imon_cmd simulates commands thrown to imon as ioctl(2)s (but remember
++// we use a pipe).
++struct imon_cmd {
++#define IMON_CMD_EXPRESS 0
++#define IMON_CMD_REVOKE 1
++ int ic_type;
++
++ // imon identifies files through a device/inode pair.
++ struct devino ic_di;
++
++ // A pipe that will be used to receive the result of the command
++ // (asynchronously).
++ int ic_stat[2];
++
++ // If this is an 'express' command, we need the descriptor to monitor.
++ int ic_fd;
++};
++
++// ------------------------------------------------------------------------
++
++static int max_changes;
++static int last_change;
++static int kqueue_fd;
++static int pipe_in[2], pipe_out[2];
++static pthread_t kevent_thread;
++static struct kevent *changes;
++
++typedef std::map<struct devino, int> DEVINOFD_MAP;
++static DEVINOFD_MAP devino_to_fd;
++typedef std::map<int, struct devino> FDDEVINO_MAP;
++static FDDEVINO_MAP fd_to_devino;
++
++// ------------------------------------------------------------------------
++
++static void *kqueue_monitor(void *data);
++static void process_command(void);
++
++// ------------------------------------------------------------------------
++
++int
++IMon::imon_open(void)
++{
++ // Get the kernel event queue. We only need one during all the life
++ // of famd.
++ kqueue_fd = kqueue();
++ if (kqueue_fd == -1)
++ return -1;
++
++ // Create "emulation" pipes.
++ if (pipe(pipe_in) == -1) {
++ close(kqueue_fd);
++ return -1;
++ }
++ if (pipe(pipe_out) == -1) {
++ close(kqueue_fd);
++ close(pipe_in[0]); close(pipe_in[1]);
++ return -1;
++ }
++
++ // Get the maximum number of files we can open and use it to set a
++ // limit of the files we can monitor.
++ size_t len = sizeof(max_changes);
++ if (sysctlbyname("kern.maxfiles", &max_changes, &len, NULL, 0) == -1)
++ max_changes = 128;
++ else
++ max_changes /= 2;
++
++ // Unlimit maximum number of open files. We don't go to RLIM_INFINITY
++ // to avoid possible open descriptor leaks produce a system DoS. 75%
++ // of the system limit seems a good number (we request more than the
++ // number calculated previously to leave room for temporary pipes).
++ // We need to be root to do this.
++ uid_t olduid = geteuid();
++ seteuid(0);
++ struct rlimit rlp;
++ rlp.rlim_cur = rlp.rlim_max = max_changes * 3 / 2;
++ if (setrlimit(RLIMIT_NOFILE, &rlp) == -1)
++ Log::error("can't unlimit number of open files");
++ seteuid(olduid);
++
++ changes = new struct kevent[max_changes];
++
++ // We must monitor pipe_in for any commands that may alter the actual
++ // set of files being monitored.
++ EV_SET(&changes[0], pipe_in[0], EVFILT_READ,
++ EV_ADD | EV_ENABLE | EV_ONESHOT, 0, 0, 0);
++ last_change = 1;
++
++ // Create a thread that will run the kevent(2) function continuously.
++ if (pthread_create(&kevent_thread, NULL, kqueue_monitor, NULL) != 0) {
++ close(kqueue_fd);
++ close(pipe_in[0]); close(pipe_in[1]);
++ close(pipe_out[0]); close(pipe_out[1]);
++ return -1;
++ }
++
++ return pipe_out[0];
++}
++
++// ------------------------------------------------------------------------
++
++IMon::Status
++IMon::imon_express(const char *name, struct stat *status)
++{
++ // Get file information.
++ struct stat sb;
++ if (status == NULL)
++ status = &sb;
++ if (lstat(name, status) == -1)
++ return BAD;
++
++ // Open the file to be monitored; kqueue only works with open descriptors
++ // so we have to keep this descriptor during the life of this 'interest'.
++ int fd = open(name, O_RDONLY);
++ if (fd == -1)
++ return BAD;
++
++ // Construct a command to 'express' interest in a file. This will be
++ // handled by the kqueue_monitor thread as soon as possible.
++ struct imon_cmd cmd;
++ cmd.ic_type = IMON_CMD_EXPRESS;
++ cmd.ic_di.di_dev = status->st_dev;
++ cmd.ic_di.di_ino = status->st_ino;
++ cmd.ic_fd = fd;
++ if (pipe(cmd.ic_stat) == -1) {
++ close(fd);
++ return BAD;
++ }
++ write(pipe_in[1], &cmd, sizeof(struct imon_cmd));
++
++ // Wait for a result form the previous operation.
++ bool result;
++ read(cmd.ic_stat[0], &result, sizeof(bool));
++ close(cmd.ic_stat[0]); close(cmd.ic_stat[1]);
++ if (!result) {
++ close(fd);
++ Log::error("kqueue can't monitor more than %d files", max_changes);
++ return BAD;
++ }
++
++ Log::debug("told kqueue to monitor \"%s\", descriptor = %d, dev = %d, "
++ "ino = %d", name, cmd.ic_fd, cmd.ic_di.di_dev,
++ cmd.ic_di.di_ino);
++
++ return OK;
++}
++
++// ------------------------------------------------------------------------
++
++IMon::Status
++IMon::imon_revoke(const char *name, dev_t dev, ino_t ino)
++{
++ // Construct a command to 'revoke' interest from a file. This will be
++ // handled by the kqueue_monitor thread as soon as possible.
++ struct imon_cmd cmd;
++ cmd.ic_type = IMON_CMD_REVOKE;
++ cmd.ic_di.di_dev = dev;
++ cmd.ic_di.di_ino = ino;
++ if (pipe(cmd.ic_stat) == -1)
++ return BAD;
++ write(pipe_in[1], &cmd, sizeof(struct imon_cmd));
++
++ // Wait for a result form the previous operation.
++ bool result;
++ read(cmd.ic_stat[0], &result, sizeof(bool));
++ close(cmd.ic_stat[0]); close(cmd.ic_stat[1]);
++ if (!result) {
++ Log::error("kqueue can't revoke \"%s\", dev = %d, ino = %d", name,
++ cmd.ic_di.di_dev, cmd.ic_di.di_ino);
++ return BAD;
++ }
++
++ Log::debug("told kqueue to forget \"%s\", dev = %d, ino = %d", name,
++ cmd.ic_di.di_dev, cmd.ic_di.di_ino);
++
++ return OK;
++}
++
++// ------------------------------------------------------------------------
++
++static void *
++kqueue_monitor(void *data)
++{
++ struct kevent event;
++
++ for (;;) {
++ int nev = kevent(kqueue_fd, changes, last_change, &event, 1, NULL);
++ if (nev == -1)
++ Log::perror("kevent");
++ else if (nev > 0) {
++ assert(nev == 1);
++
++ if (event.flags & EV_ERROR) {
++ int fd = event.ident;
++
++ FDDEVINO_MAP::const_iterator iter = fd_to_devino.find(fd);
++ assert(iter != fd_to_devino.end());
++ struct devino di = iter->second;
++
++ Log::error("kqueue returned error for fd = %d, dev = %d, "
++ "ino = %d", fd, di.di_dev, di.di_ino);
++
++ // Remove offending entry from the mappings.
++ assert(devino_to_fd.find(di) != devino_to_fd.end());
++ devino_to_fd.erase(di);
++ assert(devino_to_fd.find(di) == devino_to_fd.end());
++ assert(fd_to_devino.find(fd) != fd_to_devino.end());
++ fd_to_devino.erase(fd);
++ assert(fd_to_devino.find(fd) == fd_to_devino.end());
++
++ // Remove the entry associated to the descriptor from the list
++ // of changes monitored by kqueue.
++ int i;
++ for (i = 1; i < last_change; i++)
++ if (changes[i].ident == fd)
++ break;
++ for (int j = i; j < last_change - 1; j++)
++ changes[j] = changes[j + 1];
++ last_change--;
++
++ close(fd);
++
++ continue;
++ }
++
++ if (event.ident == pipe_in[0]) {
++ // We have got a control command, so process it.
++ process_command();
++ } else {
++ // One of the descriptors we are monitoring has got activity.
++ FDDEVINO_MAP::const_iterator iter =
++ fd_to_devino.find(event.ident);
++ if (iter != fd_to_devino.end()) {
++ qelem_t elem;
++
++ // Set device/inode identifier on imon element.
++ const struct devino &di = (*iter).second;
++ elem.qe_dev = di.di_dev;
++ elem.qe_inode = di.di_ino;
++
++ // Convert the modification flags reported by kqueue to
++ // flags understood by imon.
++ elem.qe_what = 0;
++ if (event.fflags & NOTE_DELETE)
++ elem.qe_what |= IMON_DELETE;
++ if (event.fflags & NOTE_RENAME)
++ elem.qe_what |= IMON_RENAME;
++ if (event.fflags & NOTE_ATTRIB or event.fflags &
NOTE_LINK)
++ elem.qe_what |= IMON_ATTRIBUTE;
++ if (event.fflags & NOTE_WRITE or event.fflags &
NOTE_EXTEND)
++ elem.qe_what |= IMON_CONTENT;
++
++ // Deliver the element.
++ write(pipe_out[1], &elem, sizeof(qelem_t));
++ } else
++ Log::error("got an event from an unhandled device/inode "
++ "pair");
++ }
++ }
++ }
++}
++
++// ------------------------------------------------------------------------
++
++static void
++process_command(void)
++{
++ bool result = false;
++ struct imon_cmd cmd;
++
++ // Read the command from the control pipe.
++ read(pipe_in[0], &cmd, sizeof(struct imon_cmd));
++ if (cmd.ic_type == IMON_CMD_EXPRESS) {
++ Log::debug("process_command: express, dev = %d, ino = %d",
++ cmd.ic_di.di_dev, cmd.ic_di.di_ino);
++ if (devino_to_fd.find(cmd.ic_di) != devino_to_fd.end()) {
++ // The file is already being monitored.
++ close(cmd.ic_fd);
++ result = true;
++ } else if (fd_to_devino.find(cmd.ic_fd) != fd_to_devino.end()) {
++ // We can't receive a new interest of a descriptor that is
++ // already being monitored. If this happens, there is an
++ // inconsistency in the data somewhere.
++ assert(false);
++ } else if (last_change < max_changes) {
++ // Add the new descriptor to the list of changes to monitor.
++ // We watch for any change that happens on it.
++ EV_SET(&changes[last_change], cmd.ic_fd, EVFILT_VNODE,
++ EV_ADD | EV_ENABLE | EV_ONESHOT,
++ NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |
++ NOTE_LINK | NOTE_RENAME | NOTE_REVOKE,
++ 0, 0);
++ last_change++;
++
++ // Map the device/inode pair to the file descriptor associated
++ // to it and viceversa. We will need this information during
++ // 'revoke' and when we receive events. We use two different
++ // maps to speed up searches in both directions later.
++ assert(devino_to_fd.find(cmd.ic_di) == devino_to_fd.end());
++ devino_to_fd.insert
++ (DEVINOFD_MAP::value_type(cmd.ic_di, cmd.ic_fd));
++ assert(devino_to_fd.find(cmd.ic_di) != devino_to_fd.end());
++ assert(fd_to_devino.find(cmd.ic_fd) == fd_to_devino.end());
++ fd_to_devino.insert
++ (FDDEVINO_MAP::value_type(cmd.ic_fd, cmd.ic_di));
++ assert(fd_to_devino.find(cmd.ic_fd) != fd_to_devino.end());
++
++ result = true;
++ }
++ } else if (cmd.ic_type == IMON_CMD_REVOKE) {
++ Log::debug("process_command: revoke, dev = %d, ino = %d",
++ cmd.ic_di.di_dev, cmd.ic_di.di_ino);
++ DEVINOFD_MAP::const_iterator iter = devino_to_fd.find(cmd.ic_di);
++ if (iter != devino_to_fd.end()) {
++ // Get the descriptor associated to the given device/inode pair
++ // and remove the mapping from the required structure.
++ int fd = (*iter).second;
++ assert(devino_to_fd.find(cmd.ic_di) != devino_to_fd.end());
++ devino_to_fd.erase(cmd.ic_di);
++ assert(devino_to_fd.find(cmd.ic_di) == devino_to_fd.end());
++ assert(fd_to_devino.find(fd) != fd_to_devino.end());
++ fd_to_devino.erase(fd);
++ assert(fd_to_devino.find(fd) == fd_to_devino.end());
++
++ // Remove the entry associated to the descriptor from the list
++ // of changes monitored by kqueue.
++ int i;
++ for (i = 1; i < last_change; i++)
++ if (changes[i].ident == fd)
++ break;
++ for (int j = i; j < last_change - 1; j++)
++ changes[j] = changes[j + 1];
++ last_change--;
++
++ close(fd);
++
++ result = true;
++ }
++ } else {
++ // Huh? Unknown command received.
++ assert(false);
++ }
++
++ // Deliver the result of the operation.
++ write(cmd.ic_stat[1], &result, sizeof(bool));
++}
+diff -uNr fam-2.7.0/src/Interest.c++ fam-2.7.0-patched/src/Interest.c++
+--- fam-2.7.0/src/Interest.c++ 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/src/Interest.c++ 2007-01-02 13:22:13.000000000 -0500
+@@ -23,7 +23,9 @@
+ #include "Interest.h"
+
+ #include <sys/param.h>
++#if HAVE_SYS_SYSMACROS_H
+ #include <sys/sysmacros.h>
++#endif
+
+ #include <errno.h>
+ #include <string.h>
+@@ -46,7 +48,7 @@
+ #include "Pollster.h"
+ #include "timeval.h"
+
+-Interest *Interest::hashtable[];
++Interest *Interest::hashtable[HASHSIZE];
+ IMon Interest::imon(imon_handler);
+ bool Interest::xtab_verification = true;
+
+diff -uNr fam-2.7.0/src/InternalClient.c++
fam-2.7.0-patched/src/InternalClient.c++
+--- fam-2.7.0/src/InternalClient.c++ 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/src/InternalClient.c++ 2007-01-02 13:22:13.000000000
-0500
+@@ -35,8 +35,8 @@
+ {
+ assert(filename);
+ assert(h);
+- assert(filename[0] == '/');
+ Log::debug("%s watching %s", name(), filename);
++ assert(filename[0] == '/');
+ interest = new File(filename, this, Request(0), Cred::SuperUser);
+ }
+
+diff -uNr fam-2.7.0/src/Listener.c++ fam-2.7.0-patched/src/Listener.c++
+--- fam-2.7.0/src/Listener.c++ 2003-01-19 19:37:29.000000000 -0500
++++ fam-2.7.0-patched/src/Listener.c++ 2007-01-02 13:22:13.000000000 -0500
+@@ -22,6 +22,8 @@
+
+ #include "Listener.h"
+
++#include <stdio.h>
++#include <stdlib.h>
+ #include <assert.h>
+ #include <fcntl.h>
+ #include <sys/types.h>
+@@ -32,6 +34,7 @@
+ #include <rpc/clnt.h>
+ #include <sys/ioctl.h>
+ #include <sys/socket.h>
++#include <sys/param.h>
+ #include <sys/stat.h>
+ #include <sys/un.h>
+ #include <unistd.h>
+@@ -205,11 +208,11 @@
+ #ifdef HAVE_UNSETENV
+ unsetenv("TMPDIR");
+ #else
+- putenv("TMPDIR=");
++ putenv("TMPDIR=/tmp");
+ #endif
+
+ char *tmpfile = tempnam("/tmp", ".fam");
+-#ifdef HAVE_SOCKADDR_SUN_LEN
++#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
+ sockaddr_un sun = { sizeof(sockaddr_un), AF_UNIX, "" };
+ #else
+ sockaddr_un sun = { AF_UNIX, "" };
+@@ -283,7 +286,7 @@
+
+ // Get the new socket.
+
+-#ifdef HAVE_SOCKADDR_SUN_LEN
++#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
+ struct sockaddr_un sun = { sizeof(sockaddr_un), AF_UNIX, "" };
+ #else
+ struct sockaddr_un sun = { AF_UNIX, "" };
+@@ -349,7 +352,7 @@
+ void
+ Listener::dirty_ugly_hack()
+ {
+-#ifdef HAVE_SOCKADDR_SUN_LEN
++#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
+ static sockaddr_un sun = { sizeof (sockaddr_un), AF_UNIX,
"/tmp/.fam_socket" };
+ #else
+ static sockaddr_un sun = { AF_UNIX, "/tmp/.fam_socket" };
+diff -uNr fam-2.7.0/src/LocalFileSystem.c++
fam-2.7.0-patched/src/LocalFileSystem.c++
+--- fam-2.7.0/src/LocalFileSystem.c++ 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/src/LocalFileSystem.c++ 2007-01-02 13:22:14.000000000
-0500
+@@ -27,7 +27,11 @@
+ #include "Log.h"
+ #include "Pollster.h"
+
++#if defined(HAVE_SYS_MNTTAB_H)
++LocalFileSystem::LocalFileSystem(const mnttab& mnt)
++#else
+ LocalFileSystem::LocalFileSystem(const mntent& mnt)
++#endif
+ : FileSystem(mnt)
+ { }
+
+diff -uNr fam-2.7.0/src/LocalFileSystem.h
fam-2.7.0-patched/src/LocalFileSystem.h
+--- fam-2.7.0/src/LocalFileSystem.h 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/src/LocalFileSystem.h 2007-01-02 13:22:14.000000000
-0500
+@@ -38,7 +38,11 @@
+
+ public:
+
++#if defined(HAVE_SYS_MNTTAB_H)
++ LocalFileSystem(const mnttab&);
++#else
+ LocalFileSystem(const mntent&);
++#endif
+
+ virtual bool dir_entries_scanned() const;
+ virtual int get_attr_cache_timeout() const;
+diff -uNr fam-2.7.0/src/Log.c++ fam-2.7.0-patched/src/Log.c++
+--- fam-2.7.0/src/Log.c++ 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/src/Log.c++ 2007-01-02 13:22:14.000000000 -0500
+@@ -28,9 +28,9 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <syslog.h>
++#include <sys/time.h>
+ #include <sys/resource.h>
+ #include <sys/stat.h>
+-#include <sys/time.h>
+ #include <sys/types.h>
+ #include <unistd.h>
+ #ifdef HAVE_AUDIT
+diff -uNr fam-2.7.0/src/NFSFileSystem.c++
fam-2.7.0-patched/src/NFSFileSystem.c++
+--- fam-2.7.0/src/NFSFileSystem.c++ 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/src/NFSFileSystem.c++ 2007-01-02 13:22:13.000000000
-0500
+@@ -24,7 +24,7 @@
+ #include "NFSFileSystem.h"
+
+ #include <assert.h>
+-#include <mntent.h>
++#include "fam-mntent.h"
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
+@@ -41,12 +41,20 @@
+ #define ACREGMIN 3
+ #endif
+
++#if defined(HAVE_SYS_MNTTAB_H)
++NFSFileSystem::NFSFileSystem(const mnttab& mnt)
++#else
+ NFSFileSystem::NFSFileSystem(const mntent& mnt)
++#endif
+ : FileSystem(mnt)
+ {
+ // Extract the host name from the fs name.
+
++#if defined(HAVE_SYS_MNTTAB_H)
++ const char *fsname = mnt.mnt_special;
++#else
+ const char *fsname = mnt.mnt_fsname;
++#endif
+ const char *colon = strchr(fsname, ':');
+ if(colon == NULL)
+ {
+@@ -55,12 +63,12 @@
+ assert(colon);
+ colon = fsname;
+ }
+- char hostname[NAME_MAX + 1];
++ char hostname[MAXPATHLEN + 1];
+ int hostnamelen = colon - fsname;
+- if(hostnamelen > NAME_MAX)
++ if(hostnamelen > MAXPATHLEN)
+ {
+- assert(hostnamelen <= NAME_MAX);
+- hostnamelen = NAME_MAX;
++ assert(hostnamelen <= MAXPATHLEN);
++ hostnamelen = MAXPATHLEN;
+ }
+ strncpy(hostname, fsname, hostnamelen);
+ hostname[hostnamelen] = '\0';
+@@ -84,7 +92,11 @@
+ // acregmin, acregmax, actimeo, and noac options in the mount
+ // options. Otherwise, use defaults.
+
++#if defined(HAVE_SYS_MNTTAB_H)
++ const char * opt = mnt.mnt_mntopts;
++#else
+ const char * opt = mnt.mnt_opts;
++#endif
+
+ bool f_noac = false;
+ bool f_actimeo = false;
+@@ -102,20 +114,20 @@
+ if (strstr(opt, "noac")) {
+ f_noac = true;
+ }
+- if ((p = strstr(opt, "actimeo")))
++ if ((p = strstr((char *)opt, "actimeo")))
+ {
+ if (sscanf(p, "actimeo=%i", &actimeo) == 1) {
+ f_actimeo = true;
+ }
+ }
+
+- if ((p = strstr(opt, "acregmin"))) {
++ if ((p = strstr((char *)opt, "acregmin"))) {
+ if (sscanf(p, "acregmin=%i", &acregmin) == 1) {
+ f_acregmin = true;
+ }
+ }
+
+- if ((p = strstr(opt, "acregmax"))) {
++ if ((p = strstr((char *)opt, "acregmax"))) {
+ if (sscanf(p, "acregmax=%i", &acregmax) == 1) {
+ f_acregmax = true;
+ }
+diff -uNr fam-2.7.0/src/NFSFileSystem.h fam-2.7.0-patched/src/NFSFileSystem.h
+--- fam-2.7.0/src/NFSFileSystem.h 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/src/NFSFileSystem.h 2007-01-02 13:22:14.000000000
-0500
+@@ -39,7 +39,11 @@
+
+ public:
+
++#if defined(HAVE_SYS_MNTTAB_H)
++ NFSFileSystem(const mnttab&);
++#else
+ NFSFileSystem(const mntent&);
++#endif
+ ~NFSFileSystem();
+
+ virtual bool dir_entries_scanned() const;
+diff -uNr fam-2.7.0/src/NetConnection.c++
fam-2.7.0-patched/src/NetConnection.c++
+--- fam-2.7.0/src/NetConnection.c++ 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/src/NetConnection.c++ 2007-01-02 13:22:14.000000000
-0500
+@@ -21,6 +21,7 @@
+ // Temple Place - Suite 330, Boston MA 02111-1307, USA.
+
+ #include "NetConnection.h"
++#include "config.h"
+
+ #include <assert.h>
+ #include <errno.h>
+@@ -29,6 +30,9 @@
+ #include <stdio.h>
+ #include <string.h>
+ #include <sys/ioctl.h>
++#ifdef HAVE_SYS_FILIO_H
++#include <sys/filio.h>
++#endif
+ #include <sys/socket.h>
+ #include <unistd.h>
+ #include <netinet/in.h>
+diff -uNr fam-2.7.0/src/NetConnection.h fam-2.7.0-patched/src/NetConnection.h
+--- fam-2.7.0/src/NetConnection.h 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/src/NetConnection.h 2007-01-02 13:22:14.000000000
-0500
+@@ -68,6 +68,8 @@
+ void ready_for_input(bool);
+ int get_fd() const { return fd; }
+
++ enum { MAXMSGSIZE = PATH_MAX + 40 };
++
+ protected:
+
+ virtual bool input_msg(const char *data, unsigned nbytes) = 0;
+@@ -75,7 +77,6 @@
+
+ private:
+
+- enum { MAXMSGSIZE = PATH_MAX + 40 };
+ typedef u_int32_t Length;
+ typedef struct msgList_s {
+ char msg[MAXMSGSIZE+5]; // + 4 for 32-bit length, + 1 for overflow
+diff -uNr fam-2.7.0/src/RPC_TCP_Connector.c++
fam-2.7.0-patched/src/RPC_TCP_Connector.c++
+--- fam-2.7.0/src/RPC_TCP_Connector.c++ 2003-01-18 09:18:12.000000000
-0500
++++ fam-2.7.0-patched/src/RPC_TCP_Connector.c++ 2007-01-02
13:22:14.000000000 -0500
+@@ -21,11 +21,23 @@
+ // Temple Place - Suite 330, Boston MA 02111-1307, USA.
+
+ #include "RPC_TCP_Connector.h"
++#include "config.h"
++
++#define PORTMAP
+
+ #include <errno.h>
++#ifdef __SUNPRO_CC
++extern "C" {
++#endif
+ #include <rpc/rpc.h>
+ #include <rpc/pmap_prot.h>
++#ifdef __SUNPRO_CC
++}
++#endif
+ #include <sys/ioctl.h>
++#ifdef HAVE_SYS_FILIO_H
++#include <sys/filio.h>
++#endif
+ #include <sys/socket.h>
+ #include <unistd.h>
+ #include <string.h>
+diff -uNr fam-2.7.0/src/Scheduler.h fam-2.7.0-patched/src/Scheduler.h
+--- fam-2.7.0/src/Scheduler.h 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/src/Scheduler.h 2007-01-02 13:22:14.000000000 -0500
+@@ -88,8 +88,6 @@
+ static void loop() { running = true;
+ while (running) select(); }
+
+-private:
+-
+ // Per-filedescriptor info is the set of three handlers and their
+ // closures.
+
+diff -uNr fam-2.7.0/src/ServerHost.h fam-2.7.0-patched/src/ServerHost.h
+--- fam-2.7.0/src/ServerHost.h 2003-01-18 09:18:12.000000000 -0500
++++ fam-2.7.0-patched/src/ServerHost.h 2007-01-02 13:22:14.000000000 -0500
+@@ -24,6 +24,7 @@
+ #define ServerHost_included
+
+ #include <limits.h>
++#include <stdio.h>
+ #include "Boolean.h"
+ #include "ClientInterest.h"
+ #include "RequestMap.h"
+@@ -101,7 +102,7 @@
+ private:
+
+ Request myrequest;
+- char mypath[NAME_MAX];
++ char mypath[MAXPATHLEN];
+
+ };
+
+diff -uNr fam-2.7.0/src/fam-mntent.h fam-2.7.0-patched/src/fam-mntent.h
+--- fam-2.7.0/src/fam-mntent.h 1969-12-31 19:00:00.000000000 -0500
++++ fam-2.7.0-patched/src/fam-mntent.h 2007-01-02 13:22:14.000000000 -0500
+@@ -0,0 +1,62 @@
++/*
++ * mntent
++ * fam-mntent.h - compatability header for BSD
++ *
++ * Copyright (c) 2001 David Rufino <[EMAIL PROTECTED]>
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ */
++
++#if defined(HAVE_MNTENT_H)
++#include <mntent.h>
++#elif defined(HAVE_SYS_MNTTAB_H)
++#include <stdio.h>
++#include <unistd.h>
++#include <sys/mntent.h>
++#include <sys/mnttab.h>
++#define MOUNTED MNTTAB
++#else
++#ifndef _MNTENT_H
++#define _MNTENT_H
++#include <stdio.h>
++
++#define MOUNTED "dummy"
++
++#define MNTTYPE_NFS "nfs"
++
++struct mntent {
++ char *mnt_fsname;
++ char *mnt_dir;
++ char *mnt_type;
++ char *mnt_opts;
++ int mnt_freq;
++ int mnt_passno;
++};
++
++#define setmntent(x,y) ((FILE *)0x1)
++struct mntent *getmntent __P ((FILE *fp));
++char *hasmntopt __P ((const struct mntent *mnt, const char *option));
++#define endmntent(x) ((int)1)
++
++#endif /* _MNTENT_H */
++#endif /* HAVE_MNTENT_H */
+diff -uNr fam-2.7.0/src/imon-compat.h fam-2.7.0-patched/src/imon-compat.h
+--- fam-2.7.0/src/imon-compat.h 1969-12-31 19:00:00.000000000 -0500
++++ fam-2.7.0-patched/src/imon-compat.h 2007-01-02 13:23:12.000000000
-0500
+@@ -0,0 +1,53 @@
++// $NetBSD: imon-compat.h,v 1.1 2004/10/17 19:20:53 jmmv Exp $
++//
++// Copyright (c) 2004 Julio M. Merino Vidal.
++//
++// This program is free software; you can redistribute it and/or modify it
++// under the terms of version 2 of the GNU General Public License as
++// published by the Free Software Foundation.
++//
++// This program is distributed in the hope that it would be useful, but
++// WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any
++// license provided herein, whether implied or otherwise, is limited to
++// this program in accordance with the express provisions of the GNU
++// General Public License. Patent licenses, if any, provided herein do not
++// apply to combinations of this program with other product or programs, or
++// any other product whatsoever. This program is distributed without any
++// warranty that the program is delivered free of the rightful claim of any
++// third person by way of infringement or the like. See the GNU General
++// Public License for more details.
++//
++// You should have received a copy of the GNU General Public License along
++// with this program; if not, write the Free Software Foundation, Inc., 59
++// Temple Place - Suite 330, Boston MA 02111-1307, USA.
++
++#if !defined(IMON_COMPAT_H)
++#define IMON_COMPAT_H
++
++#if defined(HAVE_IMON)
++# error "cannot include imon-compat.h if imon is really present"
++#endif
++
++#if defined(HAVE_KQUEUE)
++#define HAVE_IMON 1
++
++typedef int intmask_t;
++
++typedef struct {
++ dev_t qe_dev;
++ ino_t qe_inode;
++ intmask_t qe_what;
++} qelem_t;
++
++#define IMON_CONTENT (1 << 0)
++#define IMON_ATTRIBUTE (1 << 1)
++#define IMON_DELETE (1 << 2)
++#define IMON_EXEC (1 << 3)
++#define IMON_EXIT (1 << 4)
++#define IMON_RENAME (1 << 5)
++#define IMON_OVER 0xff
++
++#endif // defined(HAVE_KQUEUE)
++
++#endif // !defined(IMON_COMPAT_H)
+diff -uNr fam-2.7.0/src/mntent_compat.c++
fam-2.7.0-patched/src/mntent_compat.c++
+--- fam-2.7.0/src/mntent_compat.c++ 1969-12-31 19:00:00.000000000 -0500
++++ fam-2.7.0-patched/src/mntent_compat.c++ 2007-01-02 13:22:14.000000000
-0500
+@@ -0,0 +1,191 @@
++/*
++ * Copyright (c) 1980, 1989, 1993, 1994
++ * The Regents of the University of California. All rights reserved.
++ * Copyright (c) 2001
++ * David Rufino <[EMAIL PROTECTED]>
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ * must display the following acknowledgement:
++ * This product includes software developed by the University of
++ * California, Berkeley and its contributors.
++ * 4. Neither the name of the University nor the names of its contributors
++ * may be used to endorse or promote products derived from this software
++ * without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ */
++
++/* most of this was ripped from the mount(3) source */
++
++#include "config.h"
++#include "fam-mntent.h"
++#if !defined(HAVE_MNTENT_H) && !defined(HAVE_SYS_MNTTAB_H)
++#include <stdlib.h>
++#include <string.h>
++#include <sys/param.h>
++#include <sys/ucred.h>
++#include <sys/mount.h>
++#if defined(HAVE_SYS_STATVFS_H) && !defined(__APPLE__) &&
!defined(__DragonFly__) && !defined(__FreeBSD__)
++# include <sys/statvfs.h>
++#endif
++
++static int pos = -1;
++static int mntsize = -1;
++static struct mntent _mntent;
++
++char *
++hasmntopt (const struct mntent *mnt, const char *option)
++{
++ int found;
++ char *opt, *optbuf;
++
++ optbuf = strdup(mnt->mnt_opts);
++ found = 0;
++ for (opt = optbuf; (opt = strtok(opt, " ")) != NULL; opt = NULL) {
++ if (!strcasecmp(opt, option)) {
++ opt = opt - optbuf + mnt->mnt_opts;
++ free (optbuf);
++ return (opt);
++ }
++ }
++ free (optbuf);
++ return (NULL);
++}
++
++static char *
++catopt (char *s0, const char *s1)
++{
++ size_t i;
++ char *cp;
++
++ if (s1 == NULL || *s1 == '\0')
++ return s0;
++ if (s0 && *s0) {
++ i = strlen(s0) + strlen(s1) + 1 + 1;
++ if ((cp = (char *)malloc(i)) == NULL)
++ return (NULL);
++ (void)snprintf(cp, i, "%s %s", s0, s1);
++ } else
++ cp = strdup(s1);
++
++ if (s0)
++ free(s0);
++ return (cp);
++}
++
++
++static char *
++flags2opts (int flags)
++{
++ char *res;
++ res = NULL;
++ res = catopt(res, (flags & MNT_RDONLY) ? "ro" : "rw");
++ if (flags & MNT_SYNCHRONOUS) res = catopt(res, "sync");
++ if (flags & MNT_NOEXEC) res = catopt(res, "noexec");
++ if (flags & MNT_NOSUID) res = catopt(res, "nosuid");
++ if (flags & MNT_NODEV) res = catopt(res, "nodev");
++ if (flags & MNT_UNION) res = catopt(res, "union");
++ if (flags & MNT_ASYNC) res = catopt(res, "async");
++#ifdef MNT_NOATIME
++ if (flags & MNT_NOATIME) res = catopt(res, "noatime");
++#endif
++#ifdef MNT_NOCLUSTERR
++ if (flags & MNT_NOCLUSTERR) res = catopt(res, "noclusterr");
++#endif
++#ifdef MNT_NOCLUSTERW
++ if (flags & MNT_NOCLUSTERW) res = catopt(res, "noclusterw");
++#endif
++#ifdef MNT_NOSYMFOLLOW
++ if (flags & MNT_NOSYMFOLLOW) res = catopt(res, "nosymfollow");
++#endif
++#ifdef MNT_SUIDDIR
++ if (flags & MNT_SUIDDIR) res = catopt(res, "suiddir");
++#endif
++#ifdef MNT_NOCOREDUMP
++ if (flags & MNT_NOCOREDUMP) res = catopt(res, "nocoredump");
++#endif
++#ifdef MNT_IGNORE
++ if (flags & MNT_IGNORE) res = catopt(res, "hidden");
++#endif
++#ifdef MNT_SYMPERM
++ if (flags & MNT_SYMPERM) res = catopt(res, "symperm");
++#endif
++#ifdef MNT_NODEVMTIME
++ if (flags & MNT_NODEVMTIME) res = catopt(res, "nodevmtime");
++#endif
++#ifdef MNT_SOFTDEP
++ if (flags & MNT_SOFTDEP) res = catopt(res, "softdep");
++#endif
++
++ return res;
++}
++
++static struct mntent *
++#if defined(HAVE_SYS_STATVFS_H) && !defined(__APPLE__) &&
!defined(__DragonFly__) && !defined(__FreeBSD__)
++statfs_to_mntent (struct statvfs *mntbuf)
++#else
++statfs_to_mntent (struct statfs *mntbuf)
++#endif
++{
++ static char opts_buf[40], *tmp;
++
++ _mntent.mnt_fsname = mntbuf->f_mntfromname;
++ _mntent.mnt_dir = mntbuf->f_mntonname;
++ _mntent.mnt_type = mntbuf->f_fstypename;
++#if defined(HAVE_SYS_STATVFS_H) && !defined(__APPLE__) &&
!defined(__DragonFly__) && !defined(__FreeBSD__)
++ tmp = flags2opts (mntbuf->f_flag);
++#else
++ tmp = flags2opts (mntbuf->f_flags);
++#endif
++ if (tmp) {
++ opts_buf[sizeof(opts_buf)-1] = '\0';
++ strncpy (opts_buf, tmp, sizeof(opts_buf)-1);
++ free (tmp);
++ } else {
++ *opts_buf = '\0';
++ }
++ _mntent.mnt_opts = opts_buf;
++ _mntent.mnt_freq = _mntent.mnt_passno = 0;
++ return (&_mntent);
++}
++
++struct mntent *
++getmntent (FILE *fp)
++{
++#if defined(HAVE_SYS_STATVFS_H) && !defined(__APPLE__) &&
!defined(__DragonFly__) && !defined(__FreeBSD__)
++ static struct statvfs *mntbuf;
++#else
++ static struct statfs *mntbuf;
++#endif
++
++ if (pos == -1 || mntsize == -1)
++ mntsize = getmntinfo (&mntbuf, MNT_NOWAIT);
++
++ ++pos;
++ if (pos == mntsize) {
++ pos = mntsize = -1;
++ return (NULL);
++ }
++
++ return (statfs_to_mntent (&mntbuf[pos]));
++}
++
++#endif /* HAVE_MNTENT_H */
+--- fam-2.7.0/src/Makefile.am 2003-01-19 07:00:17.000000000 -0500
++++ fam-2.7.0-patched/src/Makefile.am 2007-01-02 14:19:24.000000000 -0500
+@@ -71,7 +71,8 @@
+ main.c++ \
+ timeval.c++ \
+ timeval.h \
+- @[EMAIL PROTECTED]
++ IMonKQueue.c++ \
++ mntent_compat.c++
+
+ EXTRA_famd_SOURCES = IMonIrix.c++ IMonLinux.c++ IMonNone.c++
+
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Fink-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/fink-commits