00001
00005 #include "system.h"
00006
00007 #include "Python.h"
00008 #ifdef __LCLINT__
00009 #undef PyObject_HEAD
00010 #define PyObject_HEAD int _PyObjectHead;
00011 #endif
00012
00013 #include <rpmcli.h>
00014 #include <rpmpgp.h>
00015 #include <rpmdb.h>
00016
00017 #include "header-py.h"
00018 #include "rpmds-py.h"
00019 #include "rpmfi-py.h"
00020 #include "rpmmi-py.h"
00021 #include "rpmte-py.h"
00022
00023 #define _RPMTS_INTERNAL
00024 #include "rpmts-py.h"
00025
00026 #include "debug.h"
00027
00028
00029
00030 static int _rpmts_debug = 0;
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00162 struct rpmtsCallbackType_s {
00163 PyObject * cb;
00164 PyObject * data;
00165 rpmtsObject * tso;
00166 int pythonError;
00167 PyThreadState *_save;
00168 };
00169
00172 static PyObject *
00173 rpmts_Debug( rpmtsObject * s, PyObject * args)
00174
00175
00176 {
00177 if (!PyArg_ParseTuple(args, "i:Debug", &_rpmts_debug)) return NULL;
00178
00179 if (_rpmts_debug < 0)
00180 fprintf(stderr, "*** rpmts_Debug(%p) ts %p\n", s, s->ts);
00181
00182 Py_INCREF(Py_None);
00183 return Py_None;
00184 }
00185
00192 static void rpmtsAddAvailableElement(rpmts ts, Header h,
00193 fnpyKey key)
00194
00195 {
00196 int scareMem = 0;
00197 rpmds provides = rpmdsNew(h, RPMTAG_PROVIDENAME, scareMem);
00198 rpmfi fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
00199
00200
00201 (void) rpmalAdd(&ts->availablePackages, RPMAL_NOMATCH, key,
00202 provides, fi, rpmtsColor(ts));
00203 fi = rpmfiFree(fi);
00204 provides = rpmdsFree(provides);
00205
00206 if (_rpmts_debug < 0)
00207 fprintf(stderr, "\tAddAvailable(%p) list %p\n", ts, ts->availablePackages);
00208
00209 }
00210
00213 static PyObject *
00214 rpmts_AddInstall(rpmtsObject * s, PyObject * args)
00215
00216
00217 {
00218 hdrObject * h;
00219 PyObject * key;
00220 char * how = NULL;
00221 int isUpgrade = 0;
00222
00223 if (!PyArg_ParseTuple(args, "O!O|s:AddInstall", &hdr_Type, &h, &key, &how))
00224 return NULL;
00225
00226 { PyObject * hObj = (PyObject *) h;
00227 if (hObj->ob_type != &hdr_Type) {
00228 PyErr_SetString(PyExc_TypeError, "bad type for header argument");
00229 return NULL;
00230 }
00231 }
00232
00233 if (_rpmts_debug < 0 || (_rpmts_debug > 0 && *how != 'a'))
00234 fprintf(stderr, "*** rpmts_AddInstall(%p,%p,%p,%s) ts %p\n", s, h, key, how, s->ts);
00235
00236 if (how && strcmp(how, "a") && strcmp(how, "u") && strcmp(how, "i")) {
00237 PyErr_SetString(PyExc_TypeError, "how argument must be \"u\", \"a\", or \"i\"");
00238 return NULL;
00239 } else if (how && !strcmp(how, "u"))
00240 isUpgrade = 1;
00241
00242 if (how && !strcmp(how, "a"))
00243 rpmtsAddAvailableElement(s->ts, hdrGetHeader(h), key);
00244 else
00245 rpmtsAddInstallElement(s->ts, hdrGetHeader(h), key, isUpgrade, NULL);
00246
00247
00248 if (key)
00249 PyList_Append(s->keyList, key);
00250
00251 Py_INCREF(Py_None);
00252 return Py_None;
00253 }
00254
00258 static PyObject *
00259 rpmts_AddErase(rpmtsObject * s, PyObject * args)
00260
00261
00262 {
00263 PyObject * o;
00264 int count;
00265 rpmdbMatchIterator mi;
00266
00267 if (_rpmts_debug)
00268 fprintf(stderr, "*** rpmts_AddErase(%p) ts %p\n", s, s->ts);
00269
00270 if (!PyArg_ParseTuple(args, "O:AddErase", &o))
00271 return NULL;
00272
00273 if (PyString_Check(o)) {
00274 char * name = PyString_AsString(o);
00275
00276 mi = rpmtsInitIterator(s->ts, RPMDBI_LABEL, name, 0);
00277 count = rpmdbGetIteratorCount(mi);
00278 if (count <= 0) {
00279 mi = rpmdbFreeIterator(mi);
00280 PyErr_SetString(pyrpmError, "package not installed");
00281 return NULL;
00282 } else {
00283 Header h;
00284 while ((h = rpmdbNextIterator(mi)) != NULL) {
00285 unsigned int recOffset = rpmdbGetIteratorOffset(mi);
00286 if (recOffset)
00287 rpmtsAddEraseElement(s->ts, h, recOffset);
00288 }
00289 }
00290 mi = rpmdbFreeIterator(mi);
00291 } else
00292 if (PyInt_Check(o)) {
00293 uint_32 instance = PyInt_AsLong(o);
00294
00295 mi = rpmtsInitIterator(s->ts, RPMDBI_PACKAGES, &instance, sizeof(instance));
00296 if (instance == 0 || mi == NULL) {
00297 mi = rpmdbFreeIterator(mi);
00298 PyErr_SetString(pyrpmError, "package not installed");
00299 return NULL;
00300 } else {
00301 Header h;
00302 while ((h = rpmdbNextIterator(mi)) != NULL) {
00303 uint_32 recOffset = rpmdbGetIteratorOffset(mi);
00304 if (recOffset)
00305 rpmtsAddEraseElement(s->ts, h, recOffset);
00306 break;
00307 }
00308 }
00309 mi = rpmdbFreeIterator(mi);
00310 }
00311
00312 Py_INCREF(Py_None);
00313 return Py_None;
00314 }
00315
00318 static int
00319 rpmts_SolveCallback(rpmts ts, rpmds ds, const void * data)
00320
00321 {
00322 struct rpmtsCallbackType_s * cbInfo = (struct rpmtsCallbackType_s *) data;
00323 PyObject * args, * result;
00324 int res = 1;
00325
00326 if (_rpmts_debug)
00327 fprintf(stderr, "*** rpmts_SolveCallback(%p,%p,%p) \"%s\"\n", ts, ds, data, rpmdsDNEVR(ds));
00328
00329 if (cbInfo->tso == NULL) return res;
00330 if (cbInfo->pythonError) return res;
00331 if (cbInfo->cb == Py_None) return res;
00332
00333 PyEval_RestoreThread(cbInfo->_save);
00334
00335 args = Py_BuildValue("(Oissi)", cbInfo->tso,
00336 rpmdsTagN(ds), rpmdsN(ds), rpmdsEVR(ds), rpmdsFlags(ds));
00337 result = PyEval_CallObject(cbInfo->cb, args);
00338 Py_DECREF(args);
00339
00340 if (!result) {
00341 cbInfo->pythonError = 1;
00342 } else {
00343 if (PyInt_Check(result))
00344 res = PyInt_AsLong(result);
00345 Py_DECREF(result);
00346 }
00347
00348 cbInfo->_save = PyEval_SaveThread();
00349
00350 return res;
00351 }
00352
00355 static PyObject *
00356 rpmts_Check(rpmtsObject * s, PyObject * args)
00357
00358
00359 {
00360 rpmps ps;
00361 rpmProblem p;
00362 PyObject * list, * cf;
00363 struct rpmtsCallbackType_s cbInfo;
00364 int i;
00365 int xx;
00366
00367 memset(&cbInfo, 0, sizeof(cbInfo));
00368 if (!PyArg_ParseTuple(args, "|O:Check", &cbInfo.cb))
00369 return NULL;
00370
00371 if (cbInfo.cb != NULL) {
00372 if (!PyCallable_Check(cbInfo.cb)) {
00373 PyErr_SetString(PyExc_TypeError, "expected a callable");
00374 return NULL;
00375 }
00376 xx = rpmtsSetSolveCallback(s->ts, rpmts_SolveCallback, (void *)&cbInfo);
00377 }
00378
00379 if (_rpmts_debug)
00380 fprintf(stderr, "*** rpmts_Check(%p) ts %p cb %p\n", s, s->ts, cbInfo.cb);
00381
00382 cbInfo.tso = s;
00383 cbInfo.pythonError = 0;
00384 cbInfo._save = PyEval_SaveThread();
00385
00386
00387 rpmalMakeIndex(s->ts->availablePackages);
00388
00389 xx = rpmtsCheck(s->ts);
00390 ps = rpmtsProblems(s->ts);
00391
00392 if (cbInfo.cb)
00393 xx = rpmtsSetSolveCallback(s->ts, rpmtsSolve, NULL);
00394
00395 PyEval_RestoreThread(cbInfo._save);
00396
00397 if (ps) {
00398 list = PyList_New(0);
00399
00400
00401 for (i = 0; i < ps->numProblems; i++) {
00402 #ifdef DYING
00403 cf = Py_BuildValue("((sss)(ss)iOi)", conflicts[i].byName,
00404 conflicts[i].byVersion, conflicts[i].byRelease,
00405
00406 conflicts[i].needsName,
00407 conflicts[i].needsVersion,
00408
00409 conflicts[i].needsFlags,
00410 conflicts[i].suggestedPkgs ?
00411 conflicts[i].suggestedPkgs[0] : Py_None,
00412 conflicts[i].sense);
00413 #else
00414 char * byName, * byVersion, * byRelease;
00415 char * needsName = NULL, * needsOP = NULL, * needsVersion = NULL;
00416 int needsFlags, sense;
00417 fnpyKey key;
00418
00419 p = ps->probs + i;
00420
00421 byName = p->pkgNEVR;
00422 if ((byRelease = strrchr(byName, '-')) != NULL)
00423 *byRelease++ = '\0';
00424 if ((byVersion = strrchr(byName, '-')) != NULL)
00425 *byVersion++ = '\0';
00426
00427 key = p->key;
00428
00429 needsName = p->altNEVR;
00430 if ((p->altNEVR != NULL) && needsName[1] == ' ') {
00431 sense = (needsName[0] == 'C')
00432 ? RPMDEP_SENSE_CONFLICTS : RPMDEP_SENSE_REQUIRES;
00433 needsName += 2;
00434 } else
00435 sense = RPMDEP_SENSE_REQUIRES;
00436 if ((p->altNEVR != NULL) &&
00437 (needsVersion = strrchr(needsName, ' ')) != NULL)
00438 *needsVersion++ = '\0';
00439
00440 needsFlags = 0;
00441 if ((p->altNEVR != NULL) &&
00442 (needsOP = strrchr(needsName, ' ')) != NULL) {
00443 for (*needsOP++ = '\0'; *needsOP != '\0'; needsOP++) {
00444 if (*needsOP == '<') needsFlags |= RPMSENSE_LESS;
00445 else if (*needsOP == '>') needsFlags |= RPMSENSE_GREATER;
00446 else if (*needsOP == '=') needsFlags |= RPMSENSE_EQUAL;
00447 }
00448 }
00449
00450 cf = Py_BuildValue("((sss)(ss)iOi)", byName, byVersion, byRelease,
00451 needsName, needsVersion, needsFlags,
00452 (key != NULL ? key : Py_None),
00453 sense);
00454 #endif
00455 PyList_Append(list, (PyObject *) cf);
00456 Py_DECREF(cf);
00457 }
00458
00459 ps = rpmpsFree(ps);
00460
00461 return list;
00462 }
00463
00464 Py_INCREF(Py_None);
00465 return Py_None;
00466 }
00467
00470 static PyObject *
00471 rpmts_Order(rpmtsObject * s, PyObject * args)
00472
00473 {
00474 int rc;
00475
00476 if (_rpmts_debug)
00477 fprintf(stderr, "*** rpmts_Order(%p) ts %p\n", s, s->ts);
00478
00479 if (!PyArg_ParseTuple(args, ":Order")) return NULL;
00480
00481 Py_BEGIN_ALLOW_THREADS
00482 rc = rpmtsOrder(s->ts);
00483 Py_END_ALLOW_THREADS
00484
00485 return Py_BuildValue("i", rc);
00486 }
00487
00490 static PyObject *
00491 rpmts_Clean(rpmtsObject * s, PyObject * args)
00492
00493
00494 {
00495 if (_rpmts_debug)
00496 fprintf(stderr, "*** rpmts_Clean(%p) ts %p\n", s, s->ts);
00497
00498 if (!PyArg_ParseTuple(args, ":Clean")) return NULL;
00499
00500 rpmtsClean(s->ts);
00501
00502 Py_INCREF(Py_None);
00503 return Py_None;
00504 }
00505
00508 static PyObject *
00509 rpmts_IDTXload(rpmtsObject * s, PyObject * args)
00510
00511
00512 {
00513 PyObject * result = NULL;
00514 rpmTag tag = RPMTAG_INSTALLTID;
00515 IDTX idtx;
00516
00517 if (_rpmts_debug)
00518 fprintf(stderr, "*** rpmts_IDTXload(%p) ts %p\n", s, s->ts);
00519
00520 if (!PyArg_ParseTuple(args, ":IDTXload")) return NULL;
00521
00522 Py_BEGIN_ALLOW_THREADS
00523 idtx = IDTXload(s->ts, tag);
00524 Py_END_ALLOW_THREADS
00525
00526 if (idtx == NULL || idtx->nidt <= 0) {
00527 Py_INCREF(Py_None);
00528 result = Py_None;
00529 } else {
00530 PyObject * tuple;
00531 PyObject * ho;
00532 IDT idt;
00533 int i;
00534
00535 result = PyTuple_New(idtx->nidt);
00536 for (i = 0; i < idtx->nidt; i++) {
00537 idt = idtx->idt + i;
00538 ho = (PyObject *) hdr_Wrap(idt->h);
00539 tuple = Py_BuildValue("(iOi)", idt->val.u32, ho, idt->instance);
00540 PyTuple_SET_ITEM(result, i, tuple);
00541 Py_DECREF(ho);
00542 }
00543 }
00544
00545 idtx = IDTXfree(idtx);
00546
00547 return result;
00548 }
00549
00552 static PyObject *
00553 rpmts_IDTXglob(rpmtsObject * s, PyObject * args)
00554
00555
00556 {
00557 PyObject * result = NULL;
00558 rpmTag tag = RPMTAG_REMOVETID;
00559 const char * globstr;
00560 IDTX idtx;
00561
00562 if (_rpmts_debug)
00563 fprintf(stderr, "*** rpmts_IDTXglob(%p) ts %p\n", s, s->ts);
00564
00565 if (!PyArg_ParseTuple(args, ":IDTXglob")) return NULL;
00566
00567 Py_BEGIN_ALLOW_THREADS
00568 globstr = rpmExpand("%{_repackage_dir}/*.rpm", NULL);
00569 idtx = IDTXglob(s->ts, globstr, tag);
00570 globstr = _free(globstr);
00571 Py_END_ALLOW_THREADS
00572
00573 if (idtx == NULL || idtx->nidt <= 0) {
00574 Py_INCREF(Py_None);
00575 result = Py_None;
00576 } else {
00577 PyObject * tuple;
00578 PyObject * ho;
00579 IDT idt;
00580 int i;
00581
00582 result = PyTuple_New(idtx->nidt);
00583 for (i = 0; i < idtx->nidt; i++) {
00584 idt = idtx->idt + i;
00585 ho = (PyObject *) hdr_Wrap(idt->h);
00586 tuple = Py_BuildValue("(iOs)", idt->val.u32, ho, idt->key);
00587 PyTuple_SET_ITEM(result, i, tuple);
00588 Py_DECREF(ho);
00589 }
00590 }
00591
00592 idtx = IDTXfree(idtx);
00593
00594 return result;
00595 }
00596
00599 static PyObject *
00600 rpmts_Rollback(rpmtsObject * s, PyObject * args)
00601
00602
00603 {
00604 struct rpmInstallArguments_s * ia = alloca(sizeof(*ia));
00605 rpmtransFlags transFlags;
00606 const char ** av = NULL;
00607 uint_32 rbtid;
00608 int rc;
00609
00610 if (_rpmts_debug)
00611 fprintf(stderr, "*** rpmts_Rollback(%p) ts %p\n", s, s->ts);
00612
00613 if (!PyArg_ParseTuple(args, "i:Rollback", &rbtid)) return NULL;
00614
00615 Py_BEGIN_ALLOW_THREADS
00616 memset(ia, 0, sizeof(*ia));
00617 ia->qva_flags = (VERIFY_DIGEST|VERIFY_SIGNATURE|VERIFY_HDRCHK);
00618 ia->transFlags |= (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL);
00619 ia->transFlags |= RPMTRANS_FLAG_NOMD5;
00620 ia->installInterfaceFlags = (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL);
00621 ia->rbtid = rbtid;
00622 ia->relocations = NULL;
00623 ia->probFilter |= RPMPROB_FILTER_OLDPACKAGE;
00624
00625 transFlags = rpmtsSetFlags(s->ts, ia->transFlags);
00626 rc = rpmRollback(s->ts, ia, av);
00627 transFlags = rpmtsSetFlags(s->ts, transFlags);
00628 Py_END_ALLOW_THREADS
00629
00630 return Py_BuildValue("i", rc);
00631 }
00632
00635 static PyObject *
00636 rpmts_OpenDB(rpmtsObject * s, PyObject * args)
00637
00638
00639 {
00640
00641 if (_rpmts_debug)
00642 fprintf(stderr, "*** rpmts_OpenDB(%p) ts %p\n", s, s->ts);
00643
00644 if (!PyArg_ParseTuple(args, ":OpenDB")) return NULL;
00645
00646 if (s->ts->dbmode == -1)
00647 s->ts->dbmode = O_RDONLY;
00648
00649 return Py_BuildValue("i", rpmtsOpenDB(s->ts, s->ts->dbmode));
00650 }
00651
00654 static PyObject *
00655 rpmts_CloseDB(rpmtsObject * s, PyObject * args)
00656
00657 {
00658 int rc;
00659
00660 if (_rpmts_debug)
00661 fprintf(stderr, "*** rpmts_CloseDB(%p) ts %p\n", s, s->ts);
00662
00663 if (!PyArg_ParseTuple(args, ":CloseDB")) return NULL;
00664
00665 rc = rpmtsCloseDB(s->ts);
00666 s->ts->dbmode = -1;
00667
00668 return Py_BuildValue("i", rc);
00669 }
00670
00673 static PyObject *
00674 rpmts_InitDB(rpmtsObject * s, PyObject * args)
00675
00676
00677 {
00678 int rc;
00679
00680 if (_rpmts_debug)
00681 fprintf(stderr, "*** rpmts_InitDB(%p) ts %p\n", s, s->ts);
00682
00683 if (!PyArg_ParseTuple(args, ":InitDB")) return NULL;
00684
00685 rc = rpmtsInitDB(s->ts, O_RDONLY);
00686 if (rc == 0)
00687 rc = rpmtsCloseDB(s->ts);
00688
00689 return Py_BuildValue("i", rc);
00690 }
00691
00694 static PyObject *
00695 rpmts_RebuildDB(rpmtsObject * s, PyObject * args)
00696
00697
00698 {
00699 int rc;
00700
00701 if (_rpmts_debug)
00702 fprintf(stderr, "*** rpmts_RebuildDB(%p) ts %p\n", s, s->ts);
00703
00704 if (!PyArg_ParseTuple(args, ":RebuildDB")) return NULL;
00705
00706 Py_BEGIN_ALLOW_THREADS
00707 rc = rpmtsRebuildDB(s->ts);
00708 Py_END_ALLOW_THREADS
00709
00710 return Py_BuildValue("i", rc);
00711 }
00712
00715 static PyObject *
00716 rpmts_VerifyDB(rpmtsObject * s, PyObject * args)
00717
00718
00719 {
00720 int rc;
00721
00722 if (_rpmts_debug)
00723 fprintf(stderr, "*** rpmts_VerifyDB(%p) ts %p\n", s, s->ts);
00724
00725 if (!PyArg_ParseTuple(args, ":VerifyDB")) return NULL;
00726
00727 Py_BEGIN_ALLOW_THREADS
00728 rc = rpmtsVerifyDB(s->ts);
00729 Py_END_ALLOW_THREADS
00730
00731 return Py_BuildValue("i", rc);
00732 }
00733
00736 static PyObject *
00737 rpmts_HdrFromFdno(rpmtsObject * s, PyObject * args)
00738
00739
00740 {
00741 PyObject * result = NULL;
00742 Header h;
00743 FD_t fd;
00744 int fdno;
00745 rpmRC rpmrc;
00746
00747 if (!PyArg_ParseTuple(args, "i:HdrFromFdno", &fdno)) return NULL;
00748
00749 fd = fdDup(fdno);
00750 rpmrc = rpmReadPackageFile(s->ts, fd, "rpmts_HdrFromFdno", &h);
00751 Fclose(fd);
00752
00753 if (_rpmts_debug)
00754 fprintf(stderr, "*** rpmts_HdrFromFdno(%p) ts %p rc %d\n", s, s->ts, rpmrc);
00755
00756 switch (rpmrc) {
00757 case RPMRC_OK:
00758 if (h)
00759 result = Py_BuildValue("N", hdr_Wrap(h));
00760 h = headerFree(h);
00761 break;
00762
00763 case RPMRC_NOKEY:
00764 PyErr_SetString(pyrpmError, "public key not available");
00765 break;
00766
00767 case RPMRC_NOTFOUND:
00768 case RPMRC_NOTTRUSTED:
00769 PyErr_SetString(pyrpmError, "public key not trusted");
00770 break;
00771
00772 case RPMRC_FAIL:
00773 default:
00774 PyErr_SetString(pyrpmError, "error reading package header");
00775 break;
00776 }
00777
00778 return result;
00779 }
00780
00783 static PyObject *
00784 rpmts_HdrCheck(rpmtsObject * s, PyObject * args)
00785
00786
00787 {
00788 PyObject * blob;
00789 PyObject * result = NULL;
00790 const char * msg = NULL;
00791 const void * uh;
00792 int uc;
00793 rpmRC rpmrc;
00794
00795 if (_rpmts_debug)
00796 fprintf(stderr, "*** rpmts_HdrCheck(%p) ts %p\n", s, s->ts);
00797
00798 if (!PyArg_ParseTuple(args, "O:HdrCheck", &blob)) return NULL;
00799 if (blob == Py_None) {
00800 Py_INCREF(Py_None);
00801 return Py_None;
00802 }
00803 if (!PyString_Check(blob)) {
00804 PyErr_SetString(pyrpmError, "hdrCheck takes a string of octets");
00805 return result;
00806 }
00807 uh = PyString_AsString(blob);
00808 uc = PyString_Size(blob);
00809
00810 rpmrc = headerCheck(s->ts, uh, uc, &msg);
00811
00812 switch (rpmrc) {
00813 case RPMRC_OK:
00814 Py_INCREF(Py_None);
00815 result = Py_None;
00816 break;
00817
00818 case RPMRC_NOKEY:
00819 PyErr_SetString(pyrpmError, "public key not availaiable");
00820 break;
00821
00822 case RPMRC_NOTTRUSTED:
00823 PyErr_SetString(pyrpmError, "public key not trusted");
00824 break;
00825
00826 case RPMRC_FAIL:
00827 default:
00828 PyErr_SetString(pyrpmError, msg);
00829 break;
00830 }
00831 msg = _free(msg);
00832
00833 return result;
00834 }
00835
00838 static PyObject *
00839 rpmts_SetVSFlags(rpmtsObject * s, PyObject * args)
00840
00841 {
00842 rpmVSFlags vsflags;
00843
00844 if (_rpmts_debug)
00845 fprintf(stderr, "*** rpmts_SetVSFlags(%p) ts %p\n", s, s->ts);
00846
00847 if (!PyArg_ParseTuple(args, "i:SetVSFlags", &vsflags)) return NULL;
00848
00849
00850
00851 return Py_BuildValue("i", rpmtsSetVSFlags(s->ts, vsflags));
00852 }
00853
00856 static PyObject *
00857 rpmts_SetColor(rpmtsObject * s, PyObject * args)
00858
00859 {
00860 uint_32 tscolor;
00861
00862 if (_rpmts_debug)
00863 fprintf(stderr, "*** rpmts_SetColor(%p) ts %p\n", s, s->ts);
00864
00865 if (!PyArg_ParseTuple(args, "i:Color", &tscolor)) return NULL;
00866
00867
00868
00869 return Py_BuildValue("i", rpmtsSetColor(s->ts, tscolor));
00870 }
00871
00874 static PyObject *
00875 rpmts_PgpPrtPkts(rpmtsObject * s, PyObject * args)
00876
00877
00878 {
00879 PyObject * blob;
00880 unsigned char * pkt;
00881 unsigned int pktlen;
00882 int rc;
00883
00884 if (_rpmts_debug)
00885 fprintf(stderr, "*** rpmts_PgpPrtPkts(%p) ts %p\n", s, s->ts);
00886
00887 if (!PyArg_ParseTuple(args, "O:PgpPrtPkts", &blob)) return NULL;
00888 if (blob == Py_None) {
00889 Py_INCREF(Py_None);
00890 return Py_None;
00891 }
00892 if (!PyString_Check(blob)) {
00893 PyErr_SetString(pyrpmError, "pgpPrtPkts takes a string of octets");
00894 return NULL;
00895 }
00896 pkt = PyString_AsString(blob);
00897 pktlen = PyString_Size(blob);
00898
00899 rc = pgpPrtPkts(pkt, pktlen, NULL, 1);
00900
00901 return Py_BuildValue("i", rc);
00902 }
00903
00906 static PyObject *
00907 rpmts_PgpImportPubkey(rpmtsObject * s, PyObject * args)
00908
00909
00910 {
00911 PyObject * blob;
00912 unsigned char * pkt;
00913 unsigned int pktlen;
00914 int rc;
00915
00916 if (_rpmts_debug)
00917 fprintf(stderr, "*** rpmts_PgpImportPubkey(%p) ts %p\n", s, s->ts);
00918
00919 if (!PyArg_ParseTuple(args, "O:PgpImportPubkey", &blob)) return NULL;
00920 if (blob == Py_None) {
00921 Py_INCREF(Py_None);
00922 return Py_None;
00923 }
00924 if (!PyString_Check(blob)) {
00925 PyErr_SetString(pyrpmError, "PgpImportPubkey takes a string of octets");
00926 return NULL;
00927 }
00928 pkt = PyString_AsString(blob);
00929 pktlen = PyString_Size(blob);
00930
00931 rc = rpmcliImportPubkey(s->ts, pkt, pktlen);
00932
00933 return Py_BuildValue("i", rc);
00934 }
00935
00938 static PyObject *
00939 rpmts_GetKeys(rpmtsObject * s, PyObject * args)
00940
00941
00942 {
00943 const void **data = NULL;
00944 int num, i;
00945 PyObject *tuple;
00946
00947 if (_rpmts_debug)
00948 fprintf(stderr, "*** rpmts_GetKeys(%p) ts %p\n", s, s->ts);
00949
00950 if (!PyArg_ParseTuple(args, ":GetKeys")) return NULL;
00951
00952 rpmtsGetKeys(s->ts, &data, &num);
00953 if (data == NULL || num <= 0) {
00954 data = _free(data);
00955 Py_INCREF(Py_None);
00956 return Py_None;
00957 }
00958
00959 tuple = PyTuple_New(num);
00960
00961 for (i = 0; i < num; i++) {
00962 PyObject *obj;
00963 obj = (data[i] ? (PyObject *) data[i] : Py_None);
00964 Py_INCREF(obj);
00965 PyTuple_SetItem(tuple, i, obj);
00966 }
00967
00968 data = _free(data);
00969
00970 return tuple;
00971 }
00972
00975 static void *
00976 rpmtsCallback( const void * hd, const rpmCallbackType what,
00977 const unsigned long amount, const unsigned long total,
00978 const void * pkgKey, rpmCallbackData data)
00979
00980
00981 {
00982
00983 Header h = (Header) hd;
00984
00985 struct rpmtsCallbackType_s * cbInfo = data;
00986 PyObject * pkgObj = (PyObject *) pkgKey;
00987 PyObject * args, * result;
00988 static FD_t fd;
00989
00990 if (cbInfo->pythonError) return NULL;
00991 if (cbInfo->cb == Py_None) return NULL;
00992
00993
00994 if (pkgObj == NULL) {
00995 if (h) {
00996 const char * n = NULL;
00997 (void) headerNVR(h, &n, NULL, NULL);
00998 pkgObj = Py_BuildValue("s", n);
00999 } else {
01000 pkgObj = Py_None;
01001 Py_INCREF(pkgObj);
01002 }
01003 } else
01004 Py_INCREF(pkgObj);
01005
01006 PyEval_RestoreThread(cbInfo->_save);
01007
01008 args = Py_BuildValue("(illOO)", what, amount, total, pkgObj, cbInfo->data);
01009 result = PyEval_CallObject(cbInfo->cb, args);
01010 Py_DECREF(args);
01011 Py_DECREF(pkgObj);
01012
01013 if (!result) {
01014 cbInfo->pythonError = 1;
01015 cbInfo->_save = PyEval_SaveThread();
01016 return NULL;
01017 }
01018
01019 if (what == RPMCALLBACK_INST_OPEN_FILE) {
01020 int fdno;
01021
01022 if (!PyArg_Parse(result, "i", &fdno)) {
01023 cbInfo->pythonError = 1;
01024 cbInfo->_save = PyEval_SaveThread();
01025 return NULL;
01026 }
01027 Py_DECREF(result);
01028 cbInfo->_save = PyEval_SaveThread();
01029
01030 fd = fdDup(fdno);
01031 if (_rpmts_debug)
01032 fprintf(stderr, "\t%p = fdDup(%d)\n", fd, fdno);
01033
01034 return fd;
01035 } else
01036 if (what == RPMCALLBACK_INST_CLOSE_FILE) {
01037 if (_rpmts_debug)
01038 fprintf(stderr, "\tFclose(%p)\n", fd);
01039 Fclose (fd);
01040 } else {
01041 if (_rpmts_debug)
01042 fprintf(stderr, "\t%ld:%ld key %p\n", amount, total, pkgKey);
01043 }
01044
01045 Py_DECREF(result);
01046 cbInfo->_save = PyEval_SaveThread();
01047
01048 return NULL;
01049 }
01050
01053 static PyObject * rpmts_SetFlags(rpmtsObject * s, PyObject * args)
01054
01055 {
01056 rpmtransFlags transFlags = 0;
01057
01058 if (!PyArg_ParseTuple(args, "i:SetFlags", &transFlags))
01059 return NULL;
01060
01061 if (_rpmts_debug)
01062 fprintf(stderr, "*** rpmts_SetFlags(%p) ts %p transFlags %x\n", s, s->ts, transFlags);
01063
01064 return Py_BuildValue("i", rpmtsSetFlags(s->ts, transFlags));
01065 }
01066
01069 static PyObject * rpmts_SetProbFilter(rpmtsObject * s, PyObject * args)
01070
01071 {
01072 rpmprobFilterFlags ignoreSet = 0;
01073 rpmprobFilterFlags oignoreSet;
01074
01075 if (!PyArg_ParseTuple(args, "i:ProbFilter", &ignoreSet))
01076 return NULL;
01077
01078 if (_rpmts_debug)
01079 fprintf(stderr, "*** rpmts_SetProbFilter(%p) ts %p ignoreSet %x\n", s, s->ts, ignoreSet);
01080
01081 oignoreSet = s->ignoreSet;
01082 s->ignoreSet = ignoreSet;
01083
01084 return Py_BuildValue("i", oignoreSet);
01085 }
01086
01089 static PyObject * rpmts_Run(rpmtsObject * s, PyObject * args)
01090
01091
01092 {
01093 int rc, i;
01094 PyObject * list;
01095 rpmps ps;
01096 struct rpmtsCallbackType_s cbInfo;
01097
01098 if (!PyArg_ParseTuple(args, "OO:Run", &cbInfo.cb, &cbInfo.data))
01099 return NULL;
01100
01101 cbInfo.tso = s;
01102 cbInfo.pythonError = 0;
01103 cbInfo._save = PyEval_SaveThread();
01104
01105 if (cbInfo.cb != NULL) {
01106 if (!PyCallable_Check(cbInfo.cb)) {
01107 PyErr_SetString(PyExc_TypeError, "expected a callable");
01108 return NULL;
01109 }
01110 (void) rpmtsSetNotifyCallback(s->ts, rpmtsCallback, (void *) &cbInfo);
01111 }
01112
01113
01114 if (_rpmts_debug)
01115 fprintf(stderr, "*** rpmts_Run(%p) ts %p ignore %x\n", s, s->ts, s->ignoreSet);
01116
01117 rc = rpmtsRun(s->ts, NULL, s->ignoreSet);
01118 ps = rpmtsProblems(s->ts);
01119
01120 if (cbInfo.cb)
01121 (void) rpmtsSetNotifyCallback(s->ts, NULL, NULL);
01122
01123 PyEval_RestoreThread(cbInfo._save);
01124
01125 if (cbInfo.pythonError) {
01126 ps = rpmpsFree(ps);
01127 return NULL;
01128 }
01129
01130 if (rc < 0) {
01131 list = PyList_New(0);
01132 return list;
01133 } else if (!rc) {
01134 Py_INCREF(Py_None);
01135 return Py_None;
01136 }
01137
01138 list = PyList_New(0);
01139 for (i = 0; i < ps->numProblems; i++) {
01140 rpmProblem p = ps->probs + i;
01141 PyObject * prob = Py_BuildValue("s(isN)", rpmProblemString(p),
01142 p->type,
01143 p->str1,
01144 PyLong_FromLongLong(p->ulong1));
01145 PyList_Append(list, prob);
01146 Py_DECREF(prob);
01147 }
01148
01149 ps = rpmpsFree(ps);
01150
01151 return list;
01152 }
01153
01154 #if Py_TPFLAGS_HAVE_ITER
01155 static PyObject *
01156 rpmts_iter(rpmtsObject * s)
01157
01158 {
01159 if (_rpmts_debug)
01160 fprintf(stderr, "*** rpmts_iter(%p) ts %p\n", s, s->ts);
01161
01162 Py_INCREF(s);
01163 return (PyObject *)s;
01164 }
01165 #endif
01166
01170 static PyObject *
01171 rpmts_iternext(rpmtsObject * s)
01172
01173 {
01174 PyObject * result = NULL;
01175 rpmte te;
01176
01177 if (_rpmts_debug)
01178 fprintf(stderr, "*** rpmts_iternext(%p) ts %p tsi %p %d\n", s, s->ts, s->tsi, s->tsiFilter);
01179
01180
01181 if (s->tsi == NULL) {
01182 s->tsi = rpmtsiInit(s->ts);
01183 if (s->tsi == NULL)
01184 return NULL;
01185 s->tsiFilter = 0;
01186 }
01187
01188 te = rpmtsiNext(s->tsi, s->tsiFilter);
01189 if (te != NULL) {
01190 result = (PyObject *) rpmte_Wrap(te);
01191 } else {
01192 s->tsi = rpmtsiFree(s->tsi);
01193 s->tsiFilter = 0;
01194 }
01195
01196 return result;
01197 }
01198
01202 static PyObject *
01203 rpmts_Next(rpmtsObject * s)
01204
01205
01206 {
01207 PyObject * result;
01208
01209 if (_rpmts_debug)
01210 fprintf(stderr, "*** rpmts_Next(%p) ts %p\n", s, s->ts);
01211
01212 result = rpmts_iternext(s);
01213
01214 if (result == NULL) {
01215 Py_INCREF(Py_None);
01216 return Py_None;
01217 }
01218
01219 return result;
01220 }
01221
01224 static rpmmiObject *
01225 rpmts_Match(rpmtsObject * s, PyObject * args)
01226
01227
01228 {
01229 PyObject *TagN = NULL;
01230 char *key = NULL;
01231 int len = 0;
01232 int tag = RPMDBI_PACKAGES;
01233
01234 if (_rpmts_debug)
01235 fprintf(stderr, "*** rpmts_Match(%p) ts %p\n", s, s->ts);
01236
01237 if (!PyArg_ParseTuple(args, "|Ozi", &TagN, &key, &len))
01238 return NULL;
01239
01240 if (TagN && (tag = tagNumFromPyObject (TagN)) == -1) {
01241 PyErr_SetString(PyExc_TypeError, "unknown tag type");
01242 return NULL;
01243 }
01244
01245
01246 if (s->ts->rdb == NULL) {
01247 int rc = rpmtsOpenDB(s->ts, O_RDONLY);
01248 if (rc || s->ts->rdb == NULL) {
01249 PyErr_SetString(PyExc_TypeError, "rpmdb open failed");
01250 return NULL;
01251 }
01252 }
01253
01254 return rpmmi_Wrap( rpmtsInitIterator(s->ts, tag, key, len) );
01255 }
01256
01259
01260
01261 static struct PyMethodDef rpmts_methods[] = {
01262 {"Debug", (PyCFunction)rpmts_Debug, METH_VARARGS,
01263 NULL},
01264
01265 {"addInstall", (PyCFunction) rpmts_AddInstall, METH_VARARGS,
01266 NULL },
01267 {"addErase", (PyCFunction) rpmts_AddErase, METH_VARARGS,
01268 NULL },
01269 {"check", (PyCFunction) rpmts_Check, METH_VARARGS,
01270 NULL },
01271 {"order", (PyCFunction) rpmts_Order, METH_VARARGS,
01272 NULL },
01273 {"setFlags", (PyCFunction) rpmts_SetFlags, METH_VARARGS,
01274 "ts.setFlags(transFlags) -> previous transFlags\n\
01275 - Set control bit(s) for executing ts.run().\n\
01276 Note: This method replaces the 1st argument to the old ts.run()\n" },
01277 {"setProbFilter", (PyCFunction) rpmts_SetProbFilter, METH_VARARGS,
01278 "ts.setProbFilter(ignoreSet) -> previous ignoreSet\n\
01279 - Set control bit(s) for ignoring problems found by ts.run().\n\
01280 Note: This method replaces the 2nd argument to the old ts.run()\n" },
01281 {"run", (PyCFunction) rpmts_Run, METH_VARARGS,
01282 "ts.run(callback, data) -> (problems)\n\
01283 - Run a transaction set, returning list of problems found.\n\
01284 Note: The callback may not be None.\n" },
01285 {"clean", (PyCFunction) rpmts_Clean, METH_VARARGS,
01286 NULL },
01287 {"IDTXload", (PyCFunction) rpmts_IDTXload, METH_VARARGS,
01288 "ts.IDTXload() -> ((tid,hdr,instance)+)\n\
01289 - Return list of installed packages reverse sorted by transaction id.\n" },
01290 {"IDTXglob", (PyCFunction) rpmts_IDTXglob, METH_VARARGS,
01291 "ts.IDTXglob() -> ((tid,hdr,instance)+)\n\
01292 - Return list of removed packages reverse sorted by transaction id.\n" },
01293 {"rollback", (PyCFunction) rpmts_Rollback, METH_VARARGS,
01294 NULL },
01295 {"openDB", (PyCFunction) rpmts_OpenDB, METH_VARARGS,
01296 "ts.openDB() -> None\n\
01297 - Open the default transaction rpmdb.\n\
01298 Note: The transaction rpmdb is lazily opened, so ts.openDB() is seldom needed.\n" },
01299 {"closeDB", (PyCFunction) rpmts_CloseDB, METH_VARARGS,
01300 "ts.closeDB() -> None\n\
01301 - Close the default transaction rpmdb.\n\
01302 Note: ts.closeDB() disables lazy opens, and should hardly ever be used.\n" },
01303 {"initDB", (PyCFunction) rpmts_InitDB, METH_VARARGS,
01304 "ts.initDB() -> None\n\
01305 - Initialize the default transaction rpmdb.\n\
01306 Note: ts.initDB() is seldom needed anymore.\n" },
01307 {"rebuildDB", (PyCFunction) rpmts_RebuildDB, METH_VARARGS,
01308 "ts.rebuildDB() -> None\n\
01309 - Rebuild the default transaction rpmdb.\n" },
01310 {"verifyDB", (PyCFunction) rpmts_VerifyDB, METH_VARARGS,
01311 "ts.verifyDB() -> None\n\
01312 - Verify the default transaction rpmdb.\n" },
01313 {"hdrFromFdno",(PyCFunction) rpmts_HdrFromFdno,METH_VARARGS,
01314 "ts.hdrFromFdno(fdno) -> hdr\n\
01315 - Read a package header from a file descriptor.\n" },
01316 {"hdrCheck", (PyCFunction) rpmts_HdrCheck, METH_VARARGS,
01317 NULL },
01318 {"setVSFlags",(PyCFunction) rpmts_SetVSFlags, METH_VARARGS,
01319 "ts.setVSFlags(vsflags) -> ovsflags\n\
01320 - Set signature verification flags. Values for vsflags are:\n\
01321 rpm.RPMVSF_NOHDRCHK if set, don't check rpmdb headers\n\
01322 rpm.RPMVSF_NEEDPAYLOAD if not set, check header+payload (if possible)\n\
01323 rpm.RPMVSF_NOSHA1HEADER if set, don't check header SHA1 digest\n\
01324 rpm.RPMVSF_NODSAHEADER if set, don't check header DSA signature\n\
01325 rpm.RPMVSF_NOMD5 if set, don't check header+payload MD5 digest\n\
01326 rpm.RPMVSF_NODSA if set, don't check header+payload DSA signature\n\
01327 rpm.RPMVSF_NORSA if set, don't check header+payload RSA signature\n\
01328 rpm._RPMVSF_NODIGESTS if set, don't check digest(s)\n\
01329 rpm._RPMVSF_NOSIGNATURES if set, don't check signature(s)\n" },
01330 {"setColor",(PyCFunction) rpmts_SetColor, METH_VARARGS,
01331 NULL },
01332 {"pgpPrtPkts", (PyCFunction) rpmts_PgpPrtPkts, METH_VARARGS,
01333 NULL },
01334 {"pgpImportPubkey", (PyCFunction) rpmts_PgpImportPubkey, METH_VARARGS,
01335 NULL },
01336 {"getKeys", (PyCFunction) rpmts_GetKeys, METH_VARARGS,
01337 NULL },
01338 {"dbMatch", (PyCFunction) rpmts_Match, METH_VARARGS,
01339 "ts.dbMatch([TagN, [key, [len]]]) -> mi\n\
01340 - Create a match iterator for the default transaction rpmdb.\n" },
01341 {"next", (PyCFunction)rpmts_Next, METH_VARARGS,
01342 "ts.next() -> te\n\
01343 - Retrieve next transaction set element.\n" },
01344 {NULL, NULL}
01345 };
01346
01347
01350 static void rpmts_dealloc( rpmtsObject * s)
01351
01352 {
01353
01354 if (_rpmts_debug)
01355 fprintf(stderr, "%p -- ts %p db %p\n", s, s->ts, s->ts->rdb);
01356 s->ts = rpmtsFree(s->ts);
01357
01358 if (s->scriptFd) Fclose(s->scriptFd);
01359
01360
01361 Py_DECREF(s->keyList);
01362 PyObject_Del((PyObject *)s);
01363 }
01364
01367 static PyObject * rpmts_getattr(rpmtsObject * o, char * name)
01368
01369 {
01370 return Py_FindMethod(rpmts_methods, (PyObject *) o, name);
01371 }
01372
01375 static int rpmts_setattr(rpmtsObject * o, char * name, PyObject * val)
01376
01377 {
01378 int i;
01379
01380 if (!strcmp(name, "scriptFd")) {
01381 if (!PyArg_Parse(val, "i", &i)) return 0;
01382 if (i < 0) {
01383 PyErr_SetString(PyExc_TypeError, "bad file descriptor");
01384 return -1;
01385 } else {
01386 o->scriptFd = fdDup(i);
01387 rpmtsSetScriptFd(o->ts, o->scriptFd);
01388 }
01389 } else {
01390 PyErr_SetString(PyExc_AttributeError, name);
01391 return -1;
01392 }
01393
01394 return 0;
01395 }
01396
01399 static int rpmts_init(rpmtsObject * s, PyObject *args, PyObject *kwds)
01400
01401
01402 {
01403 char * rootDir = "/";
01404 int vsflags = rpmExpandNumeric("%{?_vsflags_up2date}");
01405
01406 if (_rpmts_debug < 0)
01407 fprintf(stderr, "*** rpmts_init(%p,%p,%p)\n", s, args, kwds);
01408
01409 if (!PyArg_ParseTuple(args, "|si:rpmts_init", &rootDir, &vsflags))
01410 return -1;
01411
01412 s->ts = rpmtsCreate();
01413 (void) rpmtsSetRootDir(s->ts, rootDir);
01414 (void) rpmtsSetVSFlags(s->ts, vsflags);
01415 s->keyList = PyList_New(0);
01416 s->scriptFd = NULL;
01417 s->tsi = NULL;
01418 s->tsiFilter = 0;
01419
01420 return 0;
01421 }
01422
01425 static void rpmts_free( rpmtsObject * s)
01426
01427 {
01428 if (_rpmts_debug)
01429 fprintf(stderr, "%p -- ts %p db %p\n", s, s->ts, s->ts->rdb);
01430 rpmtsFree(s->ts);
01431
01432 if (s->scriptFd)
01433 Fclose(s->scriptFd);
01434
01435
01436
01437 Py_DECREF(s->keyList);
01438
01439 PyObject_Del((PyObject *)s);
01440 }
01441
01444 static PyObject * rpmts_alloc(PyTypeObject * subtype, int nitems)
01445
01446 {
01447 PyObject * s = PyType_GenericAlloc(subtype, nitems);
01448
01449 if (_rpmts_debug < 0)
01450 fprintf(stderr, "*** rpmts_alloc(%p,%d) ret %p\n", subtype, nitems, s);
01451 return s;
01452 }
01453
01456 static PyObject * rpmts_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
01457
01458
01459 {
01460 rpmtsObject * s = (void *) PyObject_New(rpmtsObject, subtype);
01461
01462
01463 if (rpmts_init(s, args, kwds) < 0) {
01464 rpmts_free(s);
01465 return NULL;
01466 }
01467
01468 if (_rpmts_debug)
01469 fprintf(stderr, "%p ++ ts %p db %p\n", s, s->ts, s->ts->rdb);
01470
01471 return (PyObject *)s;
01472 }
01473
01476
01477 static char rpmts_doc[] =
01478 "";
01479
01482
01483 PyTypeObject rpmts_Type = {
01484 PyObject_HEAD_INIT(&PyType_Type)
01485 0,
01486 "rpm.ts",
01487 sizeof(rpmtsObject),
01488 0,
01489 (destructor) rpmts_dealloc,
01490 0,
01491 (getattrfunc) rpmts_getattr,
01492 (setattrfunc) rpmts_setattr,
01493 0,
01494 0,
01495 0,
01496 0,
01497 0,
01498 0,
01499 0,
01500 0,
01501 0,
01502 0,
01503 0,
01504 Py_TPFLAGS_DEFAULT,
01505 rpmts_doc,
01506 #if Py_TPFLAGS_HAVE_ITER
01507 0,
01508 0,
01509 0,
01510 0,
01511 (getiterfunc) rpmts_iter,
01512 (iternextfunc) rpmts_iternext,
01513 rpmts_methods,
01514 0,
01515 0,
01516 0,
01517 0,
01518 0,
01519 0,
01520 0,
01521 (initproc) rpmts_init,
01522 (allocfunc) rpmts_alloc,
01523 (newfunc) rpmts_new,
01524 (destructor) rpmts_free,
01525 0,
01526 #endif
01527 };
01528
01529
01532 rpmtsObject *
01533 rpmts_Create( PyObject * self, PyObject * args)
01534 {
01535 rpmtsObject * o;
01536 char * rootDir = "/";
01537 int vsflags = rpmExpandNumeric("%{?_vsflags_up2date}");
01538
01539 if (!PyArg_ParseTuple(args, "|si:Create", &rootDir, &vsflags))
01540 return NULL;
01541
01542 o = (void *) PyObject_New(rpmtsObject, &rpmts_Type);
01543
01544 o->ts = rpmtsCreate();
01545 (void) rpmtsSetRootDir(o->ts, rootDir);
01546 (void) rpmtsSetVSFlags(o->ts, vsflags);
01547
01548 o->keyList = PyList_New(0);
01549 o->scriptFd = NULL;
01550 o->tsi = NULL;
01551 o->tsiFilter = 0;
01552
01553 if (_rpmts_debug)
01554 fprintf(stderr, "%p ++ ts %p db %p\n", o, o->ts, o->ts->rdb);
01555 return o;
01556 }