import File Alteration Monitor 2.7.0
FAM, the File Alteration Monitor, provides an API which applications can use to be notified when specific files or directories are changed. from alek@, with minor tweaks by me feedback and ok espie@ martynas@
This commit is contained in:
parent
ae5419667a
commit
98ef4ecd06
40
sysutils/fam/Makefile
Normal file
40
sysutils/fam/Makefile
Normal file
@ -0,0 +1,40 @@
|
||||
# $OpenBSD: Makefile,v 1.1.1.1 2007/04/27 22:00:55 jasper Exp $
|
||||
|
||||
COMMENT= "File Alteration Monitor"
|
||||
|
||||
DISTNAME= fam-2.7.0
|
||||
SHARED_LIBS += fam 0.0 # .0.0
|
||||
CATEGORIES= sysutils
|
||||
|
||||
HOMEPAGE= http://oss.sgi.com/projects/fam/
|
||||
|
||||
MAINTAINER= Aleksander Piotrowski <alek@openbsd.org>
|
||||
|
||||
# GPL
|
||||
PERMIT_PACKAGE_FTP= Yes
|
||||
PERMIT_PACKAGE_CDROM= Yes
|
||||
PERMIT_DISTFILES_FTP= Yes
|
||||
PERMIT_DISTFILES_CDROM= Yes
|
||||
WANTLIB= c m pthread rpcsvc stdc++
|
||||
|
||||
MASTER_SITES= ftp://oss.sgi.com/projects/fam/download/stable/ \
|
||||
http://humppa.nl/distfiles/
|
||||
|
||||
USE_LIBTOOL= Yes
|
||||
|
||||
AUTOCONF_VERSION=2.59
|
||||
CONFIGURE_STYLE=autoconf
|
||||
CONFIGURE_ENV= CXXFLAGS="${CXXFLAGS} -DHAVE_SOCKADDR_SUN_LEN" \
|
||||
LDFLAGS="-pthread"
|
||||
|
||||
post-patch:
|
||||
rm -f ${WRKSRC}/configure
|
||||
|
||||
pre-configure:
|
||||
cp ${FILESDIR}/* ${WRKSRC}/src
|
||||
|
||||
post-install:
|
||||
${INSTALL_DATA_DIR} ${PREFIX}/share/examples/fam/
|
||||
mv ${WRKINST}/${SYSCONFDIR}/fam.conf ${PREFIX}/share/examples/fam/
|
||||
|
||||
.include <bsd.port.mk>
|
5
sysutils/fam/distinfo
Normal file
5
sysutils/fam/distinfo
Normal file
@ -0,0 +1,5 @@
|
||||
MD5 (fam-2.7.0.tar.gz) = G/OubAxY0yAa/JfGpINOOQ==
|
||||
RMD160 (fam-2.7.0.tar.gz) = GJW1eNahQcNtW+5OP7vCopipFDA=
|
||||
SHA1 (fam-2.7.0.tar.gz) = bCMW8CrPiaQcQv/D1/2c9erag6g=
|
||||
SHA256 (fam-2.7.0.tar.gz) = HgqhNmk6Pp9LQ+vXHnvZNM6jGBekpsui7ceqw1O4qT8=
|
||||
SIZE (fam-2.7.0.tar.gz) = 301974
|
459
sysutils/fam/files/IMonKQueue.c++
Normal file
459
sysutils/fam/files/IMonKQueue.c++
Normal file
@ -0,0 +1,459 @@
|
||||
// $OpenBSD: IMonKQueue.c++,v 1.1.1.1 2007/04/27 22:00:55 jasper Exp $
|
||||
// $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);
|
||||
int mib[2];
|
||||
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_MAXFILES;
|
||||
|
||||
if (sysctl(mib, 2, &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));
|
||||
}
|
51
sysutils/fam/files/imon-compat.h
Normal file
51
sysutils/fam/files/imon-compat.h
Normal file
@ -0,0 +1,51 @@
|
||||
// $OpenBSD: imon-compat.h,v 1.1.1.1 2007/04/27 22:00:55 jasper Exp $
|
||||
// $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
|
||||
|
||||
#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(IMON_COMPAT_H)
|
62
sysutils/fam/files/mntent.h
Normal file
62
sysutils/fam/files/mntent.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* mntent
|
||||
* fam-mntent.h - compatability header for BSD
|
||||
*
|
||||
* Copyright (c) 2001 David Rufino <daverufino@btinternet.com>
|
||||
* 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 */
|
194
sysutils/fam/files/mntent_compat.c++
Normal file
194
sysutils/fam/files/mntent_compat.c++
Normal file
@ -0,0 +1,194 @@
|
||||
// $OpenBSD: mntent_compat.c++,v 1.1.1.1 2007/04/27 22:00:55 jasper Exp $
|
||||
/*
|
||||
* Copyright (c) 1980, 1989, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Copyright (c) 2001
|
||||
* David Rufino <daverufino@btinternet.com>
|
||||
*
|
||||
* 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 "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");
|
||||
#ifdef MNT_UNION
|
||||
if (flags & MNT_UNION) res = catopt(res, "union");
|
||||
#endif
|
||||
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 */
|
11
sysutils/fam/patches/patch-conf-fam_conf
Normal file
11
sysutils/fam/patches/patch-conf-fam_conf
Normal file
@ -0,0 +1,11 @@
|
||||
$OpenBSD: patch-conf-fam_conf,v 1.1.1.1 2007/04/27 22:00:55 jasper Exp $
|
||||
--- conf/fam.conf.orig Sun Jan 19 13:20:52 2003
|
||||
+++ conf/fam.conf Fri Apr 27 22:52:14 2007
|
||||
@@ -51,3 +51,7 @@ xtab_verification = true
|
||||
#
|
||||
#nfs_polling_interval = 6
|
||||
|
||||
+#
|
||||
+# bind fam to 127.0.0.1 by default, so it won't allow external connections
|
||||
+#
|
||||
+bind = 127.0.0.1
|
12
sysutils/fam/patches/patch-configure_ac
Normal file
12
sysutils/fam/patches/patch-configure_ac
Normal file
@ -0,0 +1,12 @@
|
||||
$OpenBSD: patch-configure_ac,v 1.1.1.1 2007/04/27 22:00:55 jasper Exp $
|
||||
--- configure.ac.orig Sat Feb 10 16:08:00 2007
|
||||
+++ configure.ac Sat Feb 10 16:08:13 2007
|
||||
@@ -38,7 +38,7 @@ if test "$have_sys_imon_h"; then
|
||||
elif test "$have_linux_imon_h"; then
|
||||
MONITOR_FUNCS=IMonLinux
|
||||
else
|
||||
- MONITOR_FUNCS=IMonNone
|
||||
+ MONITOR_FUNCS=IMonKQueue
|
||||
fi
|
||||
AC_SUBST(MONITOR_FUNCS)
|
||||
|
11
sysutils/fam/patches/patch-src_FileSystemTable_c++
Normal file
11
sysutils/fam/patches/patch-src_FileSystemTable_c++
Normal file
@ -0,0 +1,11 @@
|
||||
$OpenBSD: patch-src_FileSystemTable_c++,v 1.1.1.1 2007/04/27 22:00:55 jasper Exp $
|
||||
--- src/FileSystemTable.c++.orig Sat Jan 18 15:18:12 2003
|
||||
+++ src/FileSystemTable.c++ Tue Apr 24 20:03:39 2007
|
||||
@@ -255,7 +255,6 @@ FileSystemTable::find(const char *path, const Cred& cr
|
||||
// create_fs_by_name initializes our "root" member variable.
|
||||
if (!fs_by_name)
|
||||
{ create_fs_by_name();
|
||||
- mtab_watcher = new InternalClient(mtab_name, mtab_event_handler, NULL);
|
||||
}
|
||||
|
||||
cr.become_user();
|
15
sysutils/fam/patches/patch-src_IMon_c++
Normal file
15
sysutils/fam/patches/patch-src_IMon_c++
Normal file
@ -0,0 +1,15 @@
|
||||
$OpenBSD: patch-src_IMon_c++,v 1.1.1.1 2007/04/27 22:00:55 jasper Exp $
|
||||
--- src/IMon.c++.orig Sat Jan 18 15:18:12 2003
|
||||
+++ src/IMon.c++ Sat Feb 10 19:44:25 2007
|
||||
@@ -32,9 +32,10 @@
|
||||
#else
|
||||
#include <linux/imon.h>
|
||||
#endif
|
||||
+#else
|
||||
+#include "imon-compat.h"
|
||||
#endif
|
||||
|
||||
-#include <sys/sysmacros.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "Interest.h"
|
11
sysutils/fam/patches/patch-src_Interest_c++
Normal file
11
sysutils/fam/patches/patch-src_Interest_c++
Normal file
@ -0,0 +1,11 @@
|
||||
$OpenBSD: patch-src_Interest_c++,v 1.1.1.1 2007/04/27 22:00:55 jasper Exp $
|
||||
--- src/Interest.c++.orig Sat Feb 10 16:43:43 2007
|
||||
+++ src/Interest.c++ Sat Feb 10 16:43:47 2007
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "Interest.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
-#include <sys/sysmacros.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
13
sysutils/fam/patches/patch-src_InternalClient_c++
Normal file
13
sysutils/fam/patches/patch-src_InternalClient_c++
Normal file
@ -0,0 +1,13 @@
|
||||
$OpenBSD: patch-src_InternalClient_c++,v 1.1.1.1 2007/04/27 22:00:55 jasper Exp $
|
||||
--- src/InternalClient.c++.orig Sat Jan 18 15:18:12 2003
|
||||
+++ src/InternalClient.c++ Tue Apr 24 20:03:39 2007
|
||||
@@ -35,8 +35,8 @@ InternalClient::InternalClient(const char *filename,
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
22
sysutils/fam/patches/patch-src_Listener_c++
Normal file
22
sysutils/fam/patches/patch-src_Listener_c++
Normal file
@ -0,0 +1,22 @@
|
||||
$OpenBSD: patch-src_Listener_c++,v 1.1.1.1 2007/04/27 22:00:55 jasper Exp $
|
||||
--- src/Listener.c++.orig Mon Jan 20 01:37:29 2003
|
||||
+++ src/Listener.c++ Tue Apr 24 20:03:39 2007
|
||||
@@ -22,6 +22,9 @@
|
||||
|
||||
#include "Listener.h"
|
||||
|
||||
+#include <stdlib.h>
|
||||
+#include <stdio.h>
|
||||
+
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
@@ -204,8 +207,6 @@ Listener::create_local_client(TCP_Client &inet_client,
|
||||
// Unset TMPDIR to ensure that tempnam() works as desired
|
||||
#ifdef HAVE_UNSETENV
|
||||
unsetenv("TMPDIR");
|
||||
-#else
|
||||
- putenv("TMPDIR=");
|
||||
#endif
|
||||
|
||||
char *tmpfile = tempnam("/tmp", ".fam");
|
20
sysutils/fam/patches/patch-src_Makefile_in
Normal file
20
sysutils/fam/patches/patch-src_Makefile_in
Normal file
@ -0,0 +1,20 @@
|
||||
$OpenBSD: patch-src_Makefile_in,v 1.1.1.1 2007/04/27 22:00:55 jasper Exp $
|
||||
--- src/Makefile.in.orig Mon Jan 20 01:38:44 2003
|
||||
+++ src/Makefile.in Tue Apr 24 20:03:42 2007
|
||||
@@ -161,6 +161,7 @@ famd_SOURCES = \
|
||||
main.c++ \
|
||||
timeval.c++ \
|
||||
timeval.h \
|
||||
+ mntent_compat.c++ \
|
||||
@MONITOR_FUNCS@.c++
|
||||
|
||||
|
||||
@@ -185,7 +186,7 @@ am_famd_OBJECTS = Activity.$(OBJEXT) Client.$(OBJEXT)
|
||||
Scheduler.$(OBJEXT) ServerConnection.$(OBJEXT) \
|
||||
ServerHost.$(OBJEXT) ServerHostRef.$(OBJEXT) \
|
||||
TCP_Client.$(OBJEXT) main.$(OBJEXT) timeval.$(OBJEXT) \
|
||||
- @MONITOR_FUNCS@.$(OBJEXT)
|
||||
+ mntent_compat.c++ @MONITOR_FUNCS@.$(OBJEXT)
|
||||
famd_OBJECTS = $(am_famd_OBJECTS)
|
||||
famd_LDADD = $(LDADD)
|
||||
famd_DEPENDENCIES =
|
2
sysutils/fam/pkg/DESCR
Normal file
2
sysutils/fam/pkg/DESCR
Normal file
@ -0,0 +1,2 @@
|
||||
FAM, the File Alteration Monitor, provides an API which applications can
|
||||
use to be notified when specific files or directories are changed.
|
21
sysutils/fam/pkg/MESSAGE
Normal file
21
sysutils/fam/pkg/MESSAGE
Normal file
@ -0,0 +1,21 @@
|
||||
Because FAM uses RPC, please make sure you have following line in the
|
||||
system portmapper file (/etc/rpc):
|
||||
|
||||
sgi_fam 391002 fam # File Alteration Monitor
|
||||
|
||||
Also make sure that the RPC port mapper is enabled by checking whether
|
||||
portmap=YES is in /etc/rc.conf.local. After that, restart the portmap(8)
|
||||
server.
|
||||
|
||||
Furthermore, you have to enable the FAM daemon. There are two ways to do
|
||||
this: through inetd(8) or as a standalone server. If you prefer the former
|
||||
way, add the following line to /etc/inetd.conf:
|
||||
|
||||
sgi_fam/1-2 stream rpc/tcp wait root ${PREFIX}/sbin/famd famd
|
||||
|
||||
and reload inetd(8) daemon. To enable the FAM daemon in as a standalone
|
||||
server add the following lines to /etc/rc.local file:
|
||||
|
||||
if [ -x ${PREFIX}/sbin/famd ]; then
|
||||
${PREFIX}/sbin/famd -T 0
|
||||
fi
|
2
sysutils/fam/pkg/PFRAG.shared
Normal file
2
sysutils/fam/pkg/PFRAG.shared
Normal file
@ -0,0 +1,2 @@
|
||||
@comment $OpenBSD: PFRAG.shared,v 1.1.1.1 2007/04/27 22:00:55 jasper Exp $
|
||||
@lib lib/libfam.so.${LIBfam_VERSION}
|
12
sysutils/fam/pkg/PLIST
Normal file
12
sysutils/fam/pkg/PLIST
Normal file
@ -0,0 +1,12 @@
|
||||
@comment $OpenBSD: PLIST,v 1.1.1.1 2007/04/27 22:00:55 jasper Exp $
|
||||
%%SHARED%%
|
||||
include/fam.h
|
||||
lib/libfam.a
|
||||
lib/libfam.la
|
||||
@man man/man3/fam.3
|
||||
@man man/man5/famd.conf.5
|
||||
@man man/man8/famd.8
|
||||
sbin/famd
|
||||
share/examples/fam/
|
||||
share/examples/fam/fam.conf
|
||||
@sample ${SYSCONFDIR}/fam.conf
|
Loading…
Reference in New Issue
Block a user