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