##// END OF EJS Templates
inotify: make proper use of Python API to get object size....
Renato Cunha -
r11547:36a6aeb6 default
parent child Browse files
Show More
@@ -1,601 +1,601 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 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 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 Py_TYPE(evt)->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(
360 ret = PyString_FromFormat(
361 "event(wd=%d, mask=%s, name=%s)",
361 "event(wd=%d, mask=%s, name=%s)",
362 wd, maskstr, name);
362 wd, maskstr, name);
363 else
363 else
364 ret = PyString_FromFormat("event(wd=%d, mask=%s, "
364 ret = PyString_FromFormat("event(wd=%d, mask=%s, "
365 "cookie=0x%x, name=%s)",
365 "cookie=0x%x, name=%s)",
366 wd, maskstr, cookie, name);
366 wd, maskstr, cookie, name);
367
367
368 Py_XDECREF(pyname);
368 Py_XDECREF(pyname);
369 } else {
369 } else {
370 if (cookie == -1)
370 if (cookie == -1)
371 ret = PyString_FromFormat("event(wd=%d, mask=%s)",
371 ret = PyString_FromFormat("event(wd=%d, mask=%s)",
372 wd, maskstr);
372 wd, maskstr);
373 else {
373 else {
374 ret = PyString_FromFormat(
374 ret = PyString_FromFormat(
375 "event(wd=%d, mask=%s, cookie=0x%x)",
375 "event(wd=%d, mask=%s, cookie=0x%x)",
376 wd, maskstr, cookie);
376 wd, maskstr, cookie);
377 }
377 }
378 }
378 }
379
379
380 goto done;
380 goto done;
381 bail:
381 bail:
382 Py_CLEAR(ret);
382 Py_CLEAR(ret);
383
383
384 done:
384 done:
385 Py_XDECREF(pymask);
385 Py_XDECREF(pymask);
386 Py_XDECREF(pymasks);
386 Py_XDECREF(pymasks);
387 Py_XDECREF(join);
387 Py_XDECREF(join);
388
388
389 return ret;
389 return ret;
390 }
390 }
391
391
392 static PyTypeObject event_type = {
392 static PyTypeObject event_type = {
393 PyObject_HEAD_INIT(NULL)
393 PyObject_HEAD_INIT(NULL)
394 0, /*ob_size*/
394 0, /*ob_size*/
395 "_inotify.event", /*tp_name*/
395 "_inotify.event", /*tp_name*/
396 sizeof(struct event), /*tp_basicsize*/
396 sizeof(struct event), /*tp_basicsize*/
397 0, /*tp_itemsize*/
397 0, /*tp_itemsize*/
398 (destructor)event_dealloc, /*tp_dealloc*/
398 (destructor)event_dealloc, /*tp_dealloc*/
399 0, /*tp_print*/
399 0, /*tp_print*/
400 0, /*tp_getattr*/
400 0, /*tp_getattr*/
401 0, /*tp_setattr*/
401 0, /*tp_setattr*/
402 0, /*tp_compare*/
402 0, /*tp_compare*/
403 (reprfunc)event_repr, /*tp_repr*/
403 (reprfunc)event_repr, /*tp_repr*/
404 0, /*tp_as_number*/
404 0, /*tp_as_number*/
405 0, /*tp_as_sequence*/
405 0, /*tp_as_sequence*/
406 0, /*tp_as_mapping*/
406 0, /*tp_as_mapping*/
407 0, /*tp_hash */
407 0, /*tp_hash */
408 0, /*tp_call*/
408 0, /*tp_call*/
409 0, /*tp_str*/
409 0, /*tp_str*/
410 0, /*tp_getattro*/
410 0, /*tp_getattro*/
411 0, /*tp_setattro*/
411 0, /*tp_setattro*/
412 0, /*tp_as_buffer*/
412 0, /*tp_as_buffer*/
413 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
413 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
414 event_doc, /* tp_doc */
414 event_doc, /* tp_doc */
415 0, /* tp_traverse */
415 0, /* tp_traverse */
416 0, /* tp_clear */
416 0, /* tp_clear */
417 0, /* tp_richcompare */
417 0, /* tp_richcompare */
418 0, /* tp_weaklistoffset */
418 0, /* tp_weaklistoffset */
419 0, /* tp_iter */
419 0, /* tp_iter */
420 0, /* tp_iternext */
420 0, /* tp_iternext */
421 0, /* tp_methods */
421 0, /* tp_methods */
422 0, /* tp_members */
422 0, /* tp_members */
423 event_getsets, /* tp_getset */
423 event_getsets, /* tp_getset */
424 0, /* tp_base */
424 0, /* tp_base */
425 0, /* tp_dict */
425 0, /* tp_dict */
426 0, /* tp_descr_get */
426 0, /* tp_descr_get */
427 0, /* tp_descr_set */
427 0, /* tp_descr_set */
428 0, /* tp_dictoffset */
428 0, /* tp_dictoffset */
429 0, /* tp_init */
429 0, /* tp_init */
430 0, /* tp_alloc */
430 0, /* tp_alloc */
431 event_new, /* tp_new */
431 event_new, /* tp_new */
432 };
432 };
433
433
434 PyObject *read_events(PyObject *self, PyObject *args)
434 PyObject *read_events(PyObject *self, PyObject *args)
435 {
435 {
436 PyObject *ctor_args = NULL;
436 PyObject *ctor_args = NULL;
437 PyObject *pybufsize = NULL;
437 PyObject *pybufsize = NULL;
438 PyObject *ret = NULL;
438 PyObject *ret = NULL;
439 int bufsize = 65536;
439 int bufsize = 65536;
440 char *buf = NULL;
440 char *buf = NULL;
441 int nread, pos;
441 int nread, pos;
442 int fd;
442 int fd;
443
443
444 if (!PyArg_ParseTuple(args, "i|O:read", &fd, &pybufsize))
444 if (!PyArg_ParseTuple(args, "i|O:read", &fd, &pybufsize))
445 goto bail;
445 goto bail;
446
446
447 if (pybufsize && pybufsize != Py_None)
447 if (pybufsize && pybufsize != Py_None)
448 bufsize = PyInt_AsLong(pybufsize);
448 bufsize = PyInt_AsLong(pybufsize);
449
449
450 ret = PyList_New(0);
450 ret = PyList_New(0);
451 if (ret == NULL)
451 if (ret == NULL)
452 goto bail;
452 goto bail;
453
453
454 if (bufsize <= 0) {
454 if (bufsize <= 0) {
455 int r;
455 int r;
456
456
457 Py_BEGIN_ALLOW_THREADS;
457 Py_BEGIN_ALLOW_THREADS;
458 r = ioctl(fd, FIONREAD, &bufsize);
458 r = ioctl(fd, FIONREAD, &bufsize);
459 Py_END_ALLOW_THREADS;
459 Py_END_ALLOW_THREADS;
460
460
461 if (r == -1) {
461 if (r == -1) {
462 PyErr_SetFromErrno(PyExc_OSError);
462 PyErr_SetFromErrno(PyExc_OSError);
463 goto bail;
463 goto bail;
464 }
464 }
465 if (bufsize == 0)
465 if (bufsize == 0)
466 goto done;
466 goto done;
467 }
467 }
468 else {
468 else {
469 static long name_max;
469 static long name_max;
470 static long name_fd = -1;
470 static long name_fd = -1;
471 long min;
471 long min;
472
472
473 if (name_fd != fd) {
473 if (name_fd != fd) {
474 name_fd = fd;
474 name_fd = fd;
475 Py_BEGIN_ALLOW_THREADS;
475 Py_BEGIN_ALLOW_THREADS;
476 name_max = fpathconf(fd, _PC_NAME_MAX);
476 name_max = fpathconf(fd, _PC_NAME_MAX);
477 Py_END_ALLOW_THREADS;
477 Py_END_ALLOW_THREADS;
478 }
478 }
479
479
480 min = sizeof(struct inotify_event) + name_max + 1;
480 min = sizeof(struct inotify_event) + name_max + 1;
481
481
482 if (bufsize < min) {
482 if (bufsize < min) {
483 PyErr_Format(PyExc_ValueError,
483 PyErr_Format(PyExc_ValueError,
484 "bufsize must be at least %d", (int)min);
484 "bufsize must be at least %d", (int)min);
485 goto bail;
485 goto bail;
486 }
486 }
487 }
487 }
488
488
489 buf = alloca(bufsize);
489 buf = alloca(bufsize);
490
490
491 Py_BEGIN_ALLOW_THREADS;
491 Py_BEGIN_ALLOW_THREADS;
492 nread = read(fd, buf, bufsize);
492 nread = read(fd, buf, bufsize);
493 Py_END_ALLOW_THREADS;
493 Py_END_ALLOW_THREADS;
494
494
495 if (nread == -1) {
495 if (nread == -1) {
496 PyErr_SetFromErrno(PyExc_OSError);
496 PyErr_SetFromErrno(PyExc_OSError);
497 goto bail;
497 goto bail;
498 }
498 }
499
499
500 ctor_args = PyTuple_New(0);
500 ctor_args = PyTuple_New(0);
501
501
502 if (ctor_args == NULL)
502 if (ctor_args == NULL)
503 goto bail;
503 goto bail;
504
504
505 pos = 0;
505 pos = 0;
506
506
507 while (pos < nread) {
507 while (pos < nread) {
508 struct inotify_event *in = (struct inotify_event *)(buf + pos);
508 struct inotify_event *in = (struct inotify_event *)(buf + pos);
509 struct event *evt;
509 struct event *evt;
510 PyObject *obj;
510 PyObject *obj;
511
511
512 obj = PyObject_CallObject((PyObject *)&event_type, ctor_args);
512 obj = PyObject_CallObject((PyObject *)&event_type, ctor_args);
513
513
514 if (obj == NULL)
514 if (obj == NULL)
515 goto bail;
515 goto bail;
516
516
517 evt = (struct event *)obj;
517 evt = (struct event *)obj;
518
518
519 evt->wd = PyInt_FromLong(in->wd);
519 evt->wd = PyInt_FromLong(in->wd);
520 evt->mask = PyInt_FromLong(in->mask);
520 evt->mask = PyInt_FromLong(in->mask);
521 if (in->mask & IN_MOVE)
521 if (in->mask & IN_MOVE)
522 evt->cookie = PyInt_FromLong(in->cookie);
522 evt->cookie = PyInt_FromLong(in->cookie);
523 else {
523 else {
524 Py_INCREF(Py_None);
524 Py_INCREF(Py_None);
525 evt->cookie = Py_None;
525 evt->cookie = Py_None;
526 }
526 }
527 if (in->len)
527 if (in->len)
528 evt->name = PyString_FromString(in->name);
528 evt->name = PyString_FromString(in->name);
529 else {
529 else {
530 Py_INCREF(Py_None);
530 Py_INCREF(Py_None);
531 evt->name = Py_None;
531 evt->name = Py_None;
532 }
532 }
533
533
534 if (!evt->wd || !evt->mask || !evt->cookie || !evt->name)
534 if (!evt->wd || !evt->mask || !evt->cookie || !evt->name)
535 goto mybail;
535 goto mybail;
536
536
537 if (PyList_Append(ret, obj) == -1)
537 if (PyList_Append(ret, obj) == -1)
538 goto mybail;
538 goto mybail;
539
539
540 pos += sizeof(struct inotify_event) + in->len;
540 pos += sizeof(struct inotify_event) + in->len;
541 continue;
541 continue;
542
542
543 mybail:
543 mybail:
544 Py_CLEAR(evt->wd);
544 Py_CLEAR(evt->wd);
545 Py_CLEAR(evt->mask);
545 Py_CLEAR(evt->mask);
546 Py_CLEAR(evt->cookie);
546 Py_CLEAR(evt->cookie);
547 Py_CLEAR(evt->name);
547 Py_CLEAR(evt->name);
548 Py_DECREF(obj);
548 Py_DECREF(obj);
549
549
550 goto bail;
550 goto bail;
551 }
551 }
552
552
553 goto done;
553 goto done;
554
554
555 bail:
555 bail:
556 Py_CLEAR(ret);
556 Py_CLEAR(ret);
557
557
558 done:
558 done:
559 Py_XDECREF(ctor_args);
559 Py_XDECREF(ctor_args);
560
560
561 return ret;
561 return ret;
562 }
562 }
563
563
564 PyDoc_STRVAR(
564 PyDoc_STRVAR(
565 read_doc,
565 read_doc,
566 "read(fd, bufsize[=65536]) -> list_of_events\n"
566 "read(fd, bufsize[=65536]) -> list_of_events\n"
567 "\n"
567 "\n"
568 "\nRead inotify events from a file descriptor.\n"
568 "\nRead inotify events from a file descriptor.\n"
569 "\n"
569 "\n"
570 " fd: file descriptor returned by init()\n"
570 " fd: file descriptor returned by init()\n"
571 " bufsize: size of buffer to read into, in bytes\n"
571 " bufsize: size of buffer to read into, in bytes\n"
572 "\n"
572 "\n"
573 "Return a list of event objects.\n"
573 "Return a list of event objects.\n"
574 "\n"
574 "\n"
575 "If bufsize is > 0, block until events are available to be read.\n"
575 "If bufsize is > 0, block until events are available to be read.\n"
576 "Otherwise, immediately return all events that can be read without\n"
576 "Otherwise, immediately return all events that can be read without\n"
577 "blocking.");
577 "blocking.");
578
578
579 static PyMethodDef methods[] = {
579 static PyMethodDef methods[] = {
580 {"init", init, METH_VARARGS, init_doc},
580 {"init", init, METH_VARARGS, init_doc},
581 {"add_watch", add_watch, METH_VARARGS, add_watch_doc},
581 {"add_watch", add_watch, METH_VARARGS, add_watch_doc},
582 {"remove_watch", remove_watch, METH_VARARGS, remove_watch_doc},
582 {"remove_watch", remove_watch, METH_VARARGS, remove_watch_doc},
583 {"read", read_events, METH_VARARGS, read_doc},
583 {"read", read_events, METH_VARARGS, read_doc},
584 {"decode_mask", pydecode_mask, METH_VARARGS, decode_mask_doc},
584 {"decode_mask", pydecode_mask, METH_VARARGS, decode_mask_doc},
585 {NULL},
585 {NULL},
586 };
586 };
587
587
588 void init_inotify(void)
588 void init_inotify(void)
589 {
589 {
590 PyObject *mod, *dict;
590 PyObject *mod, *dict;
591
591
592 if (PyType_Ready(&event_type) == -1)
592 if (PyType_Ready(&event_type) == -1)
593 return;
593 return;
594
594
595 mod = Py_InitModule3("_inotify", methods, doc);
595 mod = Py_InitModule3("_inotify", methods, doc);
596
596
597 dict = PyModule_GetDict(mod);
597 dict = PyModule_GetDict(mod);
598
598
599 if (dict)
599 if (dict)
600 define_consts(dict);
600 define_consts(dict);
601 }
601 }
General Comments 0
You need to be logged in to leave comments. Login now