1 CL-INOTIFY - Interface to the Linux inotify(7) API.
3 Copyright (C) 2011-12 Olof-Joachim Frahm
5 Released under a Simplified BSD license.
7 Working, but unfinished.
9 Implementations currently running on: SBCL.
11 Uses CFFI, binary-types (from [my Github][1] or see [CLiki][2]) and
12 trivial-utf-8. Doesn't use iolib, because I don't need most of the
13 functionality, although it might gain us some implementation
14 independence (patches which can be conditionally compiled are most
15 welcome; in any case patches are welcome).
17 A similar package is at [stassats Github][3].
19 This document helps only with the aspects of this binding, so reading
20 the man-page and other information on the inotify-facility may be
21 needed. Reading the next sections and the docstrings of exported
22 symbols should get you going, otherwise the source itself may also be of
28 Macros make keeping track easier, so the following example is
31 > (with-inotify (inotify T ("." :all-events))
32 > (loop (format T "~{~A~%~}" (next-events inotify))))
34 > #S(CL-INOTIFY::INOTIFY-EVENT :WD 1 :MASK (CREATE) :COOKIE 0 :NAME .zshist.LOCK)
35 > #S(CL-INOTIFY::INOTIFY-EVENT :WD 1 :MASK (OPEN) :COOKIE 0 :NAME .zshist)
36 > #S(CL-INOTIFY::INOTIFY-EVENT :WD 1 :MASK (MODIFY) :COOKIE 0 :NAME .zshist)
37 > #S(CL-INOTIFY::INOTIFY-EVENT :WD 1 :MASK (CLOSE-WRITE) :COOKIE 0 :NAME .zshist)
38 > #S(CL-INOTIFY::INOTIFY-EVENT :WD 1 :MASK (DELETE) :COOKIE 0 :NAME .zshist.LOCK)
41 (Tilde-expansion has to happen at another level, else I would've used
44 The first parameter is (per convention) the symbol to which the queue is
45 bound, the second is the parameter to `MAKE-INOTIFY`. The `&REST` list
46 consists of parameter lists for the `WATCH`-function, which is called
47 for every list before the `&BODY` is executed. We don't actually need
48 to `UNWATCH` every watched path as closing the queue will also take care
52 # LOWER-LEVEL USAGE EXAMPLE
54 You don't have to use macros: all functionality is available in function
55 form, although some care should be taken as currently no cleanup handler
56 is registered for opened queues, or rather their file handles.
58 > (use-package '#:cl-inotify)
60 > (setf *tmp* (make-notify))
61 > (watch *tmp* "/var/tmp/" :all-events)
63 > (close-inotify *tmp*)
68 So this section deals in depth with the various bits which make the
72 After loading the library use `MAKE-INOTIFY` to create a new event
73 queue. The `NONBLOCKING` argument sets the `SB-POSIX:O-NONBLOCK` bit on
74 the stream so we don't block while reading. Nevertheless,
75 `EVENT-AVAILABLE-P` works either way (by using `CL:LISTEN`, or a custom
76 function which works directly on the file descriptor).
78 The result of `MAKE-INOTIFY` is used with `WATCH` and `UNWATCH`, the first
79 being used to watch a file or directory, the second to stop watching
80 it. The `FLAGS` parameter of `WATCH` is described in the notify(7)
81 man-page; you can use a combination of the flags (as keywords) to create
82 a suitable bitmask. The types `INOTIFY-ADD/READ-FLAG`,
83 `INOTIFY-READ-FLAG` and `INOTIFY-ADD-FLAG` are also defined and can be
86 For example, to watch for modified or closed files in a directory, call
87 `(WATCH inotify "foo/" '(:modify :close))`.
89 The result of `WATCH` is a handle (currently a `FIXNUM`, but I wouldn't
90 rely on that) which can be fed to `UNWATCH` and can be translated from
91 events with `EVENT-PATHNAME/FLAGS`.
93 To finally get the events from the queue, use `READ-EVENT` (which
94 blocks) or `NEXT-EVENT` (which doesn't block). `EVENT-AVAILABLEP` does
95 what it should do, `NEXT-EVENTS` retrieves all currently available
96 events as a list and `DO-EVENTS` (nonblocking) iterates over available
99 The enhanced API registers all watched paths in a hashtable, so you can
100 use `PATHNAME-HANDLE/FLAGS` to check if a pathname (exact match) is
101 being watched and `LIST-WATCHED` to return all watched paths as a list.
102 `EVENT-PATHNAME/FLAGS` may be used to get the pathname and flags for a
105 `UNWATCH` has to be called with the path or the handle of the watched
106 file or directory (a path will be looked up in the same table as with
107 `PATHNAME-HANDLE/FLAGS`).
110 The raw API, which doesn't register watched paths, consists of
111 `READ-RAW-EVENT-FROM-STREAM`, `READ-EVENT-FROM-STREAM`, `WATCH-RAW` and
112 `UNWATCH-RAW`. They are just a thin wrapper around the C functions, but
113 they're exported in case someone doesn't like the upper layers.
116 # EVENT-BASED PROCESSING
118 In case you want to use `epoll` or `select` on the event queue you can
119 access the file descriptor yourself and then use the normal functions
120 afterwards. Currently no such functionality is integrated here, however
121 the following sketch shows how something can be accomplished using
124 (with-unregistered-inotify (inotify T ("." :all-events))
125 (flet ((inotify-input (&rest rest)
126 (declare (ignore rest))
127 (format T "~{~A~%~}" (next-events inotify))))
128 (iolib:with-event-base (event-base)
129 (iolib:set-io-handler event-base (inotify-fd inotify) :read #'inotify-input)
130 (iolib:event-dispatch event-base))))
132 Note that we perform all inotify business only when something happens in
133 that directory, so instead of doing nothing, we could actually do useful
134 work, e.g. communicating with a process: This snippet was extracted
135 from a function which uses behaviour to monitor a LaTeX process for
136 written files to get the output file name without relying on heuristics
137 about the generated filename. As it stands you have to split this into
138 threads, or use `IOLIB:EVENT-DISPATCH` with a timeout while periodically
139 checking the process status.
144 Here follows a list of valid keywords for the `INOTIFY-FLAG` type:
171 The `INOTIFY-EVENT` structure has the slots `WD`, `MASK`, `COOKIE` and
172 `NAME` (with default `CONC-NAME`: `INOTIFY-EVENT-`).
174 The `INOTIFY-INSTANCE` structure has the slots `FD`, `STREAM` and
175 `NONBLOCKING` with `CONC-NAME` `INOTIFY-`.
177 The `REGISTERED-INOTIFY-INSTANCE` includes the previous structure and
178 only adds the `WATCHED` slot under the same `CONC-NAME`.
183 - more functionality to examine read events
184 - extend to other APIs?
185 - make things more implementation independent (partly done, still needs
186 fd-streams everywhere, or skip them entirely)
187 - (maybe) don't use the libc for this, direct syscall
188 - (maybe) add iolib replacement for io functions
190 [1]: https://github.com/Ferada/binary-types
191 [2]: http://www.cliki.net/Binary-types
192 [3]: https://github.com/stassats/inotify