rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

python/rpmfts-py.c
Go to the documentation of this file.

    00001
    00005 #include "system.h"
    00006
    00007 #include "structmember.h"
    00008
    00009 #ifdef __LCLINT__
    00010 #undef  PyObject_HEAD
    00011 #define PyObject_HEAD   int _PyObjectHead;
    00012 #endif
    00013
    00014 #include <fts.h>
    00015
    00016 #include "rpmfts-py.h"
    00017
    00018 #include <rpmiotypes.h>
    00019
    00020 #include "debug.h"
    00021
    00022 /*@unchecked@*/
    00023 static int _rpmfts_debug = 1;
    00024
    00025 #define infoBit(_ix)    (1 << (((unsigned)(_ix)) & 0x1f))
    00026
    00027 static const char * ftsInfoStrings[] = {
    00028     "UNKNOWN",
    00029     "D",
    00030     "DC",
    00031     "DEFAULT",
    00032     "DNR",
    00033     "DOT",
    00034     "DP",
    00035     "ERR",
    00036     "F",
    00037     "INIT",
    00038     "NS",
    00039     "NSOK",
    00040     "SL",
    00041     "SLNONE",
    00042     "W",
    00043 };
    00044
    00045 /*@observer@*/
    00046 static const char * ftsInfoStr(int fts_info)
    00047         /*@*/
    00048 {
    00049     if (!(fts_info >= 1 && fts_info <= 14))
    00050         fts_info = 0;
    00051     return ftsInfoStrings[ fts_info ];
    00052 }
    00053
    00054 #define RPMFTS_CLOSE            0
    00055 #define RPMFTS_OPEN             1
    00056 #define RPMFTS_OPEN_LAZY        2
    00057
    00058 static void
    00059 rpmfts_debug (const char * msg, rpmftsObject * s)
    00060 {
    00061     if (_rpmfts_debug == 0)
    00062         return;
    00063     if (msg)
    00064         fprintf(stderr, "*** %s(%p)", msg, s);
    00065     if (s)
    00066         fprintf(stderr, " %u %d ftsp %p fts %p\n", (unsigned) s->ob_refcnt, s->active, s->ftsp, s->fts);
    00067 }
    00068
    00069 static int
    00070 rpmfts_initialize(rpmftsObject * s, const char * root, int options, int ignore)
    00071         /*@modifies s @*/
    00072 {
    00073     int ac = 1;
    00074     size_t nb;
    00075
    00076 /*@-branchstate@*/
    00077     if (root == NULL)   root = "/";
    00078 /*@=branchstate@*/
    00079     if (options == -1)  options = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT);
    00080     if (ignore == -1)   ignore = infoBit(FTS_DP);
    00081
    00082     s->roots = _free(s->roots);
    00083
    00084     nb = (ac + 1) * sizeof(*s->roots);
    00085     nb += strlen(root) + 1;
    00086     s->roots = malloc(nb);
    00087     if (s->roots != NULL) {
    00088         char *t = (char *) &s->roots[ac + 1];
    00089         s->roots[0] = t;
    00090         s->roots[ac] = NULL;
    00091         (void) stpcpy(t, root);
    00092     }
    00093
    00094     s->options = options;
    00095     s->ignore = ignore;
    00096     s->compare = NULL;
    00097
    00098     s->ftsp = NULL;
    00099     s->fts = NULL;
    00100     s->active = RPMFTS_CLOSE;
    00101
    00102     return 0;
    00103
    00104 }
    00105
    00106 static int
    00107 rpmfts_state(rpmftsObject * s, int nactive)
    00108         /*@modifies s @*/
    00109 {
    00110     int rc = 0;
    00111
    00112 rpmfts_debug("rpmfts_state", s);
    00113     switch (nactive) {
    00114     case RPMFTS_CLOSE:
    00115         if (s->ftsp != NULL) {
    00116             Py_BEGIN_ALLOW_THREADS
    00117             rc = Fts_close(s->ftsp);
    00118             Py_END_ALLOW_THREADS
    00119             s->ftsp = NULL;
    00120         }
    00121         break;
    00122     case RPMFTS_OPEN_LAZY:
    00123     case RPMFTS_OPEN:
    00124         if (s->ftsp == NULL) {
    00125             Py_BEGIN_ALLOW_THREADS
    00126             s->ftsp = Fts_open((char *const *)s->roots, s->options, (int (*)(const FTSENT **, const FTSENT **))s->compare);
    00127             Py_END_ALLOW_THREADS
    00128         }
    00129         break;
    00130     }
    00131     s->fts = NULL;
    00132     s->active = nactive;
    00133     return rc;
    00134 }
    00135
    00136 /*@null@*/
    00137 static PyObject *
    00138 rpmfts_step(rpmftsObject * s)
    00139         /*@modifies s @*/
    00140 {
    00141     PyObject * result = NULL;
    00142     int xx;
    00143
    00144 rpmfts_debug("rpmfts_step", s);
    00145     if (s->ftsp == NULL)
    00146         return NULL;
    00147
    00148     do {
    00149         Py_BEGIN_ALLOW_THREADS
    00150         s->fts = Fts_read(s->ftsp);
    00151         Py_END_ALLOW_THREADS
    00152     } while (s->fts && (infoBit(s->fts->fts_info) & s->ignore));
    00153
    00154     if (s->fts != NULL) {
    00155         Py_INCREF(s);
    00156         result = (PyObject *)s;
    00157     } else {
    00158         if (s->active == RPMFTS_OPEN_LAZY)
    00159             xx = rpmfts_state(s, RPMFTS_CLOSE);
    00160         s->active = RPMFTS_CLOSE;
    00161     }
    00162
    00163     return result;
    00164 }
    00165
    00166 /* ---------- */
    00167
    00178 /*@null@*/
    00179 static PyObject *
    00180 rpmfts_Debug(/*@unused@*/ rpmftsObject * s, PyObject * args,
    00181                 PyObject * kwds)
    00182         /*@globals _Py_NoneStruct @*/
    00183         /*@modifies _Py_NoneStruct @*/
    00184 {
    00185     char * kwlist[] = {"debugLevel", NULL};
    00186
    00187     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:Debug", kwlist,
    00188             &_rpmfts_debug))
    00189         return NULL;
    00190
    00191     Py_INCREF(Py_None);
    00192     return Py_None;
    00193 }
    00194
    00195 /*@null@*/
    00196 static PyObject *
    00197 rpmfts_Open(rpmftsObject * s, PyObject * args, PyObject * kwds)
    00198         /*@modifies s @*/
    00199 {
    00200     char * root = NULL;
    00201     int options = -1;
    00202     int ignore = -1;
    00203     int xx;
    00204     /* XXX: there's bound to be a better name than "ignore" */
    00205     char * kwlist[] = {"root", "options", "ignore", NULL};
    00206
    00207 rpmfts_debug("rpmfts_Open", s);
    00208     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sii:Open", kwlist,
    00209             &root, &options, &ignore))
    00210         return NULL;
    00211
    00212     xx = rpmfts_initialize(s, root, options, ignore);
    00213     xx = rpmfts_state(s, RPMFTS_OPEN);
    00214
    00215     return (PyObject *)s;
    00216 }
    00217
    00218 /*@null@*/
    00219 static PyObject *
    00220 rpmfts_Read(rpmftsObject * s)
    00221         /*@globals _Py_NoneStruct @*/
    00222         /*@modifies s, _Py_NoneStruct @*/
    00223 {
    00224     PyObject * result;
    00225
    00226 rpmfts_debug("rpmfts_Read", s);
    00227
    00228     result = rpmfts_step(s);
    00229
    00230     if (result == NULL) {
    00231         Py_INCREF(Py_None);
    00232         return Py_None;
    00233     }
    00234
    00235     return result;
    00236 }
    00237
    00238 /*@null@*/
    00239 static PyObject *
    00240 rpmfts_Children(rpmftsObject * s, PyObject * args, PyObject * kwds)
    00241         /*@globals _Py_NoneStruct @*/
    00242         /*@modifies s, _Py_NoneStruct @*/
    00243 {
    00244     int instr;
    00245     char * kwlist[] = {"instructions", NULL};
    00246
    00247 rpmfts_debug("rpmfts_Children", s);
    00248     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:Children", kwlist, &instr))
    00249         return NULL;
    00250
    00251     if (!(s && s->ftsp))
    00252         return NULL;
    00253
    00254     Py_BEGIN_ALLOW_THREADS
    00255     s->fts = Fts_children(s->ftsp, instr);
    00256     Py_END_ALLOW_THREADS
    00257
    00258     Py_INCREF(Py_None);
    00259     return Py_None;
    00260 }
    00261
    00262 /*@null@*/
    00263 static PyObject *
    00264 rpmfts_Close(rpmftsObject * s)
    00265         /*@modifies s @*/
    00266 {
    00267
    00268 rpmfts_debug("rpmfts_Close", s);
    00269
    00270     return Py_BuildValue("i", rpmfts_state(s, RPMFTS_CLOSE));
    00271 }
    00272
    00273 /*@null@*/
    00274 static PyObject *
    00275 rpmfts_Set(rpmftsObject * s, PyObject * args, PyObject * kwds)
    00276         /*@modifies s @*/
    00277 {
    00278     int instr = 0;
    00279     int rc = 0;
    00280     char * kwlist[] = {"instructions", NULL};
    00281
    00282 rpmfts_debug("rpmfts_Set", s);
    00283     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:Set", kwlist, &instr))
    00284         return NULL;
    00285
    00286     if (s->ftsp && s->fts)
    00287         rc = Fts_set(s->ftsp, s->fts, instr);
    00288
    00289     return Py_BuildValue("i", rc);
    00290 }
    00295 /*@-fullinitblock@*/
    00296 /*@unchecked@*/ /*@observer@*/
    00297 static struct PyMethodDef rpmfts_methods[] = {
    00298     {"Debug",   (PyCFunction)rpmfts_Debug,      METH_VARARGS|METH_KEYWORDS,
    00299         NULL},
    00300     {"open",    (PyCFunction)rpmfts_Open,       METH_VARARGS|METH_KEYWORDS,
    00301         NULL},
    00302     {"read",    (PyCFunction)rpmfts_Read,       METH_NOARGS,
    00303         NULL},
    00304     {"children",(PyCFunction)rpmfts_Children,   METH_VARARGS|METH_KEYWORDS,
    00305         NULL},
    00306     {"close",   (PyCFunction)rpmfts_Close,      METH_NOARGS,
    00307         NULL},
    00308     {"set",     (PyCFunction)rpmfts_Set,        METH_VARARGS|METH_KEYWORDS,
    00309         NULL},
    00310     {NULL,              NULL}           /* sentinel */
    00311 };
    00312 /*@=fullinitblock@*/
    00313
    00314 /* ---------- */
    00315
    00316 static PyMemberDef rpmfts_members[] = {
    00317     {"__dict__",T_OBJECT,offsetof(rpmftsObject, md_dict),       READONLY,
    00318         NULL},
    00319     {"callbacks",T_OBJECT,offsetof(rpmftsObject, callbacks),    0,
    00320 "Callback dictionary per fts_info state: FTS_{D|DC|DEFAULT|DNR|DOT|DP|ERR|F|INIT|NS|NSOK|SL|SLNONE|W}"},
    00321     {"options", T_INT,  offsetof(rpmftsObject, options),        0,
    00322 "Option bit(s): FTS_{COMFOLLOW|LOGICAL|NOCHDIR|NOSTAT|PHYSICAL|SEEDOT|XDEV}"},
    00323     {"ignore",  T_INT,  offsetof(rpmftsObject, ignore),         0,
    00324 "Ignore bit(s): (1 << info) with info one of FTS_{D|DC|DEFAULT|DNR|DOT|DP|ERR|F|INIT|NS|NSOK|SL|SLNONE|W}"},
    00325     {NULL, 0, 0, 0, NULL}
    00326 };
    00327
    00328 static PyObject * rpmfts_getattro(PyObject * o, PyObject * n)
    00329         /*@*/
    00330 {
    00331 rpmfts_debug("rpmfts_getattro", (rpmftsObject *)o);
    00332     return PyObject_GenericGetAttr(o, n);
    00333 }
    00334
    00335 static int rpmfts_setattro(PyObject * o, PyObject * n, PyObject * v)
    00336         /*@*/
    00337 {
    00338 rpmfts_debug("rpmfts_setattro", (rpmftsObject *)o);
    00339     return PyObject_GenericSetAttr(o, n, v);
    00340 }
    00341
    00342 /* ---------- */
    00343
    00344 static PyObject *
    00345 rpmfts_iter(rpmftsObject * s)
    00346         /*@*/
    00347 {
    00348     Py_INCREF(s);
    00349     return (PyObject *)s;
    00350 }
    00351
    00352 /*@null@*/
    00353 static PyObject *
    00354 rpmfts_iternext(rpmftsObject * s)
    00355         /*@modifies s @*/
    00356 {
    00357     int xx;
    00358
    00359     /* Reset loop indices on 1st entry. */
    00360     if (s->active == RPMFTS_CLOSE)
    00361         xx = rpmfts_state(s, RPMFTS_OPEN_LAZY);
    00362     return rpmfts_step(s);
    00363 }
    00364
    00365 /* ---------- */
    00366
    00367 static void rpmfts_free(/*@only@*/ PyObject * s)
    00368         /*@*/
    00369 {
    00370     _PyObject_GC_Del(s);
    00371 }
    00372
    00373 static PyObject * rpmfts_alloc(PyTypeObject * type, Py_ssize_t nitems)
    00374         /*@*/
    00375 {
    00376     return PyType_GenericAlloc(type, nitems);
    00377 }
    00378
    00379 static void rpmfts_dealloc(/*@only@*/ rpmftsObject * s)
    00380         /*@modifies s @*/
    00381 {
    00382     int xx;
    00383
    00384 rpmfts_debug("rpmfts_dealloc", s);
    00385     xx = rpmfts_state(s, RPMFTS_CLOSE);
    00386
    00387     s->roots = _free(s->roots);
    00388
    00389     PyObject_GC_UnTrack((PyObject *)s);
    00390     if (s->md_dict != NULL) {
    00391         _PyModule_Clear((PyObject *)s);
    00392         Py_DECREF(s->md_dict);
    00393     }
    00394     if (s->callbacks != NULL) {
    00395         _PyModule_Clear((PyObject *)s);
    00396         Py_DECREF(s->callbacks);
    00397     }
    00398     _PyObject_GC_Del((PyObject *)s);
    00399 }
    00400
    00401 static int rpmfts_init(rpmftsObject * s, PyObject *args, PyObject *kwds)
    00402         /*@modifies s @*/
    00403 {
    00404     char * root = NULL;
    00405     int options = -1;
    00406     int ignore = -1;
    00407     char * kwlist[] = {"root", "options", "ignore", NULL};
    00408
    00409 rpmfts_debug("rpmfts_init", s);
    00410     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sii:rpmfts_init", kwlist,
    00411             &root, &options, &ignore))
    00412         return -1;
    00413
    00414     return rpmfts_initialize(s, root, options, ignore);
    00415 }
    00416
    00417 /*@null@*/
    00418 static PyObject * rpmfts_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
    00419         /*@*/
    00420 {
    00421     rpmftsObject *s;
    00422     PyObject *o;
    00423     PyObject *n = NULL;
    00424     char * kwlist[] = {0};
    00425
    00426     /* All the other _new() functions claim to be _init in their errors...*/
    00427     if (!PyArg_ParseTupleAndKeywords(args, kwds, ":rpmfts_new", kwlist))
    00428         return NULL;
    00429
    00430     if ((s = PyObject_GC_New(rpmftsObject, type)) == NULL)
    00431         return NULL;
    00432 rpmfts_debug("rpmfts_new", s);
    00433
    00434     s->md_dict = PyDict_New();
    00435     if (s->md_dict == NULL)
    00436         goto fail;
    00437     s->callbacks = PyDict_New();
    00438     if (s->md_dict == NULL)
    00439         goto fail;
    00440     if (type->tp_name) {
    00441         const char * name;
    00442         if ((name = strrchr(type->tp_name, '.')) != NULL)
    00443             name++;
    00444         else
    00445             name = type->tp_name;
    00446         n = PyString_FromString(name);
    00447     }
    00448     if (n != NULL && PyDict_SetItemString(s->md_dict, "__name__", n) != 0)
    00449         goto fail;
    00450     if (PyDict_SetItemString(s->md_dict, "__doc__", Py_None) != 0)
    00451         goto fail;
    00452
    00453 #define CONSTANT(_v) \
    00454     PyDict_SetItemString(s->md_dict, #_v, o=PyInt_FromLong(_v)); Py_DECREF(o)
    00455
    00456     CONSTANT(FTS_ROOTPARENTLEVEL);
    00457     CONSTANT(FTS_ROOTLEVEL);
    00458
    00459     CONSTANT(FTS_COMFOLLOW);
    00460     CONSTANT(FTS_LOGICAL);
    00461     CONSTANT(FTS_NOCHDIR);
    00462     CONSTANT(FTS_NOSTAT);
    00463     CONSTANT(FTS_PHYSICAL);
    00464     CONSTANT(FTS_SEEDOT);
    00465     CONSTANT(FTS_XDEV);
    00466     CONSTANT(FTS_WHITEOUT);
    00467     CONSTANT(FTS_OPTIONMASK);
    00468
    00469     CONSTANT(FTS_NAMEONLY);
    00470     CONSTANT(FTS_STOP);
    00471
    00472     CONSTANT(FTS_D);
    00473     CONSTANT(FTS_DC);
    00474     CONSTANT(FTS_DEFAULT);
    00475     CONSTANT(FTS_DNR);
    00476     CONSTANT(FTS_DOT);
    00477     CONSTANT(FTS_DP);
    00478     CONSTANT(FTS_ERR);
    00479     CONSTANT(FTS_F);
    00480     CONSTANT(FTS_NS);
    00481     CONSTANT(FTS_NSOK);
    00482     CONSTANT(FTS_SL);
    00483     CONSTANT(FTS_SLNONE);
    00484     CONSTANT(FTS_W);
    00485
    00486     CONSTANT(FTS_DONTCHDIR);
    00487     CONSTANT(FTS_SYMFOLLOW);
    00488
    00489     CONSTANT(FTS_AGAIN);
    00490     CONSTANT(FTS_FOLLOW);
    00491     CONSTANT(FTS_NOINSTR);
    00492     CONSTANT(FTS_SKIP);
    00493
    00494     s->roots = NULL;
    00495     s->compare = NULL;
    00496     s->ftsp = NULL;
    00497     s->fts = NULL;
    00498
    00499     Py_XDECREF(n);
    00500     PyObject_GC_Track((PyObject *)s);
    00501     return (PyObject *)s;
    00502
    00503  fail:
    00504     Py_XDECREF(n);
    00505     Py_DECREF(s);
    00506     return NULL;
    00507 }
    00508
    00509 static int rpmfts_traverse(rpmftsObject * s, visitproc visit, void * arg)
    00510         /*@*/
    00511 {
    00512     if (s->md_dict != NULL)
    00513         return visit(s->md_dict, arg);
    00514     if (s->callbacks != NULL)
    00515         return visit(s->callbacks, arg);
    00516     return 0;
    00517 }
    00518
    00519 static int rpmfts_print(rpmftsObject * s,  FILE * fp,
    00520                 /*@unused@*/ int flags)
    00521         /*@globals fileSystem @*/
    00522         /*@modifies fp, fileSystem @*/
    00523 {
    00524     static int indent = 2;
    00525
    00526     if (!(s != NULL && s->ftsp != NULL && s->fts != NULL))
    00527         return -1;
    00528     fprintf(fp, "FTS_%-7s %*s%s", ftsInfoStr(s->fts->fts_info),
    00529         indent * (s->fts->fts_level < 0 ? 0 : s->fts->fts_level), "",
    00530         s->fts->fts_name);
    00531     return 0;
    00532 }
    00533
    00536 /*@unchecked@*/ /*@observer@*/
    00537 static char rpmfts_doc[] =
    00538 "";
    00539
    00542 /*@-fullinitblock@*/
    00543 PyTypeObject rpmfts_Type = {
    00544         PyObject_HEAD_INIT(&PyType_Type)
    00545         0,                              /* ob_size */
    00546         "rpm.fts",                      /* tp_name */
    00547         sizeof(rpmftsObject),           /* tp_size */
    00548         0,                              /* tp_itemsize */
    00549         /* methods */
    00550         (destructor) rpmfts_dealloc,    /* tp_dealloc */
    00551         (printfunc) rpmfts_print,       /* tp_print */
    00552         (getattrfunc)0,                 /* tp_getattr */
    00553         (setattrfunc)0,                 /* tp_setattr */
    00554         (cmpfunc)0,                     /* tp_compare */
    00555         (reprfunc)0,                    /* tp_repr */
    00556         0,                              /* tp_as_number */
    00557         0,                              /* tp_as_sequence */
    00558         0,                              /* tp_as_mapping */
    00559         (hashfunc)0,                    /* tp_hash */
    00560         (ternaryfunc)0,                 /* tp_call */
    00561         (reprfunc)0,                    /* tp_str */
    00562         (getattrofunc) rpmfts_getattro, /* tp_getattro */
    00563         (setattrofunc) rpmfts_setattro, /* tp_setattro */
    00564         0,                              /* tp_as_buffer */
    00565         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
    00566         rpmfts_doc,                     /* tp_doc */
    00567         (traverseproc) rpmfts_traverse, /* tp_traverse */
    00568         0,                              /* tp_clear */
    00569         0,                              /* tp_richcompare */
    00570         0,                              /* tp_weaklistoffset */
    00571         (getiterfunc) rpmfts_iter,      /* tp_iter */
    00572         (iternextfunc) rpmfts_iternext, /* tp_iternext */
    00573         rpmfts_methods,                 /* tp_methods */
    00574         rpmfts_members,                 /* tp_members */
    00575         0,                              /* tp_getset */
    00576         0,                              /* tp_base */
    00577         0,                              /* tp_dict */
    00578         0,                              /* tp_descr_get */
    00579         0,                              /* tp_descr_set */
    00580         offsetof(rpmftsObject, md_dict),/* tp_dictoffset */
    00581         (initproc) rpmfts_init,         /* tp_init */
    00582         rpmfts_alloc,                   /* tp_alloc */
    00583         rpmfts_new,                     /* tp_new */
    00584         (freefunc) rpmfts_free,         /* tp_free */
    00585         0,                              /* tp_is_gc */
    00586 };
    00587 /*@=fullinitblock@*/