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