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 <rpmlib.h>     /* XXX _free */
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, " %d %d ftsp %p fts %p\n", 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(__FUNCTION__, 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(__FUNCTION__, 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 
00174 /*@null@*/
00175 static PyObject *
00176 rpmfts_Debug(/*@unused@*/ rpmftsObject * s, PyObject * args, PyObject * kwds)
00177         /*@globals _Py_NoneStruct @*/
00178         /*@modifies _Py_NoneStruct @*/
00179 {
00180     char * kwlist[] = {"debugLevel", NULL};
00181 
00182     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:Debug", kwlist,
00183             &_rpmfts_debug))
00184         return NULL;
00185 
00186     Py_INCREF(Py_None);
00187     return Py_None;
00188 }
00189 
00190 /*@null@*/
00191 static PyObject *
00192 rpmfts_Open(rpmftsObject * s, PyObject * args, PyObject * kwds)
00193         /*@modifies s @*/
00194 {
00195     char * root = NULL;
00196     int options = -1;
00197     int ignore = -1;
00198     int xx;
00199     /* XXX: there's bound to be a better name than "ignore" */
00200     char * kwlist[] = {"root", "options", "ignore", NULL};
00201 
00202 rpmfts_debug(__FUNCTION__, s);
00203     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sii:Open", kwlist,
00204             &root, &options, &ignore))
00205         return NULL;
00206 
00207     xx = rpmfts_initialize(s, root, options, ignore);
00208     xx = rpmfts_state(s, RPMFTS_OPEN);
00209 
00210     return (PyObject *)s;
00211 }
00212 
00213 /*@null@*/
00214 static PyObject *
00215 rpmfts_Read(rpmftsObject * s)
00216         /*@globals _Py_NoneStruct @*/
00217         /*@modifies s, _Py_NoneStruct @*/
00218 {
00219     PyObject * result;
00220 
00221 rpmfts_debug(__FUNCTION__, s);
00222 
00223     result = rpmfts_step(s);
00224 
00225     if (result == NULL) {
00226         Py_INCREF(Py_None);
00227         return Py_None;
00228     }
00229 
00230     return result;
00231 }
00232 
00233 /*@null@*/
00234 static PyObject *
00235 rpmfts_Children(rpmftsObject * s, PyObject * args, PyObject * kwds)
00236         /*@globals _Py_NoneStruct @*/
00237         /*@modifies s, _Py_NoneStruct @*/
00238 {
00239     int instr;
00240     char * kwlist[] = {"instructions", NULL};
00241 
00242 rpmfts_debug(__FUNCTION__, s);
00243     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:Children", kwlist, &instr))
00244         return NULL;
00245 
00246     if (!(s && s->ftsp))
00247         return NULL;
00248 
00249     Py_BEGIN_ALLOW_THREADS
00250     s->fts = Fts_children(s->ftsp, instr);
00251     Py_END_ALLOW_THREADS
00252 
00253     Py_INCREF(Py_None);
00254     return Py_None;
00255 }
00256 
00257 /*@null@*/
00258 static PyObject *
00259 rpmfts_Close(rpmftsObject * s)
00260         /*@modifies s @*/
00261 {
00262 
00263 rpmfts_debug(__FUNCTION__, s);
00264 
00265     return Py_BuildValue("i", rpmfts_state(s, RPMFTS_CLOSE));
00266 }
00267 
00268 /*@null@*/
00269 static PyObject *
00270 rpmfts_Set(rpmftsObject * s, PyObject * args, PyObject * kwds)
00271         /*@modifies s @*/
00272 {
00273     int instr = 0;
00274     int rc = 0;
00275     char * kwlist[] = {"instructions", NULL};
00276 
00277 rpmfts_debug(__FUNCTION__, s);
00278     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:Set", kwlist, &instr))
00279         return NULL;
00280 
00281     if (s->ftsp && s->fts)
00282         rc = Fts_set(s->ftsp, s->fts, instr);
00283 
00284     return Py_BuildValue("i", rc);
00285 }
00286 
00289 /*@-fullinitblock@*/
00290 /*@unchecked@*/ /*@observer@*/
00291 static struct PyMethodDef rpmfts_methods[] = {
00292     {"Debug",   (PyCFunction)rpmfts_Debug,      METH_VARARGS|METH_KEYWORDS,
00293         NULL},
00294     {"open",    (PyCFunction)rpmfts_Open,       METH_VARARGS|METH_KEYWORDS,
00295         NULL},
00296     {"read",    (PyCFunction)rpmfts_Read,       METH_NOARGS,
00297         NULL},
00298     {"children",(PyCFunction)rpmfts_Children,   METH_VARARGS|METH_KEYWORDS,
00299         NULL},
00300     {"close",   (PyCFunction)rpmfts_Close,      METH_NOARGS,
00301         NULL},
00302     {"set",     (PyCFunction)rpmfts_Set,        METH_VARARGS|METH_KEYWORDS,
00303         NULL},
00304     {NULL,              NULL}           /* sentinel */
00305 };
00306 /*@=fullinitblock@*/
00307 
00308 /* ---------- */
00309 
00310 static PyMemberDef rpmfts_members[] = {
00311     {"__dict__",T_OBJECT,offsetof(rpmftsObject, md_dict),       READONLY,
00312         NULL},
00313     {"callbacks",T_OBJECT,offsetof(rpmftsObject, callbacks),    0,
00314 "Callback dictionary per fts_info state: FTS_{D|DC|DEFAULT|DNR|DOT|DP|ERR|F|INIT|NS|NSOK|SL|SLNONE|W}"},
00315     {"options", T_INT,  offsetof(rpmftsObject, options),        0,
00316 "Option bit(s): FTS_{COMFOLLOW|LOGICAL|NOCHDIR|NOSTAT|PHYSICAL|SEEDOT|XDEV}"},
00317     {"ignore",  T_INT,  offsetof(rpmftsObject, ignore),         0,
00318 "Ignore bit(s): (1 << info) with info one of FTS_{D|DC|DEFAULT|DNR|DOT|DP|ERR|F|INIT|NS|NSOK|SL|SLNONE|W}"},
00319     {NULL, 0, 0, 0, NULL}
00320 };
00321 
00322 static PyObject * rpmfts_getattro(PyObject * o, PyObject * n)
00323         /*@*/
00324 {
00325 rpmfts_debug(__FUNCTION__, (rpmftsObject *)o);
00326     return PyObject_GenericGetAttr(o, n);
00327 }
00328 
00329 static int rpmfts_setattro(PyObject * o, PyObject * n, PyObject * v)
00330         /*@*/
00331 {
00332 rpmfts_debug(__FUNCTION__, (rpmftsObject *)o);
00333     return PyObject_GenericSetAttr(o, n, v);
00334 }
00335 
00336 /* ---------- */
00337 
00338 static PyObject *
00339 rpmfts_iter(rpmftsObject * s)
00340         /*@*/
00341 {
00342     Py_INCREF(s);
00343     return (PyObject *)s;
00344 }
00345 
00346 /*@null@*/
00347 static PyObject *
00348 rpmfts_iternext(rpmftsObject * s)
00349         /*@modifies s @*/
00350 {
00351     int xx;
00352 
00353     /* Reset loop indices on 1st entry. */
00354     if (s->active == RPMFTS_CLOSE)
00355         xx = rpmfts_state(s, RPMFTS_OPEN_LAZY);
00356     return rpmfts_step(s);
00357 }
00358 
00359 /* ---------- */
00360 
00361 static void rpmfts_free(/*@only@*/ PyObject * s)
00362         /*@*/
00363 {
00364     _PyObject_GC_Del(s);
00365 }
00366 
00367 static PyObject * rpmfts_alloc(PyTypeObject * type, int nitems)
00368         /*@*/
00369 {
00370     return PyType_GenericAlloc(type, nitems);
00371 }
00372 
00373 static void rpmfts_dealloc(/*@only@*/ rpmftsObject * s)
00374         /*@modifies s @*/
00375 {
00376     int xx;
00377 
00378 rpmfts_debug(__FUNCTION__, s);
00379     xx = rpmfts_state(s, RPMFTS_CLOSE);
00380 
00381     s->roots = _free(s->roots);
00382 
00383     PyObject_GC_UnTrack((PyObject *)s);
00384     if (s->md_dict != NULL) {
00385         _PyModule_Clear((PyObject *)s);
00386         Py_DECREF(s->md_dict);
00387     }
00388     if (s->callbacks != NULL) {
00389         _PyModule_Clear((PyObject *)s);
00390         Py_DECREF(s->callbacks);
00391     }
00392     _PyObject_GC_Del((PyObject *)s);
00393 }
00394 
00395 static int rpmfts_init(rpmftsObject * s, PyObject *args, PyObject *kwds)
00396         /*@modifies s @*/
00397 {
00398     char * root = NULL;
00399     int options = -1;
00400     int ignore = -1;
00401     char * kwlist[] = {"root", "options", "ignore", NULL};
00402 
00403 rpmfts_debug(__FUNCTION__, s);
00404     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sii:rpmfts_init", kwlist,
00405             &root, &options, &ignore))
00406         return -1;
00407 
00408     return rpmfts_initialize(s, root, options, ignore);
00409 }
00410 
00411 /*@null@*/
00412 static PyObject * rpmfts_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
00413         /*@*/
00414 {
00415     rpmftsObject *s;
00416     PyObject *o;
00417     PyObject *n = NULL;
00418     char * kwlist[] = {0};
00419 
00420     /* All the other _new() functions claim to be _init in their errors...*/
00421     if (!PyArg_ParseTupleAndKeywords(args, kwds, ":rpmfts_new", kwlist))
00422         return NULL;
00423 
00424     if ((s = PyObject_GC_New(rpmftsObject, type)) == NULL)
00425         return NULL;
00426 rpmfts_debug(__FUNCTION__, s);
00427 
00428     s->md_dict = PyDict_New();
00429     if (s->md_dict == NULL)
00430         goto fail;
00431     s->callbacks = PyDict_New();
00432     if (s->md_dict == NULL)
00433         goto fail;
00434     if (type->tp_name) {
00435         char * name;
00436         if ((name = strrchr(type->tp_name, '.')) != NULL)
00437             name++;
00438         else
00439             name = type->tp_name;
00440         n = PyString_FromString(name);
00441     }
00442     if (n != NULL && PyDict_SetItemString(s->md_dict, "__name__", n) != 0)
00443         goto fail;
00444     if (PyDict_SetItemString(s->md_dict, "__doc__", Py_None) != 0)
00445         goto fail;
00446 
00447 #define CONSTANT(_v) \
00448     PyDict_SetItemString(s->md_dict, #_v, o=PyInt_FromLong(_v)); Py_DECREF(o)
00449 
00450     CONSTANT(FTS_ROOTPARENTLEVEL);
00451     CONSTANT(FTS_ROOTLEVEL);
00452 
00453     CONSTANT(FTS_COMFOLLOW);
00454     CONSTANT(FTS_LOGICAL);
00455     CONSTANT(FTS_NOCHDIR);
00456     CONSTANT(FTS_NOSTAT);
00457     CONSTANT(FTS_PHYSICAL);
00458     CONSTANT(FTS_SEEDOT);
00459     CONSTANT(FTS_XDEV);
00460     CONSTANT(FTS_WHITEOUT);
00461     CONSTANT(FTS_OPTIONMASK);
00462 
00463     CONSTANT(FTS_NAMEONLY);
00464     CONSTANT(FTS_STOP);
00465 
00466     CONSTANT(FTS_D);
00467     CONSTANT(FTS_DC);
00468     CONSTANT(FTS_DEFAULT);
00469     CONSTANT(FTS_DNR);
00470     CONSTANT(FTS_DOT);
00471     CONSTANT(FTS_DP);
00472     CONSTANT(FTS_ERR);
00473     CONSTANT(FTS_F);
00474     CONSTANT(FTS_NS);
00475     CONSTANT(FTS_NSOK);
00476     CONSTANT(FTS_SL);
00477     CONSTANT(FTS_SLNONE);
00478     CONSTANT(FTS_W);
00479 
00480     CONSTANT(FTS_DONTCHDIR);
00481     CONSTANT(FTS_SYMFOLLOW);
00482 
00483     CONSTANT(FTS_AGAIN);
00484     CONSTANT(FTS_FOLLOW);
00485     CONSTANT(FTS_NOINSTR);
00486     CONSTANT(FTS_SKIP);
00487 
00488     s->roots = NULL;
00489     s->compare = NULL;
00490     s->ftsp = NULL;
00491     s->fts = NULL;
00492 
00493     Py_XDECREF(n);
00494     PyObject_GC_Track((PyObject *)s);
00495     return (PyObject *)s;
00496 
00497  fail:
00498     Py_XDECREF(n);
00499     Py_DECREF(s);
00500     return NULL;
00501 }
00502 
00503 static int rpmfts_traverse(rpmftsObject * s, visitproc visit, void * arg)
00504         /*@*/
00505 {
00506     if (s->md_dict != NULL)
00507         return visit(s->md_dict, arg);
00508     if (s->callbacks != NULL)
00509         return visit(s->callbacks, arg);
00510     return 0;
00511 }
00512 
00513 static int rpmfts_print(rpmftsObject * s,  FILE * fp, /*@unused@*/ int flags)
00514         /*@globals fileSystem @*/
00515         /*@modifies fp, fileSystem @*/
00516 {
00517     static int indent = 2;
00518 
00519     if (!(s != NULL && s->ftsp != NULL && s->fts != NULL))
00520         return -1;
00521     fprintf(fp, "FTS_%-7s %*s%s", ftsInfoStr(s->fts->fts_info),
00522         indent * (s->fts->fts_level < 0 ? 0 : s->fts->fts_level), "",
00523         s->fts->fts_name);
00524     return 0;
00525 }
00526 
00529 /*@unchecked@*/ /*@observer@*/
00530 static char rpmfts_doc[] =
00531 "";
00532 
00535 /*@-fullinitblock@*/
00536 PyTypeObject rpmfts_Type = {
00537         PyObject_HEAD_INIT(&PyType_Type)
00538         0,                              /* ob_size */
00539         "rpm.fts",                      /* tp_name */
00540         sizeof(rpmftsObject),           /* tp_size */
00541         0,                              /* tp_itemsize */
00542         /* methods */
00543         (destructor) rpmfts_dealloc,    /* tp_dealloc */
00544         (printfunc) rpmfts_print,       /* tp_print */
00545         (getattrfunc)0,                 /* tp_getattr */
00546         (setattrfunc)0,                 /* tp_setattr */
00547         (cmpfunc)0,                     /* tp_compare */
00548         (reprfunc)0,                    /* tp_repr */
00549         0,                              /* tp_as_number */
00550         0,                              /* tp_as_sequence */
00551         0,                              /* tp_as_mapping */
00552         (hashfunc)0,                    /* tp_hash */
00553         (ternaryfunc)0,                 /* tp_call */
00554         (reprfunc)0,                    /* tp_str */
00555         (getattrofunc) rpmfts_getattro, /* tp_getattro */
00556         (setattrofunc) rpmfts_setattro, /* tp_setattro */
00557         0,                              /* tp_as_buffer */
00558         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
00559         rpmfts_doc,                     /* tp_doc */
00560         (traverseproc) rpmfts_traverse, /* tp_traverse */
00561         0,                              /* tp_clear */
00562         0,                              /* tp_richcompare */
00563         0,                              /* tp_weaklistoffset */
00564         (getiterfunc) rpmfts_iter,      /* tp_iter */
00565         (iternextfunc) rpmfts_iternext, /* tp_iternext */
00566         rpmfts_methods,                 /* tp_methods */
00567         rpmfts_members,                 /* tp_members */
00568         0,                              /* tp_getset */
00569         0,                              /* tp_base */
00570         0,                              /* tp_dict */
00571         0,                              /* tp_descr_get */
00572         0,                              /* tp_descr_set */
00573         offsetof(rpmftsObject, md_dict),/* tp_dictoffset */
00574         (initproc) rpmfts_init,         /* tp_init */
00575         rpmfts_alloc,                   /* tp_alloc */
00576         rpmfts_new,                     /* tp_new */
00577         rpmfts_free,                    /* tp_free */
00578         0,                              /* tp_is_gc */
00579 };
00580 /*@=fullinitblock@*/

Generated on Fri Oct 12 08:44:54 2007 for rpm by  doxygen 1.5.2