rpm  5.4.10
rpmts-py.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <rpmio_internal.h> /* XXX for fdSetOpen */
8 #include <rpmcb.h>
9 
10 #define _RPMPS_INTERNAL /* XXX almost (but not quite) opaque. */
11 #include <rpmpgp.h>
12 
13 #include <rpmtypes.h>
14 #include <rpmtag.h>
15 #include <pkgio.h> /* XXX headerCheck() */
16 #include <rpmdb.h>
17 
18 #define _RPMTS_INTERNAL /* XXX expose rpmtsSetScriptFd */
19 #include <rpmbuild.h>
20 
21 #include <rpmcli.h>
22 #define _RPMROLLBACK_INTERNAL /* XXX IDTX et al */
23 #include <rpmrollback.h>
24 
25 #include "header-py.h"
26 #include "rpmds-py.h" /* XXX for rpmdsNew */
27 #include "rpmfi-py.h" /* XXX for rpmfiNew */
28 #include "rpmmi-py.h"
29 #include "rpmps-py.h"
30 #include "rpmte-py.h"
31 #include "spec-py.h"
32 
33 #include "rpmts-py.h"
34 
35 #include "debug.h"
36 
37 #define rpmtsfree() rpmioFreePoolItem()
38 
39 /*@unchecked@*/
40 /*@-shadow@*/
41 extern int _rpmts_debug;
42 /*@=shadow@*/
43 
44 /*@access alKey @*/
45 /*@access FD_t @*/
46 /*@access Header @*/
47 /*@access rpmal @*/
48 /*@access rpmdb @*/
49 /*@access rpmds @*/
50 /*@access rpmts @*/
51 /*@access rpmtsi @*/
52 
170  PyObject * cb;
171  PyObject * data;
174  PyThreadState *_save;
175 };
176 
179 /*@exits@*/
180 static void rpmts_Die(PyObject *cb)
181  /*@*/
182 {
183  PyObject * r = PyObject_Repr(cb);
184  char *pyfn = (r != NULL ? PyString_AsString(r) : "???");
185 
186  if (PyErr_Occurred())
187  PyErr_Print();
188  rpmlog(RPMLOG_ERR, _("python callback %s failed, aborting!\n"), pyfn);
190  exit(EXIT_FAILURE);
191 }
192 
195 static int
196 rpmts_SolveCallback(rpmts ts, rpmds ds, const void * data)
197  /*@*/
198 {
199  struct rpmtsCallbackType_s * cbInfo = (struct rpmtsCallbackType_s *) data;
200  PyObject * args, * result;
201  int res = 1;
202 
203 if (_rpmts_debug)
204 fprintf(stderr, "*** rpmts_SolveCallback(%p,%p,%p) \"%s\"\n", ts, ds, data, rpmdsDNEVR(ds));
205 
206  if (cbInfo->tso == NULL) return res;
207  if (cbInfo->cb == Py_None) return res;
208 
209  PyEval_RestoreThread(cbInfo->_save);
210 
211  cbInfo->dso = rpmds_Wrap(ds); /* XXX perhaps persistent? */
212  args = Py_BuildValue("(OO)", cbInfo->tso, cbInfo->dso);
213  result = PyEval_CallObject(cbInfo->cb, args);
214  Py_XDECREF(cbInfo->dso);
215  cbInfo->dso = NULL;
216  Py_XDECREF(args);
217 
218  if (!result) {
219  rpmts_Die(cbInfo->cb);
220  /*@notreached@*/
221  } else {
222  if (PyInt_Check(result))
223  res = PyInt_AsLong(result);
224  Py_XDECREF(result);
225  }
226 
227  cbInfo->_save = PyEval_SaveThread();
228 
229  return res;
230 }
231 
234 /*@null@*/
235 static void *
236 rpmtsCallback(/*@unused@*/ const void * hd, const rpmCallbackType what,
237  const rpmuint64_t amount, const rpmuint64_t total,
238  fnpyKey pkgKey, rpmCallbackData data)
239  /*@globals _Py_NoneStruct @*/
240  /*@modifies _Py_NoneStruct @*/
241 {
242 /*@-castexpose@*/
243  Header h = (Header) hd;
244 /*@=castexpose@*/
245  struct rpmtsCallbackType_s * cbInfo = data;
246  PyObject * pkgObj = (PyObject *) pkgKey;
247  PyObject * oh = NULL;
248  const char * origin = NULL;
249  PyObject * args, * result;
250  static FD_t fd;
251 
252  if (cbInfo->cb == Py_None) return NULL;
253 
254  /* Synthesize a python object for callback (if necessary). */
255  if (pkgObj == NULL) {
256  if (h) {
257  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
258  he->tag = RPMTAG_NAME;
259  if (headerGet(h, he, 0)) {
260  pkgObj = Py_BuildValue("s", he->p.str);
261  he->p.ptr = _free(he->p.ptr);
262  } else {
263  pkgObj = Py_None;
264  Py_INCREF(pkgObj);
265  }
266  } else {
267  pkgObj = Py_None;
268  Py_INCREF(pkgObj);
269  }
270  } else {
271  Py_INCREF(pkgObj);
272  /* XXX yum has (h, rpmloc) tuple as pkgKey. Extract the path. */
273  if (!(PyTuple_Check(pkgObj) && PyArg_ParseTuple(pkgObj, "|Os", &oh, &origin)))
274  origin = NULL;
275  /* XXX clean up the path, yum paths start "//..." */
276  if (origin && origin[0] == '/' && origin[1] == '/')
277  origin++;
278  }
279 
280  PyEval_RestoreThread(cbInfo->_save);
281 
282  args = Py_BuildValue("(iLLOO)", what, amount, total, pkgObj, cbInfo->data);
283  result = PyEval_CallObject(cbInfo->cb, args);
284  Py_XDECREF(args);
285  Py_XDECREF(pkgObj);
286 
287  if (!result) {
288  rpmts_Die(cbInfo->cb);
289  /*@notreached@*/
290  }
291 
292  if (what == RPMCALLBACK_INST_OPEN_FILE) {
293  int fdno;
294 
295  if (!PyArg_Parse(result, "i", &fdno)) {
296  rpmts_Die(cbInfo->cb);
297  /*@notreached@*/
298  }
299  Py_XDECREF(result);
300  cbInfo->_save = PyEval_SaveThread();
301 
302  fd = fdDup(fdno);
303 if (_rpmts_debug)
304 fprintf(stderr, "\t%p = fdDup(%d)\n", fd, fdno);
305 
306  fcntl(Fileno(fd), F_SETFD, FD_CLOEXEC);
307 
308  if (origin != NULL)
309  (void) fdSetOpen(fd, origin, 0, 0);
310 
311  return fd;
312  } else
313  if (what == RPMCALLBACK_INST_CLOSE_FILE) {
314 if (_rpmts_debug)
315 fprintf(stderr, "\tFclose(%p)\n", fd);
316  Fclose (fd);
317  } else {
318 if (_rpmts_debug)
319 fprintf(stderr, "\t%llu:%llu key %p\n", (unsigned long long)amount, (unsigned long long)total, pkgKey);
320  }
321 
322  Py_XDECREF(result);
323  cbInfo->_save = PyEval_SaveThread();
324 
325  return NULL;
326 }
327 
328 #if Py_TPFLAGS_HAVE_ITER
329 
331 static PyObject *
333  /*@*/
334 {
335 if (_rpmts_debug)
336 fprintf(stderr, "*** rpmts_iter(%p) ts %p\n", s, s->ts);
337 
338  Py_INCREF(s);
339  return (PyObject *)s;
340 }
341 #endif
342 
346 /*@null@*/
347 static PyObject *
349  /*@modifies s @*/
350 {
351  PyObject * result = NULL;
352  rpmte te;
353 
354 if (_rpmts_debug)
355 fprintf(stderr, "*** rpmts_iternext(%p) ts %p tsi %p %d\n", s, s->ts, s->tsi, s->tsiFilter);
356 
357  /* Reset iterator on 1st entry. */
358  if (s->tsi == NULL) {
359  s->tsi = rpmtsiInit(s->ts);
360  if (s->tsi == NULL)
361  return NULL;
362  s->tsiFilter = 0;
363  }
364 
365  te = rpmtsiNext(s->tsi, s->tsiFilter);
366 /*@-branchstate@*/
367  if (te != NULL) {
368  result = (PyObject *) rpmte_Wrap(te);
369  } else {
370  s->tsi = rpmtsiFree(s->tsi);
371  s->tsiFilter = 0;
372  }
373 /*@=branchstate@*/
374 
375  return result;
376 }
377 
382 
385 /*@null@*/
386 static PyObject *
387 rpmts_Debug(/*@unused@*/ rpmtsObject * s, PyObject * args, PyObject * kwds)
388  /*@globals _Py_NoneStruct @*/
389  /*@modifies _Py_NoneStruct @*/
390 {
391  char * kwlist[] = {"debugLevel", NULL};
392 
393  if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:Debug", kwlist,
394  &_rpmts_debug))
395  return NULL;
396 
397 if (_rpmts_debug < 0)
398 fprintf(stderr, "*** rpmts_Debug(%p) ts %p\n", s, s->ts);
399 
400  Py_INCREF(Py_None);
401  return Py_None;
402 }
403 
406 /*@null@*/
407 static PyObject *
408 rpmts_AddInstall(rpmtsObject * s, PyObject * args, PyObject * kwds)
409  /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
410  /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
411 {
412  hdrObject * h;
413  PyObject * key;
414  char * how = "u"; /* XXX default to upgrade element if missing */
415  int isUpgrade = 0;
416  char * kwlist[] = {"header", "key", "how", NULL};
417 
418  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O|s:AddInstall", kwlist,
419  &hdr_Type, &h, &key, &how))
420  return NULL;
421 
422  { PyObject * hObj = (PyObject *) h;
423  if (hObj->ob_type != &hdr_Type) {
424  PyErr_SetString(PyExc_TypeError, "bad type for header argument");
425  return NULL;
426  }
427  }
428 
429 if (_rpmts_debug < 0 || (_rpmts_debug > 0 && *how != 'a'))
430 fprintf(stderr, "*** rpmts_AddInstall(%p,%p,%p,%s) ts %p\n", s, h, key, how, s->ts);
431 
432  if (how && strcmp(how, "a") && strcmp(how, "u") && strcmp(how, "i")) {
433  PyErr_SetString(PyExc_TypeError, "how argument must be \"u\", \"a\", or \"i\"");
434  return NULL;
435  } else if (how && !strcmp(how, "u"))
436  isUpgrade = 1;
437 
438  rpmtsAddInstallElement(s->ts, hdrGetHeader(h), key, isUpgrade, NULL);
439 
440  /* This should increment the usage count for me */
441  if (key)
442  PyList_Append(s->keyList, key);
443 
444  Py_INCREF(Py_None);
445  return Py_None;
446 }
447 
451 /*@null@*/
452 static PyObject *
453 rpmts_AddErase(rpmtsObject * s, PyObject * args, PyObject * kwds)
454  /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
455  /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
456 {
457  PyObject * o;
458  int count;
459  rpmmi mi;
460  char * kwlist[] = {"name", NULL};
461 
462 if (_rpmts_debug)
463 fprintf(stderr, "*** rpmts_AddErase(%p) ts %p\n", s, s->ts);
464 
465  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:AddErase", kwlist, &o))
466  return NULL;
467 
468  if (PyString_Check(o) || PyUnicode_Check(o)) {
469  char * name = PyString_AsString(o);
470 
471  mi = rpmtsInitIterator(s->ts, RPMTAG_NVRA, name, 0);
472  count = rpmmiCount(mi);
473  if (count <= 0) {
474  mi = rpmmiFree(mi);
475  PyErr_SetString(pyrpmError, "package not installed");
476  return NULL;
477  } else { /* XXX: Note that we automatically choose to remove all matches */
478  Header h;
479  while ((h = rpmmiNext(mi)) != NULL) {
480  uint32_t hdrNum = rpmmiInstance(mi);
481  if (hdrNum)
482  rpmtsAddEraseElement(s->ts, h, hdrNum);
483  }
484  }
485  mi = rpmmiFree(mi);
486  } else
487  if (PyInt_Check(o)) {
488  uint32_t instance = PyInt_AsLong(o);
489 
490  mi = rpmtsInitIterator(s->ts, RPMDBI_PACKAGES, &instance, sizeof(instance));
491  if (instance == 0 || mi == NULL) {
492  mi = rpmmiFree(mi);
493  PyErr_SetString(pyrpmError, "package not installed");
494  return NULL;
495  } else {
496  Header h;
497  while ((h = rpmmiNext(mi)) != NULL) {
498  uint32_t hdrNum = rpmmiInstance(mi);
499  if (hdrNum)
500  rpmtsAddEraseElement(s->ts, h, hdrNum);
501  break;
502  }
503  }
504  mi = rpmmiFree(mi);
505  }
506 
507  Py_INCREF(Py_None);
508  return Py_None;
509 }
510 
513 /*@null@*/
514 static PyObject *
515 rpmts_Check(rpmtsObject * s, PyObject * args, PyObject * kwds)
516  /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
517  /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
518 {
519  rpmps ps;
520  rpmProblem p;
521  PyObject * list, * cf;
522  struct rpmtsCallbackType_s cbInfo;
523  int i;
524  int xx;
525  char * kwlist[] = {"callback", NULL};
526 
527  memset(&cbInfo, 0, sizeof(cbInfo));
528  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:Check", kwlist,
529  &cbInfo.cb))
530  return NULL;
531 
532  if (cbInfo.cb != NULL) {
533  if (!PyCallable_Check(cbInfo.cb)) {
534  PyErr_SetString(PyExc_TypeError, "expected a callable");
535  return NULL;
536  }
537  xx = rpmtsSetSolveCallback(s->ts, rpmts_SolveCallback, (void *)&cbInfo);
538  }
539 
540 if (_rpmts_debug)
541 fprintf(stderr, "*** rpmts_Check(%p) ts %p cb %p\n", s, s->ts, cbInfo.cb);
542 
543  cbInfo.tso = s;
544  cbInfo.dso = NULL; /* XXX perhaps persistent? */
545  cbInfo._save = PyEval_SaveThread();
546 
547  xx = rpmtsCheck(s->ts);
548  ps = rpmtsProblems(s->ts);
549 
550  if (cbInfo.cb)
551  xx = rpmtsSetSolveCallback(s->ts, rpmtsSolve, NULL);
552 
553  PyEval_RestoreThread(cbInfo._save);
554 
555  if (ps != NULL) {
556  list = PyList_New(0);
557  if (!list) {
558  return NULL;
559  }
560 
561  rpmpsi psi = rpmpsInitIterator(ps);
562 
563  while ((i = rpmpsNextIterator(psi)) >= 0) {
564 #ifdef DYING
565  cf = Py_BuildValue("((sss)(ss)iOi)", conflicts[i].byName,
566  conflicts[i].byVersion, conflicts[i].byRelease,
567 
568  conflicts[i].needsName,
569  conflicts[i].needsVersion,
570 
571  conflicts[i].needsFlags,
572  conflicts[i].suggestedPkgs ?
573  conflicts[i].suggestedPkgs[0] : Py_None,
574  conflicts[i].sense);
575 #else
576  char * byName, * byVersion, * byRelease, *byArch;
577  char * needsName, * needsOP, * needsVersion;
578  char * a, * b;
579  int needsFlags, sense;
580  fnpyKey key;
581 
582  p = rpmpsProblem(psi);
583 
584  /* XXX autorelocated i386 on ia64, fix system-config-packages! */
586  continue;
587 
588  a = byName = xstrdup(rpmProblemGetPkgNEVR(p));
589  if ((byArch= strrchr(byName, '.')) != NULL)
590  *byArch++ = '\0';
591  if ((byRelease = strrchr(byName, '-')) != NULL)
592  *byRelease++ = '\0';
593  if ((byVersion = strrchr(byName, '-')) != NULL)
594  *byVersion++ = '\0';
595 
596  key = rpmProblemKey(p);
597 
598  b = needsName = xstrdup(rpmProblemGetAltNEVR(p));
599  if (needsName[1] == ' ') {
600  sense = (needsName[0] == 'C')
602  needsName += 2;
603  } else
604  sense = RPMDEP_SENSE_REQUIRES;
605  if ((needsVersion = strrchr(needsName, ' ')) != NULL)
606  *needsVersion++ = '\0';
607 
608  needsFlags = 0;
609  if ((needsOP = strrchr(needsName, ' ')) != NULL) {
610  for (*needsOP++ = '\0'; *needsOP != '\0'; needsOP++) {
611  if (*needsOP == '<') needsFlags |= RPMSENSE_LESS;
612  else if (*needsOP == '>') needsFlags |= RPMSENSE_GREATER;
613  else if (*needsOP == '=') needsFlags |= RPMSENSE_EQUAL;
614  }
615  }
616 
617  cf = Py_BuildValue("((sss)(ss)iOi)", byName, byVersion, byRelease,
618  needsName, needsVersion, needsFlags,
619  (key != NULL ? key : Py_None),
620  sense);
621  a = _free(a);
622  b = _free(b);
623 #endif
624  PyList_Append(list, (PyObject *) cf);
625  Py_XDECREF(cf);
626  }
627 
628  psi = rpmpsFreeIterator(psi);
629  ps = rpmpsFree(ps);
630 
631  return list;
632  }
633 
634  Py_INCREF(Py_None);
635  return Py_None;
636 }
637 
640 /*@null@*/
641 static PyObject *
643  /*@globals rpmGlobalMacroContext @*/
644  /*@modifies s, rpmGlobalMacroContext @*/
645 {
646  int rc;
647 
648 if (_rpmts_debug)
649 fprintf(stderr, "*** rpmts_Order(%p) ts %p\n", s, s->ts);
650 
651  Py_BEGIN_ALLOW_THREADS
652  rc = rpmtsOrder(s->ts);
653  Py_END_ALLOW_THREADS
654 
655  return Py_BuildValue("i", rc);
656 }
657 
660 /*@null@*/
661 static PyObject *
663  /*@globals _Py_NoneStruct @*/
664  /*@modifies s, _Py_NoneStruct @*/
665 {
666 if (_rpmts_debug)
667 fprintf(stderr, "*** rpmts_Clean(%p) ts %p\n", s, s->ts);
668 
669  rpmtsClean(s->ts);
670 
671  Py_INCREF(Py_None);
672  return Py_None;
673 }
674 
677 /*@null@*/
678 static PyObject *
679 rpmts_IDTXload(rpmtsObject * s, PyObject * args, PyObject * kwds)
680  /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
681  /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
682 {
683  PyObject * result = NULL;
685  char * kwlist[] = {"rbtid", NULL};
686  uint32_t rbtid = 0;
687  IDTX idtx;
688 
689 if (_rpmts_debug)
690 fprintf(stderr, "*** rpmts_IDTXload(%p) ts %p\n", s, s->ts);
691 
692  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:IDTXload", kwlist, &rbtid))
693  return NULL;
694 
695  Py_BEGIN_ALLOW_THREADS
696  idtx = IDTXload(s->ts, tag, rbtid);
697  Py_END_ALLOW_THREADS
698 
699 /*@-branchstate@*/
700  if (idtx == NULL || idtx->nidt <= 0) {
701  Py_INCREF(Py_None);
702  result = Py_None;
703  } else {
704  PyObject * tuple;
705  PyObject * ho;
706  IDT idt;
707  int i;
708 
709  result = PyTuple_New(idtx->nidt);
710  for (i = 0; i < idtx->nidt; i++) {
711  idt = idtx->idt + i;
712  ho = (PyObject *) hdr_Wrap(idt->h);
713  tuple = Py_BuildValue("(iOi)", idt->val.u32, ho, idt->instance);
714  PyTuple_SET_ITEM(result, i, tuple);
715  Py_XDECREF(ho);
716  }
717  }
718 /*@=branchstate@*/
719 
720  idtx = IDTXfree(idtx);
721 
722  return result;
723 }
724 
727 /*@null@*/
728 static PyObject *
729 rpmts_IDTXglob(rpmtsObject * s, PyObject * args, PyObject * kwds)
730  /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
731  /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
732 {
733  PyObject * result = NULL;
734  const char * globstr;
735  rpmTag tag = RPMTAG_REMOVETID;
736  char * kwlist[] = {"rbtid", NULL};
737  uint32_t rbtid = 0;
738  IDTX idtx;
739 
740 if (_rpmts_debug)
741 fprintf(stderr, "*** rpmts_IDTXglob(%p) ts %p\n", s, s->ts);
742 
743  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:IDTXglob", kwlist, &rbtid))
744  return NULL;
745 
746  Py_BEGIN_ALLOW_THREADS
747  globstr = rpmExpand("%{_repackage_dir}/*.rpm", NULL);
748  idtx = IDTXglob(s->ts, globstr, tag, rbtid);
749  globstr = _free(globstr);
750  Py_END_ALLOW_THREADS
751 
752 /*@-branchstate@*/
753  if (idtx == NULL || idtx->nidt <= 0) {
754  Py_INCREF(Py_None);
755  result = Py_None;
756  } else {
757  PyObject * tuple;
758  PyObject * ho;
759  IDT idt;
760  int i;
761 
762  result = PyTuple_New(idtx->nidt);
763  for (i = 0; i < idtx->nidt; i++) {
764  idt = idtx->idt + i;
765  ho = (PyObject *) hdr_Wrap(idt->h);
766  tuple = Py_BuildValue("(iOs)", idt->val.u32, ho, idt->key);
767  PyTuple_SET_ITEM(result, i, tuple);
768  Py_XDECREF(ho);
769  }
770  }
771 /*@=branchstate@*/
772 
773  idtx = IDTXfree(idtx);
774 
775  return result;
776 }
777 
780 /*@null@*/
781 static PyObject *
782 rpmts_Rollback(rpmtsObject * s, PyObject * args, PyObject * kwds)
783  /*@globals rpmGlobalMacroContext @*/
784  /*@modifies s, rpmGlobalMacroContext @*/
785 {
786  QVA_t ia = memset(alloca(sizeof(*ia)), 0, sizeof(*ia));
787  rpmtransFlags transFlags;
788  const char ** av = NULL;
789  uint32_t rbtid;
790  int rc;
791  char * kwlist[] = {"transactionId", NULL};
792 
793 if (_rpmts_debug)
794 fprintf(stderr, "*** rpmts_Rollback(%p) ts %p\n", s, s->ts);
795 
796  if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:Rollback", kwlist, &rbtid))
797  return NULL;
798 
799  Py_BEGIN_ALLOW_THREADS
804  ia->rbtid = rbtid;
805  ia->relocations = NULL;
807 
808  transFlags = rpmtsSetFlags(s->ts, ia->transFlags);
809  rc = rpmRollback(s->ts, ia, av);
810  transFlags = rpmtsSetFlags(s->ts, transFlags);
811  Py_END_ALLOW_THREADS
812 
813  return Py_BuildValue("i", rc);
814 }
815 
818 /*@null@*/
819 static PyObject *
821  /*@globals rpmGlobalMacroContext @*/
822  /*@modifies s, rpmGlobalMacroContext @*/
823 {
824 
825 if (_rpmts_debug)
826 fprintf(stderr, "*** rpmts_OpenDB(%p) ts %p\n", s, s->ts);
827 
828  if (rpmtsDBMode(s->ts) == -1)
829  (void) rpmtsSetDBMode(s->ts, O_RDONLY);
830 
831  return Py_BuildValue("i", rpmtsOpenDB(s->ts, rpmtsDBMode(s->ts)));
832 }
833 
836 /*@null@*/
837 static PyObject *
839  /*@modifies s @*/
840 {
841  int rc;
842 
843 if (_rpmts_debug)
844 fprintf(stderr, "*** rpmts_CloseDB(%p) ts %p\n", s, s->ts);
845 
846  rc = rpmtsCloseDB(s->ts);
847  (void) rpmtsSetDBMode(s->ts, -1); /* XXX disable lazy opens */
848 
849  return Py_BuildValue("i", rc);
850 }
851 
854 /*@null@*/
855 static PyObject *
857  /*@globals rpmGlobalMacroContext @*/
858  /*@modifies s, rpmGlobalMacroContext @*/
859 {
860  int rc;
861 
862 if (_rpmts_debug)
863 fprintf(stderr, "*** rpmts_InitDB(%p) ts %p\n", s, s->ts);
864 
865  rc = rpmtsInitDB(s->ts, O_RDONLY);
866  if (rc == 0)
867  rc = rpmtsCloseDB(s->ts);
868 
869  return Py_BuildValue("i", rc);
870 }
871 
874 /*@null@*/
875 static PyObject *
877  /*@globals rpmGlobalMacroContext @*/
878  /*@modifies s, rpmGlobalMacroContext @*/
879 {
880  int rc;
881 
882 if (_rpmts_debug)
883 fprintf(stderr, "*** rpmts_RebuildDB(%p) ts %p\n", s, s->ts);
884 
885  Py_BEGIN_ALLOW_THREADS
886  rc = rpmtsRebuildDB(s->ts);
887  Py_END_ALLOW_THREADS
888 
889  return Py_BuildValue("i", rc);
890 }
891 
894 /*@null@*/
895 static PyObject *
897  /*@globals rpmGlobalMacroContext @*/
898  /*@modifies s, rpmGlobalMacroContext @*/
899 {
900  int rc;
901 
902 if (_rpmts_debug)
903 fprintf(stderr, "*** rpmts_VerifyDB(%p) ts %p\n", s, s->ts);
904 
905  Py_BEGIN_ALLOW_THREADS
906  rc = rpmtsVerifyDB(s->ts);
907  Py_END_ALLOW_THREADS
908 
909  return Py_BuildValue("i", rc);
910 }
911 
914 /*@null@*/
915 static PyObject *
916 rpmts_HdrFromFdno(rpmtsObject * s, PyObject * args, PyObject * kwds)
917  /*@globals rpmGlobalMacroContext, fileSystem @*/
918  /*@modifies s, rpmGlobalMacroContext, fileSystem @*/
919 {
920  PyObject * result = NULL;
921  Header h;
922  FD_t fd;
923  int fdno;
924  rpmRC rpmrc;
925  char * kwlist[] = {"fd", NULL};
926 
927  if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:HdrFromFdno", kwlist,
928  &fdno))
929  return NULL;
930 
931  fd = fdDup(fdno);
932  rpmrc = rpmReadPackageFile(s->ts, fd, "rpmts_HdrFromFdno", &h);
933  Fclose(fd);
934 
935 if (_rpmts_debug)
936 fprintf(stderr, "*** rpmts_HdrFromFdno(%p) ts %p rc %d\n", s, s->ts, rpmrc);
937 
938 /*@-branchstate@*/
939  switch (rpmrc) {
940  case RPMRC_OK:
941  if (h)
942  result = Py_BuildValue("N", hdr_Wrap(h));
943  (void)headerFree(h); /* XXX ref held by result */
944  h = NULL;
945  break;
946 
947  case RPMRC_NOKEY:
948  PyErr_SetString(pyrpmError, "public key not available");
949  break;
950 
951  case RPMRC_NOTTRUSTED:
952  PyErr_SetString(pyrpmError, "public key not trusted");
953  break;
954 
955  case RPMRC_NOTFOUND:
956  case RPMRC_FAIL:
957  default:
958  PyErr_SetString(pyrpmError, "error reading package header");
959  break;
960  }
961 /*@=branchstate@*/
962 
963  return result;
964 }
965 
968 /*@null@*/
969 static PyObject *
970 rpmts_HdrCheck(rpmtsObject * s, PyObject * args, PyObject * kwds)
971  /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
972  /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
973 {
974  PyObject * blob;
975  PyObject * result = NULL;
976  const char * msg = NULL;
977  const void * uh;
978  int uc;
979  pgpDig dig;
980  rpmRC rpmrc;
981  char * kwlist[] = {"headers", NULL};
982 
983 if (_rpmts_debug)
984 fprintf(stderr, "*** rpmts_HdrCheck(%p) ts %p\n", s, s->ts);
985 
986  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:HdrCheck", kwlist, &blob))
987  return NULL;
988 
989  if (blob == Py_None) {
990  Py_INCREF(Py_None);
991  return Py_None;
992  }
993  if (!(PyString_Check(blob) || PyUnicode_Check(blob))) {
994  PyErr_SetString(pyrpmError, "hdrCheck takes a string of octets");
995  return result;
996  }
997  uh = PyString_AsString(blob);
998  uc = PyString_Size(blob);
999 
1000  dig = pgpDigNew(rpmtsVSFlags(s->ts), 0);
1001  rpmrc = headerCheck(dig, uh, uc, &msg);
1002  dig = pgpDigFree(dig);
1003 
1004  switch (rpmrc) {
1005  case RPMRC_OK:
1006  Py_INCREF(Py_None);
1007  result = Py_None;
1008  break;
1009 
1010  case RPMRC_NOKEY:
1011  /* XXX note "availaiable", the script kiddies need the misspelling. */
1012  PyErr_SetString(pyrpmError, "public key not availaiable");
1013  break;
1014 
1015  case RPMRC_NOTTRUSTED:
1016  PyErr_SetString(pyrpmError, "public key not trusted");
1017  break;
1018 
1019  case RPMRC_FAIL:
1020  default:
1021  PyErr_SetString(pyrpmError, msg);
1022  break;
1023  }
1024  msg = _free(msg);
1025 
1026  return result;
1027 }
1028 
1031 static PyObject *
1033 {
1034  return Py_BuildValue("i", rpmtsVSFlags(s->ts));
1035 }
1036 
1039 /*@null@*/
1040 static PyObject *
1041 rpmts_SetVSFlags(rpmtsObject * s, PyObject * args, PyObject * kwds)
1042  /*@modifies s @*/
1043 {
1045  char * kwlist[] = {"flags", NULL};
1046 
1047 if (_rpmts_debug)
1048 fprintf(stderr, "*** rpmts_SetVSFlags(%p) ts %p\n", s, s->ts);
1049 
1050  if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:SetVSFlags", kwlist,
1051  &vsflags))
1052  return NULL;
1053 
1054  /* XXX FIXME: value check on vsflags, or build pure python object
1055  * for it, and require an object of that type */
1056 
1057  return Py_BuildValue("i", rpmtsSetVSFlags(s->ts, vsflags));
1058 }
1059 
1062 /*@null@*/
1063 static PyObject *
1064 rpmts_SetColor(rpmtsObject * s, PyObject * args, PyObject * kwds)
1065  /*@modifies s @*/
1066 {
1067  uint32_t tscolor;
1068  char * kwlist[] = {"color", NULL};
1069 
1070 if (_rpmts_debug)
1071 fprintf(stderr, "*** rpmts_SetColor(%p) ts %p\n", s, s->ts);
1072 
1073  if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:Color", kwlist, &tscolor))
1074  return NULL;
1075 
1076  /* XXX FIXME: value check on tscolor, or build pure python object
1077  * for it, and require an object of that type */
1078 
1079  return Py_BuildValue("i", rpmtsSetColor(s->ts, tscolor));
1080 }
1081 
1084 /*@null@*/
1085 static PyObject *
1086 rpmts_PgpPrtPkts(rpmtsObject * s, PyObject * args, PyObject * kwds)
1087  /*@globals _Py_NoneStruct @*/
1088  /*@modifies _Py_NoneStruct @*/
1089 {
1090  PyObject * blob;
1091  unsigned char * pkt;
1092  unsigned int pktlen;
1093  int rc;
1094  char * kwlist[] = {"octets", NULL};
1095 
1096 if (_rpmts_debug)
1097 fprintf(stderr, "*** rpmts_PgpPrtPkts(%p) ts %p\n", s, s->ts);
1098 
1099  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:PgpPrtPkts", kwlist, &blob))
1100  return NULL;
1101 
1102  if (blob == Py_None) {
1103  Py_INCREF(Py_None);
1104  return Py_None;
1105  }
1106  if (!(PyString_Check(blob) || PyUnicode_Check(blob))) {
1107  PyErr_SetString(pyrpmError, "pgpPrtPkts takes a string of octets");
1108  return NULL;
1109  }
1110  pkt = (unsigned char *) PyString_AsString(blob);
1111  pktlen = PyString_Size(blob);
1112 
1113  rc = pgpPrtPkts(pkt, pktlen, NULL, 1);
1114 
1115  return Py_BuildValue("i", rc);
1116 }
1117 
1120 /*@null@*/
1121 static PyObject *
1122 rpmts_PgpImportPubkey(rpmtsObject * s, PyObject * args, PyObject * kwds)
1123  /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
1124  /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
1125 {
1126  PyObject * blob;
1127  unsigned char * pkt;
1128  unsigned int pktlen;
1129  int rc;
1130  char * kwlist[] = {"pubkey", NULL};
1131 
1132 if (_rpmts_debug)
1133 fprintf(stderr, "*** rpmts_PgpImportPubkey(%p) ts %p\n", s, s->ts);
1134 
1135  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:PgpImportPubkey",
1136  kwlist, &blob))
1137  return NULL;
1138 
1139  if (blob == Py_None) {
1140  Py_INCREF(Py_None);
1141  return Py_None;
1142  }
1143  if (!(PyString_Check(blob) || PyUnicode_Check(blob))) {
1144  PyErr_SetString(pyrpmError, "PgpImportPubkey takes a string of octets");
1145  return NULL;
1146  }
1147  pkt = (unsigned char *) PyString_AsString(blob);
1148  pktlen = PyString_Size(blob);
1149 
1150  rc = rpmcliImportPubkey(s->ts, pkt, pktlen);
1151 
1152  return Py_BuildValue("i", rc);
1153 }
1154 
1157 static PyObject *
1158 rpmts_SetFlags(rpmtsObject * s, PyObject * args, PyObject * kwds)
1159  /*@modifies s @*/
1160 {
1161  rpmtransFlags transFlags = 0;
1162  char * kwlist[] = {"flags", NULL};
1163 
1164  if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:SetFlags", kwlist,
1165  &transFlags))
1166  return NULL;
1167 
1168 if (_rpmts_debug)
1169 fprintf(stderr, "*** rpmts_SetFlags(%p) ts %p transFlags 0x%x\n", s, s->ts, transFlags);
1170 
1171  /* XXX FIXME: value check on flags, or build pure python object
1172  * for it, and require an object of that type */
1173 
1174  return Py_BuildValue("i", rpmtsSetFlags(s->ts, transFlags));
1175 }
1176 
1179 static PyObject *
1180 rpmts_SetDFlags(rpmtsObject * s, PyObject * args, PyObject * kwds)
1181  /*@modifies s @*/
1182 {
1183  rpmdepFlags depFlags = 0;
1184  char * kwlist[] = {"flags", NULL};
1185 
1186  if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:SetDFlags", kwlist,
1187  &depFlags))
1188  return NULL;
1189 
1190 if (_rpmts_debug)
1191 fprintf(stderr, "*** rpmts_SetDFlags(%p) ts %p depFlags 0x%x\n", s, s->ts, depFlags);
1192 
1193  /* XXX FIXME: value check on flags, or build pure python object
1194  * for it, and require an object of that type */
1195 
1196  return Py_BuildValue("i", rpmtsSetDFlags(s->ts, depFlags));
1197 }
1198 
1201 static PyObject *
1202 rpmts_SetProbFilter(rpmtsObject * s, PyObject * args, PyObject * kwds)
1203  /*@modifies s @*/
1204 {
1205  rpmprobFilterFlags ignoreSet = 0;
1206  rpmprobFilterFlags oignoreSet;
1207  char * kwlist[] = {"ignoreSet", NULL};
1208 
1209  if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:ProbFilter", kwlist,
1210  &ignoreSet))
1211  return NULL;
1212 
1213 if (_rpmts_debug)
1214 fprintf(stderr, "*** rpmts_SetProbFilter(%p) ts %p ignoreSet %x\n", s, s->ts, ignoreSet);
1215 
1216  oignoreSet = s->ignoreSet;
1217  s->ignoreSet = ignoreSet;
1218 
1219  return Py_BuildValue("i", oignoreSet);
1220 }
1221 
1224 /*@null@*/
1225 static rpmpsObject *
1227  /*@modifies s @*/
1228 {
1229 
1230 if (_rpmts_debug)
1231 fprintf(stderr, "*** rpmts_Problems(%p) ts %p\n", s, s->ts);
1232 
1233  return rpmps_Wrap( rpmtsProblems(s->ts) );
1234 }
1235 
1238 static PyObject *
1239 rpmts_Run(rpmtsObject * s, PyObject * args, PyObject * kwds)
1240  /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
1241  /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
1242 {
1243  int rc;
1244  PyObject * list;
1245  rpmps ps;
1246  rpmpsi psi;
1247  struct rpmtsCallbackType_s cbInfo;
1248  char * kwlist[] = {"callback", "data", NULL};
1249 
1250  if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO:Run", kwlist,
1251  &cbInfo.cb, &cbInfo.data))
1252  return NULL;
1253 
1254  cbInfo.tso = s;
1255  cbInfo.dso = NULL;
1256  cbInfo._save = PyEval_SaveThread();
1257 
1258  if (cbInfo.cb != NULL) {
1259  if (!PyCallable_Check(cbInfo.cb)) {
1260  PyErr_SetString(PyExc_TypeError, "expected a callable");
1261  return NULL;
1262  }
1263  (void) rpmtsSetNotifyCallback(s->ts, rpmtsCallback, (void *) &cbInfo);
1264  }
1265 
1266 if (_rpmts_debug)
1267 fprintf(stderr, "*** rpmts_Run(%p) ts %p ignore %x\n", s, s->ts, s->ignoreSet);
1268 
1269  rc = rpmtsRun(s->ts, NULL, s->ignoreSet);
1270  ps = rpmtsProblems(s->ts);
1271 
1272  if (cbInfo.cb)
1273  (void) rpmtsSetNotifyCallback(s->ts, NULL, NULL);
1274 
1275  PyEval_RestoreThread(cbInfo._save);
1276 
1277  if (rc < 0) {
1278  list = PyList_New(0);
1279  return list;
1280  } else if (!rc) {
1281  Py_INCREF(Py_None);
1282  return Py_None;
1283  }
1284 
1285  list = PyList_New(0);
1286  if (!list) {
1287  return NULL;
1288  }
1289  psi = rpmpsInitIterator(ps);
1290  while (rpmpsNextIterator(psi) >= 0) {
1291  rpmProblem p = rpmpsProblem(psi);
1292  PyObject * prob = Py_BuildValue("s(isN)", rpmProblemString(p),
1293  rpmProblemGetType(p),
1294  rpmProblemGetStr(p),
1295  PyLong_FromLongLong(rpmProblemGetDiskNeed(p)));
1296  PyList_Append(list, prob);
1297  Py_XDECREF(prob);
1298  }
1299  psi = rpmpsFreeIterator(psi);
1300 
1301  ps = rpmpsFree(ps);
1302 
1303  return list;
1304 }
1305 
1309 static PyObject *
1311  /*@globals _Py_NoneStruct @*/
1312  /*@modifies s, _Py_NoneStruct @*/
1313 {
1314  PyObject * result;
1315 
1316 if (_rpmts_debug)
1317 fprintf(stderr, "*** rpmts_Next(%p) ts %p\n", s, s->ts);
1318 
1319  result = rpmts_iternext(s);
1320 
1321  if (result == NULL) {
1322  Py_INCREF(Py_None);
1323  return Py_None;
1324  }
1325 
1326  return result;
1327 }
1328 
1331 /*@null@*/
1332 static specObject *
1333 spec_Parse(rpmtsObject * s, PyObject * args, PyObject * kwds)
1334  /*@globals rpmGlobalMacroContext @*/
1335  /*@modifies s, rpmGlobalMacroContext @*/
1336 {
1337  const char * specfile;
1338  Spec spec;
1339  int recursing = 0;
1340  char * passPhrase = "";
1341  char *cookie = NULL;
1342  int anyarch = 1;
1343  int verify = 1;
1344  int force = 1;
1345  char * kwlist[] = {"specfile", NULL};
1346 
1347  if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:Parse", kwlist, &specfile))
1348  return NULL;
1349 
1350  if (parseSpec(s->ts, specfile,"/", recursing, passPhrase,
1351  cookie, anyarch, force, verify)!=0) {
1352  PyErr_SetString(pyrpmError, "can't parse specfile\n");
1353  return NULL;
1354  }
1355 
1356  spec = rpmtsSpec(s->ts);
1357  return spec_Wrap(spec);
1358 }
1359 
1362 /*@null@*/
1363 static rpmmiObject *
1364 rpmts_Match(rpmtsObject * s, PyObject * args, PyObject * kwds)
1365  /*@globals rpmGlobalMacroContext @*/
1366  /*@modifies s, rpmGlobalMacroContext @*/
1367 {
1368  PyObject *TagN = NULL;
1369  PyObject *Key = NULL;
1370  char *key = NULL;
1371 /* XXX lkey *must* be a 32 bit integer, int "works" on all known platforms. */
1372  int lkey = 0;
1373  int len = 0;
1374  int tag = RPMDBI_PACKAGES;
1375  char * kwlist[] = {"tagNumber", "key", NULL};
1376 
1377 if (_rpmts_debug)
1378 fprintf(stderr, "*** rpmts_Match(%p) ts %p\n", s, s->ts);
1379 
1380  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:Match", kwlist,
1381  &TagN, &Key))
1382  return NULL;
1383 
1384  if (TagN && (tag = tagNumFromPyObject (TagN)) == -1) {
1385  PyErr_SetString(PyExc_TypeError, "unknown tag type");
1386  return NULL;
1387  }
1388 
1389  if (Key) {
1390 /*@-branchstate@*/
1391  if (PyString_Check(Key) || PyUnicode_Check(Key)) {
1392  key = PyString_AsString(Key);
1393  len = PyString_Size(Key);
1394  } else if (PyInt_Check(Key)) {
1395  lkey = PyInt_AsLong(Key);
1396  key = (char *)&lkey;
1397  len = sizeof(lkey);
1398  } else {
1399  PyErr_SetString(PyExc_TypeError, "unknown key type");
1400  return NULL;
1401  }
1402 /*@=branchstate@*/
1403  }
1404 
1405  /* XXX If not already opened, open the database O_RDONLY now. */
1406  /* XXX FIXME: lazy default rdonly open also done by rpmtsInitIterator(). */
1407  if (rpmtsGetRdb(s->ts) == NULL) {
1408  int rc = rpmtsOpenDB(s->ts, O_RDONLY);
1409  if (rc || rpmtsGetRdb(s->ts) == NULL) {
1410  PyErr_SetString(PyExc_TypeError, "rpmdb open failed");
1411  return NULL;
1412  }
1413  }
1414 
1415  return rpmmi_Wrap( rpmtsInitIterator(s->ts, tag, key, len) );
1416 }
1417 
1422 /*@-fullinitblock@*/
1423 /*@unchecked@*/ /*@observer@*/
1424 static struct PyMethodDef rpmts_methods[] = {
1425  {"Debug", (PyCFunction)rpmts_Debug, METH_VARARGS|METH_KEYWORDS,
1426  NULL},
1427 
1428  {"addInstall", (PyCFunction) rpmts_AddInstall, METH_VARARGS|METH_KEYWORDS,
1429  NULL },
1430  {"addErase", (PyCFunction) rpmts_AddErase, METH_VARARGS|METH_KEYWORDS,
1431  NULL },
1432  {"setDFlags", (PyCFunction) rpmts_SetDFlags, METH_VARARGS|METH_KEYWORDS,
1433 "ts.setDFlags(depFlags) -> previous depFlags\n\
1434 - Set control bit(s) for executing ts.check() and ts.order().\n" },
1435  {"check", (PyCFunction) rpmts_Check, METH_VARARGS|METH_KEYWORDS,
1436  NULL },
1437  {"order", (PyCFunction) rpmts_Order, METH_NOARGS,
1438  NULL },
1439  {"setFlags", (PyCFunction) rpmts_SetFlags, METH_VARARGS|METH_KEYWORDS,
1440 "ts.setFlags(transFlags) -> previous transFlags\n\
1441 - Set control bit(s) for executing ts.run().\n\
1442  Note: This method replaces the 1st argument to the old ts.run()\n" },
1443  {"setProbFilter", (PyCFunction) rpmts_SetProbFilter, METH_VARARGS|METH_KEYWORDS,
1444 "ts.setProbFilter(ignoreSet) -> previous ignoreSet\n\
1445 - Set control bit(s) for ignoring problems found by ts.run().\n\
1446  Note: This method replaces the 2nd argument to the old ts.run()\n" },
1447  {"problems", (PyCFunction) rpmts_Problems, METH_NOARGS,
1448 "ts.problems() -> ps\n\
1449 - Return current problem set.\n" },
1450  {"run", (PyCFunction) rpmts_Run, METH_VARARGS|METH_KEYWORDS,
1451 "ts.run(callback, data) -> (problems)\n\
1452 - Run a transaction set, returning list of problems found.\n\
1453  Note: The callback may not be None.\n" },
1454  {"clean", (PyCFunction) rpmts_Clean, METH_NOARGS,
1455  NULL },
1456  {"IDTXload", (PyCFunction) rpmts_IDTXload, METH_VARARGS|METH_KEYWORDS,
1457 "ts.IDTXload(rbtid=iid) -> ((tid,hdr,instance)+)\n\
1458 - Return list of installed packages reverse sorted by transaction id.\n" },
1459  {"IDTXglob", (PyCFunction) rpmts_IDTXglob, METH_VARARGS|METH_KEYWORDS,
1460 "ts.IDTXglob(rbtid=rid) -> ((tid,hdr,instance)+)\n\
1461 - Return list of removed packages reverse sorted by transaction id.\n" },
1462  {"rollback", (PyCFunction) rpmts_Rollback, METH_VARARGS|METH_KEYWORDS,
1463  NULL },
1464  {"openDB", (PyCFunction) rpmts_OpenDB, METH_NOARGS,
1465 "ts.openDB() -> None\n\
1466 - Open the default transaction rpmdb.\n\
1467  Note: The transaction rpmdb is lazily opened, so ts.openDB() is seldom needed.\n" },
1468  {"closeDB", (PyCFunction) rpmts_CloseDB, METH_NOARGS,
1469 "ts.closeDB() -> None\n\
1470 - Close the default transaction rpmdb.\n\
1471  Note: ts.closeDB() disables lazy opens, and should hardly ever be used.\n" },
1472  {"initDB", (PyCFunction) rpmts_InitDB, METH_NOARGS,
1473 "ts.initDB() -> None\n\
1474 - Initialize the default transaction rpmdb.\n\
1475  Note: ts.initDB() is seldom needed anymore.\n" },
1476  {"rebuildDB", (PyCFunction) rpmts_RebuildDB, METH_NOARGS,
1477 "ts.rebuildDB() -> None\n\
1478 - Rebuild the default transaction rpmdb.\n" },
1479  {"verifyDB", (PyCFunction) rpmts_VerifyDB, METH_NOARGS,
1480 "ts.verifyDB() -> None\n\
1481 - Verify the default transaction rpmdb.\n" },
1482  {"hdrFromFdno",(PyCFunction) rpmts_HdrFromFdno,METH_VARARGS|METH_KEYWORDS,
1483 "ts.hdrFromFdno(fdno) -> hdr\n\
1484 - Read a package header from a file descriptor.\n" },
1485  {"hdrCheck", (PyCFunction) rpmts_HdrCheck, METH_VARARGS|METH_KEYWORDS,
1486  NULL },
1487 {"getVSFlags",(PyCFunction) rpmts_GetVSFlags, METH_NOARGS,
1488 "ts.getVSFlags() -> vsflags\n\
1489 - Retrieve current signature verification flags from transaction\n" },
1490  {"setVSFlags",(PyCFunction) rpmts_SetVSFlags, METH_VARARGS|METH_KEYWORDS,
1491 "ts.setVSFlags(vsflags) -> ovsflags\n\
1492 - Set signature verification flags. Values for vsflags are:\n\
1493  rpm.RPMVSF_NOHDRCHK if set, don't check rpmdb headers\n\
1494  rpm.RPMVSF_NEEDPAYLOAD if not set, check header+payload (if possible)\n\
1495  rpm.RPMVSF_NOSHA1HEADER if set, don't check header SHA1 digest\n\
1496  rpm.RPMVSF_NODSAHEADER if set, don't check header DSA signature\n\
1497  rpm.RPMVSF_NORSAHEADER if set, don't check header RSA signature\n\
1498  rpm.RPMVSF_NOMD5 if set, don't check header+payload MD5 digest\n\
1499  rpm.RPMVSF_NODSA if set, don't check header+payload DSA signature\n\
1500  rpm.RPMVSF_NORSA if set, don't check header+payload RSA signature\n\
1501 " },
1502  {"setColor",(PyCFunction) rpmts_SetColor, METH_VARARGS|METH_KEYWORDS,
1503  NULL },
1504  {"pgpPrtPkts", (PyCFunction) rpmts_PgpPrtPkts, METH_VARARGS|METH_KEYWORDS,
1505  NULL },
1506  {"pgpImportPubkey", (PyCFunction) rpmts_PgpImportPubkey, METH_VARARGS|METH_KEYWORDS,
1507  NULL },
1508  {"parseSpec", (PyCFunction) spec_Parse, METH_VARARGS|METH_KEYWORDS,
1509 "ts.parseSpec(\"/path/to/foo.spec\") -> spec\n\
1510 - Parse a spec file.\n" },
1511  {"dbMatch", (PyCFunction) rpmts_Match, METH_VARARGS|METH_KEYWORDS,
1512 "ts.dbMatch([TagN, [key, [len]]]) -> mi\n\
1513 - Create a match iterator for the default transaction rpmdb.\n" },
1514  {"next", (PyCFunction)rpmts_Next, METH_NOARGS,
1515 "ts.next() -> te\n\
1516 - Retrieve next transaction set element.\n" },
1517  {NULL, NULL} /* sentinel */
1518 };
1519 /*@=fullinitblock@*/
1520 
1523 static void rpmts_dealloc(/*@only@*/ rpmtsObject * s)
1524  /*@modifies *s @*/
1525 {
1526 
1527 if (_rpmts_debug)
1528 fprintf(stderr, "%p -- ts %p db %p\n", s, s->ts, rpmtsGetRdb(s->ts));
1529  (void)rpmtsFree(s->ts);
1530  s->ts = NULL;
1531 
1532  if (s->scriptFd) Fclose(s->scriptFd);
1533  /* this will free the keyList, and decrement the ref count of all
1534  the items on the list as well :-) */
1535  Py_XDECREF(s->keyList);
1536  PyObject_Del((PyObject *)s);
1537 }
1538 
1539 static PyObject * rpmts_getattro(PyObject * o, PyObject * n)
1540  /*@*/
1541 {
1542  return PyObject_GenericGetAttr(o, n);
1543 }
1544 
1547 static int rpmts_setattro(PyObject * o, PyObject * n, PyObject * v)
1548  /*@*/
1549 {
1550  rpmtsObject *s = (rpmtsObject *)o;
1551  char * name = PyString_AsString(n);
1552  int fdno;
1553 
1554  if (!strcmp(name, "scriptFd")) {
1555  if (!PyArg_Parse(v, "i", &fdno)) return 0;
1556  if (fdno < 0) {
1557  PyErr_SetString(PyExc_TypeError, "bad file descriptor");
1558  return -1;
1559  } else {
1560  s->scriptFd = fdDup(fdno);
1561  rpmtsSetScriptFd(s->ts, s->scriptFd);
1562  }
1563  } else {
1564  PyErr_SetString(PyExc_AttributeError, name);
1565  return -1;
1566  }
1567 
1568  return 0;
1569 }
1570 
1573 static int rpmts_init(rpmtsObject * s, PyObject *args, PyObject *kwds)
1574  /*@globals rpmGlobalMacroContext @*/
1575  /*@modifies s, rpmGlobalMacroContext @*/
1576 {
1577  /* nothing to do atm... */
1578  return 0;
1579 }
1580 
1583 static void rpmts_free(/*@only@*/ rpmtsObject * s)
1584  /*@modifies s @*/
1585 {
1586 if (_rpmts_debug)
1587 fprintf(stderr, "%p -- ts %p db %p\n", s, s->ts, rpmtsGetRdb(s->ts));
1588  (void)rpmtsFree(s->ts);
1589  s->ts = NULL;
1590 
1591  if (s->scriptFd)
1592  Fclose(s->scriptFd);
1593 
1594  /* this will free the keyList, and decrement the ref count of all
1595  the items on the list as well :-) */
1596  Py_XDECREF(s->keyList);
1597 
1598  PyObject_Del((PyObject *)s);
1599 }
1600 
1603 static PyObject * rpmts_alloc(PyTypeObject * subtype, int nitems)
1604  /*@*/
1605 {
1606  PyObject * s = PyType_GenericAlloc(subtype, nitems);
1607 
1608 if (_rpmts_debug < 0)
1609 fprintf(stderr, "*** rpmts_alloc(%p,%d) ret %p\n", subtype, nitems, s);
1610  return s;
1611 }
1612 
1615 static PyObject * rpmts_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
1616  /*@globals rpmGlobalMacroContext @*/
1617  /*@modifies rpmGlobalMacroContext @*/
1618 {
1619  rpmtsObject * s = (void *) PyObject_New(rpmtsObject, subtype);
1620 
1621  char * rootDir = "/";
1622  int vsflags = rpmExpandNumeric("%{?_vsflags}");
1623  char * kwlist[] = {"rootdir", "vsflags", 0};
1624 
1625 if (_rpmts_debug < 0)
1626 fprintf(stderr, "*** rpmts_init(%p,%p,%p)\n", s, args, kwds);
1627 
1628  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|si:rpmts_init", kwlist,
1629  &rootDir, &vsflags))
1630  return NULL;
1631 
1632  s->ts = rpmtsCreate();
1633  /* XXX: Why is there no rpmts_SetRootDir() ? */
1634  (void) rpmtsSetRootDir(s->ts, rootDir);
1635  /* XXX: make this use common code with rpmts_SetVSFlags() to check the
1636  * python objects */
1637  (void) rpmtsSetVSFlags(s->ts, vsflags);
1638  s->keyList = PyList_New(0);
1639  s->ignoreSet = 0;
1640  s->scriptFd = NULL;
1641  s->tsi = NULL;
1642  s->tsiFilter = 0;
1643 
1644 if (_rpmts_debug)
1645 fprintf(stderr, "%p ++ ts %p db %p\n", s, s->ts, rpmtsGetRdb(s->ts));
1646 
1647  return (PyObject *)s;
1648 }
1649 
1652 /*@unchecked@*/ /*@observer@*/
1653 static char rpmts_doc[] =
1654 "";
1655 
1658 /*@-fullinitblock@*/
1659 PyTypeObject rpmts_Type = {
1660  PyObject_HEAD_INIT(&PyType_Type)
1661  0, /* ob_size */
1662  "rpm.ts", /* tp_name */
1663  sizeof(rpmtsObject), /* tp_size */
1664  0, /* tp_itemsize */
1665  (destructor) rpmts_dealloc, /* tp_dealloc */
1666  0, /* tp_print */
1667  (getattrfunc)0, /* tp_getattr */
1668  (setattrfunc)0, /* tp_setattr */
1669  0, /* tp_compare */
1670  0, /* tp_repr */
1671  0, /* tp_as_number */
1672  0, /* tp_as_sequence */
1673  0, /* tp_as_mapping */
1674  0, /* tp_hash */
1675  0, /* tp_call */
1676  0, /* tp_str */
1677  (getattrofunc) rpmts_getattro, /* tp_getattro */
1678  (setattrofunc) rpmts_setattro, /* tp_setattro */
1679  0, /* tp_as_buffer */
1680  Py_TPFLAGS_DEFAULT, /* tp_flags */
1681  rpmts_doc, /* tp_doc */
1682 #if Py_TPFLAGS_HAVE_ITER
1683  0, /* tp_traverse */
1684  0, /* tp_clear */
1685  0, /* tp_richcompare */
1686  0, /* tp_weaklistoffset */
1687  (getiterfunc) rpmts_iter, /* tp_iter */
1688  (iternextfunc) rpmts_iternext, /* tp_iternext */
1689  rpmts_methods, /* tp_methods */
1690  0, /* tp_members */
1691  0, /* tp_getset */
1692  0, /* tp_base */
1693  0, /* tp_dict */
1694  0, /* tp_descr_get */
1695  0, /* tp_descr_set */
1696  0, /* tp_dictoffset */
1697  (initproc) rpmts_init, /* tp_init */
1698  (allocfunc) rpmts_alloc, /* tp_alloc */
1699  (newfunc) rpmts_new, /* tp_new */
1700  (freefunc) rpmts_free, /* tp_free */
1701  0, /* tp_is_gc */
1702 #endif
1703 };
1704 /*@=fullinitblock@*/
1705 
1708 PyObject *
1709 rpmts_Create(/*@unused@*/ PyObject * s, PyObject * args,
1710  PyObject * kwds)
1711 {
1712  return PyObject_Call((PyObject *) &rpmts_Type, args, kwds);
1713 }