Update documentation.
[cl-inotify.git] / README.md
1 CL-INOTIFY - Interface to the Linux inotify(7) API.
2
3 Copyright (C) 2011-12 Olof-Joachim Frahm
4
5 Released under a Simplified BSD license.
6
7 Working, but unfinished.
8
9 Implementations currently running on: SBCL.
10
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).
16
17 A similar package is at [stassats Github][3].
18
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
23 some value.
24
25
26 # REPLSHOT
27
28 Macros make keeping track easier, so the following example is
29 straightforward:
30
31     > (with-inotify (inotify T ("." :all-events))
32     >   (loop (format T "~{~A~%~}" (next-events inotify))))
33     > =>
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)
39     > ...
40
41 (Tilde-expansion has to happen at another level, else I would've used
42 that.)
43
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
49 of that.
50
51
52 # LOWER-LEVEL USAGE EXAMPLE
53
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.
57
58     > (use-package '#:cl-inotify)
59     > (defvar *tmp*)
60     > (setf *tmp* (make-notify))
61     > (watch *tmp* "/var/tmp/" :all-events)
62     > (next-events *tmp*)
63     > (close-inotify *tmp*)
64
65
66 # HOWTO
67
68 So this section deals in depth with the various bits which make the
69 examples above tick.
70
71
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).
77
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
84 examined.
85
86 For example, to watch for modified or closed files in a directory, call
87 `(WATCH inotify "foo/" '(:modify :close))`.
88
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`.
92
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
97 events.
98
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
103 read event.
104
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`). 
108
109
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.
114
115
116 # EVENT-BASED PROCESSING
117
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
122 iolib:
123
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))))
131
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.
140
141
142 # REFERENCE
143
144 Here follows a list of valid keywords for the `INOTIFY-FLAG` type:
145
146 * `:ACCESS`
147 * `:MODIFY`
148 * `:ATTRIB`
149 * `:CLOSE-WRITE`
150 * `:CLOSE-NOWRITE`
151 * `:CLOSE`
152 * `:OPEN`
153 * `:MOVED-FROM`
154 * `:MOVED-TO`
155 * `:MOVE`
156 * `:CREATE`
157 * `:DELETE`
158 * `:DELETE-SELF`
159 * `:MOVE-SELF`
160 * `:UNMOUNT`
161 * `:Q-OVERFLOW`
162 * `:IGNORED`
163 * `:ONLYDIR`
164 * `:DONT-FOLLOW`
165 * `:MASK-ADD`
166 * `:ISDIR`
167 * `:ONESHOT`
168 * `:ALL-EVENTS`
169
170
171 The `INOTIFY-EVENT` structure has the slots `WD`, `MASK`, `COOKIE` and
172 `NAME` (with default `CONC-NAME`: `INOTIFY-EVENT-`).
173
174 The `INOTIFY-INSTANCE` structure has the slots `FD`, `STREAM` and
175 `NONBLOCKING` with `CONC-NAME` `INOTIFY-`.
176
177 The `REGISTERED-INOTIFY-INSTANCE` includes the previous structure and
178 only adds the `WATCHED` slot under the same `CONC-NAME`.
179
180
181 # TODO
182
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
189
190 [1]: https://github.com/Ferada/binary-types
191 [2]: http://www.cliki.net/Binary-types
192 [3]: https://github.com/stassats/inotify