Skip to content

libinotify-kqueue/libinotify-kqueue

Repository files navigation

libinotify-kqueue
=================

Copyright (c) 2011-2014 Dmitry Matveev <me@dmitrymatveev.co.uk>
Copyright (c) 2014-2018 Vladimir Kondratyev <vladimir@kondratyev.su>

The purpose of this library is to provide inotify API on the
*BSD family of operating systems. The library uses kqueue(2)
to monitor the file system activity.



Requirements
------------

- gcc, g++, automake, autoconf, libtool;
- NetBSD, OpenBSD, FreeBSD (all tested), Mac OS X (reported
  to work).



Downloading
-----------

This project does not have a special home page yet. The source
code and the issue tracker are hosted on Github:

  https://github.com/libinotify-kqueue/libinotify-kqueue



Building
--------

Building from a git snaphost is as simple as:

  $ autoreconf -fvi
  $ ./configure
  $ make



Testing
-------

After you build the library, you can run tests to ensure that
everything works in your system:

  $ make test

There are 100+ tests, and since some events cann't be implemented
using only original kqueue(2), these tests will most probably fail:

> In test "Directory notifications":
>    failed: receive IN_MOVED_FROM event on moving file from directory to
>            another location within the same mount point
>    failed: receive IN_MOVED_TO event on moving file to directory from
>            another location within the same mount point

> In test "Open/close notifications":
>    failed: receive IN_OPEN on cat
>    failed: receive IN_CLOSE_NOWRITE on cat
>    failed: receive IN_OPEN on ls
>    failed: receive IN_CLOSE_NOWRITE on ls
>    failed: receive IN_OPEN on modify
>    failed: receive IN_CLOSE_WRITE on modify

> In test "Symbolic links":
>    failed: Start watch successfully on a symlink file with IN_DONT_FOLLOW
>    failed: Receive IN_ATTRIB after touching symlink itself
>    failed: Receive IN_MOVE_SELF after moving the symlink
>    failed: Receive IN_DELETE_SELF after removing the symlink

To solve these issues some vfs and kqueue extensions were developed
and commited to FreeBSD kernel. A FreeBSD 13-STABLE passes all tests
flawlessly.

If you will get any other results, please feel free to report it at:

  https://github.com/libinotify-kqueue/libinotify-kqueue/issues



Building under linuxolator (FreeBSD 13+)
----------------------------------------

It is possible to use libinotify with binary Linux applications. To do
that, download, build and install linux-libbsd which makes BSD kqueue
syscall available to linuxolator: https://github.com/wulf7/linux-libbsd
Install devel/linux-c7-devtools port, than compile libinotify.so
library and install it somewhere under /compat/linux.

To build and install 64-bit library:

  $ env CC="/compat/linux/bin/gcc" \
        CFLAGS="--sysroot /compat/linux -include bsd.h" \
        LDFLAGS="-lbsd" \
        ./configure --libdir=/usr/lib64
  $ make
  $ sudo make install-exec DESTDIR=/compat/linux

To build and install 32-bit library:

  $ env CC="/compat/linux/bin/gcc" \
        CFLAGS="--sysroot /compat/linux -m32 -include bsd.h" \
        LDFLAGS="-lbsd" \
        ./configure --libdir=/usr/lib
  $ make
  $ sudo make install-exec DESTDIR=/compat/linux

To run my_64bit_app or my_32bit_app with inotify support use

  $ LD_PRELOAD=/usr/lib64/libinotify.so my_64bit_app

or

  $ LD_PRELOAD=/usr/lib/libinotify.so my_32bit_app



Using
-----

To use the library, all you need to do is to link your application
with it (adding -linotify to LDFLAGS works in almost all cases).
Of course, you will need to have include (-I) and linker (-L)
directories to be properly set in your project.

Since the heart of the library is kqueue(2), the library has to
keep many files open to provide proper monitoring. It is especially
important when you monitor a single but large directory. Rules are:
If application specifies only IN_CREATE, IN_DELETE, IN_MOVED_FROM,
IN_MOVED_TO, IN_DELETE_SELF or IN_MOVE_SELF events in mask argument
of inotify_add_watch(2) then libinotify opens only watched directory
itself. Adding IN_CLOSE_WRITE and/or IN_MODIFY events to ones
mentioned before leads to opening of every regular file inside a
watched directory. And adding one of IN_ACCESS, IN_ATTRIB,
IN_CLOSE_NOWRITE or IN_OPEN flags to event mask leads to opening of
all directories as well as regular files inside a watched directory.
You can run out of file descriptors, so do not forget request more
with setrlimit(2) before starting monitoring.

Note that fcntl(2) calls are not supported on descriptors returned
by the library's inotify_init().

Linux implementation does not allow partial event reads from inotify
file descriptor while socketpair(2) used for libinotify-kqueue allows
arbitrary amount of data to be read from. So software unaware of
that can lose datastream event position synchronization that leads to
unpredictable results. To avoid that as much as possible socketpair
buffer size has been reduced to reasonable small value (currently 4K)
exposed as IN_DEF_SOCKBUFSIZE in sys/inotify.h header so it completely
fits in read(2) buffer of most common applications. Applications using
smaller read(2) buffer sizes should be fixed by increasing it or
supporting concatenation of event parts. Usage of dynamically
allocated buffers and read(2)s sized with FIONREAD ioctl(2) or alike
can be considered safe.


Status
------

The library is almost feature-complete, i.e. it implements and
provides most of what can be implemented/provided using kqueue(2).
Current state of project is described in following table:

                    Original Extended
  Inotify event     kqueue   kqueue     Event flags     Supported

  IN_ACCESS         No       Yes        IN_IGNORED      Yes
  IN_ATTRIB         Yes      Yes        IN_ISDIR        Yes
  IN_CLOSE_WRITE    No       Yes        IN_UNMOUNT      Yes **
  IN_CLOSE_NOWRITE  No       Yes        IN_Q_OVERFLOW   Yes
  IN_CREATE         Yes      Yes
  IN_DELETE         Yes      Yes        Watch flags     Supported
  IN_DELETE_SELF    Yes      Yes
  IN_MODIFY         Yes      Yes        IN_ONLYDIR      Yes
  IN_MOVE_SELF      Yes      Yes        IN_DONT_FOLLOW  Yes ***
  IN_MOVED_FROM     Yes *    Yes        IN_EXCL_UNLINK  No  ****
  IN_MOVED_TO       Yes *    Yes        IN_MASK_ADD     Yes
  IN_OPEN           No       Yes        IN_ONESHOT      Yes

* Only renaming file inside watched directory is supported
** libinotify prevents unmount unless O_EVTONLY or O_PATH is supported
*** Watching a symlink requires kernel with O_SYMLINK or O_PATH support
**** Libinotify-kqueue behaves as IN_EXCL_UNLINK flag is always set


Thanks
------

Thanks to Julio Merino for mentoring this work during the initial
library development on Google Summer Of Code 2011.

Thanks to Antoine Jacoutot for support, reports, and the work
on the related glib-kqueue project.

Thanks to bugreporters: Baptiste Daroussin, Stanislav Sedov,
Dmitry Okunev, luoqi-git.



License
-------

libinotify-kqueue is redistributed under the terms of MIT License.
See file LICENSE for details.