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

# python/rpmmodule.c

Go to the documentation of this file.

    00001
    00005 #include <alloca.h>
    00006 #include <errno.h>
    00007 #include <fcntl.h>
    00008 #include <time.h>
    00009 #include <sys/stat.h>
    00010 #include <sys/time.h>
    00011 #include <unistd.h>
    00012 #include <glob.h>       /* XXX rpmio.h */
    00013 #include <dirent.h>     /* XXX rpmio.h */
    00014 #include <locale.h>
    00015 #include <time.h>
    00016
    00017 #include "Python.h"
    00018 #include "rpmio_internal.h"
    00019 #include "rpmcli.h"     /* XXX for rpmCheckSig */
    00020 #include "misc.h"
    00021 #include "header_internal.h"
    00022 #include "upgrade.h"
    00023
    00024 #include "db-py.h"
    00025 #include "header-py.h"
    00026
    00027 extern int _rpmio_debug;
    00028
    00029 #ifdef __LCLINT__
    00030 #undef  PyObject_HEAD
    00031 #define PyObject_HEAD   int _PyObjectHead
    00032 #endif
    00033
    00034 extern int mdfile(const char *fn, unsigned char *digest);
    00035
    00036 void initrpm(void);
    00037
    00038 /* from lib/misc.c */
    00039 int rpmvercmp(const char * one, const char * two);
    00040
    00043 typedef struct rpmtransObject_s rpmtransObject;
    00044
    00096
    00199
    00202 struct rpmtransObject_s {
    00203     PyObject_HEAD;
    00204     rpmdbObject * dbo;
    00205     rpmTransactionSet ts;
    00206     PyObject * keyList;                 /* keeps reference counts correct */
    00207     FD_t scriptFd;
    00208 } ;
    00209
    00212 static PyObject * rpmtransAdd(rpmtransObject * s, PyObject * args) {
    00213     hdrObject * h;
    00214     PyObject * key;
    00215     char * how = NULL;
    00216     int isUpgrade = 0;
    00217     PyObject * hObj;
    00218
    00219     if (!PyArg_ParseTuple(args, "OO|s", &h, &key, &how)) return NULL;
    00220
    00221     hObj = (PyObject *) h;
    00222     if (hObj->ob_type != &hdrType) {
    00223         PyErr_SetString(PyExc_TypeError, "bad type for header argument");
    00224         return NULL;
    00225     }
    00226
    00227     if (how && strcmp(how, "a") && strcmp(how, "u") && strcmp(how, "i")) {
    00228         PyErr_SetString(PyExc_TypeError, "how argument must be \"u\", \"a\", or \"i\"");
    00229         return NULL;
    00230     } else if (how && !strcmp(how, "u"))
    00231         isUpgrade = 1;
    00232
    00233     if (how && !strcmp(how, "a"))
    00234         rpmtransAvailablePackage(s->ts, hdrGetHeader(h), key);
    00235     else
    00236         rpmtransAddPackage(s->ts, hdrGetHeader(h), NULL, key, isUpgrade, NULL);
    00237
    00238     /* This should increment the usage count for me */
    00239     if (key) {
    00240         PyList_Append(s->keyList, key);
    00241     }
    00242
    00243     Py_INCREF(Py_None);
    00244     return Py_None;
    00245 }
    00246
    00249 static PyObject * rpmtransRemove(rpmtransObject * s, PyObject * args) {
    00250     char * name;
    00251     int count;
    00252     rpmdbMatchIterator mi;
    00253
    00254     if (!PyArg_ParseTuple(args, "s", &name))
    00255         return NULL;
    00256
    00257     /* XXX: Copied hack from ../lib/rpminstall.c, rpmErase() */
    00258     mi = rpmdbInitIterator(dbFromDb(s->dbo), RPMDBI_LABEL, name, 0);
    00259     count = rpmdbGetIteratorCount(mi);
    00260     if (count <= 0) {
    00261         PyErr_SetString(pyrpmError, "package not installed");
    00262         return NULL;
    00263     } else { /* XXX: Note that we automatically choose to remove all matches */
    00264         Header h;
    00265         while ((h = rpmdbNextIterator(mi)) != NULL) {
    00266             unsigned int recOffset = rpmdbGetIteratorOffset(mi);
    00267             if (recOffset) {
    00268                 rpmtransRemovePackage(s->ts, recOffset);
    00269             }
    00270         }
    00271     }
    00272     rpmdbFreeIterator(mi);
    00273
    00274     Py_INCREF(Py_None);
    00275     return Py_None;
    00276 }
    00277
    00280 static PyObject * rpmtransDepCheck(rpmtransObject * s, PyObject * args) {
    00281     rpmDependencyConflict conflicts;
    00282     int numConflicts;
    00283     PyObject * list, * cf, * suggestions;
    00284     int i, j;
    00285     int allSuggestions = 0;
    00286
    00287     if (!PyArg_ParseTuple(args, "|i", &allSuggestions)) return NULL;
    00288
    00289     rpmdepCheck(s->ts, &conflicts, &numConflicts);
    00290     if (numConflicts) {
    00291         list = PyList_New(0);
    00292
    00293         /* XXX TODO: rpmlib-4.0.3 can return multiple suggested packages. */
    00294         for (i = 0; i < numConflicts; i++) {
    00295             if (!conflicts[i].suggestedPackages)
    00296                 suggestions = Py_None;
    00297             else if (!allSuggestions)
    00298                 suggestions = conflicts[i].suggestedPackages[0];
    00299             else {
    00300                 suggestions = PyList_New(0);
    00301
    00302                 for (j = 0; conflicts[i].suggestedPackages[j]; j++)
    00303                     PyList_Append(suggestions,
    00304                                   conflicts[i].suggestedPackages[j]);
    00305             }
    00306
    00307             cf = Py_BuildValue("((sss)(ss)iOi)", conflicts[i].byName,
    00308                                conflicts[i].byVersion, conflicts[i].byRelease,
    00309
    00310                                conflicts[i].needsName,
    00311                                conflicts[i].needsVersion,
    00312
    00313                                conflicts[i].needsFlags,
    00314                                suggestions,
    00315                                conflicts[i].sense);
    00316             PyList_Append(list, (PyObject *) cf);
    00317             Py_DECREF(cf);
    00318         }
    00319
    00320         conflicts = rpmdepFreeConflicts(conflicts, numConflicts);
    00321
    00322         return list;
    00323     }
    00324
    00325     Py_INCREF(Py_None);
    00326     return Py_None;
    00327 }
    00328
    00331 static PyObject * rpmtransOrder(rpmtransObject * s, PyObject * args) {
    00332     if (!PyArg_ParseTuple(args, "")) return NULL;
    00333
    00334     rpmdepOrder(s->ts);
    00335
    00336     Py_INCREF(Py_None);
    00337     return Py_None;
    00338 }
    00339
    00342 static PyObject * py_rpmtransGetKeys(rpmtransObject * s, PyObject * args) {
    00343     const void **data = NULL;
    00344     int num, i;
    00345     PyObject *tuple;
    00346
    00347     rpmtransGetKeys(s->ts, &data, &num);
    00348     if (data == NULL) {
    00349         Py_INCREF(Py_None);
    00350         return Py_None;
    00351     }
    00352
    00353     tuple = PyTuple_New(num);
    00354
    00355     for (i = 0; i < num; i++) {
    00356         PyObject *obj = (PyObject *) data[i];
    00357         Py_INCREF(obj);
    00358         PyTuple_SetItem(tuple, i, obj);
    00359     }
    00360
    00361     free (data);
    00362
    00363     return tuple;
    00364 }
    00365
    00368 struct tsCallbackType {
    00369     PyObject * cb;
    00370     PyObject * data;
    00371     int pythonError;
    00372 };
    00373
    00377 static Header transactionSetHeader = NULL;
    00378
    00381 static void * tsCallback(const void * hd, const rpmCallbackType what,
    00382                          const unsigned long amount, const unsigned long total,
    00383                          const void * pkgKey, rpmCallbackData data) {
    00384     struct tsCallbackType * cbInfo = data;
    00385     PyObject * args, * result;
    00386     int fd;
    00387     static FD_t fdt;
    00388     const Header h = (Header) hd;
    00389
    00390     if (cbInfo->pythonError) return NULL;
    00391     if (cbInfo->cb == Py_None) return NULL;
    00392
    00393     if (!pkgKey) pkgKey = Py_None;
    00394     transactionSetHeader = h;
    00395
    00396     args = Py_BuildValue("(illOO)", what, amount, total, pkgKey, cbInfo->data);
    00397     result = PyEval_CallObject(cbInfo->cb, args);
    00398     Py_DECREF(args);
    00399
    00400     if (!result) {
    00401         cbInfo->pythonError = 1;
    00402         return NULL;
    00403     }
    00404
    00405     if (what == RPMCALLBACK_INST_OPEN_FILE) {
    00406         if (!PyArg_Parse(result, "i", &fd)) {
    00407             cbInfo->pythonError = 1;
    00408             return NULL;
    00409         }
    00410         fdt = fdDup(fd);
    00411
    00412         Py_DECREF(result);
    00413         return fdt;
    00414     }
    00415
    00416     if (what == RPMCALLBACK_INST_CLOSE_FILE) {
    00417         Fclose (fdt);
    00418     }
    00419
    00420     Py_DECREF(result);
    00421
    00422     return NULL;
    00423 }
    00424
    00427 static PyObject * rpmtransRun(rpmtransObject * s, PyObject * args) {
    00428     int flags, ignoreSet;
    00429     int rc, i;
    00430     PyObject * list, * prob;
    00431     rpmProblemSet probs;
    00432     struct tsCallbackType cbInfo;
    00433
    00434     if (!PyArg_ParseTuple(args, "iiOO", &flags, &ignoreSet, &cbInfo.cb,
    00435                           &cbInfo.data))
    00436         return NULL;
    00437
    00438     cbInfo.pythonError = 0;
    00439
    00440     rc = rpmRunTransactions(s->ts, tsCallback, &cbInfo, NULL, &probs, flags,
    00441                             ignoreSet);
    00442
    00443     if (cbInfo.pythonError) {
    00444         if (rc > 0)
    00445             rpmProblemSetFree(probs);
    00446         return NULL;
    00447     }
    00448
    00449     if (rc < 0) {
    00450         list = PyList_New(0);
    00451         return list;
    00452     } else if (!rc) {
    00453         Py_INCREF(Py_None);
    00454         return Py_None;
    00455     }
    00456
    00457     list = PyList_New(0);
    00458     for (i = 0; i < probs->numProblems; i++) {
    00459         rpmProblem myprob = probs->probs + i;
    00460         prob = Py_BuildValue("s(isN)", rpmProblemString(myprob),
    00461                              myprob->type,
    00462                              myprob->str1,
    00463                              PyLong_FromLongLong(myprob->ulong1));
    00464         PyList_Append(list, prob);
    00465         Py_DECREF(prob);
    00466     }
    00467
    00468     rpmProblemSetFree(probs);
    00469
    00470     return list;
    00471 }
    00472
    00475 static struct PyMethodDef rpmtransMethods[] = {
    00476         {"add",         (PyCFunction) rpmtransAdd,      1 },
    00477         {"remove",      (PyCFunction) rpmtransRemove,   1 },
    00478         {"depcheck",    (PyCFunction) rpmtransDepCheck, 1 },
    00479         {"order",       (PyCFunction) rpmtransOrder,    1 },
    00480         {"getKeys",     (PyCFunction) py_rpmtransGetKeys, 1 },
    00481         {"run",         (PyCFunction) rpmtransRun, 1 },
    00482         {NULL,          NULL}           /* sentinel */
    00483 };
    00484
    00487 static PyObject * rpmtransGetAttr(rpmtransObject * o, char * name) {
    00488     return Py_FindMethod(rpmtransMethods, (PyObject *) o, name);
    00489 }
    00490
    00493 static void rpmtransDealloc(PyObject * o) {
    00494     rpmtransObject * trans = (void *) o;
    00495
    00496     rpmtransFree(trans->ts);
    00497     if (trans->dbo) {
    00498         Py_DECREF(trans->dbo);
    00499     }
    00500     if (trans->scriptFd) Fclose(trans->scriptFd);
    00501     /* this will free the keyList, and decrement the ref count of all
    00502        the items on the list as well :-) */
    00503     Py_DECREF(trans->keyList);
    00504     PyMem_DEL(o);
    00505 }
    00506
    00509 static int rpmtransSetAttr(rpmtransObject * o, char * name,
    00510                            PyObject * val) {
    00511     int i;
    00512
    00513     if (!strcmp(name, "scriptFd")) {
    00514         if (!PyArg_Parse(val, "i", &i)) return 0;
    00515         if (i < 0) {
    00516             PyErr_SetString(PyExc_TypeError, "bad file descriptor");
    00517             return -1;
    00518         } else {
    00519             o->scriptFd = fdDup(i);
    00520             rpmtransSetScriptFd(o->ts, o->scriptFd);
    00521         }
    00522     } else {
    00523         PyErr_SetString(PyExc_AttributeError, name);
    00524         return -1;
    00525     }
    00526
    00527     return 0;
    00528 }
    00529
    00532 static PyTypeObject rpmtransType = {
    00533         PyObject_HEAD_INIT(NULL)
    00534         0,                              /* ob_size */
    00535         "rpmtrans",                     /* tp_name */
    00536         sizeof(rpmtransObject),         /* tp_size */
    00537         0,                              /* tp_itemsize */
    00538         (destructor) rpmtransDealloc,   /* tp_dealloc */
    00539         0,                              /* tp_print */
    00540         (getattrfunc) rpmtransGetAttr,  /* tp_getattr */
    00541         (setattrfunc) rpmtransSetAttr,  /* tp_setattr */
    00542         0,                              /* tp_compare */
    00543         0,                              /* tp_repr */
    00544         0,                              /* tp_as_number */
    00545         0,                              /* tp_as_sequence */
    00546         0,                              /* tp_as_mapping */
    00547 };
    00548
    00555
    00558 static PyObject * rpmtransCreate(PyObject * self, PyObject * args) {
    00559     rpmtransObject * o;
    00560     rpmdbObject * db = NULL;
    00561     char * rootPath = "/";
    00562
    00563     if (!PyArg_ParseTuple(args, "|sO", &rootPath, &db)) return NULL;
    00564     if (db && ((PyObject *) db)->ob_type != &rpmdbType) {
    00565         PyErr_SetString(PyExc_TypeError, "bad type for database argument");
    00566         return NULL;
    00567     }
    00568
    00569     o = (void *) PyObject_NEW(rpmtransObject, &rpmtransType);
    00570
    00571     Py_XINCREF(db);
    00572     o->dbo = db;
    00573     o->scriptFd = NULL;
    00574     o->ts = rpmtransCreateSet(db ? dbFromDb(db) : NULL, rootPath);
    00575     o->keyList = PyList_New(0);
    00576
    00577     return (void *) o;
    00578 }
    00579
    00582 static PyObject * doAddMacro(PyObject * self, PyObject * args) {
    00583     char * name, * val;
    00584
    00585     if (!PyArg_ParseTuple(args, "ss", &name, &val))
    00586         return NULL;
    00587
    00588     addMacro(NULL, name, NULL, val, RMIL_DEFAULT);
    00589
    00590     Py_INCREF(Py_None);
    00591     return Py_None;
    00592 }
    00593
    00596 static PyObject * doDelMacro(PyObject * self, PyObject * args) {
    00597     char * name;
    00598
    00599     if (!PyArg_ParseTuple(args, "s", &name))
    00600         return NULL;
    00601
    00602     delMacro(NULL, name);
    00603
    00604     Py_INCREF(Py_None);
    00605     return Py_None;
    00606 }
    00607
    00610 static PyObject * archScore(PyObject * self, PyObject * args) {
    00611     char * arch;
    00612     int score;
    00613
    00614     if (!PyArg_ParseTuple(args, "s", &arch))
    00615         return NULL;
    00616
    00617     score = rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch);
    00618
    00619     return Py_BuildValue("i", score);
    00620 }
    00621
    00624 static int psGetArchScore(Header h) {
    00625     void * pkgArch;
    00626     int type, count;
    00627
    00628     if (!headerGetEntry(h, RPMTAG_ARCH, &type, (void **) &pkgArch, &count) ||
    00629         type == RPM_INT8_TYPE)
    00630        return 150;
    00631     else
    00632         return rpmMachineScore(RPM_MACHTABLE_INSTARCH, pkgArch);
    00633 }
    00634
    00637 static int pkgCompareVer(void * first, void * second) {
    00638     struct packageInfo ** a = first;
    00639     struct packageInfo ** b = second;
    00640     int ret, score1, score2;
    00641
    00642     /* put packages w/o names at the end */
    00643     if (!(*a)->name) return 1;
    00644     if (!(*b)->name) return -1;
    00645
    00646     ret = xstrcasecmp((*a)->name, (*b)->name);
    00647     if (ret) return ret;
    00648     score1 = psGetArchScore((*a)->h);
    00649     if (!score1) return 1;
    00650     score2 = psGetArchScore((*b)->h);
    00651     if (!score2) return -1;
    00652     if (score1 < score2) return -1;
    00653     if (score1 > score2) return 1;
    00654     return rpmVersionCompare((*b)->h, (*a)->h);
    00655 }
    00656
    00659 static void pkgSort(struct pkgSet * psp) {
    00660     int i;
    00661     char *name;
    00662
    00663     if (psp->numPackages <= 0)
    00664         return;
    00665
    00666     qsort(psp->packages, psp->numPackages, sizeof(*psp->packages),
    00667          (void *) pkgCompareVer);
    00668
    00669     name = psp->packages[0]->name;
    00670     if (!name) {
    00671        psp->numPackages = 0;
    00672        return;
    00673     }
    00674     for (i = 1; i < psp->numPackages; i++) {
    00675        if (!psp->packages[i]->name) break;
    00676        if (!strcmp(psp->packages[i]->name, name))
    00677            psp->packages[i]->name = NULL;
    00678        else
    00679            name = psp->packages[i]->name;
    00680     }
    00681
    00682     qsort(psp->packages, psp->numPackages, sizeof(*psp->packages),
    00683          (void *) pkgCompareVer);
    00684
    00685     for (i = 0; i < psp->numPackages; i++)
    00686        if (!psp->packages[i]->name) break;
    00687     psp->numPackages = i;
    00688 }
    00689
    00692 static PyObject * findUpgradeSet(PyObject * self, PyObject * args) {
    00693     PyObject * hdrList, * result;
    00694     char * root = "/";
    00695     int i;
    00696     struct pkgSet list;
    00697     hdrObject * hdr;
    00698
    00699     if (!PyArg_ParseTuple(args, "O|s", &hdrList, &root)) return NULL;
    00700
    00701     if (!PyList_Check(hdrList)) {
    00702         PyErr_SetString(PyExc_TypeError, "list of headers expected");
    00703         return NULL;
    00704     }
    00705
    00706     list.numPackages = PyList_Size(hdrList);
    00707     list.packages = alloca(sizeof(list.packages) * list.numPackages);
    00708     for (i = 0; i < list.numPackages; i++) {
    00709         hdr = (hdrObject *) PyList_GetItem(hdrList, i);
    00710         if (((PyObject *) hdr)->ob_type != &hdrType) {
    00711             PyErr_SetString(PyExc_TypeError, "list of headers expected");
    00712             return NULL;
    00713         }
    00714         list.packages[i] = alloca(sizeof(struct packageInfo));
    00715         list.packages[i]->h = hdrGetHeader(hdr);
    00716         list.packages[i]->selected = 0;
    00717         list.packages[i]->data = hdr;
    00718
    00719         headerGetEntry(list.packages[i]->h, RPMTAG_NAME, NULL,
    00720                       (void **) &list.packages[i]->name, NULL);
    00721     }
    00722
    00723     pkgSort (&list);
    00724
    00725     if (ugFindUpgradePackages(&list, root)) {
    00726         PyErr_SetString(pyrpmError, "error during upgrade check");
    00727         return NULL;
    00728     }
    00729
    00730     result = PyList_New(0);
    00731     for (i = 0; i < list.numPackages; i++) {
    00732         if (list.packages[i]->selected) {
    00733             PyList_Append(result, list.packages[i]->data);
    00734 /*          Py_DECREF(list.packages[i]->data); */
    00735         }
    00736     }
    00737
    00738     return result;
    00739 }
    00740
    00743 static PyObject * rpmInitDB(PyObject * self, PyObject * args) {
    00744     char *root;
    00745     int forWrite = 0;
    00746
    00747     if (!PyArg_ParseTuple(args, "i|s", &forWrite, &root)) return NULL;
    00748
    00749     if (rpmdbInit(root, forWrite ? O_RDWR | O_CREAT: O_RDONLY)) {
    00750         char * errmsg = "cannot initialize database in %s";
    00751         char * errstr = NULL;
    00752         int errsize;
    00753
    00754         errsize = strlen(errmsg) + strlen(root);
    00755         errstr = alloca(errsize);
    00756         snprintf(errstr, errsize, errmsg, root);
    00757         PyErr_SetString(pyrpmError, errstr);
    00758         return NULL;
    00759     }
    00760
    00761     Py_INCREF(Py_None);
    00762     return(Py_None);
    00763 }
    00764
    00765
    00768 static PyObject * errorCB = NULL, * errorData = NULL;
    00769
    00772 static void errorcb (void)
    00773 {
    00774     PyObject * result, * args = NULL;
    00775
    00776     if (errorData)
    00777         args = Py_BuildValue("(O)", errorData);
    00778
    00779     result = PyEval_CallObject(errorCB, args);
    00780     Py_XDECREF(args);
    00781
    00782     if (result == NULL) {
    00783         PyErr_Print();
    00784         PyErr_Clear();
    00785     }
    00786     Py_DECREF (result);
    00787 }
    00788
    00791 static PyObject * errorSetCallback (PyObject * self, PyObject * args) {
    00792     PyObject *newCB = NULL, *newData = NULL;
    00793
    00794     if (!PyArg_ParseTuple(args, "O|O", &newCB, &newData)) return NULL;
    00795
    00796     /* if we're getting a void*, set the error callback to this. */
    00797     /* also, we can possibly decref any python callbacks we had  */
    00798     /* and set them to NULL.                                     */
    00799     if (PyCObject_Check (newCB)) {
    00800         rpmErrorSetCallback (PyCObject_AsVoidPtr(newCB));
    00801
    00802         Py_XDECREF (errorCB);
    00803         Py_XDECREF (errorData);
    00804
    00805         errorCB   = NULL;
    00806         errorData = NULL;
    00807
    00808         Py_INCREF(Py_None);
    00809         return Py_None;
    00810     }
    00811
    00812     if (!PyCallable_Check (newCB)) {
    00813         PyErr_SetString(PyExc_TypeError, "parameter must be callable");
    00814         return NULL;
    00815     }
    00816
    00817     Py_XDECREF(errorCB);
    00818     Py_XDECREF(errorData);
    00819
    00820     errorCB = newCB;
    00821     errorData = newData;
    00822
    00823     Py_INCREF (errorCB);
    00824     Py_XINCREF (errorData);
    00825
    00826     return PyCObject_FromVoidPtr(rpmErrorSetCallback (errorcb), NULL);
    00827 }
    00828
    00831 static PyObject * errorString (PyObject * self, PyObject * args) {
    00832     return PyString_FromString(rpmErrorString ());
    00833 }
    00834
    00837 static PyObject * checkSig (PyObject * self, PyObject * args) {
    00838     char * filename;
    00839     int flags;
    00840     int rc = 255;
    00841
    00842     if (PyArg_ParseTuple(args, "si", &filename, &flags)) {
    00843         const char *av[2];
    00844         av[0] = filename;
    00845         av[1] = NULL;
    00846         rc = rpmCheckSig(flags, av);
    00847     }
    00848     return Py_BuildValue("i", rc);
    00849 }
    00850
    00851 /* hack to get the current header that's in the transaction set */
    00854 static PyObject * getTsHeader (PyObject * self, PyObject * args) {
    00855     if (!PyArg_ParseTuple(args, ""))
    00856         return NULL;
    00857
    00858     if (transactionSetHeader) {
    00859         return (PyObject *) createHeaderObject(transactionSetHeader);;
    00860     }
    00861     Py_INCREF(Py_None);
    00862     return (PyObject *) Py_None;
    00863 }
    00864
    00865
    00866 static PyObject * setVerbosity (PyObject * self, PyObject * args) {
    00867     int level;
    00868
    00869     if (!PyArg_ParseTuple(args, "i", &level))
    00870         return NULL;
    00871
    00872     rpmSetVerbosity(level);
    00873
    00874     Py_INCREF(Py_None);
    00875     return (PyObject *) Py_None;
    00876 }
    00877
    00880 typedef struct FDlist_t FDlist;
    00881
    00884 struct FDlist_t {
    00885     FILE *f;
    00886     FD_t fd;
    00887     char *note;
    00888     FDlist *next;
    00889 } ;
    00890
    00893 static FDlist *fdhead = NULL;
    00894
    00897 static FDlist *fdtail = NULL;
    00898
    00901 static int closeCallback(FILE * f) {
    00902     FDlist *node, *last;
    00903
    00904     printf ("close callback on %p\n", f);
    00905
    00906     node = fdhead;
    00907     last = NULL;
    00908     while (node) {
    00909         if (node->f == f)
    00910             break;
    00911         last = node;
    00912         node = node->next;
    00913     }
    00914     if (node) {
    00915         if (last)
    00916             last->next = node->next;
    00917         else
    00918             fdhead = node->next;
    00919         printf ("closing %s %p\n", node->note, node->fd);
    00920         free (node->note);
    00921         node->fd = fdLink(node->fd, "closeCallback");
    00922         Fclose (node->fd);
    00923         while (node->fd)
    00924             node->fd = fdFree(node->fd, "closeCallback");
    00925         free (node);
    00926     }
    00927     return 0;
    00928 }
    00929
    00932 static PyObject * doFopen(PyObject * self, PyObject * args) {
    00933     char * path, * mode;
    00934     FDlist *node;
    00935
    00936     if (!PyArg_ParseTuple(args, "ss", &path, &mode))
    00937         return NULL;
    00938
    00939     node = malloc (sizeof(FDlist));
    00940
    00941     node->fd = Fopen(path, mode);
    00942     node->fd = fdLink(node->fd, "doFopen");
    00943     node->note = strdup (path);
    00944
    00945     if (!node->fd) {
    00946         PyErr_SetFromErrno(pyrpmError);
    00947         free (node);
    00948         return NULL;
    00949     }
    00950
    00951     if (Ferror(node->fd)) {
    00952         const char *err = Fstrerror(node->fd);
    00953         free(node);
    00954         if (err) {
    00955             PyErr_SetString(pyrpmError, err);
    00956             return NULL;
    00957         }
    00958     }
    00959     node->f = fdGetFp(node->fd);
    00960     printf ("opening %s fd = %p f = %p\n", node->note, node->fd, node->f);
    00961     if (!node->f) {
    00962         PyErr_SetString(pyrpmError, "FD_t has no FILE*");
    00963         free(node);
    00964         return NULL;
    00965     }
    00966
    00967     node->next = NULL;
    00968     if (!fdhead) {
    00969         fdhead = fdtail = node;
    00970     } else if (fdtail) {
    00971         fdtail->next = node;
    00972     } else {
    00973         fdhead = node;
    00974     }
    00975     fdtail = node;
    00976
    00977     return PyFile_FromFile (node->f, path, mode, closeCallback);
    00978 }
    00979
    00982 static PyMethodDef rpmModuleMethods[] = {
    00983     { "TransactionSet", (PyCFunction) rpmtransCreate, METH_VARARGS, NULL },
    00984     { "addMacro", (PyCFunction) doAddMacro, METH_VARARGS, NULL },
    00985     { "delMacro", (PyCFunction) doDelMacro, METH_VARARGS, NULL },
    00986     { "archscore", (PyCFunction) archScore, METH_VARARGS, NULL },
    00987     { "findUpgradeSet", (PyCFunction) findUpgradeSet, METH_VARARGS, NULL },
    00988     { "headerFromPackage", (PyCFunction) rpmHeaderFromPackage, METH_VARARGS, NULL },
    00989     { "headerLoad", (PyCFunction) hdrLoad, METH_VARARGS, NULL },
    00990     { "rhnLoad", (PyCFunction) rhnLoad, METH_VARARGS, NULL },
    00991     { "initdb", (PyCFunction) rpmInitDB, METH_VARARGS, NULL },
    00992     { "opendb", (PyCFunction) rpmOpenDB, METH_VARARGS, NULL },
    00993     { "rebuilddb", (PyCFunction) rebuildDB, METH_VARARGS, NULL },
    00994     { "mergeHeaderListFromFD", (PyCFunction) rpmMergeHeadersFromFD, METH_VARARGS, NULL },
    00995     { "readHeaderListFromFD", (PyCFunction) rpmHeaderFromFD, METH_VARARGS, NULL },
    00996     { "readHeaderListFromFile", (PyCFunction) rpmHeaderFromFile, METH_VARARGS, NULL },
    00997     { "errorSetCallback", (PyCFunction) errorSetCallback, METH_VARARGS, NULL },
    00998     { "errorString", (PyCFunction) errorString, METH_VARARGS, NULL },
    00999     { "versionCompare", (PyCFunction) versionCompare, METH_VARARGS, NULL },
    01000     { "labelCompare", (PyCFunction) labelCompare, METH_VARARGS, NULL },
    01001     { "checksig", (PyCFunction) checkSig, METH_VARARGS, NULL },
    01002     { "getTransactionCallbackHeader", (PyCFunction) getTsHeader, METH_VARARGS, NULL },
    01003 /*      { "Fopen", (PyCFunction) doFopen, METH_VARARGS, NULL }, */
    01004     { "setVerbosity", (PyCFunction) setVerbosity, METH_VARARGS, NULL },
    01005     { NULL }
    01006 } ;
    01007
    01010 void initrpm(void) {
    01011     PyObject * m, * d, *o, * tag = NULL, * dict;
    01012     int i;
    01013     const struct headerSprintfExtension_s * extensions = rpmHeaderFormats;
    01014     struct headerSprintfExtension_s * ext;
    01015
    01016     m = Py_InitModule("rpm", rpmModuleMethods);
    01017
    01018     hdrType.ob_type = &PyType_Type;
    01019     rpmdbMIType.ob_type = &PyType_Type;
    01020     rpmdbType.ob_type = &PyType_Type;
    01021     rpmtransType.ob_type = &PyType_Type;
    01022
    01023     if(!m)
    01024         return;
    01025
    01026 /*      _rpmio_debug = -1; */
    01027     rpmReadConfigFiles(NULL, NULL);
    01028
    01029     d = PyModule_GetDict(m);
    01030
    01031     pyrpmError = PyString_FromString("rpm.error");
    01032     PyDict_SetItemString(d, "error", pyrpmError);
    01033     Py_DECREF(pyrpmError);
    01034
    01035     dict = PyDict_New();
    01036
    01037     for (i = 0; i < rpmTagTableSize; i++) {
    01038         tag = PyInt_FromLong(rpmTagTable[i].val);
    01039         PyDict_SetItemString(d, (char *) rpmTagTable[i].name, tag);
    01040         Py_DECREF(tag);
    01041         PyDict_SetItem(dict, tag, o=PyString_FromString(rpmTagTable[i].name + 7));
    01042         Py_DECREF(o);
    01043     }
    01044
    01045     while (extensions->name) {
    01046         if (extensions->type == HEADER_EXT_TAG) {
    01047             (const struct headerSprintfExtension *) ext = extensions;
    01048             PyDict_SetItemString(d, extensions->name, o=PyCObject_FromVoidPtr(ext, NULL));
    01049             Py_DECREF(o);
    01050             PyDict_SetItem(dict, tag, o=PyString_FromString(ext->name + 7));
    01051             Py_DECREF(o);
    01052         }
    01053         extensions++;
    01054     }
    01055
    01056     PyDict_SetItemString(d, "tagnames", dict);
    01057     Py_DECREF(dict);
    01058
    01059
    01060 #define REGISTER_ENUM(val) \
    01061     PyDict_SetItemString(d, #val, o=PyInt_FromLong( val )); \
    01062     Py_DECREF(o);
    01063
    01064     REGISTER_ENUM(RPMFILE_STATE_NORMAL);
    01065     REGISTER_ENUM(RPMFILE_STATE_REPLACED);
    01066     REGISTER_ENUM(RPMFILE_STATE_NOTINSTALLED);
    01067     REGISTER_ENUM(RPMFILE_STATE_NETSHARED);
    01068
    01069     REGISTER_ENUM(RPMFILE_CONFIG);
    01070     REGISTER_ENUM(RPMFILE_DOC);
    01071     REGISTER_ENUM(RPMFILE_MISSINGOK);
    01072     REGISTER_ENUM(RPMFILE_NOREPLACE);
    01073     REGISTER_ENUM(RPMFILE_GHOST);
    01074     REGISTER_ENUM(RPMFILE_LICENSE);
    01075     REGISTER_ENUM(RPMFILE_README);
    01076
    01077     REGISTER_ENUM(RPMDEP_SENSE_REQUIRES);
    01078     REGISTER_ENUM(RPMDEP_SENSE_CONFLICTS);
    01079
    01080     REGISTER_ENUM(RPMSENSE_SERIAL);
    01081     REGISTER_ENUM(RPMSENSE_LESS);
    01082     REGISTER_ENUM(RPMSENSE_GREATER);
    01083     REGISTER_ENUM(RPMSENSE_EQUAL);
    01084     REGISTER_ENUM(RPMSENSE_PREREQ);
    01085     REGISTER_ENUM(RPMSENSE_INTERP);
    01086     REGISTER_ENUM(RPMSENSE_SCRIPT_PRE);
    01087     REGISTER_ENUM(RPMSENSE_SCRIPT_POST);
    01088     REGISTER_ENUM(RPMSENSE_SCRIPT_PREUN);
    01089     REGISTER_ENUM(RPMSENSE_SCRIPT_POSTUN);
    01090     REGISTER_ENUM(RPMSENSE_SCRIPT_VERIFY);
    01091     REGISTER_ENUM(RPMSENSE_FIND_REQUIRES);
    01092     REGISTER_ENUM(RPMSENSE_FIND_PROVIDES);
    01093     REGISTER_ENUM(RPMSENSE_TRIGGERIN);
    01094     REGISTER_ENUM(RPMSENSE_TRIGGERUN);
    01095     REGISTER_ENUM(RPMSENSE_TRIGGERPOSTUN);
    01096     REGISTER_ENUM(RPMSENSE_MULTILIB);
    01097     REGISTER_ENUM(RPMSENSE_SCRIPT_PREP);
    01098     REGISTER_ENUM(RPMSENSE_SCRIPT_BUILD);
    01099     REGISTER_ENUM(RPMSENSE_SCRIPT_INSTALL);
    01100     REGISTER_ENUM(RPMSENSE_SCRIPT_CLEAN);
    01101     REGISTER_ENUM(RPMSENSE_RPMLIB);
    01102     REGISTER_ENUM(RPMSENSE_TRIGGERPREIN);
    01103
    01104     REGISTER_ENUM(RPMTRANS_FLAG_TEST);
    01105     REGISTER_ENUM(RPMTRANS_FLAG_BUILD_PROBS);
    01106     REGISTER_ENUM(RPMTRANS_FLAG_NOSCRIPTS);
    01107     REGISTER_ENUM(RPMTRANS_FLAG_JUSTDB);
    01108     REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERS);
    01109     REGISTER_ENUM(RPMTRANS_FLAG_NODOCS);
    01110     REGISTER_ENUM(RPMTRANS_FLAG_ALLFILES);
    01111     REGISTER_ENUM(RPMTRANS_FLAG_KEEPOBSOLETE);
    01112     REGISTER_ENUM(RPMTRANS_FLAG_MULTILIB);
    01113
    01114     REGISTER_ENUM(RPMPROB_FILTER_IGNOREOS);
    01115     REGISTER_ENUM(RPMPROB_FILTER_IGNOREARCH);
    01116     REGISTER_ENUM(RPMPROB_FILTER_REPLACEPKG);
    01117     REGISTER_ENUM(RPMPROB_FILTER_FORCERELOCATE);
    01118     REGISTER_ENUM(RPMPROB_FILTER_REPLACENEWFILES);
    01119     REGISTER_ENUM(RPMPROB_FILTER_REPLACEOLDFILES);
    01120     REGISTER_ENUM(RPMPROB_FILTER_OLDPACKAGE);
    01121     REGISTER_ENUM(RPMPROB_FILTER_DISKSPACE);
    01122     REGISTER_ENUM(RPMPROB_FILTER_DISKNODES);
    01123
    01124     REGISTER_ENUM(RPMCALLBACK_INST_PROGRESS);
    01125     REGISTER_ENUM(RPMCALLBACK_INST_START);
    01126     REGISTER_ENUM(RPMCALLBACK_INST_OPEN_FILE);
    01127     REGISTER_ENUM(RPMCALLBACK_INST_CLOSE_FILE);
    01128     REGISTER_ENUM(RPMCALLBACK_TRANS_PROGRESS);
    01129     REGISTER_ENUM(RPMCALLBACK_TRANS_START);
    01130     REGISTER_ENUM(RPMCALLBACK_TRANS_STOP);
    01131     REGISTER_ENUM(RPMCALLBACK_UNINST_PROGRESS);
    01132     REGISTER_ENUM(RPMCALLBACK_UNINST_START);
    01133     REGISTER_ENUM(RPMCALLBACK_UNINST_STOP);
    01134     REGISTER_ENUM(RPMCALLBACK_UNPACK_ERROR);
    01135     REGISTER_ENUM(RPMCALLBACK_CPIO_ERROR);
    01136
    01137     REGISTER_ENUM(RPMPROB_BADARCH);
    01138     REGISTER_ENUM(RPMPROB_BADOS);
    01139     REGISTER_ENUM(RPMPROB_PKG_INSTALLED);
    01140     REGISTER_ENUM(RPMPROB_BADRELOCATE);
    01141     REGISTER_ENUM(RPMPROB_REQUIRES);
    01142     REGISTER_ENUM(RPMPROB_CONFLICT);
    01143     REGISTER_ENUM(RPMPROB_NEW_FILE_CONFLICT);
    01144     REGISTER_ENUM(RPMPROB_FILE_CONFLICT);
    01145     REGISTER_ENUM(RPMPROB_OLDPACKAGE);
    01146     REGISTER_ENUM(RPMPROB_DISKSPACE);
    01147     REGISTER_ENUM(RPMPROB_DISKNODES);
    01148     REGISTER_ENUM(RPMPROB_BADPRETRANS);
    01149
    01150     REGISTER_ENUM(CHECKSIG_PGP);
    01151     REGISTER_ENUM(CHECKSIG_GPG);
    01152     REGISTER_ENUM(CHECKSIG_MD5);
    01153
    01154     REGISTER_ENUM(RPMLOG_EMERG);
    01155     REGISTER_ENUM(RPMLOG_ALERT);
    01156     REGISTER_ENUM(RPMLOG_CRIT);
    01157     REGISTER_ENUM(RPMLOG_ERR);
    01158     REGISTER_ENUM(RPMLOG_WARNING);
    01159     REGISTER_ENUM(RPMLOG_NOTICE);
    01160     REGISTER_ENUM(RPMLOG_INFO);
    01161     REGISTER_ENUM(RPMLOG_DEBUG);
    01162
    01163     REGISTER_ENUM(RPMMIRE_DEFAULT);
    01164     REGISTER_ENUM(RPMMIRE_STRCMP);
    01165     REGISTER_ENUM(RPMMIRE_REGEX);
    01166     REGISTER_ENUM(RPMMIRE_GLOB);
    01167
    01168 }
    01169