Date: Sun, 24 May 2009 22:16:14 +0000 (UTC) From: John Birrell <jb@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r192702 - in projects/jbuild/usr.bin/jbuild: . filemon Message-ID: <200905242216.n4OMGERa002815@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jb Date: Sun May 24 22:16:14 2009 New Revision: 192702 URL: http://svn.freebsd.org/changeset/base/192702 Log: Add jbuild, a modified version of FreeBSD's 'make' with automated dependency handling. filemon is a kernel module that provides a device interface for jbuild to read info that it saves in the meta data file for each target built. Added: projects/jbuild/usr.bin/jbuild/ projects/jbuild/usr.bin/jbuild/Makefile projects/jbuild/usr.bin/jbuild/filemon/ projects/jbuild/usr.bin/jbuild/filemon/Makefile projects/jbuild/usr.bin/jbuild/filemon/filemon.c projects/jbuild/usr.bin/jbuild/filemon/filemon.h projects/jbuild/usr.bin/jbuild/filemon/filemon_lock.c projects/jbuild/usr.bin/jbuild/filemon/filemon_wrapper.c Added: projects/jbuild/usr.bin/jbuild/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/jbuild/usr.bin/jbuild/Makefile Sun May 24 22:16:14 2009 (r192702) @@ -0,0 +1,125 @@ +# $FreeBSD$ + +.PATH : ${.CURDIR}/../make ${.CURDIR}/../jdirdep + +PROG= jbuild +CFLAGS+= -I${.CURDIR}/../make +SRCS= arch.c buf.c cond.c dir.c for.c hash.c hash_tables.c job.c \ + lst.c main.c make.c \ + parse.c proc.c shell.c str.c suff.c targ.c \ + util.c var.c + +BINDIR?= /usr/local/bin +WARNS?= 6 +NO_SHARED?= YES +NO_MAN= +IGNORE_PRAGMA= YES +DEBUG_FLAGS+= -g + +CFLAGS+= -DMAKE_VERSION=\"8000000000\" + +# We're building 'build', not 'make' so the behaviour is different in +# some areas like defaulting to silent. +CFLAGS+= -DMAKE_IS_BUILD -DJBUILD + +.ifdef BUILDMON +SRCS += buildmonreq.c +CFLAGS += -DBUILDMON -I${.CURDIR}/buildmon +.else +CFLAGS += -I${.CURDIR}/filemon +.endif + +.include "${.CURDIR}/../jdirdep/Makefile.common" + +# Make object files which depend on preprocessor symbols defined in +# the Makefile which are not compilation options but rather configuration +# options dependend on the Makefile. main.c needs MAKE_VERSION while +# shell.c uses DEFSHELLNAME. This will cause recompilation in the case +# the definition is changed in the makefile. It will of course not cause +# recompilation if one does 'make MAKE_SHELL=csh'. +main.o shell.o: ${MAKEFILE} + +# Directive and keyword tables. We use hash tables. These hash tables have been +# generated with mph (ports/devel/mph) +# If you change the directives or keywords (adding, deleting, reordering) you +# need to create new tables and hash functions (directive_hash, keyword_hash). +# +# The following changes have been made to the generated code: +# +# o prefix the names of the g, T0 and T1 arrays with 'directive_' +# resp. 'keyword_'. +# +# o make the type of the tables 'const [un]signed char' (if you change +# anything make sure that the numbers fit into a char). +# +# o make the hash function use the length for termination, +# not the trailing '\0', via the -l flag in emitc and some editing +# (only for directive_hash). + +LOCALBASE ?= /usr/local +MPH ?= ${LOCALBASE}/bin/mph +EMITC ?= ${LOCALBASE}/bin/emitc + +.PRECIOUS: hash + +hash: + ( echo '/*' ; \ + echo ' * DO NOT EDIT' ; \ + echo ' * $$''FreeBSD$$' ; \ + echo -n ' * auto-generated from ' ; \ + sed -nEe '/\$$FreeBSD/s/^.*\$$(.*)\$$.*$$/\1/p' \ + ${.CURDIR}/parse.c ; \ + echo ' * DO NOT EDIT' ; \ + echo ' */' ; \ + echo '#include <sys/types.h>' ; \ + echo ; \ + echo '#include "hash_tables.h"' ; \ + echo ; \ + cat ${.CURDIR}/parse.c | sed \ + -e '1,/DIRECTIVES-START-TAG/d' \ + -e '/DIRECTIVES-END-TAG/,$$d' \ + -e 's/^[^"]*"\([^"]*\)".*$$/\1/' | \ + ${MPH} -d2 -m1 | ${EMITC} -l -s | \ + sed \ + -e 's/^static int g\[\]/static const signed char directive_g[]/' \ + -e 's/^static int T0\[\]/static const u_char directive_T0[]/' \ + -e 's/^static int T1\[\]/static const u_char directive_T1[]/' \ + -e '/^#define uchar unsigned char/d' \ + -e 's/uchar/u_char/g' \ + -e 's/^hash(/directive_hash(/' \ + -e 's/; \*kp;/; kp < key + len;/' \ + -e 's/int len)/size_t len)/' \ + -e 's/= T0\[/= directive_T0\[/' \ + -e 's/= T1\[/= directive_T1\[/' \ + -e 's/g\[f/directive_g[f/g' ; \ + cat ${.CURDIR}/parse.c | sed \ + -e '1,/KEYWORD-START-TAG/d' \ + -e '/KEYWORD-END-TAG/,$$d' \ + -e 's/^[^"]*"\([^"]*\)".*$$/\1/' | \ + ${MPH} -d2 -m1 | ${EMITC} -l -s | \ + sed \ + -e 's/^static int g\[\]/static const signed char keyword_g[]/' \ + -e 's/^static int T0\[\]/static const u_char keyword_T0[]/' \ + -e 's/^static int T1\[\]/static const u_char keyword_T1[]/' \ + -e '/^#define uchar unsigned char/d' \ + -e 's/uchar/u_char/g' \ + -e 's/^hash(/keyword_hash(/' \ + -e 's/int len)/size_t len)/' \ + -e 's/= T0\[/= keyword_T0\[/' \ + -e 's/= T1\[/= keyword_T1\[/' \ + -e 's/g\[f/keyword_g[f/g' \ + ) > ${.CURDIR}/hash_tables.c + +# Set the shell which make(1) uses. Bourne is the default, but a decent +# Korn shell works fine, and much faster. Using the C shell for this +# will almost certainly break everything, but it's Unix tradition to +# allow you to shoot yourself in the foot if you want to :-) + +MAKE_SHELL?= sh +.if ${MAKE_SHELL} == "csh" || ${MAKE_SHELL} == "sh" || ${MAKE_SHELL} == "ksh" +CFLAGS+= -DDEFSHELLNAME=\"${MAKE_SHELL}\" +.else +.error "MAKE_SHELL must be set to one of \"csh\", \"sh\" or \"ksh\"." +.endif + +.include <bsd.prog.mk> Added: projects/jbuild/usr.bin/jbuild/filemon/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/jbuild/usr.bin/jbuild/filemon/Makefile Sun May 24 22:16:14 2009 (r192702) @@ -0,0 +1,7 @@ +# $FreeBSD$ + +KMOD = filemon +SRCS = filemon.c +SRCS += vnode_if.h + +.include <bsd.kmod.mk> Added: projects/jbuild/usr.bin/jbuild/filemon/filemon.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/jbuild/usr.bin/jbuild/filemon/filemon.c Sun May 24 22:16:14 2009 (r192702) @@ -0,0 +1,310 @@ +/* $FreeBSD$ */ + +#include <sys/cdefs.h> +#include <sys/param.h> +#include <sys/file.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/condvar.h> +#include <sys/conf.h> +#include <sys/fcntl.h> +#include <sys/ioccom.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/poll.h> +#include <sys/proc.h> +#include <sys/queue.h> +#include <sys/syscall.h> +#include <sys/sysent.h> +#include <sys/sysproto.h> +#include <sys/uio.h> +#include "filemon.h" + +extern struct sysentvec elf32_freebsd_sysvec; + +static d_close_t filemon_close; +static d_ioctl_t filemon_ioctl; +static d_open_t filemon_open; +static int filemon_unload(void); +static void filemon_load(void *); + +static struct cdevsw filemon_cdevsw = { + .d_version = D_VERSION, + .d_close = filemon_close, + .d_ioctl = filemon_ioctl, + .d_open = filemon_open, + .d_name = "filemon", +}; + +MALLOC_DECLARE(M_FILEMON); +MALLOC_DEFINE(M_FILEMON, "filemon", "File access monitor"); + +struct filemon { + pid_t pid; /* The process ID being monitored. */ + char fname1[MAXPATHLEN]; /* Temporary filename buffer. */ + char fname2[MAXPATHLEN]; /* Temporary filename buffer. */ + char msgbufr[1024]; /* Output message buffer. */ + struct file + *fp; /* Output file pointer. */ + struct thread + *locker; /* Ptr to the thread locking this */ + /* filemon.*/ + struct mtx + mtx; /* Lock mutex for this filemon. */ + struct cv + cv; /* Lock condition variable for this */ + /* filemon. */ + TAILQ_ENTRY(filemon) link; /* Link into the in-use list. */ +}; + +static TAILQ_HEAD(, filemon) filemons_inuse = TAILQ_HEAD_INITIALIZER(filemons_inuse); +static int n_readers = 0; +static struct mtx access_mtx; +static struct cv access_cv; +static struct thread *access_owner = NULL; +static struct thread *access_requester = NULL; + +#if __FreeBSD_version < 701000 +static struct clonedevs *filemon_clones; +static eventhandler_tag eh_tag; +#else +static struct cdev *filemon_dev; +#endif + +#include "filemon_lock.c" +#include "filemon_wrapper.c" + +#if __FreeBSD_version < 701000 +static void +filemon_clone(void *arg, struct ucred *cred, char *name, int namelen, + struct cdev **dev) +{ + int u = -1; + size_t len; + + if (*dev != NULL) + return; + + len = strlen(name); + + if (len != 7) + return; + + if (bcmp(name,"filemon",7) != 0) + return; + + /* Clone the device to the new minor number. */ + if (clone_create(&filemon_clones, &filemon_cdevsw, &u, dev, 0) != 0) + /* Create the /dev/filemonNN entry. */ + *dev = make_dev_cred(&filemon_cdevsw, u, cred, UID_ROOT, + GID_WHEEL, 0666, "filemon%d", u); + if (*dev != NULL) { + dev_ref(*dev); + (*dev)->si_flags |= SI_CHEAPCLONE; + } +} +#endif + +static void +filemon_dtr(void *data) +{ + struct filemon *filemon = data; + + if (filemon != NULL) { + /* Get exclusive write access. */ + filemon_lock_write(); + + /* Remove from the in-use list. */ + TAILQ_REMOVE(&filemons_inuse, filemon, link); + + /* Give up write access. */ + filemon_unlock_write(); + + if (filemon->fp != NULL) + fdrop(filemon->fp, curthread); + + mtx_destroy(&filemon->mtx); + cv_destroy(&filemon->cv); + + free(filemon, M_FILEMON); + } +} + +static int +filemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag __unused, struct thread *td) +{ + int error = 0; + struct filemon *filemon; + +#if __FreeBSD_version < 701000 + filemon = dev->si_drv1; +#else + devfs_get_cdevpriv((void **) &filemon); +#endif + + switch (cmd) { + /* Set the output file descriptor. */ + case FILEMON_SET_FD: + if ((error = fget_write(td, *((int *) data), + &filemon->fp)) == 0) + /* Write the file header. */ + filemon_comment(filemon); + break; + + /* Set the monitored process ID. */ + case FILEMON_SET_PID: + filemon->pid = *((pid_t *) data); + break; + + default: + error = EINVAL; + break; + } + + return(error); +} + +static int +filemon_open(struct cdev *dev, int oflags __unused, int devtype __unused, + struct thread *td __unused) +{ + struct filemon *filemon; + + filemon = malloc(sizeof(struct filemon), M_FILEMON, M_WAITOK | M_ZERO); + + filemon->pid = curproc->p_pid; + filemon->fp = NULL; + + mtx_init(&filemon->mtx, "filemon", "filemon", MTX_DEF); + cv_init(&filemon->cv, "filemon"); + +#if __FreeBSD_version < 701000 + dev->si_drv1 = filemon; +#else + devfs_set_cdevpriv(filemon, filemon_dtr); +#endif + + /* Get exclusive write access. */ + filemon_lock_write(); + + /* Add to the in-use list. */ + TAILQ_INSERT_TAIL(&filemons_inuse, filemon, link); + + /* Give up write access. */ + filemon_unlock_write(); + + return (0); +} + +static int +filemon_close(struct cdev *dev __unused, int flag __unused, int fmt __unused, + struct thread *td __unused) +{ +#if __FreeBSD_version < 701000 + filemon_dtr(dev->si_drv1); + + dev->si_drv1 = NULL; + + /* Schedule this cloned device to be destroyed. */ + destroy_dev_sched(dev); +#endif + + return (0); +} + +static void +filemon_load(void *dummy __unused) +{ + mtx_init(&access_mtx, "filemon", "filemon", MTX_DEF); + cv_init(&access_cv, "filemon"); + + /* Install the syscall wrappers. */ + filemon_wrapper_install(); + +#if __FreeBSD_version < 701000 + /* Enable device cloning. */ + clone_setup(&filemon_clones); + + /* Setup device cloning events. */ + eh_tag = EVENTHANDLER_REGISTER(dev_clone, filemon_clone, 0, 1000); +#else + filemon_dev = make_dev(&filemon_cdevsw, 0, UID_ROOT, GID_WHEEL, 0666, + "filemon"); +#endif +} + + +static int +filemon_unload(void) +{ + int error = 0; + + /* Get exclusive write access. */ + filemon_lock_write(); + + if (TAILQ_FIRST(&filemons_inuse) != NULL) + error = EBUSY; + else { +#if __FreeBSD_version >= 701000 + destroy_dev(filemon_dev); +#endif + + /* Deinstall the syscall wrappers. */ + filemon_wrapper_deinstall(); + } + + /* Give up write access. */ + filemon_unlock_write(); + + if (error == 0) { +#if __FreeBSD_version < 701000 + /* + * Check if there is still an event handler callback registered. + */ + if (eh_tag != 0) { + /* De-register the device cloning event handler. */ + EVENTHANDLER_DEREGISTER(dev_clone, eh_tag); + eh_tag = 0; + + /* Stop device cloning. */ + clone_cleanup(&filemon_clones); + } +#endif + + mtx_destroy(&access_mtx); + cv_destroy(&access_cv); + } + + return (error); +} + +static int +filemon_modevent(module_t mod __unused, int type, void *data) +{ + int error = 0; + + switch (type) { + case MOD_LOAD: + filemon_load(data); + break; + + case MOD_UNLOAD: + error = filemon_unload(); + break; + + case MOD_SHUTDOWN: + break; + + default: + error = EOPNOTSUPP; + break; + + } + + return (error); +} + +DEV_MODULE(filemon, filemon_modevent, NULL); +MODULE_VERSION(filemon, 1); Added: projects/jbuild/usr.bin/jbuild/filemon/filemon.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/jbuild/usr.bin/jbuild/filemon/filemon.h Sun May 24 22:16:14 2009 (r192702) @@ -0,0 +1,4 @@ +/* $FreeBSD$ */ + +#define FILEMON_SET_FD _IOWR('S', 1, int) +#define FILEMON_SET_PID _IOWR('S', 2, pid_t) Added: projects/jbuild/usr.bin/jbuild/filemon/filemon_lock.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/jbuild/usr.bin/jbuild/filemon/filemon_lock.c Sun May 24 22:16:14 2009 (r192702) @@ -0,0 +1,94 @@ +/* $FreeBSD$ */ + +static void +filemon_filemon_lock(struct filemon *filemon) +{ + mtx_lock(&filemon->mtx); + + while (filemon->locker != NULL && filemon->locker != curthread) + cv_wait(&filemon->cv, &filemon->mtx); + + filemon->locker = curthread; + + mtx_unlock(&filemon->mtx); +} + +static void +filemon_filemon_unlock(struct filemon *filemon) +{ + mtx_lock(&filemon->mtx); + + if (filemon->locker == curthread) + filemon->locker = NULL; + + /* Wake up threads waiting. */ + cv_broadcast(&filemon->cv); + + mtx_unlock(&filemon->mtx); +} + +static void +filemon_lock_read(void) +{ + mtx_lock(&access_mtx); + + while (access_owner != NULL || access_requester != NULL) + cv_wait(&access_cv, &access_mtx); + + n_readers++; + + /* Wake up threads waiting. */ + cv_broadcast(&access_cv); + + mtx_unlock(&access_mtx); +} + +static void +filemon_unlock_read(void) +{ + mtx_lock(&access_mtx); + + if (n_readers > 0) + n_readers--; + + /* Wake up a thread waiting. */ + cv_broadcast(&access_cv); + + mtx_unlock(&access_mtx); +} + +static void +filemon_lock_write(void) +{ + mtx_lock(&access_mtx); + + while (access_owner != curthread) { + if (access_owner == NULL && + (access_requester == NULL || access_requester == curthread)) { + access_owner = curthread; + access_requester = NULL; + } else { + if (access_requester == NULL) + access_requester = curthread; + + cv_wait(&access_cv, &access_mtx); + } + } + + mtx_unlock(&access_mtx); +} + +static void +filemon_unlock_write(void) +{ + mtx_lock(&access_mtx); + + /* Sanity check that the current thread actually has the write lock. */ + if (access_owner == curthread) + access_owner = NULL; + + /* Wake up a thread waiting. */ + cv_broadcast(&access_cv); + + mtx_unlock(&access_mtx); +} Added: projects/jbuild/usr.bin/jbuild/filemon/filemon_wrapper.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/jbuild/usr.bin/jbuild/filemon/filemon_wrapper.c Sun May 24 22:16:14 2009 (r192702) @@ -0,0 +1,410 @@ +/* $FreeBSD$ */ + +static void +filemon_output(struct filemon *filemon, char *msg, size_t len) +{ + struct uio auio; + struct iovec aiov; + + if (filemon->fp == NULL) + return; + + aiov.iov_base = msg; + aiov.iov_len = len; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_resid = len; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_rw = UIO_WRITE; + auio.uio_td = curthread; + auio.uio_offset = (off_t) -1; + + bwillwrite(); + + fo_write(filemon->fp, &auio, curthread->td_ucred, 0, curthread); +} + +static struct filemon * +filemon_pid_check(struct proc *p) +{ + struct filemon *filemon; + + TAILQ_FOREACH(filemon, &filemons_inuse, link) { + if (p->p_pid == filemon->pid) + return(filemon); + } + + if (p->p_pptr == NULL) + return(NULL); + + return (filemon_pid_check(p->p_pptr)); +} + +static void +filemon_comment(struct filemon *filemon) +{ + int len; + + /* Grab a read lock on the filemon inuse list. */ + filemon_lock_read(); + + /* Lock the found filemon structure. */ + filemon_filemon_lock(filemon); + + len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), + "# buildmon version 2\n# Target pid %d\nV 2\n", curproc->p_pid); + + filemon_output(filemon, filemon->msgbufr, len); + + /* Unlock the found filemon structure. */ + filemon_filemon_unlock(filemon); + + /* Release the read lock. */ + filemon_unlock_read(); +} + +static int +filemon_wrapper_chdir(struct thread *td, struct chdir_args *uap) +{ + int ret; + size_t done; + size_t len; + struct filemon *filemon; + + if ((ret = chdir(td, uap)) == 0) { + /* Grab a read lock on the filemon inuse list. */ + filemon_lock_read(); + + if ((filemon = filemon_pid_check(curproc)) != NULL) { + /* Lock the found filemon structure. */ + filemon_filemon_lock(filemon); + + copyinstr(uap->path, filemon->fname1, sizeof(filemon->fname1), &done); + + len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), "C %d %s\n", + curproc->p_pid, filemon->fname1); + + filemon_output(filemon, filemon->msgbufr, len); + + /* Unlock the found filemon structure. */ + filemon_filemon_unlock(filemon); + } + + /* Release the read lock. */ + filemon_unlock_read(); + } + + return(ret); +} + +static int +filemon_wrapper_execve(struct thread *td, struct execve_args *uap) +{ + char fname[MAXPATHLEN]; + int ret; + size_t done; + size_t len; + struct filemon *filemon; + + copyinstr(uap->fname, fname, sizeof(fname), &done); + + if ((ret = execve(td, uap)) == 0) { + /* Grab a read lock on the filemon inuse list. */ + filemon_lock_read(); + + if ((filemon = filemon_pid_check(curproc)) != NULL) { + /* Lock the found filemon structure. */ + filemon_filemon_lock(filemon); + + len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), "E %d %s\n", + curproc->p_pid, fname); + + filemon_output(filemon, filemon->msgbufr, len); + + /* Unlock the found filemon structure. */ + filemon_filemon_unlock(filemon); + } + + /* Release the read lock. */ + filemon_unlock_read(); + } + + return(ret); +} + +static int +filemon_wrapper_fork(struct thread *td, struct fork_args *uap) +{ + int ret; + size_t len; + struct filemon *filemon; + + if ((ret = fork(td, uap)) == 0) { + /* Grab a read lock on the filemon inuse list. */ + filemon_lock_read(); + + if ((filemon = filemon_pid_check(curproc)) != NULL) { + /* Lock the found filemon structure. */ + filemon_filemon_lock(filemon); + + len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), "F %d %d\n", + curproc->p_pid, curthread->td_retval[0]); + + filemon_output(filemon, filemon->msgbufr, len); + + /* Unlock the found filemon structure. */ + filemon_filemon_unlock(filemon); + } + + /* Release the read lock. */ + filemon_unlock_read(); + } + + return(ret); +} + +static int +filemon_wrapper_open(struct thread *td, struct open_args *uap) +{ + int ret; + size_t done; + size_t len; + struct filemon *filemon; + + if ((ret = open(td, uap)) == 0) { + /* Grab a read lock on the filemon inuse list. */ + filemon_lock_read(); + + if ((filemon = filemon_pid_check(curproc)) != NULL) { + /* Lock the found filemon structure. */ + filemon_filemon_lock(filemon); + + copyinstr(uap->path, filemon->fname1, sizeof(filemon->fname1), &done); + + len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), "%c %d %s\n", + (uap->flags & O_ACCMODE) ? 'W':'R', curproc->p_pid, filemon->fname1); + + filemon_output(filemon, filemon->msgbufr, len); + + /* Unlock the found filemon structure. */ + filemon_filemon_unlock(filemon); + } + + /* Release the read lock. */ + filemon_unlock_read(); + } + + return(ret); +} + +static int +filemon_wrapper_rename(struct thread *td, struct rename_args *uap) +{ + int ret; + size_t done; + size_t len; + struct filemon *filemon; + + if ((ret = rename(td, uap)) == 0) { + /* Grab a read lock on the filemon inuse list. */ + filemon_lock_read(); + + if ((filemon = filemon_pid_check(curproc)) != NULL) { + /* Lock the found filemon structure. */ + filemon_filemon_lock(filemon); + + copyinstr(uap->from, filemon->fname1, sizeof(filemon->fname1), &done); + copyinstr(uap->to, filemon->fname2, sizeof(filemon->fname2), &done); + + len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), "M %d '%s' '%s'\n", + curproc->p_pid, filemon->fname1, filemon->fname2); + + filemon_output(filemon, filemon->msgbufr, len); + + /* Unlock the found filemon structure. */ + filemon_filemon_unlock(filemon); + } + + /* Release the read lock. */ + filemon_unlock_read(); + } + + return(ret); +} + +static int +filemon_wrapper_stat(struct thread *td, struct stat_args *uap) +{ + int ret; + size_t done; + size_t len; + struct filemon *filemon; + + if ((ret = stat(td, uap)) == 0) { + /* Grab a read lock on the filemon inuse list. */ + filemon_lock_read(); + + if ((filemon = filemon_pid_check(curproc)) != NULL) { + /* Lock the found filemon structure. */ + filemon_filemon_lock(filemon); + + copyinstr(uap->path, filemon->fname1, sizeof(filemon->fname1), &done); + + len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), "S %d %s\n", + curproc->p_pid, filemon->fname1); + + filemon_output(filemon, filemon->msgbufr, len); + + /* Unlock the found filemon structure. */ + filemon_filemon_unlock(filemon); + } + + /* Release the read lock. */ + filemon_unlock_read(); + } + + return(ret); +} + +static void +filemon_wrapper_sys_exit(struct thread *td, struct sys_exit_args *uap) +{ + size_t len; + struct filemon *filemon; + + /* Grab a read lock on the filemon inuse list. */ + filemon_lock_read(); + + if ((filemon = filemon_pid_check(curproc)) != NULL) { + /* Lock the found filemon structure. */ + filemon_filemon_lock(filemon); + + len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), "X %d\n", curproc->p_pid); + + filemon_output(filemon, filemon->msgbufr, len); + + /* Check if the monitored process is about to exit. */ + if (filemon->pid == curproc->p_pid) { + len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), "# Bye bye\n"); + + filemon_output(filemon, filemon->msgbufr, len); + } + + /* Unlock the found filemon structure. */ + filemon_filemon_unlock(filemon); + } + + /* Release the read lock. */ + filemon_unlock_read(); + + sys_exit(td, uap); +} + +static int +filemon_wrapper_unlink(struct thread *td, struct unlink_args *uap) +{ + int ret; + size_t done; + size_t len; + struct filemon *filemon; + + if ((ret = unlink(td, uap)) == 0) { + /* Grab a read lock on the filemon inuse list. */ + filemon_lock_read(); + + if ((filemon = filemon_pid_check(curproc)) != NULL) { + /* Lock the found filemon structure. */ + filemon_filemon_lock(filemon); + + copyinstr(uap->path, filemon->fname1, sizeof(filemon->fname1), &done); + + len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), "D %d %s\n", + curproc->p_pid, filemon->fname1); + + filemon_output(filemon, filemon->msgbufr, len); + + /* Unlock the found filemon structure. */ + filemon_filemon_unlock(filemon); + } + + /* Release the read lock. */ + filemon_unlock_read(); + } + + return(ret); +} + +static int +filemon_wrapper_vfork(struct thread *td, struct vfork_args *uap) +{ + int ret; + size_t len; + struct filemon *filemon; + + if ((ret = vfork(td, uap)) == 0) { + /* Grab a read lock on the filemon inuse list. */ + filemon_lock_read(); + + if ((filemon = filemon_pid_check(curproc)) != NULL) { + /* Lock the found filemon structure. */ + filemon_filemon_lock(filemon); + + len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr), "F %d %d\n", + curproc->p_pid, curthread->td_retval[0]); + + filemon_output(filemon, filemon->msgbufr, len); + + /* Unlock the found filemon structure. */ + filemon_filemon_unlock(filemon); + } + + /* Release the read lock. */ + filemon_unlock_read(); + } + + return(ret); +} + +static void +filemon_wrapper_install(void) +{ +#if defined(__i386__) + struct sysent *sv_table = elf32_freebsd_sysvec.sv_table; +#elif defined(__amd64__) + struct sysent *sv_table = elf64_freebsd_sysvec.sv_table; +#else +#error Machine type not supported +#endif + + sv_table[SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir; + sv_table[SYS_exit].sy_call = (sy_call_t *) filemon_wrapper_sys_exit; + sv_table[SYS_execve].sy_call = (sy_call_t *) filemon_wrapper_execve; + sv_table[SYS_fork].sy_call = (sy_call_t *) filemon_wrapper_fork; + sv_table[SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open; + sv_table[SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename; + sv_table[SYS_stat].sy_call = (sy_call_t *) filemon_wrapper_stat; + sv_table[SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink; + sv_table[SYS_vfork].sy_call = (sy_call_t *) filemon_wrapper_vfork; +} + +static void +filemon_wrapper_deinstall(void) +{ +#if defined(__i386__) + struct sysent *sv_table = elf32_freebsd_sysvec.sv_table; +#elif defined(__amd64__) + struct sysent *sv_table = elf64_freebsd_sysvec.sv_table; +#else +#error Machine type not supported +#endif + + sv_table[SYS_chdir].sy_call = (sy_call_t *) chdir; + sv_table[SYS_exit].sy_call = (sy_call_t *) sys_exit; + sv_table[SYS_execve].sy_call = (sy_call_t *) execve; + sv_table[SYS_fork].sy_call = (sy_call_t *) fork; + sv_table[SYS_open].sy_call = (sy_call_t *) open; + sv_table[SYS_rename].sy_call = (sy_call_t *) rename; + sv_table[SYS_stat].sy_call = (sy_call_t *) stat; + sv_table[SYS_unlink].sy_call = (sy_call_t *) unlink; + sv_table[SYS_vfork].sy_call = (sy_call_t *) vfork; +}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905242216.n4OMGERa002815>