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

# python/rpmts-py.c

Go to the documentation of this file.

    00001
    00005 #include "system.h"
    00006
    00007 #include <rpmio_internal.h>     /* XXX for fdSetOpen */
    00008
    00009 #define _RPMPS_INTERNAL /* XXX almost (but not quite) opaque. */
    00010 #include <rpmcli.h>
    00011 #include <rpmpgp.h>
    00012 #include <rpmdb.h>
    00013 #include <pkgio.h>              /* XXX headerCheck() */
    00014 #include <rpmbuild.h>
    00015
    00016 #include "header-py.h"
    00017 #include "rpmds-py.h"   /* XXX for rpmdsNew */
    00018 #include "rpmfi-py.h"   /* XXX for rpmfiNew */
    00019 #include "rpmmi-py.h"
    00020 #include "rpmps-py.h"
    00021 #include "rpmte-py.h"
    00022 #include "spec-py.h"
    00023
    00024 #include "rpmts-py.h"
    00025
    00026 #include "debug.h"
    00027
    00028 /*@unchecked@*/
    00029 /*@-shadow@*/
    00030 extern int _rpmts_debug;
    00031 /*@=shadow@*/
    00032
    00033 /*@access alKey @*/
    00034 /*@access FD_t @*/
    00035 /*@access Header @*/
    00036 /*@access rpmal @*/
    00037 /*@access rpmdb @*/
    00038 /*@access rpmds @*/
    00039 /*@access rpmts @*/
    00040 /*@access rpmtsi @*/
    00041
    00162 struct rpmtsCallbackType_s {
    00163     PyObject * cb;
    00164     PyObject * data;
    00165     rpmtsObject * tso;
    00166     rpmdsObject * dso;
    00167     int pythonError;
    00168     PyThreadState *_save;
    00169 };
    00170
    00173 static int
    00174 rpmts_SolveCallback(rpmts ts, rpmds ds, const void * data)
    00175         /*@*/
    00176 {
    00177     struct rpmtsCallbackType_s * cbInfo = (struct rpmtsCallbackType_s *) data;
    00178     PyObject * args, * result;
    00179     int res = 1;
    00180
    00181 if (_rpmts_debug)
    00182 fprintf(stderr, "*** rpmts_SolveCallback(%p,%p,%p) \"%s\"\n", ts, ds, data, rpmdsDNEVR(ds));
    00183
    00184     if (cbInfo->tso == NULL) return res;
    00185     if (cbInfo->pythonError) return res;
    00186     if (cbInfo->cb == Py_None) return res;
    00187
    00188     PyEval_RestoreThread(cbInfo->_save);
    00189
    00190     cbInfo->dso = rpmds_Wrap(ds);       /* XXX perhaps persistent? */
    00191     args = Py_BuildValue("(OO)", cbInfo->tso, cbInfo->dso);
    00192     result = PyEval_CallObject(cbInfo->cb, args);
    00193     Py_DECREF(cbInfo->dso);
    00194     cbInfo->dso = NULL;
    00195     Py_DECREF(args);
    00196
    00197     if (!result) {
    00198         cbInfo->pythonError = 1;
    00199     } else {
    00200         if (PyInt_Check(result))
    00201             res = PyInt_AsLong(result);
    00202         Py_DECREF(result);
    00203     }
    00204
    00205     cbInfo->_save = PyEval_SaveThread();
    00206
    00207     return res;
    00208 }
    00209
    00212 /*@null@*/
    00213 static void *
    00214 rpmtsCallback(/*@unused@*/ const void * hd, const rpmCallbackType what,
    00215                          const uint64_t amount, const uint64_t total,
    00216                          const void * pkgKey, rpmCallbackData data)
    00217         /*@globals _Py_NoneStruct @*/
    00218         /*@modifies _Py_NoneStruct @*/
    00219 {
    00220 /*@-castexpose@*/
    00221     Header h = (Header) hd;
    00222 /*@=castexpose@*/
    00223     struct rpmtsCallbackType_s * cbInfo = data;
    00224     PyObject * pkgObj = (PyObject *) pkgKey;
    00225     PyObject * oh = NULL;
    00226     const char * origin = NULL;
    00227     PyObject * args, * result;
    00228     unsigned long oamount = amount;
    00229     unsigned long ototal = total;
    00230     static FD_t fd;
    00231
    00232     if (cbInfo->pythonError) return NULL;
    00233     if (cbInfo->cb == Py_None) return NULL;
    00234
    00235     /* Synthesize a python object for callback (if necessary). */
    00236     if (pkgObj == NULL) {
    00237         if (h) {
    00238             HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00239             he->tag = RPMTAG_NAME;
    00240             if (headerGet(h, he, 0)) {
    00241                 pkgObj = Py_BuildValue("s", he->p.str);
    00242                 he->p.ptr = _free(he->p.ptr);
    00243             } else {
    00244                 pkgObj = Py_None;
    00245                 Py_INCREF(pkgObj);
    00246             }
    00247         } else {
    00248             pkgObj = Py_None;
    00249             Py_INCREF(pkgObj);
    00250         }
    00251     } else {
    00252         Py_INCREF(pkgObj);
    00253         /* XXX yum has (h, rpmloc) tuple as pkgKey. Extract the path. */
    00254         if (!(PyTuple_Check(pkgObj) && PyArg_ParseTuple(pkgObj, "|Os", &oh, &origin)))
    00255             origin = NULL;
    00256         /* XXX clean up the path, yum paths start "//..." */
    00257         if (origin && origin[0] == '/' && origin[1] == '/')
    00258             origin++;
    00259     }
    00260
    00261     PyEval_RestoreThread(cbInfo->_save);
    00262
    00263     args = Py_BuildValue("(illOO)", what, oamount, ototal, pkgObj, cbInfo->data);
    00264     result = PyEval_CallObject(cbInfo->cb, args);
    00265     Py_DECREF(args);
    00266     Py_DECREF(pkgObj);
    00267
    00268     if (!result) {
    00269         cbInfo->pythonError = 1;
    00270         cbInfo->_save = PyEval_SaveThread();
    00271         return NULL;
    00272     }
    00273
    00274     if (what == RPMCALLBACK_INST_OPEN_FILE) {
    00275         int fdno;
    00276
    00277         if (!PyArg_Parse(result, "i", &fdno)) {
    00278             cbInfo->pythonError = 1;
    00279             cbInfo->_save = PyEval_SaveThread();
    00280             return NULL;
    00281         }
    00282         Py_DECREF(result);
    00283         cbInfo->_save = PyEval_SaveThread();
    00284
    00285         fd = fdDup(fdno);
    00286 if (_rpmts_debug)
    00287 fprintf(stderr, "\t%p = fdDup(%d)\n", fd, fdno);
    00288
    00289         fcntl(Fileno(fd), F_SETFD, FD_CLOEXEC);
    00290
    00291         if (origin != NULL)
    00292             (void) fdSetOpen(fd, origin, 0, 0);
    00293
    00294         return fd;
    00295     } else
    00296     if (what == RPMCALLBACK_INST_CLOSE_FILE) {
    00297 if (_rpmts_debug)
    00298 fprintf(stderr, "\tFclose(%p)\n", fd);
    00299         Fclose (fd);
    00300     } else {
    00301 if (_rpmts_debug)
    00302 fprintf(stderr, "\t%lu:%lu key %p\n", oamount, ototal, pkgKey);
    00303     }
    00304
    00305     Py_DECREF(result);
    00306     cbInfo->_save = PyEval_SaveThread();
    00307
    00308     return NULL;
    00309 }
    00310
    00311 #if Py_TPFLAGS_HAVE_ITER
    00312
    00314 static PyObject *
    00315 rpmts_iter(rpmtsObject * s)
    00316         /*@*/
    00317 {
    00318 if (_rpmts_debug)
    00319 fprintf(stderr, "*** rpmts_iter(%p) ts %p\n", s, s->ts);
    00320
    00321     Py_INCREF(s);
    00322     return (PyObject *)s;
    00323 }
    00324 #endif
    00325
    00329 /*@null@*/
    00330 static PyObject *
    00331 rpmts_iternext(rpmtsObject * s)
    00332         /*@modifies s @*/
    00333 {
    00334     PyObject * result = NULL;
    00335     rpmte te;
    00336
    00337 if (_rpmts_debug)
    00338 fprintf(stderr, "*** rpmts_iternext(%p) ts %p tsi %p %d\n", s, s->ts, s->tsi, s->tsiFilter);
    00339
    00340     /* Reset iterator on 1st entry. */
    00341     if (s->tsi == NULL) {
    00342         s->tsi = rpmtsiInit(s->ts);
    00343         if (s->tsi == NULL)
    00344             return NULL;
    00345         s->tsiFilter = 0;
    00346     }
    00347
    00348     te = rpmtsiNext(s->tsi, s->tsiFilter);
    00349 /*@-branchstate@*/
    00350     if (te != NULL) {
    00351         result = (PyObject *) rpmte_Wrap(te);
    00352     } else {
    00353         s->tsi = rpmtsiFree(s->tsi);
    00354         s->tsiFilter = 0;
    00355     }
    00356 /*@=branchstate@*/
    00357
    00358     return result;
    00359 }
    00360
    00365
    00368 /*@null@*/
    00369 static PyObject *
    00370 rpmts_Debug(/*@unused@*/ rpmtsObject * s, PyObject * args, PyObject * kwds)
    00371         /*@globals _Py_NoneStruct @*/
    00372         /*@modifies _Py_NoneStruct @*/
    00373 {
    00374     char * kwlist[] = {"debugLevel", NULL};
    00375
    00376     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:Debug", kwlist,
    00377             &_rpmts_debug))
    00378         return NULL;
    00379
    00380 if (_rpmts_debug < 0)
    00381 fprintf(stderr, "*** rpmts_Debug(%p) ts %p\n", s, s->ts);
    00382
    00383     Py_INCREF(Py_None);
    00384     return Py_None;
    00385 }
    00386
    00389 /*@null@*/
    00390 static PyObject *
    00391 rpmts_AddInstall(rpmtsObject * s, PyObject * args, PyObject * kwds)
    00392         /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
    00393         /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
    00394 {
    00395     hdrObject * h;
    00396     PyObject * key;
    00397     char * how = "u";   /* XXX default to upgrade element if missing */
    00398     int isUpgrade = 0;
    00399     char * kwlist[] = {"header", "key", "how", NULL};
    00400
    00401     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O|s:AddInstall", kwlist,
    00402             &hdr_Type, &h, &key, &how))
    00403         return NULL;
    00404
    00405     {   PyObject * hObj = (PyObject *) h;
    00406         if (hObj->ob_type != &hdr_Type) {
    00407             PyErr_SetString(PyExc_TypeError, "bad type for header argument");
    00408             return NULL;
    00409         }
    00410     }
    00411
    00412 if (_rpmts_debug < 0 || (_rpmts_debug > 0 && *how != 'a'))
    00413 fprintf(stderr, "*** rpmts_AddInstall(%p,%p,%p,%s) ts %p\n", s, h, key, how, s->ts);
    00414
    00415     if (how && strcmp(how, "a") && strcmp(how, "u") && strcmp(how, "i")) {
    00416         PyErr_SetString(PyExc_TypeError, "how argument must be \"u\", \"a\", or \"i\"");
    00417         return NULL;
    00418     } else if (how && !strcmp(how, "u"))
    00419         isUpgrade = 1;
    00420
    00421         rpmtsAddInstallElement(s->ts, hdrGetHeader(h), key, isUpgrade, NULL);
    00422
    00423     /* This should increment the usage count for me */
    00424     if (key)
    00425         PyList_Append(s->keyList, key);
    00426
    00427     Py_INCREF(Py_None);
    00428     return Py_None;
    00429 }
    00430
    00434 /*@null@*/
    00435 static PyObject *
    00436 rpmts_AddErase(rpmtsObject * s, PyObject * args, PyObject * kwds)
    00437         /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
    00438         /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
    00439 {
    00440     PyObject * o;
    00441     int count;
    00442     rpmdbMatchIterator mi;
    00443     char * kwlist[] = {"name", NULL};
    00444
    00445 if (_rpmts_debug)
    00446 fprintf(stderr, "*** rpmts_AddErase(%p) ts %p\n", s, s->ts);
    00447
    00448     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:AddErase", kwlist, &o))
    00449         return NULL;
    00450
    00451     if (PyString_Check(o) || PyUnicode_Check(o)) {
    00452         char * name = PyString_AsString(o);
    00453
    00454         mi = rpmtsInitIterator(s->ts, RPMDBI_LABEL, name, 0);
    00455         count = rpmdbGetIteratorCount(mi);
    00456         if (count <= 0) {
    00457             mi = rpmdbFreeIterator(mi);
    00458             PyErr_SetString(pyrpmError, "package not installed");
    00459             return NULL;
    00460         } else { /* XXX: Note that we automatically choose to remove all matches */
    00461             Header h;
    00462             while ((h = rpmdbNextIterator(mi)) != NULL) {
    00463                 unsigned int recOffset = rpmdbGetIteratorOffset(mi);
    00464                 if (recOffset)
    00465                     rpmtsAddEraseElement(s->ts, h, recOffset);
    00466             }
    00467         }
    00468         mi = rpmdbFreeIterator(mi);
    00469     } else
    00470     if (PyInt_Check(o)) {
    00471         uint32_t instance = PyInt_AsLong(o);
    00472
    00473         mi = rpmtsInitIterator(s->ts, RPMDBI_PACKAGES, &instance, sizeof(instance));
    00474         if (instance == 0 || mi == NULL) {
    00475             mi = rpmdbFreeIterator(mi);
    00476             PyErr_SetString(pyrpmError, "package not installed");
    00477             return NULL;
    00478         } else {
    00479             Header h;
    00480             while ((h = rpmdbNextIterator(mi)) != NULL) {
    00481                 uint32_t recOffset = rpmdbGetIteratorOffset(mi);
    00482                 if (recOffset)
    00483                     rpmtsAddEraseElement(s->ts, h, recOffset);
    00484                 break;
    00485             }
    00486         }
    00487         mi = rpmdbFreeIterator(mi);
    00488     }
    00489
    00490     Py_INCREF(Py_None);
    00491     return Py_None;
    00492 }
    00493
    00496 /*@null@*/
    00497 static PyObject *
    00498 rpmts_Check(rpmtsObject * s, PyObject * args, PyObject * kwds)
    00499         /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
    00500         /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
    00501 {
    00502     rpmps ps;
    00503     rpmProblem p;
    00504     PyObject * list, * cf;
    00505     struct rpmtsCallbackType_s cbInfo;
    00506     int i;
    00507     int xx;
    00508     char * kwlist[] = {"callback", NULL};
    00509
    00510     memset(&cbInfo, 0, sizeof(cbInfo));
    00511     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:Check", kwlist,
    00512             &cbInfo.cb))
    00513         return NULL;
    00514
    00515     if (cbInfo.cb != NULL) {
    00516         if (!PyCallable_Check(cbInfo.cb)) {
    00517             PyErr_SetString(PyExc_TypeError, "expected a callable");
    00518             return NULL;
    00519         }
    00520         xx = rpmtsSetSolveCallback(s->ts, rpmts_SolveCallback, (void *)&cbInfo);
    00521     }
    00522
    00523 if (_rpmts_debug)
    00524 fprintf(stderr, "*** rpmts_Check(%p) ts %p cb %p\n", s, s->ts, cbInfo.cb);
    00525
    00526     cbInfo.tso = s;
    00527     cbInfo.dso = NULL;          /* XXX perhaps persistent? */
    00528     cbInfo.pythonError = 0;
    00529     cbInfo._save = PyEval_SaveThread();
    00530
    00531     xx = rpmtsCheck(s->ts);
    00532     ps = rpmtsProblems(s->ts);
    00533
    00534     if (cbInfo.cb)
    00535         xx = rpmtsSetSolveCallback(s->ts, rpmtsSolve, NULL);
    00536
    00537     PyEval_RestoreThread(cbInfo._save);
    00538
    00539     if (ps != NULL) {
    00540         list = PyList_New(0);
    00541         rpmpsi psi = rpmpsInitIterator(ps);
    00542
    00543         while ((i = rpmpsNextIterator(psi)) >= 0) {
    00544 #ifdef  DYING
    00545             cf = Py_BuildValue("((sss)(ss)iOi)", conflicts[i].byName,
    00546                                conflicts[i].byVersion, conflicts[i].byRelease,
    00547
    00548                                conflicts[i].needsName,
    00549                                conflicts[i].needsVersion,
    00550
    00551                                conflicts[i].needsFlags,
    00552                                conflicts[i].suggestedPkgs ?
    00553                                    conflicts[i].suggestedPkgs[0] : Py_None,
    00554                                conflicts[i].sense);
    00555 #else
    00556             char * byName, * byVersion, * byRelease, *byArch;
    00557             char * needsName, * needsOP, * needsVersion;
    00558             char * a, * b;
    00559             int needsFlags, sense;
    00560             fnpyKey key;
    00561
    00562             p = rpmpsProblem(psi);
    00563
    00564             /* XXX autorelocated i386 on ia64, fix system-config-packages! */
    00565             if (rpmProblemGetType(p) == RPMPROB_BADRELOCATE)
    00566                 continue;
    00567
    00568             a = byName = xstrdup(rpmProblemGetPkgNEVR(p));
    00569             if ((byArch= strrchr(byName, '.')) != NULL)
    00570                 *byArch++ = '\0';
    00571             if ((byRelease = strrchr(byName, '-')) != NULL)
    00572                 *byRelease++ = '\0';
    00573             if ((byVersion = strrchr(byName, '-')) != NULL)
    00574                 *byVersion++ = '\0';
    00575
    00576             key = rpmProblemKey(p);
    00577
    00578             b = needsName = xstrdup(rpmProblemGetAltNEVR(p));
    00579             if (needsName[1] == ' ') {
    00580                 sense = (needsName[0] == 'C')
    00581                         ? RPMDEP_SENSE_CONFLICTS : RPMDEP_SENSE_REQUIRES;
    00582                 needsName += 2;
    00583             } else
    00584                 sense = RPMDEP_SENSE_REQUIRES;
    00585             if ((needsVersion = strrchr(needsName, ' ')) != NULL)
    00586                 *needsVersion++ = '\0';
    00587
    00588             needsFlags = 0;
    00589             if ((needsOP = strrchr(needsName, ' ')) != NULL) {
    00590                 for (*needsOP++ = '\0'; *needsOP != '\0'; needsOP++) {
    00591                     if (*needsOP == '<')        needsFlags |= RPMSENSE_LESS;
    00592                     else if (*needsOP == '>')   needsFlags |= RPMSENSE_GREATER;
    00593                     else if (*needsOP == '=')   needsFlags |= RPMSENSE_EQUAL;
    00594                 }
    00595             }
    00596
    00597             cf = Py_BuildValue("((sss)(ss)iOi)", byName, byVersion, byRelease,
    00598                                needsName, needsVersion, needsFlags,
    00599                                (key != NULL ? key : Py_None),
    00600                                sense);
    00601             a = _free(a);
    00602             b = _free(b);
    00603 #endif
    00604             PyList_Append(list, (PyObject *) cf);
    00605             Py_DECREF(cf);
    00606         }
    00607
    00608         psi = rpmpsFreeIterator(psi);
    00609         ps = rpmpsFree(ps);
    00610
    00611         return list;
    00612     }
    00613
    00614     Py_INCREF(Py_None);
    00615     return Py_None;
    00616 }
    00617
    00620 /*@null@*/
    00621 static PyObject *
    00622 rpmts_Order(rpmtsObject * s)
    00623         /*@globals rpmGlobalMacroContext @*/
    00624         /*@modifies s, rpmGlobalMacroContext @*/
    00625 {
    00626     int rc;
    00627
    00628 if (_rpmts_debug)
    00629 fprintf(stderr, "*** rpmts_Order(%p) ts %p\n", s, s->ts);
    00630
    00631     Py_BEGIN_ALLOW_THREADS
    00632     rc = rpmtsOrder(s->ts);
    00633     Py_END_ALLOW_THREADS
    00634
    00635     return Py_BuildValue("i", rc);
    00636 }
    00637
    00640 /*@null@*/
    00641 static PyObject *
    00642 rpmts_Clean(rpmtsObject * s)
    00643         /*@globals _Py_NoneStruct @*/
    00644         /*@modifies s, _Py_NoneStruct @*/
    00645 {
    00646 if (_rpmts_debug)
    00647 fprintf(stderr, "*** rpmts_Clean(%p) ts %p\n", s, s->ts);
    00648
    00649     rpmtsClean(s->ts);
    00650
    00651     Py_INCREF(Py_None);
    00652     return Py_None;
    00653 }
    00654
    00657 /*@null@*/
    00658 static PyObject *
    00659 rpmts_IDTXload(rpmtsObject * s, PyObject * args, PyObject * kwds)
    00660         /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
    00661         /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
    00662 {
    00663     PyObject * result = NULL;
    00664     rpmTag tag = RPMTAG_INSTALLTID;
    00665     char * kwlist[] = {"rbtid", NULL};
    00666     uint32_t rbtid = 0;
    00667     IDTX idtx;
    00668
    00669 if (_rpmts_debug)
    00670 fprintf(stderr, "*** rpmts_IDTXload(%p) ts %p\n", s, s->ts);
    00671
    00672     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:IDTXload", kwlist, &rbtid))
    00673         return NULL;
    00674
    00675     Py_BEGIN_ALLOW_THREADS
    00676     idtx = IDTXload(s->ts, tag, rbtid);
    00677     Py_END_ALLOW_THREADS
    00678
    00679 /*@-branchstate@*/
    00680     if (idtx == NULL || idtx->nidt <= 0) {
    00681         Py_INCREF(Py_None);
    00682         result = Py_None;
    00683     } else {
    00684         PyObject * tuple;
    00685         PyObject * ho;
    00686         IDT idt;
    00687         int i;
    00688
    00689         result = PyTuple_New(idtx->nidt);
    00690         for (i = 0; i < idtx->nidt; i++) {
    00691             idt = idtx->idt + i;
    00692             ho = (PyObject *) hdr_Wrap(idt->h);
    00693             tuple = Py_BuildValue("(iOi)", idt->val.u32, ho, idt->instance);
    00694             PyTuple_SET_ITEM(result,  i, tuple);
    00695             Py_DECREF(ho);
    00696         }
    00697     }
    00698 /*@=branchstate@*/
    00699
    00700     idtx = IDTXfree(idtx);
    00701
    00702     return result;
    00703 }
    00704
    00707 /*@null@*/
    00708 static PyObject *
    00709 rpmts_IDTXglob(rpmtsObject * s, PyObject * args, PyObject * kwds)
    00710         /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
    00711         /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
    00712 {
    00713     PyObject * result = NULL;
    00714     const char * globstr;
    00715     rpmTag tag = RPMTAG_REMOVETID;
    00716     char * kwlist[] = {"rbtid", NULL};
    00717     uint32_t rbtid = 0;
    00718     IDTX idtx;
    00719
    00720 if (_rpmts_debug)
    00721 fprintf(stderr, "*** rpmts_IDTXglob(%p) ts %p\n", s, s->ts);
    00722
    00723     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:IDTXglob", kwlist, &rbtid))
    00724         return NULL;
    00725
    00726     Py_BEGIN_ALLOW_THREADS
    00727     globstr = rpmExpand("%{_repackage_dir}/*.rpm", NULL);
    00728     idtx = IDTXglob(s->ts, globstr, tag, rbtid);
    00729     globstr = _free(globstr);
    00730     Py_END_ALLOW_THREADS
    00731
    00732 /*@-branchstate@*/
    00733     if (idtx == NULL || idtx->nidt <= 0) {
    00734         Py_INCREF(Py_None);
    00735         result = Py_None;
    00736     } else {
    00737         PyObject * tuple;
    00738         PyObject * ho;
    00739         IDT idt;
    00740         int i;
    00741
    00742         result = PyTuple_New(idtx->nidt);
    00743         for (i = 0; i < idtx->nidt; i++) {
    00744             idt = idtx->idt + i;
    00745             ho = (PyObject *) hdr_Wrap(idt->h);
    00746             tuple = Py_BuildValue("(iOs)", idt->val.u32, ho, idt->key);
    00747             PyTuple_SET_ITEM(result,  i, tuple);
    00748             Py_DECREF(ho);
    00749         }
    00750     }
    00751 /*@=branchstate@*/
    00752
    00753     idtx = IDTXfree(idtx);
    00754
    00755     return result;
    00756 }
    00757
    00760 /*@null@*/
    00761 static PyObject *
    00762 rpmts_Rollback(rpmtsObject * s, PyObject * args, PyObject * kwds)
    00763         /*@globals rpmGlobalMacroContext @*/
    00764         /*@modifies s, rpmGlobalMacroContext @*/
    00765 {
    00766     QVA_t ia = memset(alloca(sizeof(*ia)), 0, sizeof(*ia));
    00767     rpmtransFlags transFlags;
    00768     const char ** av = NULL;
    00769     uint32_t rbtid;
    00770     int rc;
    00771     char * kwlist[] = {"transactionId", NULL};
    00772
    00773 if (_rpmts_debug)
    00774 fprintf(stderr, "*** rpmts_Rollback(%p) ts %p\n", s, s->ts);
    00775
    00776     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:Rollback", kwlist, &rbtid))
    00777         return NULL;
    00778
    00779     Py_BEGIN_ALLOW_THREADS
    00780     ia->qva_flags = (VERIFY_DIGEST|VERIFY_SIGNATURE|VERIFY_HDRCHK);
    00781     ia->transFlags |= (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL);
    00782     ia->transFlags |= RPMTRANS_FLAG_NOFDIGESTS;
    00783     ia->installInterfaceFlags = (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL);
    00784     ia->rbtid = rbtid;
    00785     ia->relocations = NULL;
    00786     ia->probFilter |= RPMPROB_FILTER_OLDPACKAGE;
    00787
    00788     transFlags = rpmtsSetFlags(s->ts, ia->transFlags);
    00789     rc = rpmRollback(s->ts, ia, av);
    00790     transFlags = rpmtsSetFlags(s->ts, transFlags);
    00791     Py_END_ALLOW_THREADS
    00792
    00793     return Py_BuildValue("i", rc);
    00794 }
    00795
    00798 /*@null@*/
    00799 static PyObject *
    00800 rpmts_OpenDB(rpmtsObject * s)
    00801         /*@globals rpmGlobalMacroContext @*/
    00802         /*@modifies s, rpmGlobalMacroContext @*/
    00803 {
    00804
    00805 if (_rpmts_debug)
    00806 fprintf(stderr, "*** rpmts_OpenDB(%p) ts %p\n", s, s->ts);
    00807
    00808     if (rpmtsDBMode(s->ts) == -1)
    00809         (void) rpmtsSetDBMode(s->ts, O_RDONLY);
    00810
    00811     return Py_BuildValue("i", rpmtsOpenDB(s->ts, rpmtsDBMode(s->ts)));
    00812 }
    00813
    00816 /*@null@*/
    00817 static PyObject *
    00818 rpmts_CloseDB(rpmtsObject * s)
    00819         /*@modifies s @*/
    00820 {
    00821     int rc;
    00822
    00823 if (_rpmts_debug)
    00824 fprintf(stderr, "*** rpmts_CloseDB(%p) ts %p\n", s, s->ts);
    00825
    00826     rc = rpmtsCloseDB(s->ts);
    00827     (void) rpmtsSetDBMode(s->ts, -1);           /* XXX disable lazy opens */
    00828
    00829     return Py_BuildValue("i", rc);
    00830 }
    00831
    00834 /*@null@*/
    00835 static PyObject *
    00836 rpmts_InitDB(rpmtsObject * s)
    00837         /*@globals rpmGlobalMacroContext @*/
    00838         /*@modifies s, rpmGlobalMacroContext @*/
    00839 {
    00840     int rc;
    00841
    00842 if (_rpmts_debug)
    00843 fprintf(stderr, "*** rpmts_InitDB(%p) ts %p\n", s, s->ts);
    00844
    00845     rc = rpmtsInitDB(s->ts, O_RDONLY);
    00846     if (rc == 0)
    00847         rc = rpmtsCloseDB(s->ts);
    00848
    00849     return Py_BuildValue("i", rc);
    00850 }
    00851
    00854 /*@null@*/
    00855 static PyObject *
    00856 rpmts_RebuildDB(rpmtsObject * s)
    00857         /*@globals rpmGlobalMacroContext @*/
    00858         /*@modifies s, rpmGlobalMacroContext @*/
    00859 {
    00860     int rc;
    00861
    00862 if (_rpmts_debug)
    00863 fprintf(stderr, "*** rpmts_RebuildDB(%p) ts %p\n", s, s->ts);
    00864
    00865     Py_BEGIN_ALLOW_THREADS
    00866     rc = rpmtsRebuildDB(s->ts);
    00867     Py_END_ALLOW_THREADS
    00868
    00869     return Py_BuildValue("i", rc);
    00870 }
    00871
    00874 /*@null@*/
    00875 static PyObject *
    00876 rpmts_VerifyDB(rpmtsObject * s)
    00877         /*@globals rpmGlobalMacroContext @*/
    00878         /*@modifies s, rpmGlobalMacroContext @*/
    00879 {
    00880     int rc;
    00881
    00882 if (_rpmts_debug)
    00883 fprintf(stderr, "*** rpmts_VerifyDB(%p) ts %p\n", s, s->ts);
    00884
    00885     Py_BEGIN_ALLOW_THREADS
    00886     rc = rpmtsVerifyDB(s->ts);
    00887     Py_END_ALLOW_THREADS
    00888
    00889     return Py_BuildValue("i", rc);
    00890 }
    00891
    00894 /*@null@*/
    00895 static PyObject *
    00896 rpmts_HdrFromFdno(rpmtsObject * s, PyObject * args, PyObject * kwds)
    00897         /*@globals rpmGlobalMacroContext, fileSystem @*/
    00898         /*@modifies s, rpmGlobalMacroContext, fileSystem @*/
    00899 {
    00900     PyObject * result = NULL;
    00901     Header h;
    00902     FD_t fd;
    00903     int fdno;
    00904     rpmRC rpmrc;
    00905     char * kwlist[] = {"fd", NULL};
    00906
    00907     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:HdrFromFdno", kwlist,
    00908             &fdno))
    00909         return NULL;
    00910
    00911     fd = fdDup(fdno);
    00912     rpmrc = rpmReadPackageFile(s->ts, fd, "rpmts_HdrFromFdno", &h);
    00913     Fclose(fd);
    00914
    00915 if (_rpmts_debug)
    00916 fprintf(stderr, "*** rpmts_HdrFromFdno(%p) ts %p rc %d\n", s, s->ts, rpmrc);
    00917
    00918 /*@-branchstate@*/
    00919     switch (rpmrc) {
    00920     case RPMRC_OK:
    00921         if (h)
    00922             result = Py_BuildValue("N", hdr_Wrap(h));
    00923         h = headerFree(h);      /* XXX ref held by result */
    00924         break;
    00925
    00926     case RPMRC_NOKEY:
    00927         PyErr_SetString(pyrpmError, "public key not available");
    00928         break;
    00929
    00930     case RPMRC_NOTTRUSTED:
    00931         PyErr_SetString(pyrpmError, "public key not trusted");
    00932         break;
    00933
    00934     case RPMRC_NOTFOUND:
    00935     case RPMRC_FAIL:
    00936     default:
    00937         PyErr_SetString(pyrpmError, "error reading package header");
    00938         break;
    00939     }
    00940 /*@=branchstate@*/
    00941
    00942     return result;
    00943 }
    00944
    00947 /*@null@*/
    00948 static PyObject *
    00949 rpmts_HdrCheck(rpmtsObject * s, PyObject * args, PyObject * kwds)
    00950         /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
    00951         /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
    00952 {
    00953     PyObject * blob;
    00954     PyObject * result = NULL;
    00955     const char * msg = NULL;
    00956     const void * uh;
    00957     int uc;
    00958     pgpDig dig;
    00959     rpmRC rpmrc;
    00960     char * kwlist[] = {"headers", NULL};
    00961
    00962 if (_rpmts_debug)
    00963 fprintf(stderr, "*** rpmts_HdrCheck(%p) ts %p\n", s, s->ts);
    00964
    00965     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:HdrCheck", kwlist, &blob))
    00966         return NULL;
    00967
    00968     if (blob == Py_None) {
    00969         Py_INCREF(Py_None);
    00970         return Py_None;
    00971     }
    00972     if (!(PyString_Check(blob) || PyUnicode_Check(blob))) {
    00973         PyErr_SetString(pyrpmError, "hdrCheck takes a string of octets");
    00974         return result;
    00975     }
    00976     uh = PyString_AsString(blob);
    00977     uc = PyString_Size(blob);
    00978
    00979     dig = pgpDigNew(rpmtsVSFlags(s->ts));
    00980     rpmrc = headerCheck(dig, uh, uc, &msg);
    00981     dig = pgpDigFree(dig);
    00982
    00983     switch (rpmrc) {
    00984     case RPMRC_OK:
    00985         Py_INCREF(Py_None);
    00986         result = Py_None;
    00987         break;
    00988
    00989     case RPMRC_NOKEY:
    00990         /* XXX note "availaiable", the script kiddies need the misspelling. */
    00991         PyErr_SetString(pyrpmError, "public key not availaiable");
    00992         break;
    00993
    00994     case RPMRC_NOTTRUSTED:
    00995         PyErr_SetString(pyrpmError, "public key not trusted");
    00996         break;
    00997
    00998     case RPMRC_FAIL:
    00999     default:
    01000         PyErr_SetString(pyrpmError, msg);
    01001         break;
    01002     }
    01003     msg = _free(msg);
    01004
    01005     return result;
    01006 }
    01007
    01010 static PyObject *
    01011 rpmts_GetVSFlags(rpmtsObject * s)
    01012 {
    01013     return Py_BuildValue("i", rpmtsVSFlags(s->ts));
    01014 }
    01015
    01018 /*@null@*/
    01019 static PyObject *
    01020 rpmts_SetVSFlags(rpmtsObject * s, PyObject * args, PyObject * kwds)
    01021         /*@modifies s @*/
    01022 {
    01023     rpmVSFlags vsflags;
    01024     char * kwlist[] = {"flags", NULL};
    01025
    01026 if (_rpmts_debug)
    01027 fprintf(stderr, "*** rpmts_SetVSFlags(%p) ts %p\n", s, s->ts);
    01028
    01029     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:SetVSFlags", kwlist,
    01030             &vsflags))
    01031         return NULL;
    01032
    01033     /* XXX FIXME: value check on vsflags, or build pure python object
    01034      * for it, and require an object of that type */
    01035
    01036     return Py_BuildValue("i", rpmtsSetVSFlags(s->ts, vsflags));
    01037 }
    01038
    01041 /*@null@*/
    01042 static PyObject *
    01043 rpmts_SetColor(rpmtsObject * s, PyObject * args, PyObject * kwds)
    01044         /*@modifies s @*/
    01045 {
    01046     uint32_t tscolor;
    01047     char * kwlist[] = {"color", NULL};
    01048
    01049 if (_rpmts_debug)
    01050 fprintf(stderr, "*** rpmts_SetColor(%p) ts %p\n", s, s->ts);
    01051
    01052     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:Color", kwlist, &tscolor))
    01053         return NULL;
    01054
    01055     /* XXX FIXME: value check on tscolor, or build pure python object
    01056      * for it, and require an object of that type */
    01057
    01058     return Py_BuildValue("i", rpmtsSetColor(s->ts, tscolor));
    01059 }
    01060
    01063 /*@null@*/
    01064 static PyObject *
    01065 rpmts_PgpPrtPkts(rpmtsObject * s, PyObject * args, PyObject * kwds)
    01066         /*@globals _Py_NoneStruct @*/
    01067         /*@modifies _Py_NoneStruct @*/
    01068 {
    01069     PyObject * blob;
    01070     unsigned char * pkt;
    01071     unsigned int pktlen;
    01072     int rc;
    01073     char * kwlist[] = {"octets", NULL};
    01074
    01075 if (_rpmts_debug)
    01076 fprintf(stderr, "*** rpmts_PgpPrtPkts(%p) ts %p\n", s, s->ts);
    01077
    01078     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:PgpPrtPkts", kwlist, &blob))
    01079         return NULL;
    01080
    01081     if (blob == Py_None) {
    01082         Py_INCREF(Py_None);
    01083         return Py_None;
    01084     }
    01085     if (!(PyString_Check(blob) || PyUnicode_Check(blob))) {
    01086         PyErr_SetString(pyrpmError, "pgpPrtPkts takes a string of octets");
    01087         return NULL;
    01088     }
    01089     pkt = (unsigned char *) PyString_AsString(blob);
    01090     pktlen = PyString_Size(blob);
    01091
    01092     rc = pgpPrtPkts(pkt, pktlen, NULL, 1);
    01093
    01094     return Py_BuildValue("i", rc);
    01095 }
    01096
    01099 /*@null@*/
    01100 static PyObject *
    01101 rpmts_PgpImportPubkey(rpmtsObject * s, PyObject * args, PyObject * kwds)
    01102         /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
    01103         /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
    01104 {
    01105     PyObject * blob;
    01106     unsigned char * pkt;
    01107     unsigned int pktlen;
    01108     int rc;
    01109     char * kwlist[] = {"pubkey", NULL};
    01110
    01111 if (_rpmts_debug)
    01112 fprintf(stderr, "*** rpmts_PgpImportPubkey(%p) ts %p\n", s, s->ts);
    01113
    01114     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:PgpImportPubkey",
    01115             kwlist, &blob))
    01116         return NULL;
    01117
    01118     if (blob == Py_None) {
    01119         Py_INCREF(Py_None);
    01120         return Py_None;
    01121     }
    01122     if (!(PyString_Check(blob) || PyUnicode_Check(blob))) {
    01123         PyErr_SetString(pyrpmError, "PgpImportPubkey takes a string of octets");
    01124         return NULL;
    01125     }
    01126     pkt = (unsigned char *) PyString_AsString(blob);
    01127     pktlen = PyString_Size(blob);
    01128
    01129     rc = rpmtsImportPubkey(s->ts, pkt, pktlen);
    01130
    01131     return Py_BuildValue("i", rc);
    01132 }
    01133
    01136 static PyObject *
    01137 rpmts_SetFlags(rpmtsObject * s, PyObject * args, PyObject * kwds)
    01138         /*@modifies s @*/
    01139 {
    01140     rpmtransFlags transFlags = 0;
    01141     char * kwlist[] = {"flags", NULL};
    01142
    01143     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:SetFlags", kwlist,
    01144             &transFlags))
    01145         return NULL;
    01146
    01147 if (_rpmts_debug)
    01148 fprintf(stderr, "*** rpmts_SetFlags(%p) ts %p transFlags 0x%x\n", s, s->ts, transFlags);
    01149
    01150     /* XXX FIXME: value check on flags, or build pure python object
    01151      * for it, and require an object of that type */
    01152
    01153     return Py_BuildValue("i", rpmtsSetFlags(s->ts, transFlags));
    01154 }
    01155
    01158 static PyObject *
    01159 rpmts_SetDFlags(rpmtsObject * s, PyObject * args, PyObject * kwds)
    01160         /*@modifies s @*/
    01161 {
    01162     rpmdepFlags depFlags = 0;
    01163     char * kwlist[] = {"flags", NULL};
    01164
    01165     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:SetDFlags", kwlist,
    01166             &depFlags))
    01167         return NULL;
    01168
    01169 if (_rpmts_debug)
    01170 fprintf(stderr, "*** rpmts_SetDFlags(%p) ts %p depFlags 0x%x\n", s, s->ts, depFlags);
    01171
    01172     /* XXX FIXME: value check on flags, or build pure python object
    01173      * for it, and require an object of that type */
    01174
    01175     return Py_BuildValue("i", rpmtsSetDFlags(s->ts, depFlags));
    01176 }
    01177
    01180 static PyObject *
    01181 rpmts_SetProbFilter(rpmtsObject * s, PyObject * args, PyObject * kwds)
    01182         /*@modifies s @*/
    01183 {
    01184     rpmprobFilterFlags ignoreSet = 0;
    01185     rpmprobFilterFlags oignoreSet;
    01186     char * kwlist[] = {"ignoreSet", NULL};
    01187
    01188     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:ProbFilter", kwlist,
    01189             &ignoreSet))
    01190         return NULL;
    01191
    01192 if (_rpmts_debug)
    01193 fprintf(stderr, "*** rpmts_SetProbFilter(%p) ts %p ignoreSet %x\n", s, s->ts, ignoreSet);
    01194
    01195     oignoreSet = s->ignoreSet;
    01196     s->ignoreSet = ignoreSet;
    01197
    01198     return Py_BuildValue("i", oignoreSet);
    01199 }
    01200
    01203 /*@null@*/
    01204 static rpmpsObject *
    01205 rpmts_Problems(rpmtsObject * s)
    01206         /*@modifies s @*/
    01207 {
    01208
    01209 if (_rpmts_debug)
    01210 fprintf(stderr, "*** rpmts_Problems(%p) ts %p\n", s, s->ts);
    01211
    01212     return rpmps_Wrap( rpmtsProblems(s->ts) );
    01213 }
    01214
    01217 static PyObject *
    01218 rpmts_Run(rpmtsObject * s, PyObject * args, PyObject * kwds)
    01219         /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
    01220         /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
    01221 {
    01222     int rc;
    01223     PyObject * list;
    01224     rpmps ps;
    01225     rpmpsi psi;
    01226     struct rpmtsCallbackType_s cbInfo;
    01227     char * kwlist[] = {"callback", "data", NULL};
    01228
    01229     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO:Run", kwlist,
    01230             &cbInfo.cb, &cbInfo.data))
    01231         return NULL;
    01232
    01233     cbInfo.tso = s;
    01234     cbInfo.dso = NULL;
    01235     cbInfo.pythonError = 0;
    01236     cbInfo._save = PyEval_SaveThread();
    01237
    01238     if (cbInfo.cb != NULL) {
    01239         if (!PyCallable_Check(cbInfo.cb)) {
    01240             PyErr_SetString(PyExc_TypeError, "expected a callable");
    01241             return NULL;
    01242         }
    01243         (void) rpmtsSetNotifyCallback(s->ts, rpmtsCallback, (void *) &cbInfo);
    01244     }
    01245
    01246     /* Initialize security context patterns (if not already done). */
    01247     if (rpmtsSELinuxEnabled(s->ts)
    01248      && !(rpmtsFlags(s->ts) & RPMTRANS_FLAG_NOCONTEXTS))
    01249     {
    01250         const char *fn = rpmGetPath("%{?_install_file_context_path}", NULL);
    01251         if (fn != NULL && *fn != '\0')
    01252             rc = matchpathcon_init(fn);
    01253             fn = _free(fn);
    01254     }
    01255
    01256 if (_rpmts_debug)
    01257 fprintf(stderr, "*** rpmts_Run(%p) ts %p ignore %x\n", s, s->ts, s->ignoreSet);
    01258
    01259     rc = rpmtsRun(s->ts, NULL, s->ignoreSet);
    01260     ps = rpmtsProblems(s->ts);
    01261
    01262     if (cbInfo.cb)
    01263         (void) rpmtsSetNotifyCallback(s->ts, NULL, NULL);
    01264
    01265     PyEval_RestoreThread(cbInfo._save);
    01266
    01267     if (cbInfo.pythonError) {
    01268         ps = rpmpsFree(ps);
    01269         return NULL;
    01270     }
    01271
    01272     if (rc < 0) {
    01273         list = PyList_New(0);
    01274         return list;
    01275     } else if (!rc) {
    01276         Py_INCREF(Py_None);
    01277         return Py_None;
    01278     }
    01279
    01280     list = PyList_New(0);
    01281     psi = rpmpsInitIterator(ps);
    01282     while (rpmpsNextIterator(psi) >= 0) {
    01283         rpmProblem p = rpmpsProblem(psi);
    01284         unsigned long ulong1 = p->ulong1;
    01285         PyObject * prob = Py_BuildValue("s(isN)", rpmProblemString(p),
    01286                              rpmProblemGetType(p),
    01287                              p->str1,
    01288                              PyLong_FromLongLong(ulong1));
    01289         PyList_Append(list, prob);
    01290         Py_DECREF(prob);
    01291     }
    01292     psi = rpmpsFreeIterator(psi);
    01293
    01294     ps = rpmpsFree(ps);
    01295
    01296     return list;
    01297 }
    01298
    01302 static PyObject *
    01303 rpmts_Next(rpmtsObject * s)
    01304         /*@globals _Py_NoneStruct @*/
    01305         /*@modifies s, _Py_NoneStruct @*/
    01306 {
    01307     PyObject * result;
    01308
    01309 if (_rpmts_debug)
    01310 fprintf(stderr, "*** rpmts_Next(%p) ts %p\n", s, s->ts);
    01311
    01312     result = rpmts_iternext(s);
    01313
    01314     if (result == NULL) {
    01315         Py_INCREF(Py_None);
    01316         return Py_None;
    01317     }
    01318
    01319     return result;
    01320 }
    01321
    01324 /*@null@*/
    01325 static specObject *
    01326 spec_Parse(rpmtsObject * s, PyObject * args, PyObject * kwds)
    01327         /*@globals rpmGlobalMacroContext @*/
    01328         /*@modifies s, rpmGlobalMacroContext @*/
    01329 {
    01330     const char * specfile;
    01331     Spec spec;
    01332     int recursing = 0;
    01333     char * passPhrase = "";
    01334     char *cookie = NULL;
    01335     int anyarch = 1;
    01336     int verify = 1;
    01337     int force = 1;
    01338     char * kwlist[] = {"specfile", NULL};
    01339
    01340     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:Parse", kwlist, &specfile))
    01341         return NULL;
    01342
    01343     if (parseSpec(s->ts, specfile,"/", recursing, passPhrase,
    01344              cookie, anyarch, force, verify)!=0) {
    01345              PyErr_SetString(pyrpmError, "can't parse specfile\n");
    01346                      return NULL;
    01347    }
    01348
    01349     spec = rpmtsSpec(s->ts);
    01350     return spec_Wrap(spec);
    01351 }
    01352
    01355 /*@null@*/
    01356 static rpmmiObject *
    01357 rpmts_Match(rpmtsObject * s, PyObject * args, PyObject * kwds)
    01358         /*@globals rpmGlobalMacroContext @*/
    01359         /*@modifies s, rpmGlobalMacroContext @*/
    01360 {
    01361     PyObject *TagN = NULL;
    01362     PyObject *Key = NULL;
    01363     char *key = NULL;
    01364 /* XXX lkey *must* be a 32 bit integer, int "works" on all known platforms. */
    01365     int lkey = 0;
    01366     int len = 0;
    01367     int tag = RPMDBI_PACKAGES;
    01368     char * kwlist[] = {"tagNumber", "key", NULL};
    01369
    01370 if (_rpmts_debug)
    01371 fprintf(stderr, "*** rpmts_Match(%p) ts %p\n", s, s->ts);
    01372
    01373     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:Match", kwlist,
    01374             &TagN, &Key))
    01375         return NULL;
    01376
    01377     if (TagN && (tag = tagNumFromPyObject (TagN)) == -1) {
    01378         PyErr_SetString(PyExc_TypeError, "unknown tag type");
    01379         return NULL;
    01380     }
    01381
    01382     if (Key) {
    01383 /*@-branchstate@*/
    01384         if (PyString_Check(Key) || PyUnicode_Check(Key)) {
    01385             key = PyString_AsString(Key);
    01386             len = PyString_Size(Key);
    01387         } else if (PyInt_Check(Key)) {
    01388             lkey = PyInt_AsLong(Key);
    01389             key = (char *)&lkey;
    01390             len = sizeof(lkey);
    01391         } else {
    01392             PyErr_SetString(PyExc_TypeError, "unknown key type");
    01393             return NULL;
    01394         }
    01395 /*@=branchstate@*/
    01396     }
    01397
    01398     /* XXX If not already opened, open the database O_RDONLY now. */
    01399     /* XXX FIXME: lazy default rdonly open also done by rpmtsInitIterator(). */
    01400     if (rpmtsGetRdb(s->ts) == NULL) {
    01401         int rc = rpmtsOpenDB(s->ts, O_RDONLY);
    01402         if (rc || rpmtsGetRdb(s->ts) == NULL) {
    01403             PyErr_SetString(PyExc_TypeError, "rpmdb open failed");
    01404             return NULL;
    01405         }
    01406     }
    01407
    01408     return rpmmi_Wrap( rpmtsInitIterator(s->ts, tag, key, len) );
    01409 }
    01410
    01415 /*@-fullinitblock@*/
    01416 /*@unchecked@*/ /*@observer@*/
    01417 static struct PyMethodDef rpmts_methods[] = {
    01418  {"Debug",      (PyCFunction)rpmts_Debug,       METH_VARARGS|METH_KEYWORDS,
    01419         NULL},
    01420
    01421  {"addInstall", (PyCFunction) rpmts_AddInstall, METH_VARARGS|METH_KEYWORDS,
    01422         NULL },
    01423  {"addErase",   (PyCFunction) rpmts_AddErase,   METH_VARARGS|METH_KEYWORDS,
    01424         NULL },
    01425  {"setDFlags",  (PyCFunction) rpmts_SetDFlags,  METH_VARARGS|METH_KEYWORDS,
    01426 "ts.setDFlags(depFlags) -> previous depFlags\n\
    01427 - Set control bit(s) for executing ts.check() and ts.order().\n" },
    01428  {"check",      (PyCFunction) rpmts_Check,      METH_VARARGS|METH_KEYWORDS,
    01429         NULL },
    01430  {"order",      (PyCFunction) rpmts_Order,      METH_NOARGS,
    01431         NULL },
    01432  {"setFlags",   (PyCFunction) rpmts_SetFlags,   METH_VARARGS|METH_KEYWORDS,
    01433 "ts.setFlags(transFlags) -> previous transFlags\n\
    01434 - Set control bit(s) for executing ts.run().\n\
    01435   Note: This method replaces the 1st argument to the old ts.run()\n" },
    01436  {"setProbFilter",      (PyCFunction) rpmts_SetProbFilter,      METH_VARARGS|METH_KEYWORDS,
    01437 "ts.setProbFilter(ignoreSet) -> previous ignoreSet\n\
    01438 - Set control bit(s) for ignoring problems found by ts.run().\n\
    01439   Note: This method replaces the 2nd argument to the old ts.run()\n" },
    01440  {"problems",   (PyCFunction) rpmts_Problems,   METH_NOARGS,
    01441 "ts.problems() -> ps\n\
    01442 - Return current problem set.\n" },
    01443  {"run",        (PyCFunction) rpmts_Run,        METH_VARARGS|METH_KEYWORDS,
    01444 "ts.run(callback, data) -> (problems)\n\
    01445 - Run a transaction set, returning list of problems found.\n\
    01446   Note: The callback may not be None.\n" },
    01447  {"clean",      (PyCFunction) rpmts_Clean,      METH_NOARGS,
    01448         NULL },
    01449  {"IDTXload",   (PyCFunction) rpmts_IDTXload,   METH_VARARGS|METH_KEYWORDS,
    01450 "ts.IDTXload(rbtid=iid) -> ((tid,hdr,instance)+)\n\
    01451 - Return list of installed packages reverse sorted by transaction id.\n" },
    01452  {"IDTXglob",   (PyCFunction) rpmts_IDTXglob,   METH_VARARGS|METH_KEYWORDS,
    01453 "ts.IDTXglob(rbtid=rid) -> ((tid,hdr,instance)+)\n\
    01454 - Return list of removed packages reverse sorted by transaction id.\n" },
    01455  {"rollback",   (PyCFunction) rpmts_Rollback,   METH_VARARGS|METH_KEYWORDS,
    01456         NULL },
    01457  {"openDB",     (PyCFunction) rpmts_OpenDB,     METH_NOARGS,
    01458 "ts.openDB() -> None\n\
    01459 - Open the default transaction rpmdb.\n\
    01460   Note: The transaction rpmdb is lazily opened, so ts.openDB() is seldom needed.\n" },
    01461  {"closeDB",    (PyCFunction) rpmts_CloseDB,    METH_NOARGS,
    01462 "ts.closeDB() -> None\n\
    01463 - Close the default transaction rpmdb.\n\
    01464   Note: ts.closeDB() disables lazy opens, and should hardly ever be used.\n" },
    01465  {"initDB",     (PyCFunction) rpmts_InitDB,     METH_NOARGS,
    01466 "ts.initDB() -> None\n\
    01467 - Initialize the default transaction rpmdb.\n\
    01468  Note: ts.initDB() is seldom needed anymore.\n" },
    01469  {"rebuildDB",  (PyCFunction) rpmts_RebuildDB,  METH_NOARGS,
    01470 "ts.rebuildDB() -> None\n\
    01471 - Rebuild the default transaction rpmdb.\n" },
    01472  {"verifyDB",   (PyCFunction) rpmts_VerifyDB,   METH_NOARGS,
    01473 "ts.verifyDB() -> None\n\
    01474 - Verify the default transaction rpmdb.\n" },
    01475  {"hdrFromFdno",(PyCFunction) rpmts_HdrFromFdno,METH_VARARGS|METH_KEYWORDS,
    01476 "ts.hdrFromFdno(fdno) -> hdr\n\
    01477 - Read a package header from a file descriptor.\n" },
    01478  {"hdrCheck",   (PyCFunction) rpmts_HdrCheck,   METH_VARARGS|METH_KEYWORDS,
    01479         NULL },
    01480 {"getVSFlags",(PyCFunction) rpmts_GetVSFlags,   METH_NOARGS,
    01481 "ts.getVSFlags() -> vsflags\n\
    01482 - Retrieve current signature verification flags from transaction\n" },
    01483  {"setVSFlags",(PyCFunction) rpmts_SetVSFlags,  METH_VARARGS|METH_KEYWORDS,
    01484 "ts.setVSFlags(vsflags) -> ovsflags\n\
    01485 - Set signature verification flags. Values for vsflags are:\n\
    01486     rpm.RPMVSF_NOHDRCHK      if set, don't check rpmdb headers\n\
    01487     rpm.RPMVSF_NEEDPAYLOAD   if not set, check header+payload (if possible)\n\
    01488     rpm.RPMVSF_NOSHA1HEADER  if set, don't check header SHA1 digest\n\
    01489     rpm.RPMVSF_NODSAHEADER   if set, don't check header DSA signature\n\
    01490     rpm.RPMVSF_NORSAHEADER   if set, don't check header RSA signature\n\
    01491     rpm.RPMVSF_NOMD5         if set, don't check header+payload MD5 digest\n\
    01492     rpm.RPMVSF_NODSA         if set, don't check header+payload DSA signature\n\
    01493     rpm.RPMVSF_NORSA         if set, don't check header+payload RSA signature\n\
    01494     rpm._RPMVSF_NODIGESTS    if set, don't check digest(s)\n\
    01495     rpm._RPMVSF_NOSIGNATURES if set, don't check signature(s)\n" },
    01496  {"setColor",(PyCFunction) rpmts_SetColor,      METH_VARARGS|METH_KEYWORDS,
    01497         NULL },
    01498  {"pgpPrtPkts", (PyCFunction) rpmts_PgpPrtPkts, METH_VARARGS|METH_KEYWORDS,
    01499         NULL },
    01500  {"pgpImportPubkey",    (PyCFunction) rpmts_PgpImportPubkey,    METH_VARARGS|METH_KEYWORDS,
    01501         NULL },
    01502  {"parseSpec",  (PyCFunction) spec_Parse,       METH_VARARGS|METH_KEYWORDS,
    01503 "ts.parseSpec(\"/path/to/foo.spec\") -> spec\n\
    01504 - Parse a spec file.\n" },
    01505  {"dbMatch",    (PyCFunction) rpmts_Match,      METH_VARARGS|METH_KEYWORDS,
    01506 "ts.dbMatch([TagN, [key, [len]]]) -> mi\n\
    01507 - Create a match iterator for the default transaction rpmdb.\n" },
    01508  {"next",               (PyCFunction)rpmts_Next,        METH_NOARGS,
    01509 "ts.next() -> te\n\
    01510 - Retrieve next transaction set element.\n" },
    01511     {NULL,              NULL}           /* sentinel */
    01512 };
    01513 /*@=fullinitblock@*/
    01514
    01517 static void rpmts_dealloc(/*@only@*/ rpmtsObject * s)
    01518         /*@modifies *s @*/
    01519 {
    01520
    01521 if (_rpmts_debug)
    01522 fprintf(stderr, "%p -- ts %p db %p\n", s, s->ts, rpmtsGetRdb(s->ts));
    01523     s->ts = rpmtsFree(s->ts);
    01524
    01525     if (s->scriptFd) Fclose(s->scriptFd);
    01526     /* this will free the keyList, and decrement the ref count of all
    01527        the items on the list as well :-) */
    01528     Py_DECREF(s->keyList);
    01529     PyObject_Del((PyObject *)s);
    01530 }
    01531
    01532 static PyObject * rpmts_getattro(PyObject * o, PyObject * n)
    01533         /*@*/
    01534 {
    01535     return PyObject_GenericGetAttr(o, n);
    01536 }
    01537
    01540 static int rpmts_setattro(PyObject * o, PyObject * n, PyObject * v)
    01541         /*@*/
    01542 {
    01543     rpmtsObject *s = (rpmtsObject *)o;
    01544     char * name = PyString_AsString(n);
    01545     int fdno;
    01546
    01547     if (!strcmp(name, "scriptFd")) {
    01548         if (!PyArg_Parse(v, "i", &fdno)) return 0;
    01549         if (fdno < 0) {
    01550             PyErr_SetString(PyExc_TypeError, "bad file descriptor");
    01551             return -1;
    01552         } else {
    01553             s->scriptFd = fdDup(fdno);
    01554             rpmtsSetScriptFd(s->ts, s->scriptFd);
    01555         }
    01556     } else {
    01557         PyErr_SetString(PyExc_AttributeError, name);
    01558         return -1;
    01559     }
    01560
    01561     return 0;
    01562 }
    01563
    01566 static int rpmts_init(rpmtsObject * s, PyObject *args, PyObject *kwds)
    01567         /*@globals rpmGlobalMacroContext @*/
    01568         /*@modifies s, rpmGlobalMacroContext @*/
    01569 {
    01570     char * rootDir = "/";
    01571     int vsflags = rpmExpandNumeric("%{?_vsflags}");
    01572     char * kwlist[] = {"rootdir", "vsflags", 0};
    01573
    01574 if (_rpmts_debug < 0)
    01575 fprintf(stderr, "*** rpmts_init(%p,%p,%p)\n", s, args, kwds);
    01576
    01577     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|si:rpmts_init", kwlist,
    01578             &rootDir, &vsflags))
    01579         return -1;
    01580
    01581     s->ts = rpmtsCreate();
    01582     /* XXX: Why is there no rpmts_SetRootDir() ? */
    01583     (void) rpmtsSetRootDir(s->ts, rootDir);
    01584     /* XXX: make this use common code with rpmts_SetVSFlags() to check the
    01585      *      python objects */
    01586     (void) rpmtsSetVSFlags(s->ts, vsflags);
    01587     s->keyList = PyList_New(0);
    01588     s->scriptFd = NULL;
    01589     s->tsi = NULL;
    01590     s->tsiFilter = 0;
    01591
    01592     return 0;
    01593 }
    01594
    01597 static void rpmts_free(/*@only@*/ rpmtsObject * s)
    01598         /*@modifies s @*/
    01599 {
    01600 if (_rpmts_debug)
    01601 fprintf(stderr, "%p -- ts %p db %p\n", s, s->ts, rpmtsGetRdb(s->ts));
    01602     s->ts = rpmtsFree(s->ts);
    01603
    01604     if (s->scriptFd)
    01605         Fclose(s->scriptFd);
    01606
    01607     /* this will free the keyList, and decrement the ref count of all
    01608        the items on the list as well :-) */
    01609     Py_DECREF(s->keyList);
    01610
    01611     PyObject_Del((PyObject *)s);
    01612 }
    01613
    01616 static PyObject * rpmts_alloc(PyTypeObject * subtype, int nitems)
    01617         /*@*/
    01618 {
    01619     PyObject * s = PyType_GenericAlloc(subtype, nitems);
    01620
    01621 if (_rpmts_debug < 0)
    01622 fprintf(stderr, "*** rpmts_alloc(%p,%d) ret %p\n", subtype, nitems, s);
    01623     return s;
    01624 }
    01625
    01628 static PyObject * rpmts_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
    01629         /*@globals rpmGlobalMacroContext @*/
    01630         /*@modifies rpmGlobalMacroContext @*/
    01631 {
    01632     rpmtsObject * s = (void *) PyObject_New(rpmtsObject, subtype);
    01633
    01634     /* Perform additional initialization. */
    01635     if (rpmts_init(s, args, kwds) < 0) {
    01636         rpmts_free(s);
    01637         return NULL;
    01638     }
    01639
    01640 if (_rpmts_debug)
    01641 fprintf(stderr, "%p ++ ts %p db %p\n", s, s->ts, rpmtsGetRdb(s->ts));
    01642
    01643     return (PyObject *)s;
    01644 }
    01645
    01648 /*@unchecked@*/ /*@observer@*/
    01649 static char rpmts_doc[] =
    01650 "";
    01651
    01654 /*@-fullinitblock@*/
    01655 PyTypeObject rpmts_Type = {
    01656         PyObject_HEAD_INIT(&PyType_Type)
    01657         0,                              /* ob_size */
    01658         "rpm.ts",                       /* tp_name */
    01659         sizeof(rpmtsObject),            /* tp_size */
    01660         0,                              /* tp_itemsize */
    01661         (destructor) rpmts_dealloc,     /* tp_dealloc */
    01662         0,                              /* tp_print */
    01663         (getattrfunc)0,                 /* tp_getattr */
    01664         (setattrfunc)0,                 /* tp_setattr */
    01665         0,                              /* tp_compare */
    01666         0,                              /* tp_repr */
    01667         0,                              /* tp_as_number */
    01668         0,                              /* tp_as_sequence */
    01669         0,                              /* tp_as_mapping */
    01670         0,                              /* tp_hash */
    01671         0,                              /* tp_call */
    01672         0,                              /* tp_str */
    01673         (getattrofunc) rpmts_getattro,  /* tp_getattro */
    01674         (setattrofunc) rpmts_setattro,  /* tp_setattro */
    01675         0,                              /* tp_as_buffer */
    01676         Py_TPFLAGS_DEFAULT,             /* tp_flags */
    01677         rpmts_doc,                      /* tp_doc */
    01678 #if Py_TPFLAGS_HAVE_ITER
    01679         0,                              /* tp_traverse */
    01680         0,                              /* tp_clear */
    01681         0,                              /* tp_richcompare */
    01682         0,                              /* tp_weaklistoffset */
    01683         (getiterfunc) rpmts_iter,       /* tp_iter */
    01684         (iternextfunc) rpmts_iternext,  /* tp_iternext */
    01685         rpmts_methods,                  /* tp_methods */
    01686         0,                              /* tp_members */
    01687         0,                              /* tp_getset */
    01688         0,                              /* tp_base */
    01689         0,                              /* tp_dict */
    01690         0,                              /* tp_descr_get */
    01691         0,                              /* tp_descr_set */
    01692         0,                              /* tp_dictoffset */
    01693         (initproc) rpmts_init,          /* tp_init */
    01694         (allocfunc) rpmts_alloc,        /* tp_alloc */
    01695         (newfunc) rpmts_new,            /* tp_new */
    01696         (freefunc) rpmts_free,          /* tp_free */
    01697         0,                              /* tp_is_gc */
    01698 #endif
    01699 };
    01700 /*@=fullinitblock@*/
    01701
    01704 /* XXX: This should use the same code as rpmts_init */
    01705 rpmtsObject *
    01706 rpmts_Create(/*@unused@*/ PyObject * self, PyObject * args, PyObject * kwds)
    01707 {
    01708     rpmtsObject * o;
    01709     char * rootDir = "/";
    01710     int vsflags = rpmExpandNumeric("%{?_vsflags}");
    01711     char * kwlist[] = {"rootdir", "vsflags", NULL};
    01712
    01713     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|si:Create", kwlist,
    01714             &rootDir, &vsflags))
    01715         return NULL;
    01716
    01717     o = (void *) PyObject_New(rpmtsObject, &rpmts_Type);
    01718
    01719     o->ts = rpmtsCreate();
    01720     /* XXX: Why is there no rpmts_SetRootDir() ? */
    01721     (void) rpmtsSetRootDir(o->ts, rootDir);
    01722     /* XXX: make this use common code with rpmts_SetVSFlags() to check the
    01723      *      python objects */
    01724     (void) rpmtsSetVSFlags(o->ts, vsflags);
    01725
    01726     o->keyList = PyList_New(0);
    01727     o->scriptFd = NULL;
    01728     o->tsi = NULL;
    01729     o->tsiFilter = 0;
    01730
    01731 if (_rpmts_debug)
    01732 fprintf(stderr, "%p ++ ts %p db %p\n", o, o->ts, rpmtsGetRdb(o->ts));
    01733     return o;
    01734 }