F_NOTIFY in fcntl(2)?
Mel
fbsd.questions at rachie.is-a-geek.net
Thu Apr 3 21:04:43 UTC 2008
On Thursday 03 April 2008 16:11:59 Mel wrote:
> On Thursday 03 April 2008 12:25:55 John Conover wrote:
> > Does freebsd support the F_NOTIFY, (i.e., File and directory change
> > notification,) in fcntl(2)?
> >
> > I get that it doesn't, but its an old 5X version, and I might have to
> > upgrade.
>
> Nope, this is a GNU extension to fcntl. File change notifications are done
> with EVFILT_VNODE using kqueue(2). Directory changes have no interface that
> I know of. You might wanna take a look at how devel/gamin handles this,
> specifically the kqueue implementation.
Figured I'd give an example of how it can be done (as in: works for me for
file deletion/creation and renames). Doesn't work for utimes(2) operations on
a file, as in "touch /tmp/this_file_exists" will not fire.
Code inlined below sig.
--
Mel
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <sysexits.h>
#include <err.h>
#include <stdio.h>
#include <sys/stat.h>
#include <time.h>
#include <fcntl.h>
int main(int argc, char **argv)
{
int kq, fd;
struct kevent changes, events;
time_t *mtime;
struct stat sb;
if( -1 == (fd = open("/tmp/.", O_RDONLY)) )
err(EX_OSERR, "Cannot open dir /tmp");
if( NULL == (mtime = malloc(sizeof(time_t))) )
err(EX_OSERR, "Failed to allocate %d bytes", sizeof(time_t));
if( -1 == fstat(fd, &sb) )
err(EX_OSERR, "Cannot stat fd %u", fd);
*mtime = sb.st_mtime;
if( -1 == (kq = kqueue()) )
err(EX_OSERR, "Cannot get a kqueue");
EV_SET(&changes, fd, EVFILT_TIMER, EV_ADD|EV_ENABLE, 0, 500,
(void *)mtime);
for( ;; )
{
/* we can only get one event, really. */
if( -1 == kevent(kq, &changes, 1, &events, 1, NULL) )
err(EX_OSERR, "kevent");
if( events.flags & EV_ERROR )
errc(EX_OSERR, events.data, "Event error");
/* secretly, our timer is an fd, we probably should use udata for this
* though.
*/
if( -1 == fstat(events.ident, &sb) )
{
warn("Failed to stat fd %u", events.ident);
break;
}
else
{
if( *mtime && *mtime != sb.st_mtime )
printf("Mtime changed: %u => %u\n", *mtime, sb.st_mtime);
else
printf("Mtime unchanged: %u\n", *mtime);
*mtime = sb.st_mtime;
}
}
close(kq);
return 0;
}
More information about the freebsd-questions
mailing list