--- a/hgext/inotify/linux/_inotify.c Tue Apr 15 03:21:59 2014 +0900
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,649 +0,0 @@
-/*
- * _inotify.c - Python extension interfacing to the Linux inotify subsystem
- *
- * Copyright 2006 Bryan O'Sullivan <bos@serpentine.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of version 2.1 of the GNU Lesser General
- * Public License or any later version.
- */
-
-#include <Python.h>
-#include <alloca.h>
-#include <sys/inotify.h>
-#include <stdint.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#include <util.h>
-
-/* Variables used in the event string representation */
-static PyObject *join;
-static PyObject *er_wm;
-static PyObject *er_wmc;
-static PyObject *er_wmn;
-static PyObject *er_wmcn;
-
-static PyObject *init(PyObject *self, PyObject *args)
-{
- PyObject *ret = NULL;
- int fd = -1;
-
- if (!PyArg_ParseTuple(args, ":init"))
- goto bail;
-
- Py_BEGIN_ALLOW_THREADS;
- fd = inotify_init();
- Py_END_ALLOW_THREADS;
-
- if (fd == -1) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto bail;
- }
-
- ret = PyInt_FromLong(fd);
- if (ret == NULL)
- goto bail;
-
- goto done;
-
-bail:
- if (fd != -1)
- close(fd);
-
- Py_CLEAR(ret);
-
-done:
- return ret;
-}
-
-PyDoc_STRVAR(
- init_doc,
- "init() -> fd\n"
- "\n"
- "Initialize an inotify instance.\n"
- "Return a file descriptor associated with a new inotify event queue.");
-
-static PyObject *add_watch(PyObject *self, PyObject *args)
-{
- PyObject *ret = NULL;
- uint32_t mask;
- int wd = -1;
- char *path;
- int fd;
-
- if (!PyArg_ParseTuple(args, "isI:add_watch", &fd, &path, &mask))
- goto bail;
-
- Py_BEGIN_ALLOW_THREADS;
- wd = inotify_add_watch(fd, path, mask);
- Py_END_ALLOW_THREADS;
-
- if (wd == -1) {
- PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
- goto bail;
- }
-
- ret = PyInt_FromLong(wd);
- if (ret == NULL)
- goto bail;
-
- goto done;
-
-bail:
- if (wd != -1)
- inotify_rm_watch(fd, wd);
-
- Py_CLEAR(ret);
-
-done:
- return ret;
-}
-
-PyDoc_STRVAR(
- add_watch_doc,
- "add_watch(fd, path, mask) -> wd\n"
- "\n"
- "Add a watch to an inotify instance, or modify an existing watch.\n"
- "\n"
- " fd: file descriptor returned by init()\n"
- " path: path to watch\n"
- " mask: mask of events to watch for\n"
- "\n"
- "Return a unique numeric watch descriptor for the inotify instance\n"
- "mapped by the file descriptor.");
-
-static PyObject *remove_watch(PyObject *self, PyObject *args)
-{
- uint32_t wd;
- int fd;
- int r;
-
- if (!PyArg_ParseTuple(args, "iI:remove_watch", &fd, &wd))
- return NULL;
-
- Py_BEGIN_ALLOW_THREADS;
- r = inotify_rm_watch(fd, wd);
- Py_END_ALLOW_THREADS;
-
- if (r == -1) {
- PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
- }
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-PyDoc_STRVAR(
- remove_watch_doc,
- "remove_watch(fd, wd)\n"
- "\n"
- " fd: file descriptor returned by init()\n"
- " wd: watch descriptor returned by add_watch()\n"
- "\n"
- "Remove a watch associated with the watch descriptor wd from the\n"
- "inotify instance associated with the file descriptor fd.\n"
- "\n"
- "Removing a watch causes an IN_IGNORED event to be generated for this\n"
- "watch descriptor.");
-
-#define bit_name(x) {x, #x}
-
-static struct {
- int bit;
- const char *name;
- PyObject *pyname;
-} bit_names[] = {
- bit_name(IN_ACCESS),
- bit_name(IN_MODIFY),
- bit_name(IN_ATTRIB),
- bit_name(IN_CLOSE_WRITE),
- bit_name(IN_CLOSE_NOWRITE),
- bit_name(IN_OPEN),
- bit_name(IN_MOVED_FROM),
- bit_name(IN_MOVED_TO),
- bit_name(IN_CREATE),
- bit_name(IN_DELETE),
- bit_name(IN_DELETE_SELF),
- bit_name(IN_MOVE_SELF),
- bit_name(IN_UNMOUNT),
- bit_name(IN_Q_OVERFLOW),
- bit_name(IN_IGNORED),
- bit_name(IN_ONLYDIR),
- bit_name(IN_DONT_FOLLOW),
- bit_name(IN_MASK_ADD),
- bit_name(IN_ISDIR),
- bit_name(IN_ONESHOT),
- {0}
-};
-
-static PyObject *decode_mask(int mask)
-{
- PyObject *ret = PyList_New(0);
- int i;
-
- if (ret == NULL)
- goto bail;
-
- for (i = 0; bit_names[i].bit; i++) {
- if (mask & bit_names[i].bit) {
- if (bit_names[i].pyname == NULL) {
- bit_names[i].pyname = PyString_FromString(bit_names[i].name);
- if (bit_names[i].pyname == NULL)
- goto bail;
- }
- Py_INCREF(bit_names[i].pyname);
- if (PyList_Append(ret, bit_names[i].pyname) == -1)
- goto bail;
- }
- }
-
- goto done;
-
-bail:
- Py_CLEAR(ret);
-
-done:
- return ret;
-}
-
-static PyObject *pydecode_mask(PyObject *self, PyObject *args)
-{
- int mask;
-
- if (!PyArg_ParseTuple(args, "i:decode_mask", &mask))
- return NULL;
-
- return decode_mask(mask);
-}
-
-PyDoc_STRVAR(
- decode_mask_doc,
- "decode_mask(mask) -> list_of_strings\n"
- "\n"
- "Decode an inotify mask value into a list of strings that give the\n"
- "name of each bit set in the mask.");
-
-static char doc[] = "Low-level inotify interface wrappers.";
-
-static void define_const(PyObject *dict, const char *name, uint32_t val)
-{
- PyObject *pyval = PyInt_FromLong(val);
- PyObject *pyname = PyString_FromString(name);
-
- if (!pyname || !pyval)
- goto bail;
-
- PyDict_SetItem(dict, pyname, pyval);
-
-bail:
- Py_XDECREF(pyname);
- Py_XDECREF(pyval);
-}
-
-static void define_consts(PyObject *dict)
-{
- define_const(dict, "IN_ACCESS", IN_ACCESS);
- define_const(dict, "IN_MODIFY", IN_MODIFY);
- define_const(dict, "IN_ATTRIB", IN_ATTRIB);
- define_const(dict, "IN_CLOSE_WRITE", IN_CLOSE_WRITE);
- define_const(dict, "IN_CLOSE_NOWRITE", IN_CLOSE_NOWRITE);
- define_const(dict, "IN_OPEN", IN_OPEN);
- define_const(dict, "IN_MOVED_FROM", IN_MOVED_FROM);
- define_const(dict, "IN_MOVED_TO", IN_MOVED_TO);
-
- define_const(dict, "IN_CLOSE", IN_CLOSE);
- define_const(dict, "IN_MOVE", IN_MOVE);
-
- define_const(dict, "IN_CREATE", IN_CREATE);
- define_const(dict, "IN_DELETE", IN_DELETE);
- define_const(dict, "IN_DELETE_SELF", IN_DELETE_SELF);
- define_const(dict, "IN_MOVE_SELF", IN_MOVE_SELF);
- define_const(dict, "IN_UNMOUNT", IN_UNMOUNT);
- define_const(dict, "IN_Q_OVERFLOW", IN_Q_OVERFLOW);
- define_const(dict, "IN_IGNORED", IN_IGNORED);
-
- define_const(dict, "IN_ONLYDIR", IN_ONLYDIR);
- define_const(dict, "IN_DONT_FOLLOW", IN_DONT_FOLLOW);
- define_const(dict, "IN_MASK_ADD", IN_MASK_ADD);
- define_const(dict, "IN_ISDIR", IN_ISDIR);
- define_const(dict, "IN_ONESHOT", IN_ONESHOT);
- define_const(dict, "IN_ALL_EVENTS", IN_ALL_EVENTS);
-}
-
-struct event {
- PyObject_HEAD
- PyObject *wd;
- PyObject *mask;
- PyObject *cookie;
- PyObject *name;
-};
-
-static PyObject *event_wd(PyObject *self, void *x)
-{
- struct event *evt = (struct event *)self;
- Py_INCREF(evt->wd);
- return evt->wd;
-}
-
-static PyObject *event_mask(PyObject *self, void *x)
-{
- struct event *evt = (struct event *)self;
- Py_INCREF(evt->mask);
- return evt->mask;
-}
-
-static PyObject *event_cookie(PyObject *self, void *x)
-{
- struct event *evt = (struct event *)self;
- Py_INCREF(evt->cookie);
- return evt->cookie;
-}
-
-static PyObject *event_name(PyObject *self, void *x)
-{
- struct event *evt = (struct event *)self;
- Py_INCREF(evt->name);
- return evt->name;
-}
-
-static struct PyGetSetDef event_getsets[] = {
- {"wd", event_wd, NULL,
- "watch descriptor"},
- {"mask", event_mask, NULL,
- "event mask"},
- {"cookie", event_cookie, NULL,
- "rename cookie, if rename-related event"},
- {"name", event_name, NULL,
- "file name"},
- {NULL}
-};
-
-PyDoc_STRVAR(
- event_doc,
- "event: Structure describing an inotify event.");
-
-static PyObject *event_new(PyTypeObject *t, PyObject *a, PyObject *k)
-{
- return (*t->tp_alloc)(t, 0);
-}
-
-static void event_dealloc(struct event *evt)
-{
- Py_XDECREF(evt->wd);
- Py_XDECREF(evt->mask);
- Py_XDECREF(evt->cookie);
- Py_XDECREF(evt->name);
-
- Py_TYPE(evt)->tp_free(evt);
-}
-
-static PyObject *event_repr(struct event *evt)
-{
- int cookie = evt->cookie == Py_None ? -1 : PyInt_AsLong(evt->cookie);
- PyObject *ret = NULL, *pymasks = NULL, *pymask = NULL;
- PyObject *tuple = NULL, *formatstr = NULL;
-
- pymasks = decode_mask(PyInt_AsLong(evt->mask));
- if (pymasks == NULL)
- goto bail;
-
- pymask = _PyString_Join(join, pymasks);
- if (pymask == NULL)
- goto bail;
-
- if (evt->name != Py_None) {
- if (cookie == -1) {
- formatstr = er_wmn;
- tuple = PyTuple_Pack(3, evt->wd, pymask, evt->name);
- }
- else {
- formatstr = er_wmcn;
- tuple = PyTuple_Pack(4, evt->wd, pymask,
- evt->cookie, evt->name);
- }
- } else {
- if (cookie == -1) {
- formatstr = er_wm;
- tuple = PyTuple_Pack(2, evt->wd, pymask);
- }
- else {
- formatstr = er_wmc;
- tuple = PyTuple_Pack(3, evt->wd, pymask, evt->cookie);
- }
- }
-
- if (tuple == NULL)
- goto bail;
-
- ret = PyNumber_Remainder(formatstr, tuple);
-
- if (ret == NULL)
- goto bail;
-
- goto done;
-bail:
- Py_CLEAR(ret);
-
-done:
- Py_XDECREF(pymask);
- Py_XDECREF(pymasks);
- Py_XDECREF(tuple);
-
- return ret;
-}
-
-static PyTypeObject event_type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "_inotify.event", /*tp_name*/
- sizeof(struct event), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)event_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- (reprfunc)event_repr, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
- event_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- event_getsets, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- event_new, /* tp_new */
-};
-
-PyObject *read_events(PyObject *self, PyObject *args)
-{
- PyObject *ctor_args = NULL;
- PyObject *pybufsize = NULL;
- PyObject *ret = NULL;
- int bufsize = 65536;
- char *buf = NULL;
- int nread, pos;
- int fd;
-
- if (!PyArg_ParseTuple(args, "i|O:read", &fd, &pybufsize))
- goto bail;
-
- if (pybufsize && pybufsize != Py_None)
- bufsize = PyInt_AsLong(pybufsize);
-
- ret = PyList_New(0);
- if (ret == NULL)
- goto bail;
-
- if (bufsize <= 0) {
- int r;
-
- Py_BEGIN_ALLOW_THREADS;
- r = ioctl(fd, FIONREAD, &bufsize);
- Py_END_ALLOW_THREADS;
-
- if (r == -1) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto bail;
- }
- if (bufsize == 0)
- goto done;
- }
- else {
- static long name_max;
- static long name_fd = -1;
- long min;
-
- if (name_fd != fd) {
- name_fd = fd;
- Py_BEGIN_ALLOW_THREADS;
- name_max = fpathconf(fd, _PC_NAME_MAX);
- Py_END_ALLOW_THREADS;
- }
-
- min = sizeof(struct inotify_event) + name_max + 1;
-
- if (bufsize < min) {
- PyErr_Format(PyExc_ValueError,
- "bufsize must be at least %d", (int)min);
- goto bail;
- }
- }
-
- buf = alloca(bufsize);
-
- Py_BEGIN_ALLOW_THREADS;
- nread = read(fd, buf, bufsize);
- Py_END_ALLOW_THREADS;
-
- if (nread == -1) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto bail;
- }
-
- ctor_args = PyTuple_New(0);
-
- if (ctor_args == NULL)
- goto bail;
-
- pos = 0;
-
- while (pos < nread) {
- struct inotify_event *in = (struct inotify_event *)(buf + pos);
- struct event *evt;
- PyObject *obj;
-
- obj = PyObject_CallObject((PyObject *)&event_type, ctor_args);
-
- if (obj == NULL)
- goto bail;
-
- evt = (struct event *)obj;
-
- evt->wd = PyInt_FromLong(in->wd);
- evt->mask = PyInt_FromLong(in->mask);
- if (in->mask & IN_MOVE)
- evt->cookie = PyInt_FromLong(in->cookie);
- else {
- Py_INCREF(Py_None);
- evt->cookie = Py_None;
- }
- if (in->len)
- evt->name = PyString_FromString(in->name);
- else {
- Py_INCREF(Py_None);
- evt->name = Py_None;
- }
-
- if (!evt->wd || !evt->mask || !evt->cookie || !evt->name)
- goto mybail;
-
- if (PyList_Append(ret, obj) == -1)
- goto mybail;
-
- pos += sizeof(struct inotify_event) + in->len;
- continue;
-
- mybail:
- Py_CLEAR(evt->wd);
- Py_CLEAR(evt->mask);
- Py_CLEAR(evt->cookie);
- Py_CLEAR(evt->name);
- Py_DECREF(obj);
-
- goto bail;
- }
-
- goto done;
-
-bail:
- Py_CLEAR(ret);
-
-done:
- Py_XDECREF(ctor_args);
-
- return ret;
-}
-
-static int init_globals(void)
-{
- join = PyString_FromString("|");
- er_wm = PyString_FromString("event(wd=%d, mask=%s)");
- er_wmn = PyString_FromString("event(wd=%d, mask=%s, name=%s)");
- er_wmc = PyString_FromString("event(wd=%d, mask=%s, cookie=0x%x)");
- er_wmcn = PyString_FromString("event(wd=%d, mask=%s, cookie=0x%x, name=%s)");
-
- return join && er_wm && er_wmn && er_wmc && er_wmcn;
-}
-
-PyDoc_STRVAR(
- read_doc,
- "read(fd, bufsize[=65536]) -> list_of_events\n"
- "\n"
- "\nRead inotify events from a file descriptor.\n"
- "\n"
- " fd: file descriptor returned by init()\n"
- " bufsize: size of buffer to read into, in bytes\n"
- "\n"
- "Return a list of event objects.\n"
- "\n"
- "If bufsize is > 0, block until events are available to be read.\n"
- "Otherwise, immediately return all events that can be read without\n"
- "blocking.");
-
-static PyMethodDef methods[] = {
- {"init", init, METH_VARARGS, init_doc},
- {"add_watch", add_watch, METH_VARARGS, add_watch_doc},
- {"remove_watch", remove_watch, METH_VARARGS, remove_watch_doc},
- {"read", read_events, METH_VARARGS, read_doc},
- {"decode_mask", pydecode_mask, METH_VARARGS, decode_mask_doc},
- {NULL},
-};
-
-#ifdef IS_PY3K
-static struct PyModuleDef _inotify_module = {
- PyModuleDef_HEAD_INIT,
- "_inotify",
- doc,
- -1,
- methods
-};
-
-PyMODINIT_FUNC PyInit__inotify(void)
-{
- PyObject *mod, *dict;
-
- mod = PyModule_Create(&_inotify_module);
-
- if (mod == NULL)
- return NULL;
-
- if (!init_globals())
- return;
-
- dict = PyModule_GetDict(mod);
-
- if (dict)
- define_consts(dict);
-
- return mod;
-}
-#else
-void init_inotify(void)
-{
- PyObject *mod, *dict;
-
- if (PyType_Ready(&event_type) == -1)
- return;
-
- if (!init_globals())
- return;
-
- mod = Py_InitModule3("_inotify", methods, doc);
-
- dict = PyModule_GetDict(mod);
-
- if (dict)
- define_consts(dict);
-}
-#endif