15 #include <sys/ioctl.h> |
15 #include <sys/ioctl.h> |
16 #include <unistd.h> |
16 #include <unistd.h> |
17 |
17 |
18 static PyObject *init(PyObject *self, PyObject *args) |
18 static PyObject *init(PyObject *self, PyObject *args) |
19 { |
19 { |
20 PyObject *ret = NULL; |
20 PyObject *ret = NULL; |
21 int fd = -1; |
21 int fd = -1; |
22 |
22 |
23 if (!PyArg_ParseTuple(args, ":init")) |
23 if (!PyArg_ParseTuple(args, ":init")) |
24 goto bail; |
24 goto bail; |
25 |
25 |
26 Py_BEGIN_ALLOW_THREADS |
26 Py_BEGIN_ALLOW_THREADS; |
27 fd = inotify_init(); |
27 fd = inotify_init(); |
28 Py_END_ALLOW_THREADS |
28 Py_END_ALLOW_THREADS; |
29 |
29 |
30 if (fd == -1) { |
30 if (fd == -1) { |
31 PyErr_SetFromErrno(PyExc_OSError); |
31 PyErr_SetFromErrno(PyExc_OSError); |
32 goto bail; |
32 goto bail; |
33 } |
33 } |
34 |
34 |
35 ret = PyInt_FromLong(fd); |
35 ret = PyInt_FromLong(fd); |
36 if (ret == NULL) |
36 if (ret == NULL) |
37 goto bail; |
37 goto bail; |
38 |
38 |
39 goto done; |
39 goto done; |
40 |
40 |
41 bail: |
41 bail: |
42 if (fd != -1) |
42 if (fd != -1) |
43 close(fd); |
43 close(fd); |
44 |
44 |
45 Py_CLEAR(ret); |
45 Py_CLEAR(ret); |
46 |
46 |
47 done: |
47 done: |
48 return ret; |
48 return ret; |
49 } |
49 } |
50 |
50 |
51 PyDoc_STRVAR( |
51 PyDoc_STRVAR( |
52 init_doc, |
52 init_doc, |
53 "init() -> fd\n" |
53 "init() -> fd\n" |
54 "\n" |
54 "\n" |
55 "Initialise an inotify instance.\n" |
55 "Initialise an inotify instance.\n" |
56 "Return a file descriptor associated with a new inotify event queue."); |
56 "Return a file descriptor associated with a new inotify event queue."); |
57 |
57 |
58 static PyObject *add_watch(PyObject *self, PyObject *args) |
58 static PyObject *add_watch(PyObject *self, PyObject *args) |
59 { |
59 { |
60 PyObject *ret = NULL; |
60 PyObject *ret = NULL; |
61 uint32_t mask; |
61 uint32_t mask; |
62 int wd = -1; |
62 int wd = -1; |
63 char *path; |
63 char *path; |
64 int fd; |
64 int fd; |
65 |
65 |
66 if (!PyArg_ParseTuple(args, "isI:add_watch", &fd, &path, &mask)) |
66 if (!PyArg_ParseTuple(args, "isI:add_watch", &fd, &path, &mask)) |
67 goto bail; |
67 goto bail; |
68 |
68 |
69 Py_BEGIN_ALLOW_THREADS |
69 Py_BEGIN_ALLOW_THREADS; |
70 wd = inotify_add_watch(fd, path, mask); |
70 wd = inotify_add_watch(fd, path, mask); |
71 Py_END_ALLOW_THREADS |
71 Py_END_ALLOW_THREADS; |
72 |
72 |
73 if (wd == -1) { |
73 if (wd == -1) { |
74 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path); |
74 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path); |
75 goto bail; |
75 goto bail; |
76 } |
76 } |
77 |
77 |
78 ret = PyInt_FromLong(wd); |
78 ret = PyInt_FromLong(wd); |
79 if (ret == NULL) |
79 if (ret == NULL) |
80 goto bail; |
80 goto bail; |
81 |
81 |
82 goto done; |
82 goto done; |
83 |
83 |
84 bail: |
84 bail: |
85 if (wd != -1) |
85 if (wd != -1) |
86 inotify_rm_watch(fd, wd); |
86 inotify_rm_watch(fd, wd); |
87 |
87 |
88 Py_CLEAR(ret); |
88 Py_CLEAR(ret); |
89 |
89 |
90 done: |
90 done: |
91 return ret; |
91 return ret; |
92 } |
92 } |
93 |
93 |
94 PyDoc_STRVAR( |
94 PyDoc_STRVAR( |
95 add_watch_doc, |
95 add_watch_doc, |
96 "add_watch(fd, path, mask) -> wd\n" |
96 "add_watch(fd, path, mask) -> wd\n" |
97 "\n" |
97 "\n" |
98 "Add a watch to an inotify instance, or modify an existing watch.\n" |
98 "Add a watch to an inotify instance, or modify an existing watch.\n" |
99 "\n" |
99 "\n" |
100 " fd: file descriptor returned by init()\n" |
100 " fd: file descriptor returned by init()\n" |
101 " path: path to watch\n" |
101 " path: path to watch\n" |
102 " mask: mask of events to watch for\n" |
102 " mask: mask of events to watch for\n" |
103 "\n" |
103 "\n" |
104 "Return a unique numeric watch descriptor for the inotify instance\n" |
104 "Return a unique numeric watch descriptor for the inotify instance\n" |
105 "mapped by the file descriptor."); |
105 "mapped by the file descriptor."); |
106 |
106 |
107 static PyObject *remove_watch(PyObject *self, PyObject *args) |
107 static PyObject *remove_watch(PyObject *self, PyObject *args) |
108 { |
108 { |
109 uint32_t wd; |
109 uint32_t wd; |
110 int fd; |
110 int fd; |
111 int r; |
111 int r; |
112 |
112 |
113 if (!PyArg_ParseTuple(args, "iI:remove_watch", &fd, &wd)) |
113 if (!PyArg_ParseTuple(args, "iI:remove_watch", &fd, &wd)) |
114 return NULL; |
114 return NULL; |
115 |
115 |
116 Py_BEGIN_ALLOW_THREADS |
116 Py_BEGIN_ALLOW_THREADS; |
117 r = inotify_rm_watch(fd, wd); |
117 r = inotify_rm_watch(fd, wd); |
118 Py_END_ALLOW_THREADS |
118 Py_END_ALLOW_THREADS; |
119 |
119 |
120 if (r == -1) { |
120 if (r == -1) { |
121 PyErr_SetFromErrno(PyExc_OSError); |
121 PyErr_SetFromErrno(PyExc_OSError); |
122 return NULL; |
122 return NULL; |
123 } |
123 } |
124 |
124 |
125 Py_INCREF(Py_None); |
125 Py_INCREF(Py_None); |
126 return Py_None; |
126 return Py_None; |
127 } |
127 } |
128 |
128 |
129 PyDoc_STRVAR( |
129 PyDoc_STRVAR( |
130 remove_watch_doc, |
130 remove_watch_doc, |
131 "remove_watch(fd, wd)\n" |
131 "remove_watch(fd, wd)\n" |
132 "\n" |
132 "\n" |
133 " fd: file descriptor returned by init()\n" |
133 " fd: file descriptor returned by init()\n" |
134 " wd: watch descriptor returned by add_watch()\n" |
134 " wd: watch descriptor returned by add_watch()\n" |
135 "\n" |
135 "\n" |
136 "Remove a watch associated with the watch descriptor wd from the\n" |
136 "Remove a watch associated with the watch descriptor wd from the\n" |
137 "inotify instance associated with the file descriptor fd.\n" |
137 "inotify instance associated with the file descriptor fd.\n" |
138 "\n" |
138 "\n" |
139 "Removing a watch causes an IN_IGNORED event to be generated for this\n" |
139 "Removing a watch causes an IN_IGNORED event to be generated for this\n" |
140 "watch descriptor."); |
140 "watch descriptor."); |
141 |
141 |
142 #define bit_name(x) {x, #x} |
142 #define bit_name(x) {x, #x} |
143 |
143 |
144 static struct { |
144 static struct { |
145 int bit; |
145 int bit; |
146 const char *name; |
146 const char *name; |
147 PyObject *pyname; |
147 PyObject *pyname; |
148 } bit_names[] = { |
148 } bit_names[] = { |
149 bit_name(IN_ACCESS), |
149 bit_name(IN_ACCESS), |
150 bit_name(IN_MODIFY), |
150 bit_name(IN_MODIFY), |
151 bit_name(IN_ATTRIB), |
151 bit_name(IN_ATTRIB), |
152 bit_name(IN_CLOSE_WRITE), |
152 bit_name(IN_CLOSE_WRITE), |
153 bit_name(IN_CLOSE_NOWRITE), |
153 bit_name(IN_CLOSE_NOWRITE), |
154 bit_name(IN_OPEN), |
154 bit_name(IN_OPEN), |
155 bit_name(IN_MOVED_FROM), |
155 bit_name(IN_MOVED_FROM), |
156 bit_name(IN_MOVED_TO), |
156 bit_name(IN_MOVED_TO), |
157 bit_name(IN_CREATE), |
157 bit_name(IN_CREATE), |
158 bit_name(IN_DELETE), |
158 bit_name(IN_DELETE), |
159 bit_name(IN_DELETE_SELF), |
159 bit_name(IN_DELETE_SELF), |
160 bit_name(IN_MOVE_SELF), |
160 bit_name(IN_MOVE_SELF), |
161 bit_name(IN_UNMOUNT), |
161 bit_name(IN_UNMOUNT), |
162 bit_name(IN_Q_OVERFLOW), |
162 bit_name(IN_Q_OVERFLOW), |
163 bit_name(IN_IGNORED), |
163 bit_name(IN_IGNORED), |
164 bit_name(IN_ONLYDIR), |
164 bit_name(IN_ONLYDIR), |
165 bit_name(IN_DONT_FOLLOW), |
165 bit_name(IN_DONT_FOLLOW), |
166 bit_name(IN_MASK_ADD), |
166 bit_name(IN_MASK_ADD), |
167 bit_name(IN_ISDIR), |
167 bit_name(IN_ISDIR), |
168 bit_name(IN_ONESHOT), |
168 bit_name(IN_ONESHOT), |
169 {0} |
169 {0} |
170 }; |
170 }; |
171 |
171 |
172 static PyObject *decode_mask(int mask) |
172 static PyObject *decode_mask(int mask) |
173 { |
173 { |
174 PyObject *ret = PyList_New(0); |
174 PyObject *ret = PyList_New(0); |
175 int i; |
175 int i; |
176 |
176 |
177 if (ret == NULL) |
177 if (ret == NULL) |
178 goto bail; |
178 goto bail; |
179 |
179 |
180 for (i = 0; bit_names[i].bit; i++) { |
180 for (i = 0; bit_names[i].bit; i++) { |
181 if (mask & bit_names[i].bit) { |
181 if (mask & bit_names[i].bit) { |
182 if (bit_names[i].pyname == NULL) { |
182 if (bit_names[i].pyname == NULL) { |
183 bit_names[i].pyname = PyString_FromString(bit_names[i].name); |
183 bit_names[i].pyname = PyString_FromString(bit_names[i].name); |
184 if (bit_names[i].pyname == NULL) |
184 if (bit_names[i].pyname == NULL) |
185 goto bail; |
185 goto bail; |
186 } |
186 } |
187 Py_INCREF(bit_names[i].pyname); |
187 Py_INCREF(bit_names[i].pyname); |
188 if (PyList_Append(ret, bit_names[i].pyname) == -1) |
188 if (PyList_Append(ret, bit_names[i].pyname) == -1) |
189 goto bail; |
189 goto bail; |
190 } |
190 } |
191 } |
191 } |
192 |
192 |
193 goto done; |
193 goto done; |
194 |
194 |
195 bail: |
195 bail: |
196 Py_CLEAR(ret); |
196 Py_CLEAR(ret); |
197 |
197 |
198 done: |
198 done: |
199 return ret; |
199 return ret; |
200 } |
200 } |
201 |
201 |
202 static PyObject *pydecode_mask(PyObject *self, PyObject *args) |
202 static PyObject *pydecode_mask(PyObject *self, PyObject *args) |
203 { |
203 { |
204 int mask; |
204 int mask; |
205 |
205 |
206 if (!PyArg_ParseTuple(args, "i:decode_mask", &mask)) |
206 if (!PyArg_ParseTuple(args, "i:decode_mask", &mask)) |
207 return NULL; |
207 return NULL; |
208 |
208 |
209 return decode_mask(mask); |
209 return decode_mask(mask); |
210 } |
210 } |
211 |
211 |
212 PyDoc_STRVAR( |
212 PyDoc_STRVAR( |
213 decode_mask_doc, |
213 decode_mask_doc, |
214 "decode_mask(mask) -> list_of_strings\n" |
214 "decode_mask(mask) -> list_of_strings\n" |
215 "\n" |
215 "\n" |
216 "Decode an inotify mask value into a list of strings that give the\n" |
216 "Decode an inotify mask value into a list of strings that give the\n" |
217 "name of each bit set in the mask."); |
217 "name of each bit set in the mask."); |
218 |
218 |
219 static char doc[] = "Low-level inotify interface wrappers."; |
219 static char doc[] = "Low-level inotify interface wrappers."; |
220 |
220 |
221 static void define_const(PyObject *dict, const char *name, uint32_t val) |
221 static void define_const(PyObject *dict, const char *name, uint32_t val) |
222 { |
222 { |
223 PyObject *pyval = PyInt_FromLong(val); |
223 PyObject *pyval = PyInt_FromLong(val); |
224 PyObject *pyname = PyString_FromString(name); |
224 PyObject *pyname = PyString_FromString(name); |
225 |
225 |
226 if (!pyname || !pyval) |
226 if (!pyname || !pyval) |
227 goto bail; |
227 goto bail; |
228 |
228 |
229 PyDict_SetItem(dict, pyname, pyval); |
229 PyDict_SetItem(dict, pyname, pyval); |
230 |
230 |
231 bail: |
231 bail: |
232 Py_XDECREF(pyname); |
232 Py_XDECREF(pyname); |
233 Py_XDECREF(pyval); |
233 Py_XDECREF(pyval); |
234 } |
234 } |
235 |
235 |
236 static void define_consts(PyObject *dict) |
236 static void define_consts(PyObject *dict) |
237 { |
237 { |
238 define_const(dict, "IN_ACCESS", IN_ACCESS); |
238 define_const(dict, "IN_ACCESS", IN_ACCESS); |
239 define_const(dict, "IN_MODIFY", IN_MODIFY); |
239 define_const(dict, "IN_MODIFY", IN_MODIFY); |
240 define_const(dict, "IN_ATTRIB", IN_ATTRIB); |
240 define_const(dict, "IN_ATTRIB", IN_ATTRIB); |
241 define_const(dict, "IN_CLOSE_WRITE", IN_CLOSE_WRITE); |
241 define_const(dict, "IN_CLOSE_WRITE", IN_CLOSE_WRITE); |
242 define_const(dict, "IN_CLOSE_NOWRITE", IN_CLOSE_NOWRITE); |
242 define_const(dict, "IN_CLOSE_NOWRITE", IN_CLOSE_NOWRITE); |
243 define_const(dict, "IN_OPEN", IN_OPEN); |
243 define_const(dict, "IN_OPEN", IN_OPEN); |
244 define_const(dict, "IN_MOVED_FROM", IN_MOVED_FROM); |
244 define_const(dict, "IN_MOVED_FROM", IN_MOVED_FROM); |
245 define_const(dict, "IN_MOVED_TO", IN_MOVED_TO); |
245 define_const(dict, "IN_MOVED_TO", IN_MOVED_TO); |
246 |
246 |
247 define_const(dict, "IN_CLOSE", IN_CLOSE); |
247 define_const(dict, "IN_CLOSE", IN_CLOSE); |
248 define_const(dict, "IN_MOVE", IN_MOVE); |
248 define_const(dict, "IN_MOVE", IN_MOVE); |
249 |
249 |
250 define_const(dict, "IN_CREATE", IN_CREATE); |
250 define_const(dict, "IN_CREATE", IN_CREATE); |
251 define_const(dict, "IN_DELETE", IN_DELETE); |
251 define_const(dict, "IN_DELETE", IN_DELETE); |
252 define_const(dict, "IN_DELETE_SELF", IN_DELETE_SELF); |
252 define_const(dict, "IN_DELETE_SELF", IN_DELETE_SELF); |
253 define_const(dict, "IN_MOVE_SELF", IN_MOVE_SELF); |
253 define_const(dict, "IN_MOVE_SELF", IN_MOVE_SELF); |
254 define_const(dict, "IN_UNMOUNT", IN_UNMOUNT); |
254 define_const(dict, "IN_UNMOUNT", IN_UNMOUNT); |
255 define_const(dict, "IN_Q_OVERFLOW", IN_Q_OVERFLOW); |
255 define_const(dict, "IN_Q_OVERFLOW", IN_Q_OVERFLOW); |
256 define_const(dict, "IN_IGNORED", IN_IGNORED); |
256 define_const(dict, "IN_IGNORED", IN_IGNORED); |
257 |
257 |
258 define_const(dict, "IN_ONLYDIR", IN_ONLYDIR); |
258 define_const(dict, "IN_ONLYDIR", IN_ONLYDIR); |
259 define_const(dict, "IN_DONT_FOLLOW", IN_DONT_FOLLOW); |
259 define_const(dict, "IN_DONT_FOLLOW", IN_DONT_FOLLOW); |
260 define_const(dict, "IN_MASK_ADD", IN_MASK_ADD); |
260 define_const(dict, "IN_MASK_ADD", IN_MASK_ADD); |
261 define_const(dict, "IN_ISDIR", IN_ISDIR); |
261 define_const(dict, "IN_ISDIR", IN_ISDIR); |
262 define_const(dict, "IN_ONESHOT", IN_ONESHOT); |
262 define_const(dict, "IN_ONESHOT", IN_ONESHOT); |
263 define_const(dict, "IN_ALL_EVENTS", IN_ALL_EVENTS); |
263 define_const(dict, "IN_ALL_EVENTS", IN_ALL_EVENTS); |
264 } |
264 } |
265 |
265 |
266 struct event { |
266 struct event { |
267 PyObject_HEAD |
267 PyObject_HEAD |
268 PyObject *wd; |
268 PyObject *wd; |
269 PyObject *mask; |
269 PyObject *mask; |
270 PyObject *cookie; |
270 PyObject *cookie; |
271 PyObject *name; |
271 PyObject *name; |
272 }; |
272 }; |
273 |
273 |
274 static PyObject *event_wd(PyObject *self, void *x) |
274 static PyObject *event_wd(PyObject *self, void *x) |
275 { |
275 { |
276 struct event *evt = (struct event *) self; |
276 struct event *evt = (struct event *)self; |
277 Py_INCREF(evt->wd); |
277 Py_INCREF(evt->wd); |
278 return evt->wd; |
278 return evt->wd; |
279 } |
279 } |
280 |
280 |
281 static PyObject *event_mask(PyObject *self, void *x) |
281 static PyObject *event_mask(PyObject *self, void *x) |
282 { |
282 { |
283 struct event *evt = (struct event *) self; |
283 struct event *evt = (struct event *)self; |
284 Py_INCREF(evt->mask); |
284 Py_INCREF(evt->mask); |
285 return evt->mask; |
285 return evt->mask; |
286 } |
286 } |
287 |
287 |
288 static PyObject *event_cookie(PyObject *self, void *x) |
288 static PyObject *event_cookie(PyObject *self, void *x) |
289 { |
289 { |
290 struct event *evt = (struct event *) self; |
290 struct event *evt = (struct event *)self; |
291 Py_INCREF(evt->cookie); |
291 Py_INCREF(evt->cookie); |
292 return evt->cookie; |
292 return evt->cookie; |
293 } |
293 } |
294 |
294 |
295 static PyObject *event_name(PyObject *self, void *x) |
295 static PyObject *event_name(PyObject *self, void *x) |
296 { |
296 { |
297 struct event *evt = (struct event *) self; |
297 struct event *evt = (struct event *)self; |
298 Py_INCREF(evt->name); |
298 Py_INCREF(evt->name); |
299 return evt->name; |
299 return evt->name; |
300 } |
300 } |
301 |
301 |
302 static struct PyGetSetDef event_getsets[] = { |
302 static struct PyGetSetDef event_getsets[] = { |
303 {"wd", event_wd, NULL, |
303 {"wd", event_wd, NULL, |
304 "watch descriptor"}, |
304 "watch descriptor"}, |
305 {"mask", event_mask, NULL, |
305 {"mask", event_mask, NULL, |
306 "event mask"}, |
306 "event mask"}, |
307 {"cookie", event_cookie, NULL, |
307 {"cookie", event_cookie, NULL, |
308 "rename cookie, if rename-related event"}, |
308 "rename cookie, if rename-related event"}, |
309 {"name", event_name, NULL, |
309 {"name", event_name, NULL, |
310 "file name"}, |
310 "file name"}, |
311 {NULL} |
311 {NULL} |
312 }; |
312 }; |
313 |
313 |
314 PyDoc_STRVAR( |
314 PyDoc_STRVAR( |
315 event_doc, |
315 event_doc, |
316 "event: Structure describing an inotify event."); |
316 "event: Structure describing an inotify event."); |
317 |
317 |
318 static PyObject *event_new(PyTypeObject *t, PyObject *a, PyObject *k) |
318 static PyObject *event_new(PyTypeObject *t, PyObject *a, PyObject *k) |
319 { |
319 { |
320 return (*t->tp_alloc)(t, 0); |
320 return (*t->tp_alloc)(t, 0); |
321 } |
321 } |
322 |
322 |
323 static void event_dealloc(struct event *evt) |
323 static void event_dealloc(struct event *evt) |
324 { |
324 { |
325 Py_XDECREF(evt->wd); |
325 Py_XDECREF(evt->wd); |
326 Py_XDECREF(evt->mask); |
326 Py_XDECREF(evt->mask); |
327 Py_XDECREF(evt->cookie); |
327 Py_XDECREF(evt->cookie); |
328 Py_XDECREF(evt->name); |
328 Py_XDECREF(evt->name); |
329 |
329 |
330 (*evt->ob_type->tp_free)(evt); |
330 (*evt->ob_type->tp_free)(evt); |
331 } |
331 } |
332 |
332 |
333 static PyObject *event_repr(struct event *evt) |
333 static PyObject *event_repr(struct event *evt) |
334 { |
334 { |
335 int wd = PyInt_AsLong(evt->wd); |
335 int wd = PyInt_AsLong(evt->wd); |
336 int cookie = evt->cookie == Py_None ? -1 : PyInt_AsLong(evt->cookie); |
336 int cookie = evt->cookie == Py_None ? -1 : PyInt_AsLong(evt->cookie); |
337 PyObject *ret = NULL, *pymasks = NULL, *pymask = NULL; |
337 PyObject *ret = NULL, *pymasks = NULL, *pymask = NULL; |
338 PyObject *join = NULL; |
338 PyObject *join = NULL; |
339 char *maskstr; |
339 char *maskstr; |
340 |
340 |
341 join = PyString_FromString("|"); |
341 join = PyString_FromString("|"); |
342 if (join == NULL) |
342 if (join == NULL) |
343 goto bail; |
343 goto bail; |
344 |
344 |
345 pymasks = decode_mask(PyInt_AsLong(evt->mask)); |
345 pymasks = decode_mask(PyInt_AsLong(evt->mask)); |
346 if (pymasks == NULL) |
346 if (pymasks == NULL) |
347 goto bail; |
347 goto bail; |
348 |
348 |
349 pymask = _PyString_Join(join, pymasks); |
349 pymask = _PyString_Join(join, pymasks); |
350 if (pymask == NULL) |
350 if (pymask == NULL) |
351 goto bail; |
351 goto bail; |
352 |
352 |
353 maskstr = PyString_AsString(pymask); |
353 maskstr = PyString_AsString(pymask); |
354 |
354 |
355 if (evt->name != Py_None) { |
355 if (evt->name != Py_None) { |
356 PyObject *pyname = PyString_Repr(evt->name, 1); |
356 PyObject *pyname = PyString_Repr(evt->name, 1); |
357 char *name = pyname ? PyString_AsString(pyname) : "???"; |
357 char *name = pyname ? PyString_AsString(pyname) : "???"; |
358 |
358 |
359 if (cookie == -1) |
359 if (cookie == -1) |
360 ret = PyString_FromFormat("event(wd=%d, mask=%s, name=%s)", |
360 ret = PyString_FromFormat( |
361 wd, maskstr, name); |
361 "event(wd=%d, mask=%s, name=%s)", |
362 else |
362 wd, maskstr, name); |
363 ret = PyString_FromFormat("event(wd=%d, mask=%s, " |
363 else |
364 "cookie=0x%x, name=%s)", |
364 ret = PyString_FromFormat("event(wd=%d, mask=%s, " |
365 wd, maskstr, cookie, name); |
365 "cookie=0x%x, name=%s)", |
366 |
366 wd, maskstr, cookie, name); |
367 Py_XDECREF(pyname); |
367 |
368 } else { |
368 Py_XDECREF(pyname); |
369 if (cookie == -1) |
369 } else { |
370 ret = PyString_FromFormat("event(wd=%d, mask=%s)", |
370 if (cookie == -1) |
371 wd, maskstr); |
371 ret = PyString_FromFormat("event(wd=%d, mask=%s)", |
|
372 wd, maskstr); |
|
373 else { |
|
374 ret = PyString_FromFormat( |
|
375 "event(wd=%d, mask=%s, cookie=0x%x)", |
|
376 wd, maskstr, cookie); |
|
377 } |
|
378 } |
|
379 |
|
380 goto done; |
|
381 bail: |
|
382 Py_CLEAR(ret); |
|
383 |
|
384 done: |
|
385 Py_XDECREF(pymask); |
|
386 Py_XDECREF(pymasks); |
|
387 Py_XDECREF(join); |
|
388 |
|
389 return ret; |
|
390 } |
|
391 |
|
392 static PyTypeObject event_type = { |
|
393 PyObject_HEAD_INIT(NULL) |
|
394 0, /*ob_size*/ |
|
395 "_inotify.event", /*tp_name*/ |
|
396 sizeof(struct event), /*tp_basicsize*/ |
|
397 0, /*tp_itemsize*/ |
|
398 (destructor)event_dealloc, /*tp_dealloc*/ |
|
399 0, /*tp_print*/ |
|
400 0, /*tp_getattr*/ |
|
401 0, /*tp_setattr*/ |
|
402 0, /*tp_compare*/ |
|
403 (reprfunc)event_repr, /*tp_repr*/ |
|
404 0, /*tp_as_number*/ |
|
405 0, /*tp_as_sequence*/ |
|
406 0, /*tp_as_mapping*/ |
|
407 0, /*tp_hash */ |
|
408 0, /*tp_call*/ |
|
409 0, /*tp_str*/ |
|
410 0, /*tp_getattro*/ |
|
411 0, /*tp_setattro*/ |
|
412 0, /*tp_as_buffer*/ |
|
413 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ |
|
414 event_doc, /* tp_doc */ |
|
415 0, /* tp_traverse */ |
|
416 0, /* tp_clear */ |
|
417 0, /* tp_richcompare */ |
|
418 0, /* tp_weaklistoffset */ |
|
419 0, /* tp_iter */ |
|
420 0, /* tp_iternext */ |
|
421 0, /* tp_methods */ |
|
422 0, /* tp_members */ |
|
423 event_getsets, /* tp_getset */ |
|
424 0, /* tp_base */ |
|
425 0, /* tp_dict */ |
|
426 0, /* tp_descr_get */ |
|
427 0, /* tp_descr_set */ |
|
428 0, /* tp_dictoffset */ |
|
429 0, /* tp_init */ |
|
430 0, /* tp_alloc */ |
|
431 event_new, /* tp_new */ |
|
432 }; |
|
433 |
|
434 PyObject *read_events(PyObject *self, PyObject *args) |
|
435 { |
|
436 PyObject *ctor_args = NULL; |
|
437 PyObject *pybufsize = NULL; |
|
438 PyObject *ret = NULL; |
|
439 int bufsize = 65536; |
|
440 char *buf = NULL; |
|
441 int nread, pos; |
|
442 int fd; |
|
443 |
|
444 if (!PyArg_ParseTuple(args, "i|O:read", &fd, &pybufsize)) |
|
445 goto bail; |
|
446 |
|
447 if (pybufsize && pybufsize != Py_None) |
|
448 bufsize = PyInt_AsLong(pybufsize); |
|
449 |
|
450 ret = PyList_New(0); |
|
451 if (ret == NULL) |
|
452 goto bail; |
|
453 |
|
454 if (bufsize <= 0) { |
|
455 int r; |
|
456 |
|
457 Py_BEGIN_ALLOW_THREADS; |
|
458 r = ioctl(fd, FIONREAD, &bufsize); |
|
459 Py_END_ALLOW_THREADS; |
|
460 |
|
461 if (r == -1) { |
|
462 PyErr_SetFromErrno(PyExc_OSError); |
|
463 goto bail; |
|
464 } |
|
465 if (bufsize == 0) |
|
466 goto done; |
|
467 } |
372 else { |
468 else { |
373 ret = PyString_FromFormat("event(wd=%d, mask=%s, cookie=0x%x)", |
469 static long name_max; |
374 wd, maskstr, cookie); |
470 static long name_fd = -1; |
375 } |
471 long min; |
376 } |
472 |
377 |
473 if (name_fd != fd) { |
378 goto done; |
474 name_fd = fd; |
|
475 Py_BEGIN_ALLOW_THREADS; |
|
476 name_max = fpathconf(fd, _PC_NAME_MAX); |
|
477 Py_END_ALLOW_THREADS; |
|
478 } |
|
479 |
|
480 min = sizeof(struct inotify_event) + name_max + 1; |
|
481 |
|
482 if (bufsize < min) { |
|
483 PyErr_Format(PyExc_ValueError, |
|
484 "bufsize must be at least %d", (int)min); |
|
485 goto bail; |
|
486 } |
|
487 } |
|
488 |
|
489 buf = alloca(bufsize); |
|
490 |
|
491 Py_BEGIN_ALLOW_THREADS; |
|
492 nread = read(fd, buf, bufsize); |
|
493 Py_END_ALLOW_THREADS; |
|
494 |
|
495 if (nread == -1) { |
|
496 PyErr_SetFromErrno(PyExc_OSError); |
|
497 goto bail; |
|
498 } |
|
499 |
|
500 ctor_args = PyTuple_New(0); |
|
501 |
|
502 if (ctor_args == NULL) |
|
503 goto bail; |
|
504 |
|
505 pos = 0; |
|
506 |
|
507 while (pos < nread) { |
|
508 struct inotify_event *in = (struct inotify_event *)(buf + pos); |
|
509 struct event *evt; |
|
510 PyObject *obj; |
|
511 |
|
512 obj = PyObject_CallObject((PyObject *)&event_type, ctor_args); |
|
513 |
|
514 if (obj == NULL) |
|
515 goto bail; |
|
516 |
|
517 evt = (struct event *)obj; |
|
518 |
|
519 evt->wd = PyInt_FromLong(in->wd); |
|
520 evt->mask = PyInt_FromLong(in->mask); |
|
521 if (in->mask & IN_MOVE) |
|
522 evt->cookie = PyInt_FromLong(in->cookie); |
|
523 else { |
|
524 Py_INCREF(Py_None); |
|
525 evt->cookie = Py_None; |
|
526 } |
|
527 if (in->len) |
|
528 evt->name = PyString_FromString(in->name); |
|
529 else { |
|
530 Py_INCREF(Py_None); |
|
531 evt->name = Py_None; |
|
532 } |
|
533 |
|
534 if (!evt->wd || !evt->mask || !evt->cookie || !evt->name) |
|
535 goto mybail; |
|
536 |
|
537 if (PyList_Append(ret, obj) == -1) |
|
538 goto mybail; |
|
539 |
|
540 pos += sizeof(struct inotify_event) + in->len; |
|
541 continue; |
|
542 |
|
543 mybail: |
|
544 Py_CLEAR(evt->wd); |
|
545 Py_CLEAR(evt->mask); |
|
546 Py_CLEAR(evt->cookie); |
|
547 Py_CLEAR(evt->name); |
|
548 Py_DECREF(obj); |
|
549 |
|
550 goto bail; |
|
551 } |
|
552 |
|
553 goto done; |
|
554 |
379 bail: |
555 bail: |
380 Py_CLEAR(ret); |
556 Py_CLEAR(ret); |
381 |
557 |
382 done: |
558 done: |
383 Py_XDECREF(pymask); |
559 Py_XDECREF(ctor_args); |
384 Py_XDECREF(pymasks); |
560 |
385 Py_XDECREF(join); |
561 return ret; |
386 |
562 } |
387 return ret; |
563 |
388 } |
564 PyDoc_STRVAR( |
389 |
565 read_doc, |
390 static PyTypeObject event_type = { |
566 "read(fd, bufsize[=65536]) -> list_of_events\n" |
391 PyObject_HEAD_INIT(NULL) |
567 "\n" |
392 0, /*ob_size*/ |
568 "\nRead inotify events from a file descriptor.\n" |
393 "_inotify.event", /*tp_name*/ |
569 "\n" |
394 sizeof(struct event), /*tp_basicsize*/ |
570 " fd: file descriptor returned by init()\n" |
395 0, /*tp_itemsize*/ |
571 " bufsize: size of buffer to read into, in bytes\n" |
396 (destructor)event_dealloc, /*tp_dealloc*/ |
572 "\n" |
397 0, /*tp_print*/ |
573 "Return a list of event objects.\n" |
398 0, /*tp_getattr*/ |
574 "\n" |
399 0, /*tp_setattr*/ |
575 "If bufsize is > 0, block until events are available to be read.\n" |
400 0, /*tp_compare*/ |
576 "Otherwise, immediately return all events that can be read without\n" |
401 (reprfunc)event_repr, /*tp_repr*/ |
577 "blocking."); |
402 0, /*tp_as_number*/ |
578 |
403 0, /*tp_as_sequence*/ |
579 static PyMethodDef methods[] = { |
404 0, /*tp_as_mapping*/ |
580 {"init", init, METH_VARARGS, init_doc}, |
405 0, /*tp_hash */ |
581 {"add_watch", add_watch, METH_VARARGS, add_watch_doc}, |
406 0, /*tp_call*/ |
582 {"remove_watch", remove_watch, METH_VARARGS, remove_watch_doc}, |
407 0, /*tp_str*/ |
583 {"read", read_events, METH_VARARGS, read_doc}, |
408 0, /*tp_getattro*/ |
584 {"decode_mask", pydecode_mask, METH_VARARGS, decode_mask_doc}, |
409 0, /*tp_setattro*/ |
585 {NULL}, |
410 0, /*tp_as_buffer*/ |
|
411 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ |
|
412 event_doc, /* tp_doc */ |
|
413 0, /* tp_traverse */ |
|
414 0, /* tp_clear */ |
|
415 0, /* tp_richcompare */ |
|
416 0, /* tp_weaklistoffset */ |
|
417 0, /* tp_iter */ |
|
418 0, /* tp_iternext */ |
|
419 0, /* tp_methods */ |
|
420 0, /* tp_members */ |
|
421 event_getsets, /* tp_getset */ |
|
422 0, /* tp_base */ |
|
423 0, /* tp_dict */ |
|
424 0, /* tp_descr_get */ |
|
425 0, /* tp_descr_set */ |
|
426 0, /* tp_dictoffset */ |
|
427 0, /* tp_init */ |
|
428 0, /* tp_alloc */ |
|
429 event_new, /* tp_new */ |
|
430 }; |
586 }; |
431 |
587 |
432 PyObject *read_events(PyObject *self, PyObject *args) |
|
433 { |
|
434 PyObject *ctor_args = NULL; |
|
435 PyObject *pybufsize = NULL; |
|
436 PyObject *ret = NULL; |
|
437 int bufsize = 65536; |
|
438 char *buf = NULL; |
|
439 int nread, pos; |
|
440 int fd; |
|
441 |
|
442 if (!PyArg_ParseTuple(args, "i|O:read", &fd, &pybufsize)) |
|
443 goto bail; |
|
444 |
|
445 if (pybufsize && pybufsize != Py_None) |
|
446 bufsize = PyInt_AsLong(pybufsize); |
|
447 |
|
448 ret = PyList_New(0); |
|
449 if (ret == NULL) |
|
450 goto bail; |
|
451 |
|
452 if (bufsize <= 0) { |
|
453 int r; |
|
454 |
|
455 Py_BEGIN_ALLOW_THREADS |
|
456 r = ioctl(fd, FIONREAD, &bufsize); |
|
457 Py_END_ALLOW_THREADS |
|
458 |
|
459 if (r == -1) { |
|
460 PyErr_SetFromErrno(PyExc_OSError); |
|
461 goto bail; |
|
462 } |
|
463 if (bufsize == 0) |
|
464 goto done; |
|
465 } |
|
466 else { |
|
467 static long name_max; |
|
468 static long name_fd = -1; |
|
469 long min; |
|
470 |
|
471 if (name_fd != fd) { |
|
472 name_fd = fd; |
|
473 Py_BEGIN_ALLOW_THREADS |
|
474 name_max = fpathconf(fd, _PC_NAME_MAX); |
|
475 Py_END_ALLOW_THREADS |
|
476 } |
|
477 |
|
478 min = sizeof(struct inotify_event) + name_max + 1; |
|
479 |
|
480 if (bufsize < min) { |
|
481 PyErr_Format(PyExc_ValueError, "bufsize must be at least %d", |
|
482 (int) min); |
|
483 goto bail; |
|
484 } |
|
485 } |
|
486 |
|
487 buf = alloca(bufsize); |
|
488 |
|
489 Py_BEGIN_ALLOW_THREADS |
|
490 nread = read(fd, buf, bufsize); |
|
491 Py_END_ALLOW_THREADS |
|
492 |
|
493 if (nread == -1) { |
|
494 PyErr_SetFromErrno(PyExc_OSError); |
|
495 goto bail; |
|
496 } |
|
497 |
|
498 ctor_args = PyTuple_New(0); |
|
499 |
|
500 if (ctor_args == NULL) |
|
501 goto bail; |
|
502 |
|
503 pos = 0; |
|
504 |
|
505 while (pos < nread) { |
|
506 struct inotify_event *in = (struct inotify_event *) (buf + pos); |
|
507 struct event *evt; |
|
508 PyObject *obj; |
|
509 |
|
510 obj = PyObject_CallObject((PyObject *) &event_type, ctor_args); |
|
511 |
|
512 if (obj == NULL) |
|
513 goto bail; |
|
514 |
|
515 evt = (struct event *) obj; |
|
516 |
|
517 evt->wd = PyInt_FromLong(in->wd); |
|
518 evt->mask = PyInt_FromLong(in->mask); |
|
519 if (in->mask & IN_MOVE) |
|
520 evt->cookie = PyInt_FromLong(in->cookie); |
|
521 else { |
|
522 Py_INCREF(Py_None); |
|
523 evt->cookie = Py_None; |
|
524 } |
|
525 if (in->len) |
|
526 evt->name = PyString_FromString(in->name); |
|
527 else { |
|
528 Py_INCREF(Py_None); |
|
529 evt->name = Py_None; |
|
530 } |
|
531 |
|
532 if (!evt->wd || !evt->mask || !evt->cookie || !evt->name) |
|
533 goto mybail; |
|
534 |
|
535 if (PyList_Append(ret, obj) == -1) |
|
536 goto mybail; |
|
537 |
|
538 pos += sizeof(struct inotify_event) + in->len; |
|
539 continue; |
|
540 |
|
541 mybail: |
|
542 Py_CLEAR(evt->wd); |
|
543 Py_CLEAR(evt->mask); |
|
544 Py_CLEAR(evt->cookie); |
|
545 Py_CLEAR(evt->name); |
|
546 Py_DECREF(obj); |
|
547 |
|
548 goto bail; |
|
549 } |
|
550 |
|
551 goto done; |
|
552 |
|
553 bail: |
|
554 Py_CLEAR(ret); |
|
555 |
|
556 done: |
|
557 Py_XDECREF(ctor_args); |
|
558 |
|
559 return ret; |
|
560 } |
|
561 |
|
562 PyDoc_STRVAR( |
|
563 read_doc, |
|
564 "read(fd, bufsize[=65536]) -> list_of_events\n" |
|
565 "\n" |
|
566 "\nRead inotify events from a file descriptor.\n" |
|
567 "\n" |
|
568 " fd: file descriptor returned by init()\n" |
|
569 " bufsize: size of buffer to read into, in bytes\n" |
|
570 "\n" |
|
571 "Return a list of event objects.\n" |
|
572 "\n" |
|
573 "If bufsize is > 0, block until events are available to be read.\n" |
|
574 "Otherwise, immediately return all events that can be read without\n" |
|
575 "blocking."); |
|
576 |
|
577 |
|
578 static PyMethodDef methods[] = { |
|
579 {"init", init, METH_VARARGS, init_doc}, |
|
580 {"add_watch", add_watch, METH_VARARGS, add_watch_doc}, |
|
581 {"remove_watch", remove_watch, METH_VARARGS, remove_watch_doc}, |
|
582 {"read", read_events, METH_VARARGS, read_doc}, |
|
583 {"decode_mask", pydecode_mask, METH_VARARGS, decode_mask_doc}, |
|
584 {NULL}, |
|
585 }; |
|
586 |
|
587 void init_inotify(void) |
588 void init_inotify(void) |
588 { |
589 { |
589 PyObject *mod, *dict; |
590 PyObject *mod, *dict; |
590 |
591 |
591 if (PyType_Ready(&event_type) == -1) |
592 if (PyType_Ready(&event_type) == -1) |
592 return; |
593 return; |
593 |
594 |
594 mod = Py_InitModule3("_inotify", methods, doc); |
595 mod = Py_InitModule3("_inotify", methods, doc); |
595 |
596 |
596 dict = PyModule_GetDict(mod); |
597 dict = PyModule_GetDict(mod); |
597 |
598 |
598 if (dict) |
599 if (dict) |
599 define_consts(dict); |
600 define_consts(dict); |
600 } |
601 } |