457cfe6ee3f733992a403cdd517912b060b9192d
[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 implementation-specific and -internal functionality (since I couldn't
123 yet get iolib to build again on my system).  So, given SBCL, we register
124 ourselves for event notification on the inotify file descriptor:
125
126     > (with-unregistered-inotify (inotify T ("." :all-events))
127     >   (flet ((inotify-input (handler)
128     >            (declare (ignore handler))
129     >            (format T "~{~A~%~}" (next-events inotify))))
130     >     (sb-sys:with-fd-handler ((inotify-fd inotify) :input #'inotify-input)
131     >       (loop (sb-sys:serve-all-events 1)))))
132
133 Note that we perform all inotify business only when something happens in
134 that directory, so instead of that loop 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.
139
140
141 # REFERENCE
142
143 Here follows a list of valid keywords for the `INOTIFY-FLAG` type:
144
145 * `:ACCESS`
146 * `:MODIFY`
147 * `:ATTRIB`
148 * `:CLOSE-WRITE`
149 * `:CLOSE-NOWRITE`
150 * `:CLOSE`
151 * `:OPEN`
152 * `:MOVED-FROM`
153 * `:MOVED-TO`
154 * `:MOVE`
155 * `:CREATE`
156 * `:DELETE`
157 * `:DELETE-SELF`
158 * `:MOVE-SELF`
159 * `:UNMOUNT`
160 * `:Q-OVERFLOW`
161 * `:IGNORED`
162 * `:ONLYDIR`
163 * `:DONT-FOLLOW`
164 * `:MASK-ADD`
165 * `:ISDIR`
166 * `:ONESHOT`
167 * `:ALL-EVENTS`
168
169
170 The `INOTIFY-EVENT` structure has the slots `WD`, `MASK`, `COOKIE` and
171 `NAME` (with default `CONC-NAME`: `INOTIFY-EVENT-`).
172
173 The `INOTIFY-INSTANCE` structure has the slots `FD`, `STREAM` and
174 `NONBLOCKING` with `CONC-NAME` `INOTIFY-`.
175
176 The `REGISTERED-INOTIFY-INSTANCE` includes the previous structure and
177 only adds the `WATCHED` slot under the same `CONC-NAME`.
178
179
180 # TODO
181
182 - more functionality to examine read events
183 - extend to other APIs?
184 - make things more implementation independent
185 - (maybe) don't use the libc for this, direct syscall
186 - (maybe) add iolib replacement for io functions
187 - easier interface for (e)poll/select maybe using iolib (done partly
188   using CL:LISTEN and/or SB-UNIX:UNIX-READ)
189 - add some cleanup handler to close queue on garbage collection
190
191 [1]: https://github.com/Ferada/binary-types
192 [2]: http://www.cliki.net/Binary-types
193 [3]: https://github.com/stassats/inotify