#include "system.h"
#include "Python.h"
+#include "structmember.h"
#ifdef __LCLINT__
#undef PyObject_HEAD
#define PyObject_HEAD int _PyObjectHead;
#include <fts.h>
-#include <rpmlib.h> /* XXX _free */
-
#include "rpmfts-py.h"
+#include "rpmdebug-py.c"
+
+#include <rpmlib.h> /* XXX _free */
+
#include "debug.h"
/*@unchecked@*/
static void
rpmfts_initialize(rpmftsObject * s, const char * root, int options, int ignore)
+ /*@modifies s @*/
{
int ac = 1;
char * t;
}
+static int
+rpmfts_inactive(rpmftsObject * s)
+ /*@modifies s @*/
+{
+ int rc = 0;
+
+ if (s->ftsp) {
+ Py_BEGIN_ALLOW_THREADS
+ rc = Fts_close(s->ftsp);
+ Py_END_ALLOW_THREADS
+ s->ftsp = NULL;
+ s->fts = NULL;
+ s->active = 0;
+ }
+ return rc;
+}
+
+static PyObject *
+rpmfts_walk(rpmftsObject * s)
+ /*@modifies s @*/
+{
+ PyObject * result = NULL;
+ int xx;
+
+ if (s->ftsp == NULL)
+ return NULL;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ s->fts = Fts_read(s->ftsp);
+ Py_END_ALLOW_THREADS
+ } while (s->fts && (infoBit(s->fts->fts_info) & s->ignore));
+
+ if (s->fts != NULL) {
+ Py_INCREF(s);
+ result = (PyObject *)s;
+ } else {
+ if (s->active == 2)
+ xx = rpmfts_inactive(s);
+ s->active = 0;
+ }
+ return result;
+}
+
+/* ---------- */
+
/** \ingroup python
* \name Class: Rpmfts
* \class Rpmfts
/*@globals _Py_NoneStruct @*/
/*@modifies _Py_NoneStruct @*/
{
- if (!PyArg_ParseTuple(args, "i:Debug", &_rpmfts_debug)) return NULL;
+ if (!PyArg_ParseTuple(args, "i:Debug", &_rpmfts_debug))
+ return NULL;
Py_INCREF(Py_None);
return Py_None;
/*@*/
{
Py_INCREF(s);
-if (_rpmfts_debug < 0)
-fprintf(stderr, "*** rpmfts_iter(%p) %d %d ftsp %p fts %p\n", s, s->ob_refcnt, s->active, s->ftsp, s->fts);
return (PyObject *)s;
}
rpmfts_iternext(rpmftsObject * s)
/*@modifies s @*/
{
- PyObject * result = NULL;
- int xx;
-
/* Reset loop indices on 1st entry. */
if (!s->active) {
+ Py_BEGIN_ALLOW_THREADS
s->ftsp = Fts_open((char *const *)s->roots, s->options, (int (*)())s->compare);
+ Py_END_ALLOW_THREADS
s->fts = NULL;
s->active = 2;
}
-
- if (s->ftsp != NULL)
- do {
- s->fts = Fts_read(s->ftsp);
- } while (s->fts && (infoBit(s->fts->fts_info) & s->ignore));
-
- if (s->fts != NULL) {
- Py_INCREF(s);
- result = (PyObject *)s;
- } else {
- if (s->active == 2) {
- xx = Fts_close(s->ftsp);
- s->ftsp = NULL;
- s->fts = NULL;
- }
- s->active = 0;
- }
-
-if (_rpmfts_debug < 0)
-fprintf(stderr, "*** rpmfts_iternext(%p) %d %d ftsp %p fts %p\n", s, s->ob_refcnt, s->active, s->ftsp, s->fts);
-
- return result;
-}
-
-static PyObject *
-rpmfts_Next(rpmftsObject * s, PyObject *args)
- /*@globals _Py_NoneStruct @*/
- /*@modifies s, _Py_NoneStruct @*/
-{
- PyObject * result;
-
-if (_rpmfts_debug)
-fprintf(stderr, "*** rpmfts_Next(%p) %d %d ftsp %p fts %p\n", s, s->ob_refcnt, s->active, s->ftsp, s->fts);
-
- if (!PyArg_ParseTuple(args, ":Next"))
- return NULL;
-
- result = rpmfts_iternext(s);
-
- if (result == NULL) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return result;
+ return rpmfts_walk(s);
}
static PyObject *
return NULL;
rpmfts_initialize(s, root, options, ignore);
+ Py_BEGIN_ALLOW_THREADS
s->ftsp = Fts_open((char *const *)s->roots, s->options, (int (*)())s->compare);
+ Py_END_ALLOW_THREADS
s->active = 1;
return (PyObject *)s;
/*@globals _Py_NoneStruct @*/
/*@modifies s, _Py_NoneStruct @*/
{
- PyObject * result = NULL;
- int xx;
+ PyObject * result;
if (_rpmfts_debug)
fprintf(stderr, "*** rpmfts_Read(%p) %d %d ftsp %p fts %p\n", s, s->ob_refcnt, s->active, s->ftsp, s->fts);
if (!PyArg_ParseTuple(args, ":Read")) return NULL;
- if (s->ftsp != NULL)
- do {
- s->fts = Fts_read(s->ftsp);
- } while (s->fts && (infoBit(s->fts->fts_info) & s->ignore));
+ result = rpmfts_walk(s);
- if (s->fts != NULL) {
- Py_INCREF(s);
- result = (PyObject *)s;
- } else {
- if (s->active == 2) {
- xx = Fts_close(s->ftsp);
- s->ftsp = NULL;
- s->fts = NULL;
- }
- s->active = 0;
+ if (result == NULL) {
Py_INCREF(Py_None);
- result = Py_None;
+ return Py_None;
}
return result;
/*@globals _Py_NoneStruct @*/
/*@modifies s, _Py_NoneStruct @*/
{
- int instr = 0;
+ int instr;
if (_rpmfts_debug)
fprintf(stderr, "*** rpmfts_Children(%p) %d %d ftsp %p fts %p\n", s, s->ob_refcnt, s->active, s->ftsp, s->fts);
- if (!PyArg_ParseTuple(args, ":Children")) return NULL;
+ if (!PyArg_ParseTuple(args, "i:Children", &instr)) return NULL;
if (!(s && s->ftsp))
return NULL;
+ Py_BEGIN_ALLOW_THREADS
s->fts = Fts_children(s->ftsp, instr);
+ Py_END_ALLOW_THREADS
Py_INCREF(Py_None);
return Py_None;
rpmfts_Close(rpmftsObject * s, PyObject * args)
/*@modifies s @*/
{
- int rc = 0;
-
if (_rpmfts_debug)
fprintf(stderr, "*** rpmfts_Close(%p) %d %d ftsp %p fts %p\n", s, s->ob_refcnt, s->active, s->ftsp, s->fts);
if (!PyArg_ParseTuple(args, ":Close")) return NULL;
- if (s->ftsp) {
- rc = Fts_close(s->ftsp);
- s->ftsp = NULL;
- s->fts = NULL;
- s->active = 0;
- }
-
- return Py_BuildValue("i", rc);
+ return Py_BuildValue("i", rpmfts_inactive(s));
}
static PyObject *
if (_rpmfts_debug)
fprintf(stderr, "*** rpmfts_Set(%p) %d %d ftsp %p fts %p\n", s, s->ob_refcnt, s->active, s->ftsp, s->fts);
- if (!PyArg_ParseTuple(args, ":Set")) return NULL;
+ if (!PyArg_ParseTuple(args, "i:Set", &instr)) return NULL;
if (s->ftsp && s->fts)
rc = Fts_set(s->ftsp, s->fts, instr);
static struct PyMethodDef rpmfts_methods[] = {
{"Debug", (PyCFunction)rpmfts_Debug, METH_VARARGS,
NULL},
- {"next", (PyCFunction)rpmfts_Next, METH_VARARGS,
- NULL},
{"open", (PyCFunction)rpmfts_Open, METH_VARARGS,
NULL},
{"read", (PyCFunction)rpmfts_Read, METH_VARARGS,
/* ---------- */
-/** \ingroup python
- */
-static void
-rpmfts_dealloc(/*@only@*/ /*@null@*/ rpmftsObject * s)
- /*@modifies s @*/
+static PyMemberDef rpmfts_members[] = {
+ {"__dict__",T_OBJECT,offsetof(rpmftsObject, md_dict), READONLY,
+ NULL},
+ {"callbacks",T_OBJECT,offsetof(rpmftsObject, callbacks), 0,
+"Callback dictionary for FTS_{D|DC|DEFAULT|DNR|DOT|DP|ERR|F|INIT|NS|NSOK|SL|SLNONE|W}"},
+ {"options", T_INT, offsetof(rpmftsObject, options), 0,
+"Option bit(s): FTS_{COMFOLLOW|LOGICAL|NOCHDIR|NOSTAT|PHYSICAL|SEEDOT|XDEV}"},
+ {"ignore", T_INT, offsetof(rpmftsObject, ignore), 0,
+"Ignore bit(s): (1 << info) with info one of FTS_{D|DC|DEFAULT|DNR|DOT|DP|ERR|F|INIT|NS|NSOK|SL|SLNONE|W}"},
+ {NULL, 0, 0, 0}
+};
+
+static PyObject * rpmfts_getattro(rpmftsObject * s, PyObject * n)
+ /*@*/
{
- if (s) {
-if (_rpmfts_debug < 0)
-fprintf(stderr, "*** rpmfts_dealloc(%p) %d %d ftsp %p fts %p\n", s, s->ob_refcnt, s->active, s->ftsp, s->fts);
-
- if (s->ftsp) {
- (void) Fts_close(s->ftsp);
- s->ftsp = NULL;
- s->fts = NULL;
- s->active = 0;
- }
- s->roots = _free(s->roots);
- PyObject_Del(s);
- }
+if (_rpmfts_debug)
+fprintf(stderr, "*** rpmfts_getattro(%p[%s],%p[%s]) %d %d ftsp %p fts %p\n", s, lbl(s), n, lbl(n), s->ob_refcnt, s->active, s->ftsp, s->fts);
+
+ return PyObject_GenericGetAttr((PyObject *)s, n);
}
-/** \ingroup python
- */
-static int
-rpmfts_print(rpmftsObject * s, FILE * fp, /*@unused@*/ int flags)
- /*@globals fileSystem @*/
- /*@modifies fp, fileSystem @*/
+static int rpmfts_setattro(rpmftsObject * s, PyObject * n, PyObject * v)
+ /*@*/
{
- static int indent = 2;
- if (!(s && s->ftsp && s->fts))
- return -1;
- fprintf(fp, "FTS_%-7s %*s%s", ftsInfoStr(s->fts->fts_info),
- indent * (s->fts->fts_level < 0 ? 0 : s->fts->fts_level), "",
- s->fts->fts_name);
- return 0;
+if (_rpmfts_debug)
+fprintf(stderr, "*** rpmfts_setattro(%p[%s],%p[%s],%p[%s]) %d %d ftsp %p fts %p\n", s, lbl(s), n, lbl(n), v, lbl(v), s->ob_refcnt, s->active, s->ftsp, s->fts);
+ return PyObject_GenericSetAttr((PyObject *)s, n, v);
}
-/** \ingroup python
- */
-static PyObject * rpmfts_getattr(rpmftsObject * o, char * name)
+/* ---------- */
+
+static void rpmfts_free(/*@only@*/ PyObject * s)
+ /*@modifies s @*/
+{
+ _PyObject_GC_Del(s);
+}
+
+static PyObject * rpmfts_alloc(PyTypeObject * type, int nitems)
/*@*/
{
- return Py_FindMethod(rpmfts_methods, (PyObject *) o, name);
+ return PyType_GenericAlloc(type, nitems);
+}
+
+static void rpmfts_dealloc(/*@only@*/ rpmftsObject * s)
+ /*@modifies s @*/
+{
+ int xx;
+
+ xx = rpmfts_inactive(s);
+ s->roots = _free(s->roots);
+
+ PyObject_GC_UnTrack((PyObject *)s);
+ if (s->md_dict != NULL) {
+ _PyModule_Clear((PyObject *)s);
+ Py_DECREF(s->md_dict);
+ }
+ if (s->callbacks != NULL) {
+ _PyModule_Clear((PyObject *)s);
+ Py_DECREF(s->callbacks);
+ }
+ _PyObject_GC_Del((PyObject *)s);
}
-/** \ingroup python
- */
static int rpmfts_init(rpmftsObject * s, PyObject *args, PyObject *kwds)
/*@*/
{
int options = -1;
int ignore = -1;
-if (_rpmfts_debug < 0)
-fprintf(stderr, "*** rpmfts_init(%p,%p,%p)\n", s, args, kwds);
-
if (!PyArg_ParseTuple(args, "|sii:rpmfts_init", &root, &options, &ignore))
return -1;
rpmfts_initialize(s, root, options, ignore);
return 0;
}
-/** \ingroup python
- */
-static void rpmfts_free(/*@only@*/ rpmftsObject * s)
- /*@modifies s @*/
+static PyObject * rpmfts_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+ /*@*/
{
-if (_rpmfts_debug < 0)
-fprintf(stderr, "%p -- fts %p\n", s, s->ftsp);
+ rpmftsObject *s;
+ PyObject *o;
+ PyObject *n = NULL;
- if (s->ftsp) {
- (void) Fts_close(s->ftsp);
- s->ftsp = NULL;
- s->fts = NULL;
+ if ((s = PyObject_GC_New(rpmftsObject, type)) == NULL)
+ return NULL;
+
+ s->md_dict = PyDict_New();
+ if (s->md_dict == NULL)
+ goto fail;
+ s->callbacks = PyDict_New();
+ if (s->md_dict == NULL)
+ goto fail;
+ if (type->tp_name) {
+ char * name;
+ if ((name = strrchr(type->tp_name, '.')) != NULL)
+ name++;
+ else
+ name = type->tp_name;
+ n = PyString_FromString(name);
}
- s->roots = _free(s->roots);
+ if (n != NULL && PyDict_SetItemString(s->md_dict, "__name__", n) != 0)
+ goto fail;
+ if (PyDict_SetItemString(s->md_dict, "__doc__", Py_None) != 0)
+ goto fail;
+
+#define CONSTANT(_v) \
+ PyDict_SetItemString(s->md_dict, #_v, o=PyInt_FromLong(_v)); Py_DECREF(o)
+
+ CONSTANT(FTS_ROOTPARENTLEVEL);
+ CONSTANT(FTS_ROOTLEVEL);
+
+ CONSTANT(FTS_COMFOLLOW);
+ CONSTANT(FTS_LOGICAL);
+ CONSTANT(FTS_NOCHDIR);
+ CONSTANT(FTS_NOSTAT);
+ CONSTANT(FTS_PHYSICAL);
+ CONSTANT(FTS_SEEDOT);
+ CONSTANT(FTS_XDEV);
+ CONSTANT(FTS_WHITEOUT);
+ CONSTANT(FTS_OPTIONMASK);
+
+ CONSTANT(FTS_NAMEONLY);
+ CONSTANT(FTS_STOP);
+
+ CONSTANT(FTS_D);
+ CONSTANT(FTS_DC);
+ CONSTANT(FTS_DEFAULT);
+ CONSTANT(FTS_DNR);
+ CONSTANT(FTS_DOT);
+ CONSTANT(FTS_DP);
+ CONSTANT(FTS_ERR);
+ CONSTANT(FTS_F);
+ CONSTANT(FTS_NS);
+ CONSTANT(FTS_NSOK);
+ CONSTANT(FTS_SL);
+ CONSTANT(FTS_SLNONE);
+ CONSTANT(FTS_W);
+
+ CONSTANT(FTS_DONTCHDIR);
+ CONSTANT(FTS_SYMFOLLOW);
+
+ CONSTANT(FTS_AGAIN);
+ CONSTANT(FTS_FOLLOW);
+ CONSTANT(FTS_NOINSTR);
+ CONSTANT(FTS_SKIP);
- PyObject_Del((PyObject *)s);
-}
+ /* Perform additional initialization. */
+ if (rpmfts_init(s, args, kwds) < 0)
+ goto fail;
-/** \ingroup python
- */
-static PyObject * rpmfts_alloc(PyTypeObject * subtype, int nitems)
- /*@*/
-{
- PyObject * s = PyType_GenericAlloc(subtype, nitems);
+ Py_XDECREF(n);
+ PyObject_GC_Track((PyObject *)s);
+ return (PyObject *)s;
-if (_rpmfts_debug)
-fprintf(stderr, "*** rpmfts_alloc(%p,%d) ret %p\n", subtype, nitems, s);
- return s;
+ fail:
+ Py_XDECREF(n);
+ Py_DECREF(s);
+ return NULL;
}
-/** \ingroup python
- */
-static rpmftsObject * rpmfts_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
+static int rpmfts_traverse(rpmftsObject * s, visitproc visit, void * arg)
/*@*/
{
- rpmftsObject * s = PyObject_New(rpmftsObject, subtype);
+ if (s->md_dict != NULL)
+ return visit(s->md_dict, arg);
+ if (s->callbacks != NULL)
+ return visit(s->callbacks, arg);
+ return 0;
+}
- /* Perform additional initialization. */
- if (rpmfts_init(s, args, kwds) < 0) {
- rpmfts_free(s);
- return NULL;
- }
+static int rpmfts_print(rpmftsObject * s, FILE * fp, /*@unused@*/ int flags)
+ /*@globals fileSystem @*/
+ /*@modifies fp, fileSystem @*/
+{
+ static int indent = 2;
-if (_rpmfts_debug < 0)
-fprintf(stderr, "%p ++ fts %p\n", s, s->ftsp);
+ if (!(s && s->ftsp && s->fts))
+ return -1;
+ fprintf(fp, "FTS_%-7s %*s%s", ftsInfoStr(s->fts->fts_info),
+ indent * (s->fts->fts_level < 0 ? 0 : s->fts->fts_level), "",
+ s->fts->fts_name);
+ return 0;
- return s;
}
/**
/* methods */
(destructor) rpmfts_dealloc, /* tp_dealloc */
(printfunc) rpmfts_print, /* tp_print */
- (getattrfunc) rpmfts_getattr, /* tp_getattr */
+ (getattrfunc)0, /* tp_getattr */
(setattrfunc)0, /* tp_setattr */
(cmpfunc)0, /* tp_compare */
(reprfunc)0, /* tp_repr */
(hashfunc)0, /* tp_hash */
(ternaryfunc)0, /* tp_call */
(reprfunc)0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
+ (getattrofunc) rpmfts_getattro, /* tp_getattro */
+ (setattrofunc) rpmfts_setattro, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_TPFLAGS_DEFAULT | /* tp_flags */
+ Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
rpmfts_doc, /* tp_doc */
-#if Py_TPFLAGS_HAVE_ITER
- 0, /* tp_traverse */
+ (traverseproc) rpmfts_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc) rpmfts_iter, /* tp_iter */
(iternextfunc) rpmfts_iternext, /* tp_iternext */
rpmfts_methods, /* tp_methods */
- 0, /* tp_members */
+ rpmfts_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
- 0, /* tp_dictoffset */
+ offsetof(rpmftsObject, md_dict),/* tp_dictoffset */
(initproc) rpmfts_init, /* tp_init */
- (allocfunc) rpmfts_alloc, /* tp_alloc */
- (newfunc) rpmfts_new, /* tp_new */
- (destructor) rpmfts_free, /* tp_free */
+ rpmfts_alloc, /* tp_alloc */
+ rpmfts_new, /* tp_new */
+ rpmfts_free, /* tp_free */
0, /* tp_is_gc */
-#endif
};
/*@=fullinitblock@*/