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