Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

python/rpmfts-py.c

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

Generated on Tue May 22 19:54:14 2007 for rpm by doxygen 1.3.5