##// END OF EJS Templates
inotify: _inotify.c: bugfix: remove_watch has to return PyNone on success...
Nicolas Dumazet -
r9428:5d6659cf default
parent child Browse files
Show More
@@ -1,608 +1,600 b''
1 /*
1 /*
2 * _inotify.c - Python extension interfacing to the Linux inotify subsystem
2 * _inotify.c - Python extension interfacing to the Linux inotify subsystem
3 *
3 *
4 * Copyright 2006 Bryan O'Sullivan <bos@serpentine.com>
4 * Copyright 2006 Bryan O'Sullivan <bos@serpentine.com>
5 *
5 *
6 * This library is free software; you can redistribute it and/or
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU Lesser General
7 * modify it under the terms of version 2.1 of the GNU Lesser General
8 * Public License, incorporated herein by reference.
8 * Public License, incorporated herein by reference.
9 */
9 */
10
10
11 #include <Python.h>
11 #include <Python.h>
12 #include <alloca.h>
12 #include <alloca.h>
13 #include <sys/inotify.h>
13 #include <sys/inotify.h>
14 #include <stdint.h>
14 #include <stdint.h>
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 PyObject *ret = NULL;
110 uint32_t wd;
109 uint32_t wd;
111 int fd;
110 int fd;
112 int r;
111 int r;
113
112
114 if (!PyArg_ParseTuple(args, "iI:remove_watch", &fd, &wd))
113 if (!PyArg_ParseTuple(args, "iI:remove_watch", &fd, &wd))
115 goto bail;
114 return NULL;
116
115
117 Py_BEGIN_ALLOW_THREADS
116 Py_BEGIN_ALLOW_THREADS
118 r = inotify_rm_watch(fd, wd);
117 r = inotify_rm_watch(fd, wd);
119 Py_END_ALLOW_THREADS
118 Py_END_ALLOW_THREADS
120
119
121 if (r == -1) {
120 if (r == -1) {
122 PyErr_SetFromErrno(PyExc_OSError);
121 PyErr_SetFromErrno(PyExc_OSError);
123 goto bail;
122 return NULL;
124 }
123 }
125
124
126 Py_INCREF(Py_None);
125 Py_INCREF(Py_None);
127
126 return Py_None;
128 goto done;
129
130 bail:
131 Py_CLEAR(ret);
132
133 done:
134 return ret;
135 }
127 }
136
128
137 PyDoc_STRVAR(
129 PyDoc_STRVAR(
138 remove_watch_doc,
130 remove_watch_doc,
139 "remove_watch(fd, wd)\n"
131 "remove_watch(fd, wd)\n"
140 "\n"
132 "\n"
141 " fd: file descriptor returned by init()\n"
133 " fd: file descriptor returned by init()\n"
142 " wd: watch descriptor returned by add_watch()\n"
134 " wd: watch descriptor returned by add_watch()\n"
143 "\n"
135 "\n"
144 "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"
145 "inotify instance associated with the file descriptor fd.\n"
137 "inotify instance associated with the file descriptor fd.\n"
146 "\n"
138 "\n"
147 "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"
148 "watch descriptor.");
140 "watch descriptor.");
149
141
150 #define bit_name(x) {x, #x}
142 #define bit_name(x) {x, #x}
151
143
152 static struct {
144 static struct {
153 int bit;
145 int bit;
154 const char *name;
146 const char *name;
155 PyObject *pyname;
147 PyObject *pyname;
156 } bit_names[] = {
148 } bit_names[] = {
157 bit_name(IN_ACCESS),
149 bit_name(IN_ACCESS),
158 bit_name(IN_MODIFY),
150 bit_name(IN_MODIFY),
159 bit_name(IN_ATTRIB),
151 bit_name(IN_ATTRIB),
160 bit_name(IN_CLOSE_WRITE),
152 bit_name(IN_CLOSE_WRITE),
161 bit_name(IN_CLOSE_NOWRITE),
153 bit_name(IN_CLOSE_NOWRITE),
162 bit_name(IN_OPEN),
154 bit_name(IN_OPEN),
163 bit_name(IN_MOVED_FROM),
155 bit_name(IN_MOVED_FROM),
164 bit_name(IN_MOVED_TO),
156 bit_name(IN_MOVED_TO),
165 bit_name(IN_CREATE),
157 bit_name(IN_CREATE),
166 bit_name(IN_DELETE),
158 bit_name(IN_DELETE),
167 bit_name(IN_DELETE_SELF),
159 bit_name(IN_DELETE_SELF),
168 bit_name(IN_MOVE_SELF),
160 bit_name(IN_MOVE_SELF),
169 bit_name(IN_UNMOUNT),
161 bit_name(IN_UNMOUNT),
170 bit_name(IN_Q_OVERFLOW),
162 bit_name(IN_Q_OVERFLOW),
171 bit_name(IN_IGNORED),
163 bit_name(IN_IGNORED),
172 bit_name(IN_ONLYDIR),
164 bit_name(IN_ONLYDIR),
173 bit_name(IN_DONT_FOLLOW),
165 bit_name(IN_DONT_FOLLOW),
174 bit_name(IN_MASK_ADD),
166 bit_name(IN_MASK_ADD),
175 bit_name(IN_ISDIR),
167 bit_name(IN_ISDIR),
176 bit_name(IN_ONESHOT),
168 bit_name(IN_ONESHOT),
177 {0}
169 {0}
178 };
170 };
179
171
180 static PyObject *decode_mask(int mask)
172 static PyObject *decode_mask(int mask)
181 {
173 {
182 PyObject *ret = PyList_New(0);
174 PyObject *ret = PyList_New(0);
183 int i;
175 int i;
184
176
185 if (ret == NULL)
177 if (ret == NULL)
186 goto bail;
178 goto bail;
187
179
188 for (i = 0; bit_names[i].bit; i++) {
180 for (i = 0; bit_names[i].bit; i++) {
189 if (mask & bit_names[i].bit) {
181 if (mask & bit_names[i].bit) {
190 if (bit_names[i].pyname == NULL) {
182 if (bit_names[i].pyname == NULL) {
191 bit_names[i].pyname = PyString_FromString(bit_names[i].name);
183 bit_names[i].pyname = PyString_FromString(bit_names[i].name);
192 if (bit_names[i].pyname == NULL)
184 if (bit_names[i].pyname == NULL)
193 goto bail;
185 goto bail;
194 }
186 }
195 Py_INCREF(bit_names[i].pyname);
187 Py_INCREF(bit_names[i].pyname);
196 if (PyList_Append(ret, bit_names[i].pyname) == -1)
188 if (PyList_Append(ret, bit_names[i].pyname) == -1)
197 goto bail;
189 goto bail;
198 }
190 }
199 }
191 }
200
192
201 goto done;
193 goto done;
202
194
203 bail:
195 bail:
204 Py_CLEAR(ret);
196 Py_CLEAR(ret);
205
197
206 done:
198 done:
207 return ret;
199 return ret;
208 }
200 }
209
201
210 static PyObject *pydecode_mask(PyObject *self, PyObject *args)
202 static PyObject *pydecode_mask(PyObject *self, PyObject *args)
211 {
203 {
212 int mask;
204 int mask;
213
205
214 if (!PyArg_ParseTuple(args, "i:decode_mask", &mask))
206 if (!PyArg_ParseTuple(args, "i:decode_mask", &mask))
215 return NULL;
207 return NULL;
216
208
217 return decode_mask(mask);
209 return decode_mask(mask);
218 }
210 }
219
211
220 PyDoc_STRVAR(
212 PyDoc_STRVAR(
221 decode_mask_doc,
213 decode_mask_doc,
222 "decode_mask(mask) -> list_of_strings\n"
214 "decode_mask(mask) -> list_of_strings\n"
223 "\n"
215 "\n"
224 "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"
225 "name of each bit set in the mask.");
217 "name of each bit set in the mask.");
226
218
227 static char doc[] = "Low-level inotify interface wrappers.";
219 static char doc[] = "Low-level inotify interface wrappers.";
228
220
229 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)
230 {
222 {
231 PyObject *pyval = PyInt_FromLong(val);
223 PyObject *pyval = PyInt_FromLong(val);
232 PyObject *pyname = PyString_FromString(name);
224 PyObject *pyname = PyString_FromString(name);
233
225
234 if (!pyname || !pyval)
226 if (!pyname || !pyval)
235 goto bail;
227 goto bail;
236
228
237 PyDict_SetItem(dict, pyname, pyval);
229 PyDict_SetItem(dict, pyname, pyval);
238
230
239 bail:
231 bail:
240 Py_XDECREF(pyname);
232 Py_XDECREF(pyname);
241 Py_XDECREF(pyval);
233 Py_XDECREF(pyval);
242 }
234 }
243
235
244 static void define_consts(PyObject *dict)
236 static void define_consts(PyObject *dict)
245 {
237 {
246 define_const(dict, "IN_ACCESS", IN_ACCESS);
238 define_const(dict, "IN_ACCESS", IN_ACCESS);
247 define_const(dict, "IN_MODIFY", IN_MODIFY);
239 define_const(dict, "IN_MODIFY", IN_MODIFY);
248 define_const(dict, "IN_ATTRIB", IN_ATTRIB);
240 define_const(dict, "IN_ATTRIB", IN_ATTRIB);
249 define_const(dict, "IN_CLOSE_WRITE", IN_CLOSE_WRITE);
241 define_const(dict, "IN_CLOSE_WRITE", IN_CLOSE_WRITE);
250 define_const(dict, "IN_CLOSE_NOWRITE", IN_CLOSE_NOWRITE);
242 define_const(dict, "IN_CLOSE_NOWRITE", IN_CLOSE_NOWRITE);
251 define_const(dict, "IN_OPEN", IN_OPEN);
243 define_const(dict, "IN_OPEN", IN_OPEN);
252 define_const(dict, "IN_MOVED_FROM", IN_MOVED_FROM);
244 define_const(dict, "IN_MOVED_FROM", IN_MOVED_FROM);
253 define_const(dict, "IN_MOVED_TO", IN_MOVED_TO);
245 define_const(dict, "IN_MOVED_TO", IN_MOVED_TO);
254
246
255 define_const(dict, "IN_CLOSE", IN_CLOSE);
247 define_const(dict, "IN_CLOSE", IN_CLOSE);
256 define_const(dict, "IN_MOVE", IN_MOVE);
248 define_const(dict, "IN_MOVE", IN_MOVE);
257
249
258 define_const(dict, "IN_CREATE", IN_CREATE);
250 define_const(dict, "IN_CREATE", IN_CREATE);
259 define_const(dict, "IN_DELETE", IN_DELETE);
251 define_const(dict, "IN_DELETE", IN_DELETE);
260 define_const(dict, "IN_DELETE_SELF", IN_DELETE_SELF);
252 define_const(dict, "IN_DELETE_SELF", IN_DELETE_SELF);
261 define_const(dict, "IN_MOVE_SELF", IN_MOVE_SELF);
253 define_const(dict, "IN_MOVE_SELF", IN_MOVE_SELF);
262 define_const(dict, "IN_UNMOUNT", IN_UNMOUNT);
254 define_const(dict, "IN_UNMOUNT", IN_UNMOUNT);
263 define_const(dict, "IN_Q_OVERFLOW", IN_Q_OVERFLOW);
255 define_const(dict, "IN_Q_OVERFLOW", IN_Q_OVERFLOW);
264 define_const(dict, "IN_IGNORED", IN_IGNORED);
256 define_const(dict, "IN_IGNORED", IN_IGNORED);
265
257
266 define_const(dict, "IN_ONLYDIR", IN_ONLYDIR);
258 define_const(dict, "IN_ONLYDIR", IN_ONLYDIR);
267 define_const(dict, "IN_DONT_FOLLOW", IN_DONT_FOLLOW);
259 define_const(dict, "IN_DONT_FOLLOW", IN_DONT_FOLLOW);
268 define_const(dict, "IN_MASK_ADD", IN_MASK_ADD);
260 define_const(dict, "IN_MASK_ADD", IN_MASK_ADD);
269 define_const(dict, "IN_ISDIR", IN_ISDIR);
261 define_const(dict, "IN_ISDIR", IN_ISDIR);
270 define_const(dict, "IN_ONESHOT", IN_ONESHOT);
262 define_const(dict, "IN_ONESHOT", IN_ONESHOT);
271 define_const(dict, "IN_ALL_EVENTS", IN_ALL_EVENTS);
263 define_const(dict, "IN_ALL_EVENTS", IN_ALL_EVENTS);
272 }
264 }
273
265
274 struct event {
266 struct event {
275 PyObject_HEAD
267 PyObject_HEAD
276 PyObject *wd;
268 PyObject *wd;
277 PyObject *mask;
269 PyObject *mask;
278 PyObject *cookie;
270 PyObject *cookie;
279 PyObject *name;
271 PyObject *name;
280 };
272 };
281
273
282 static PyObject *event_wd(PyObject *self, void *x)
274 static PyObject *event_wd(PyObject *self, void *x)
283 {
275 {
284 struct event *evt = (struct event *) self;
276 struct event *evt = (struct event *) self;
285 Py_INCREF(evt->wd);
277 Py_INCREF(evt->wd);
286 return evt->wd;
278 return evt->wd;
287 }
279 }
288
280
289 static PyObject *event_mask(PyObject *self, void *x)
281 static PyObject *event_mask(PyObject *self, void *x)
290 {
282 {
291 struct event *evt = (struct event *) self;
283 struct event *evt = (struct event *) self;
292 Py_INCREF(evt->mask);
284 Py_INCREF(evt->mask);
293 return evt->mask;
285 return evt->mask;
294 }
286 }
295
287
296 static PyObject *event_cookie(PyObject *self, void *x)
288 static PyObject *event_cookie(PyObject *self, void *x)
297 {
289 {
298 struct event *evt = (struct event *) self;
290 struct event *evt = (struct event *) self;
299 Py_INCREF(evt->cookie);
291 Py_INCREF(evt->cookie);
300 return evt->cookie;
292 return evt->cookie;
301 }
293 }
302
294
303 static PyObject *event_name(PyObject *self, void *x)
295 static PyObject *event_name(PyObject *self, void *x)
304 {
296 {
305 struct event *evt = (struct event *) self;
297 struct event *evt = (struct event *) self;
306 Py_INCREF(evt->name);
298 Py_INCREF(evt->name);
307 return evt->name;
299 return evt->name;
308 }
300 }
309
301
310 static struct PyGetSetDef event_getsets[] = {
302 static struct PyGetSetDef event_getsets[] = {
311 {"wd", event_wd, NULL,
303 {"wd", event_wd, NULL,
312 "watch descriptor"},
304 "watch descriptor"},
313 {"mask", event_mask, NULL,
305 {"mask", event_mask, NULL,
314 "event mask"},
306 "event mask"},
315 {"cookie", event_cookie, NULL,
307 {"cookie", event_cookie, NULL,
316 "rename cookie, if rename-related event"},
308 "rename cookie, if rename-related event"},
317 {"name", event_name, NULL,
309 {"name", event_name, NULL,
318 "file name"},
310 "file name"},
319 {NULL}
311 {NULL}
320 };
312 };
321
313
322 PyDoc_STRVAR(
314 PyDoc_STRVAR(
323 event_doc,
315 event_doc,
324 "event: Structure describing an inotify event.");
316 "event: Structure describing an inotify event.");
325
317
326 static PyObject *event_new(PyTypeObject *t, PyObject *a, PyObject *k)
318 static PyObject *event_new(PyTypeObject *t, PyObject *a, PyObject *k)
327 {
319 {
328 return (*t->tp_alloc)(t, 0);
320 return (*t->tp_alloc)(t, 0);
329 }
321 }
330
322
331 static void event_dealloc(struct event *evt)
323 static void event_dealloc(struct event *evt)
332 {
324 {
333 Py_XDECREF(evt->wd);
325 Py_XDECREF(evt->wd);
334 Py_XDECREF(evt->mask);
326 Py_XDECREF(evt->mask);
335 Py_XDECREF(evt->cookie);
327 Py_XDECREF(evt->cookie);
336 Py_XDECREF(evt->name);
328 Py_XDECREF(evt->name);
337
329
338 (*evt->ob_type->tp_free)(evt);
330 (*evt->ob_type->tp_free)(evt);
339 }
331 }
340
332
341 static PyObject *event_repr(struct event *evt)
333 static PyObject *event_repr(struct event *evt)
342 {
334 {
343 int wd = PyInt_AsLong(evt->wd);
335 int wd = PyInt_AsLong(evt->wd);
344 int cookie = evt->cookie == Py_None ? -1 : PyInt_AsLong(evt->cookie);
336 int cookie = evt->cookie == Py_None ? -1 : PyInt_AsLong(evt->cookie);
345 PyObject *ret = NULL, *pymasks = NULL, *pymask = NULL;
337 PyObject *ret = NULL, *pymasks = NULL, *pymask = NULL;
346 PyObject *join = NULL;
338 PyObject *join = NULL;
347 char *maskstr;
339 char *maskstr;
348
340
349 join = PyString_FromString("|");
341 join = PyString_FromString("|");
350 if (join == NULL)
342 if (join == NULL)
351 goto bail;
343 goto bail;
352
344
353 pymasks = decode_mask(PyInt_AsLong(evt->mask));
345 pymasks = decode_mask(PyInt_AsLong(evt->mask));
354 if (pymasks == NULL)
346 if (pymasks == NULL)
355 goto bail;
347 goto bail;
356
348
357 pymask = _PyString_Join(join, pymasks);
349 pymask = _PyString_Join(join, pymasks);
358 if (pymask == NULL)
350 if (pymask == NULL)
359 goto bail;
351 goto bail;
360
352
361 maskstr = PyString_AsString(pymask);
353 maskstr = PyString_AsString(pymask);
362
354
363 if (evt->name != Py_None) {
355 if (evt->name != Py_None) {
364 PyObject *pyname = PyString_Repr(evt->name, 1);
356 PyObject *pyname = PyString_Repr(evt->name, 1);
365 char *name = pyname ? PyString_AsString(pyname) : "???";
357 char *name = pyname ? PyString_AsString(pyname) : "???";
366
358
367 if (cookie == -1)
359 if (cookie == -1)
368 ret = PyString_FromFormat("event(wd=%d, mask=%s, name=%s)",
360 ret = PyString_FromFormat("event(wd=%d, mask=%s, name=%s)",
369 wd, maskstr, name);
361 wd, maskstr, name);
370 else
362 else
371 ret = PyString_FromFormat("event(wd=%d, mask=%s, "
363 ret = PyString_FromFormat("event(wd=%d, mask=%s, "
372 "cookie=0x%x, name=%s)",
364 "cookie=0x%x, name=%s)",
373 wd, maskstr, cookie, name);
365 wd, maskstr, cookie, name);
374
366
375 Py_XDECREF(pyname);
367 Py_XDECREF(pyname);
376 } else {
368 } else {
377 if (cookie == -1)
369 if (cookie == -1)
378 ret = PyString_FromFormat("event(wd=%d, mask=%s)",
370 ret = PyString_FromFormat("event(wd=%d, mask=%s)",
379 wd, maskstr);
371 wd, maskstr);
380 else {
372 else {
381 ret = PyString_FromFormat("event(wd=%d, mask=%s, cookie=0x%x)",
373 ret = PyString_FromFormat("event(wd=%d, mask=%s, cookie=0x%x)",
382 wd, maskstr, cookie);
374 wd, maskstr, cookie);
383 }
375 }
384 }
376 }
385
377
386 goto done;
378 goto done;
387 bail:
379 bail:
388 Py_CLEAR(ret);
380 Py_CLEAR(ret);
389
381
390 done:
382 done:
391 Py_XDECREF(pymask);
383 Py_XDECREF(pymask);
392 Py_XDECREF(pymasks);
384 Py_XDECREF(pymasks);
393 Py_XDECREF(join);
385 Py_XDECREF(join);
394
386
395 return ret;
387 return ret;
396 }
388 }
397
389
398 static PyTypeObject event_type = {
390 static PyTypeObject event_type = {
399 PyObject_HEAD_INIT(NULL)
391 PyObject_HEAD_INIT(NULL)
400 0, /*ob_size*/
392 0, /*ob_size*/
401 "_inotify.event", /*tp_name*/
393 "_inotify.event", /*tp_name*/
402 sizeof(struct event), /*tp_basicsize*/
394 sizeof(struct event), /*tp_basicsize*/
403 0, /*tp_itemsize*/
395 0, /*tp_itemsize*/
404 (destructor)event_dealloc, /*tp_dealloc*/
396 (destructor)event_dealloc, /*tp_dealloc*/
405 0, /*tp_print*/
397 0, /*tp_print*/
406 0, /*tp_getattr*/
398 0, /*tp_getattr*/
407 0, /*tp_setattr*/
399 0, /*tp_setattr*/
408 0, /*tp_compare*/
400 0, /*tp_compare*/
409 (reprfunc)event_repr, /*tp_repr*/
401 (reprfunc)event_repr, /*tp_repr*/
410 0, /*tp_as_number*/
402 0, /*tp_as_number*/
411 0, /*tp_as_sequence*/
403 0, /*tp_as_sequence*/
412 0, /*tp_as_mapping*/
404 0, /*tp_as_mapping*/
413 0, /*tp_hash */
405 0, /*tp_hash */
414 0, /*tp_call*/
406 0, /*tp_call*/
415 0, /*tp_str*/
407 0, /*tp_str*/
416 0, /*tp_getattro*/
408 0, /*tp_getattro*/
417 0, /*tp_setattro*/
409 0, /*tp_setattro*/
418 0, /*tp_as_buffer*/
410 0, /*tp_as_buffer*/
419 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
411 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
420 event_doc, /* tp_doc */
412 event_doc, /* tp_doc */
421 0, /* tp_traverse */
413 0, /* tp_traverse */
422 0, /* tp_clear */
414 0, /* tp_clear */
423 0, /* tp_richcompare */
415 0, /* tp_richcompare */
424 0, /* tp_weaklistoffset */
416 0, /* tp_weaklistoffset */
425 0, /* tp_iter */
417 0, /* tp_iter */
426 0, /* tp_iternext */
418 0, /* tp_iternext */
427 0, /* tp_methods */
419 0, /* tp_methods */
428 0, /* tp_members */
420 0, /* tp_members */
429 event_getsets, /* tp_getset */
421 event_getsets, /* tp_getset */
430 0, /* tp_base */
422 0, /* tp_base */
431 0, /* tp_dict */
423 0, /* tp_dict */
432 0, /* tp_descr_get */
424 0, /* tp_descr_get */
433 0, /* tp_descr_set */
425 0, /* tp_descr_set */
434 0, /* tp_dictoffset */
426 0, /* tp_dictoffset */
435 0, /* tp_init */
427 0, /* tp_init */
436 0, /* tp_alloc */
428 0, /* tp_alloc */
437 event_new, /* tp_new */
429 event_new, /* tp_new */
438 };
430 };
439
431
440 PyObject *read_events(PyObject *self, PyObject *args)
432 PyObject *read_events(PyObject *self, PyObject *args)
441 {
433 {
442 PyObject *ctor_args = NULL;
434 PyObject *ctor_args = NULL;
443 PyObject *pybufsize = NULL;
435 PyObject *pybufsize = NULL;
444 PyObject *ret = NULL;
436 PyObject *ret = NULL;
445 int bufsize = 65536;
437 int bufsize = 65536;
446 char *buf = NULL;
438 char *buf = NULL;
447 int nread, pos;
439 int nread, pos;
448 int fd;
440 int fd;
449
441
450 if (!PyArg_ParseTuple(args, "i|O:read", &fd, &pybufsize))
442 if (!PyArg_ParseTuple(args, "i|O:read", &fd, &pybufsize))
451 goto bail;
443 goto bail;
452
444
453 if (pybufsize && pybufsize != Py_None)
445 if (pybufsize && pybufsize != Py_None)
454 bufsize = PyInt_AsLong(pybufsize);
446 bufsize = PyInt_AsLong(pybufsize);
455
447
456 ret = PyList_New(0);
448 ret = PyList_New(0);
457 if (ret == NULL)
449 if (ret == NULL)
458 goto bail;
450 goto bail;
459
451
460 if (bufsize <= 0) {
452 if (bufsize <= 0) {
461 int r;
453 int r;
462
454
463 Py_BEGIN_ALLOW_THREADS
455 Py_BEGIN_ALLOW_THREADS
464 r = ioctl(fd, FIONREAD, &bufsize);
456 r = ioctl(fd, FIONREAD, &bufsize);
465 Py_END_ALLOW_THREADS
457 Py_END_ALLOW_THREADS
466
458
467 if (r == -1) {
459 if (r == -1) {
468 PyErr_SetFromErrno(PyExc_OSError);
460 PyErr_SetFromErrno(PyExc_OSError);
469 goto bail;
461 goto bail;
470 }
462 }
471 if (bufsize == 0)
463 if (bufsize == 0)
472 goto done;
464 goto done;
473 }
465 }
474 else {
466 else {
475 static long name_max;
467 static long name_max;
476 static long name_fd = -1;
468 static long name_fd = -1;
477 long min;
469 long min;
478
470
479 if (name_fd != fd) {
471 if (name_fd != fd) {
480 name_fd = fd;
472 name_fd = fd;
481 Py_BEGIN_ALLOW_THREADS
473 Py_BEGIN_ALLOW_THREADS
482 name_max = fpathconf(fd, _PC_NAME_MAX);
474 name_max = fpathconf(fd, _PC_NAME_MAX);
483 Py_END_ALLOW_THREADS
475 Py_END_ALLOW_THREADS
484 }
476 }
485
477
486 min = sizeof(struct inotify_event) + name_max + 1;
478 min = sizeof(struct inotify_event) + name_max + 1;
487
479
488 if (bufsize < min) {
480 if (bufsize < min) {
489 PyErr_Format(PyExc_ValueError, "bufsize must be at least %d",
481 PyErr_Format(PyExc_ValueError, "bufsize must be at least %d",
490 (int) min);
482 (int) min);
491 goto bail;
483 goto bail;
492 }
484 }
493 }
485 }
494
486
495 buf = alloca(bufsize);
487 buf = alloca(bufsize);
496
488
497 Py_BEGIN_ALLOW_THREADS
489 Py_BEGIN_ALLOW_THREADS
498 nread = read(fd, buf, bufsize);
490 nread = read(fd, buf, bufsize);
499 Py_END_ALLOW_THREADS
491 Py_END_ALLOW_THREADS
500
492
501 if (nread == -1) {
493 if (nread == -1) {
502 PyErr_SetFromErrno(PyExc_OSError);
494 PyErr_SetFromErrno(PyExc_OSError);
503 goto bail;
495 goto bail;
504 }
496 }
505
497
506 ctor_args = PyTuple_New(0);
498 ctor_args = PyTuple_New(0);
507
499
508 if (ctor_args == NULL)
500 if (ctor_args == NULL)
509 goto bail;
501 goto bail;
510
502
511 pos = 0;
503 pos = 0;
512
504
513 while (pos < nread) {
505 while (pos < nread) {
514 struct inotify_event *in = (struct inotify_event *) (buf + pos);
506 struct inotify_event *in = (struct inotify_event *) (buf + pos);
515 struct event *evt;
507 struct event *evt;
516 PyObject *obj;
508 PyObject *obj;
517
509
518 obj = PyObject_CallObject((PyObject *) &event_type, ctor_args);
510 obj = PyObject_CallObject((PyObject *) &event_type, ctor_args);
519
511
520 if (obj == NULL)
512 if (obj == NULL)
521 goto bail;
513 goto bail;
522
514
523 evt = (struct event *) obj;
515 evt = (struct event *) obj;
524
516
525 evt->wd = PyInt_FromLong(in->wd);
517 evt->wd = PyInt_FromLong(in->wd);
526 evt->mask = PyInt_FromLong(in->mask);
518 evt->mask = PyInt_FromLong(in->mask);
527 if (in->mask & IN_MOVE)
519 if (in->mask & IN_MOVE)
528 evt->cookie = PyInt_FromLong(in->cookie);
520 evt->cookie = PyInt_FromLong(in->cookie);
529 else {
521 else {
530 Py_INCREF(Py_None);
522 Py_INCREF(Py_None);
531 evt->cookie = Py_None;
523 evt->cookie = Py_None;
532 }
524 }
533 if (in->len)
525 if (in->len)
534 evt->name = PyString_FromString(in->name);
526 evt->name = PyString_FromString(in->name);
535 else {
527 else {
536 Py_INCREF(Py_None);
528 Py_INCREF(Py_None);
537 evt->name = Py_None;
529 evt->name = Py_None;
538 }
530 }
539
531
540 if (!evt->wd || !evt->mask || !evt->cookie || !evt->name)
532 if (!evt->wd || !evt->mask || !evt->cookie || !evt->name)
541 goto mybail;
533 goto mybail;
542
534
543 if (PyList_Append(ret, obj) == -1)
535 if (PyList_Append(ret, obj) == -1)
544 goto mybail;
536 goto mybail;
545
537
546 pos += sizeof(struct inotify_event) + in->len;
538 pos += sizeof(struct inotify_event) + in->len;
547 continue;
539 continue;
548
540
549 mybail:
541 mybail:
550 Py_CLEAR(evt->wd);
542 Py_CLEAR(evt->wd);
551 Py_CLEAR(evt->mask);
543 Py_CLEAR(evt->mask);
552 Py_CLEAR(evt->cookie);
544 Py_CLEAR(evt->cookie);
553 Py_CLEAR(evt->name);
545 Py_CLEAR(evt->name);
554 Py_DECREF(obj);
546 Py_DECREF(obj);
555
547
556 goto bail;
548 goto bail;
557 }
549 }
558
550
559 goto done;
551 goto done;
560
552
561 bail:
553 bail:
562 Py_CLEAR(ret);
554 Py_CLEAR(ret);
563
555
564 done:
556 done:
565 Py_XDECREF(ctor_args);
557 Py_XDECREF(ctor_args);
566
558
567 return ret;
559 return ret;
568 }
560 }
569
561
570 PyDoc_STRVAR(
562 PyDoc_STRVAR(
571 read_doc,
563 read_doc,
572 "read(fd, bufsize[=65536]) -> list_of_events\n"
564 "read(fd, bufsize[=65536]) -> list_of_events\n"
573 "\n"
565 "\n"
574 "\nRead inotify events from a file descriptor.\n"
566 "\nRead inotify events from a file descriptor.\n"
575 "\n"
567 "\n"
576 " fd: file descriptor returned by init()\n"
568 " fd: file descriptor returned by init()\n"
577 " bufsize: size of buffer to read into, in bytes\n"
569 " bufsize: size of buffer to read into, in bytes\n"
578 "\n"
570 "\n"
579 "Return a list of event objects.\n"
571 "Return a list of event objects.\n"
580 "\n"
572 "\n"
581 "If bufsize is > 0, block until events are available to be read.\n"
573 "If bufsize is > 0, block until events are available to be read.\n"
582 "Otherwise, immediately return all events that can be read without\n"
574 "Otherwise, immediately return all events that can be read without\n"
583 "blocking.");
575 "blocking.");
584
576
585
577
586 static PyMethodDef methods[] = {
578 static PyMethodDef methods[] = {
587 {"init", init, METH_VARARGS, init_doc},
579 {"init", init, METH_VARARGS, init_doc},
588 {"add_watch", add_watch, METH_VARARGS, add_watch_doc},
580 {"add_watch", add_watch, METH_VARARGS, add_watch_doc},
589 {"remove_watch", remove_watch, METH_VARARGS, remove_watch_doc},
581 {"remove_watch", remove_watch, METH_VARARGS, remove_watch_doc},
590 {"read", read_events, METH_VARARGS, read_doc},
582 {"read", read_events, METH_VARARGS, read_doc},
591 {"decode_mask", pydecode_mask, METH_VARARGS, decode_mask_doc},
583 {"decode_mask", pydecode_mask, METH_VARARGS, decode_mask_doc},
592 {NULL},
584 {NULL},
593 };
585 };
594
586
595 void init_inotify(void)
587 void init_inotify(void)
596 {
588 {
597 PyObject *mod, *dict;
589 PyObject *mod, *dict;
598
590
599 if (PyType_Ready(&event_type) == -1)
591 if (PyType_Ready(&event_type) == -1)
600 return;
592 return;
601
593
602 mod = Py_InitModule3("_inotify", methods, doc);
594 mod = Py_InitModule3("_inotify", methods, doc);
603
595
604 dict = PyModule_GetDict(mod);
596 dict = PyModule_GetDict(mod);
605
597
606 if (dict)
598 if (dict)
607 define_consts(dict);
599 define_consts(dict);
608 }
600 }
General Comments 0
You need to be logged in to leave comments. Login now