Add iolib functions.
[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     >   (do-events (event inotify :blocking-p T)
33     >     (format T "~A~%" event)))
34     > =>
35     > #S(CL-INOTIFY::INOTIFY-EVENT :WD 1 :MASK (CREATE) :COOKIE 0 :NAME .zshist.LOCK)
36     > #S(CL-INOTIFY::INOTIFY-EVENT :WD 1 :MASK (OPEN) :COOKIE 0 :NAME .zshist)
37     > #S(CL-INOTIFY::INOTIFY-EVENT :WD 1 :MASK (MODIFY) :COOKIE 0 :NAME .zshist)
38     > #S(CL-INOTIFY::INOTIFY-EVENT :WD 1 :MASK (CLOSE-WRITE) :COOKIE 0 :NAME .zshist)
39     > #S(CL-INOTIFY::INOTIFY-EVENT :WD 1 :MASK (DELETE) :COOKIE 0 :NAME .zshist.LOCK)
40     > ...
41
42 (Tilde-expansion has to happen at another level, else I would've used
43 that.)
44
45 The first parameter is (per convention) the symbol to which the queue is
46 bound, the second is the parameter to `MAKE-INOTIFY`.  The `&REST` list
47 consists of parameter lists for the `WATCH`-function, which is called
48 for every list before the `&BODY` is executed.  We don't actually need
49 to `UNWATCH` every watched path as closing the queue will also take care
50 of that.
51
52
53 # LOWER-LEVEL USAGE EXAMPLE
54
55 You don't have to use macros: all functionality is available in function
56 form, although some care should be taken as currently no cleanup handler
57 is registered for opened queues, or rather their file handles.
58
59     > (use-package '#:cl-inotify)
60     > (defvar *tmp*)
61     > (setf *tmp* (make-notify))
62     > (watch *tmp* "/var/tmp/" :all-events)
63     > (next-events *tmp*)
64     > (close-inotify *tmp*)
65
66
67 # HOWTO
68
69 So this section deals in depth with the various bits which make the
70 examples above tick.
71
72
73 After loading the library use `MAKE-INOTIFY` to create a new event
74 queue.  The `NONBLOCKING` argument sets the `SB-POSIX:O-NONBLOCK` bit on
75 the stream so we don't block while reading.  Nevertheless,
76 `EVENT-AVAILABLE-P` works either way (by using `CL:LISTEN`, or a custom
77 function which works directly on the file descriptor).
78
79 The result of `MAKE-INOTIFY` is used with `WATCH` and `UNWATCH`, the first
80 being used to watch a file or directory, the second to stop watching
81 it.  The `FLAGS` parameter of `WATCH` is described in the notify(7)
82 man-page; you can use a combination of the flags (as keywords) to create
83 a suitable bitmask.  The types `INOTIFY-ADD/READ-FLAG`,
84 `INOTIFY-READ-FLAG` and `INOTIFY-ADD-FLAG` are also defined and can be
85 examined.
86
87 For example, to watch for modified or closed files in a directory, call
88 `(WATCH inotify "foo/" '(:modify :close))`.
89
90 The result of `WATCH` is a handle (currently a `FIXNUM`, but I wouldn't
91 rely on that) which can be fed to `UNWATCH` and can be translated from
92 events with `EVENT-PATHNAME/FLAGS`.
93
94 To finally get the events from the queue, use `READ-EVENT` (which
95 blocks) or `NEXT-EVENT` (which doesn't block).  `EVENT-AVAILABLEP` does
96 what it should do, `NEXT-EVENTS` retrieves all currently available
97 events as a list and `DO-EVENTS` (nonblocking) iterates over available
98 events.
99
100 The enhanced API registers all watched paths in a hashtable, so you can
101 use `PATHNAME-HANDLE/FLAGS` to check if a pathname (exact match) is
102 being watched and `LIST-WATCHED` to return all watched paths as a list.
103 `EVENT-PATHNAME/FLAGS` may be used to get the pathname and flags for a
104 read event.
105
106 `UNWATCH` has to be called with the path or the handle of the watched
107 file or directory (a path will be looked up in the same table as with
108 `PATHNAME-HANDLE/FLAGS`). 
109
110
111 The raw API, which doesn't register watched paths, consists of
112 `READ-RAW-EVENT-FROM-STREAM`, `READ-EVENT-FROM-STREAM`, `WATCH-RAW` and
113 `UNWATCH-RAW`.  They are just a thin wrapper around the C functions, but
114 they're exported in case someone doesn't like the upper layers.
115
116
117 # EVENT-BASED PROCESSING
118
119 In case you want to use `epoll` or `select` on the event queue you can
120 access the file descriptor yourself and then use the normal functions
121 afterwards.  Currently no such functionality is integrated here, however
122 the following sketch shows how something can be accomplished using
123 iolib:
124
125     (with-unregistered-inotify (inotify T ("." :all-events))
126       (flet ((inotify-input (&rest rest)
127                (declare (ignore rest))
128                (format T "~{~A~%~}" (next-events inotify))))
129         (iolib:with-event-base (event-base)
130           (iolib:set-io-handler event-base (inotify-fd inotify) :read #'inotify-input)
131           (iolib:event-dispatch event-base))))
132
133 Note that we perform all inotify business only when something happens in
134 that directory, so instead of doing nothing, we could actually do useful
135 work, e.g. communicating with a process:  This snippet was extracted
136 from a function which uses behaviour to monitor a LaTeX process for
137 written files to get the output file name without relying on heuristics
138 about the generated filename.  As it stands you have to split this into
139 threads, or use `IOLIB:EVENT-DISPATCH` with a timeout while periodically
140 checking the process status.
141
142
143 # REFERENCE
144
145 Here follows a list of valid keywords for the `INOTIFY-FLAG` type:
146
147 * `:ACCESS`
148 * `:MODIFY`
149 * `:ATTRIB`
150 * `:CLOSE-WRITE`
151 * `:CLOSE-NOWRITE`
152 * `:CLOSE`
153 * `:OPEN`
154 * `:MOVED-FROM`
155 * `:MOVED-TO`
156 * `:MOVE`
157 * `:CREATE`
158 * `:DELETE`
159 * `:DELETE-SELF`
160 * `:MOVE-SELF`
161 * `:UNMOUNT`
162 * `:Q-OVERFLOW`
163 * `:IGNORED`
164 * `:ONLYDIR`
165 * `:DONT-FOLLOW`
166 * `:MASK-ADD`
167 * `:ISDIR`
168 * `:ONESHOT`
169 * `:ALL-EVENTS`
170
171
172 The `INOTIFY-EVENT` structure has the slots `WD`, `MASK`, `COOKIE` and
173 `NAME` (with default `CONC-NAME`: `INOTIFY-EVENT-`).
174
175 The `INOTIFY-INSTANCE` structure has the slots `FD`, `STREAM` and
176 `NONBLOCKING` with `CONC-NAME` `INOTIFY-`.
177
178 The `REGISTERED-INOTIFY-INSTANCE` includes the previous structure and
179 only adds the `WATCHED` slot under the same `CONC-NAME`.
180
181
182 # TODO
183
184 - more functionality to examine read events
185 - extend to other APIs?
186 - make things more implementation independent (partly done, still needs
187   fd-streams everywhere, or skip them entirely)
188 - (maybe) don't use the libc for this, direct syscall
189 - (maybe) add iolib replacement for io functions
190 - the nonblocking mode is pretty useless, because for one the READ
191   functions still block and also LISTEN seems to work just fine and it's
192   not even needed for multiplexing, so why keep this in?
193
194 [1]: https://github.com/Ferada/binary-types
195 [2]: http://www.cliki.net/Binary-types
196 [3]: https://github.com/stassats/inotify