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