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