rpm 5.2.1

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

- File List
- Globals

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
173 struct rpmtsCallbackType_s {
174 PyObject * cb;
175 PyObject * data;
176 rpmtsObject * tso;
177 rpmdsObject * dso;
178 PyThreadState *_save;
179 };
180
183 /*@exits@*/
184 static void rpmts_Die(PyObject *cb)
185 /*@*/
186 {
187 PyObject * r = PyObject_Repr(cb);
188 char *pyfn = (r != NULL ? PyString_AsString(r) : "???");
189
190 if (PyErr_Occurred())
191 PyErr_Print();
192 rpmlog(RPMLOG_ERR, _("python callback %s failed, aborting!\n"), pyfn);
193 rpmdbCheckTerminate(1);
194 exit(EXIT_FAILURE);
195 }
196
199 static int
200 rpmts_SolveCallback(rpmts ts, rpmds ds, const void * data)
201 /*@*/
202 {
203 struct rpmtsCallbackType_s * cbInfo = (struct rpmtsCallbackType_s *) data;
204 PyObject * args, * result;
205 int res = 1;
206
207 if (_rpmts_debug)
208 fprintf(stderr, "*** rpmts_SolveCallback(%p,%p,%p) \"%s\"\n", ts, ds, data, rpmdsDNEVR(ds));
209
210 if (cbInfo->tso == NULL) return res;
211 if (cbInfo->cb == Py_None) return res;
212
213 PyEval_RestoreThread(cbInfo->_save);
214
215 cbInfo->dso = rpmds_Wrap(ds); /* XXX perhaps persistent? */
216 args = Py_BuildValue("(OO)", cbInfo->tso, cbInfo->dso);
217 result = PyEval_CallObject(cbInfo->cb, args);
218 Py_DECREF(cbInfo->dso);
219 cbInfo->dso = NULL;
220 Py_DECREF(args);
221
222 if (!result) {
223 rpmts_Die(cbInfo->cb);
224 /*@notreached@*/
225 } else {
226 if (PyInt_Check(result))
227 res = PyInt_AsLong(result);
228 Py_DECREF(result);
229 }
230
231 cbInfo->_save = PyEval_SaveThread();
232
233 return res;
234 }
235
238 /*@null@*/
239 static void *
240 rpmtsCallback(/*@unused@*/ const void * hd, const rpmCallbackType what,
241 const rpmuint64_t amount, const rpmuint64_t total,
242 fnpyKey pkgKey, rpmCallbackData data)
243 /*@globals _Py_NoneStruct @*/
244 /*@modifies _Py_NoneStruct @*/
245 {
246 /*@-castexpose@*/
247 Header h = (Header) hd;
248 /*@=castexpose@*/
249 struct rpmtsCallbackType_s * cbInfo = data;
250 PyObject * pkgObj = (PyObject *) pkgKey;
251 PyObject * oh = NULL;
252 const char * origin = NULL;
253 PyObject * args, * result;
254 static FD_t fd;
255
256 if (cbInfo->cb == Py_None) return NULL;
257
258 /* Synthesize a python object for callback (if necessary). */
259 if (pkgObj == NULL) {
260 if (h) {
261 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
262 he->tag = RPMTAG_NAME;
263 if (headerGet(h, he, 0)) {
264 pkgObj = Py_BuildValue("s", he->p.str);
265 he->p.ptr = _free(he->p.ptr);
266 } else {
267 pkgObj = Py_None;
268 Py_INCREF(pkgObj);
269 }
270 } else {
271 pkgObj = Py_None;
272 Py_INCREF(pkgObj);
273 }
274 } else {
275 Py_INCREF(pkgObj);
276 /* XXX yum has (h, rpmloc) tuple as pkgKey. Extract the path. */
277 if (!(PyTuple_Check(pkgObj) && PyArg_ParseTuple(pkgObj, "|Os", &oh, &origin)))
278 origin = NULL;
279 /* XXX clean up the path, yum paths start "//..." */
280 if (origin && origin[0] == '/' && origin[1] == '/')
281 origin++;
282 }
283
284 PyEval_RestoreThread(cbInfo->_save);
285
286 args = Py_BuildValue("(iLLOO)", what, amount, total, pkgObj, cbInfo->data);
287 result = PyEval_CallObject(cbInfo->cb, args);
288 Py_DECREF(args);
289 Py_DECREF(pkgObj);
290
291 if (!result) {
292 rpmts_Die(cbInfo->cb);
293 /*@notreached@*/
294 }
295
296 if (what == RPMCALLBACK_INST_OPEN_FILE) {
297 int fdno;
298
299 if (!PyArg_Parse(result, "i", &fdno)) {
300 rpmts_Die(cbInfo->cb);
301 /*@notreached@*/
302 }
303 Py_DECREF(result);
304 cbInfo->_save = PyEval_SaveThread();
305
306 fd = fdDup(fdno);
307 if (_rpmts_debug)
308 fprintf(stderr, "\t%p = fdDup(%d)\n", fd, fdno);
309
310 fcntl(Fileno(fd), F_SETFD, FD_CLOEXEC);
311
312 if (origin != NULL)
313 (void) fdSetOpen(fd, origin, 0, 0);
314
315 return fd;
316 } else
317 if (what == RPMCALLBACK_INST_CLOSE_FILE) {
318 if (_rpmts_debug)
319 fprintf(stderr, "\tFclose(%p)\n", fd);
320 Fclose (fd);
321 } else {
322 if (_rpmts_debug)
323 fprintf(stderr, "\t%llu:%llu key %p\n", (unsigned long long)amount, (unsigned long long)total, pkgKey);
324 }
325
326 Py_DECREF(result);
327 cbInfo->_save = PyEval_SaveThread();
328
329 return NULL;
330 }
331
332 #if Py_TPFLAGS_HAVE_ITER
333
335 static PyObject *
336 rpmts_iter(rpmtsObject * s)
337 /*@*/
338 {
339 if (_rpmts_debug)
340 fprintf(stderr, "*** rpmts_iter(%p) ts %p\n", s, s->ts);
341
342 Py_INCREF(s);
343 return (PyObject *)s;
344 }
345 #endif
346
350 /*@null@*/
351 static PyObject *
352 rpmts_iternext(rpmtsObject * s)
353 /*@modifies s @*/
354 {
355 PyObject * result = NULL;
356 rpmte te;
357
358 if (_rpmts_debug)
359 fprintf(stderr, "*** rpmts_iternext(%p) ts %p tsi %p %d\n", s, s->ts, s->tsi, s->tsiFilter);
360
361 /* Reset iterator on 1st entry. */
362 if (s->tsi == NULL) {
363 s->tsi = rpmtsiInit(s->ts);
364 if (s->tsi == NULL)
365 return NULL;
366 s->tsiFilter = 0;
367 }
368
369 te = rpmtsiNext(s->tsi, s->tsiFilter);
370 /*@-branchstate@*/
371 if (te != NULL) {
372 result = (PyObject *) rpmte_Wrap(te);
373 } else {
374 s->tsi = rpmtsiFree(s->tsi);
375 s->tsiFilter = 0;
376 }
377 /*@=branchstate@*/
378
379 return result;
380 }
381
386
389 /*@null@*/
390 static PyObject *
391 rpmts_Debug(/*@unused@*/ rpmtsObject * s, PyObject * args, PyObject * kwds)
392 /*@globals _Py_NoneStruct @*/
393 /*@modifies _Py_NoneStruct @*/
394 {
395 char * kwlist[] = {"debugLevel", NULL};
396
397 if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:Debug", kwlist,
398 &_rpmts_debug))
399 return NULL;
400
401 if (_rpmts_debug < 0)
402 fprintf(stderr, "*** rpmts_Debug(%p) ts %p\n", s, s->ts);
403
404 Py_INCREF(Py_None);
405 return Py_None;
406 }
407
410 /*@null@*/
411 static PyObject *
412 rpmts_AddInstall(rpmtsObject * s, PyObject * args, PyObject * kwds)
413 /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
414 /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
415 {
416 hdrObject * h;
417 PyObject * key;
418 char * how = "u"; /* XXX default to upgrade element if missing */
419 int isUpgrade = 0;
420 char * kwlist[] = {"header", "key", "how", NULL};
421
422 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O|s:AddInstall", kwlist,
423 &hdr_Type, &h, &key, &how))
424 return NULL;
425
426 { PyObject * hObj = (PyObject *) h;
427 if (hObj->ob_type != &hdr_Type) {
428 PyErr_SetString(PyExc_TypeError, "bad type for header argument");
429 return NULL;
430 }
431 }
432
433 if (_rpmts_debug < 0 || (_rpmts_debug > 0 && *how != 'a'))
434 fprintf(stderr, "*** rpmts_AddInstall(%p,%p,%p,%s) ts %p\n", s, h, key, how, s->ts);
435
436 if (how && strcmp(how, "a") && strcmp(how, "u") && strcmp(how, "i")) {
437 PyErr_SetString(PyExc_TypeError, "how argument must be \"u\", \"a\", or \"i\"");
438 return NULL;
439 } else if (how && !strcmp(how, "u"))
440 isUpgrade = 1;
441
442 rpmtsAddInstallElement(s->ts, hdrGetHeader(h), key, isUpgrade, NULL);
443
444 /* This should increment the usage count for me */
445 if (key)
446 PyList_Append(s->keyList, key);
447
448 Py_INCREF(Py_None);
449 return Py_None;
450 }
451
455 /*@null@*/
456 static PyObject *
457 rpmts_AddErase(rpmtsObject * s, PyObject * args, PyObject * kwds)
458 /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
459 /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
460 {
461 PyObject * o;
462 int count;
463 rpmmi mi;
464 char * kwlist[] = {"name", NULL};
465
466 if (_rpmts_debug)
467 fprintf(stderr, "*** rpmts_AddErase(%p) ts %p\n", s, s->ts);
468
469 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:AddErase", kwlist, &o))
470 return NULL;
471
472 if (PyString_Check(o) || PyUnicode_Check(o)) {
473 char * name = PyString_AsString(o);
474
475 mi = rpmtsInitIterator(s->ts, RPMDBI_LABEL, name, 0);
476 count = rpmmiCount(mi);
477 if (count <= 0) {
478 mi = rpmmiFree(mi);
479 PyErr_SetString(pyrpmError, "package not installed");
480 return NULL;
481 } else { /* XXX: Note that we automatically choose to remove all matches */
482 Header h;
483 while ((h = rpmmiNext(mi)) != NULL) {
484 unsigned int recOffset = rpmmiInstance(mi);
485 if (recOffset)
486 rpmtsAddEraseElement(s->ts, h, recOffset);
487 }
488 }
489 mi = rpmmiFree(mi);
490 } else
491 if (PyInt_Check(o)) {
492 uint32_t instance = PyInt_AsLong(o);
493
494 mi = rpmtsInitIterator(s->ts, RPMDBI_PACKAGES, &instance, sizeof(instance));
495 if (instance == 0 || mi == NULL) {
496 mi = rpmmiFree(mi);
497 PyErr_SetString(pyrpmError, "package not installed");
498 return NULL;
499 } else {
500 Header h;
501 while ((h = rpmmiNext(mi)) != NULL) {
502 uint32_t recOffset = rpmmiInstance(mi);
503 if (recOffset)
504 rpmtsAddEraseElement(s->ts, h, recOffset);
505 break;
506 }
507 }
508 mi = rpmmiFree(mi);
509 }
510
511 Py_INCREF(Py_None);
512 return Py_None;
513 }
514
517 /*@null@*/
518 static PyObject *
519 rpmts_Check(rpmtsObject * s, PyObject * args, PyObject * kwds)
520 /*@globals rpmGlobalMacroContext, _Py_NoneStruct @*/
521 /*@modifies s, rpmGlobalMacroContext, _Py_NoneStruct @*/
522 {
523 rpmps ps;
524 rpmProblem p;
525 PyObject * list, * cf;
526 struct rpmtsCallbackType_s cbInfo;
527 int i;
528 int xx;
529 char * kwlist[] = {"callback", NULL};
530
531 memset(&cbInfo, 0, sizeof(cbInfo));
532 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:Check", kwlist,
533 &cbInfo.cb))
534 return NULL;
535
536 if (cbInfo.cb != NULL) {
537 if (!PyCallable_Check(cbInfo.cb)) {
538 PyErr_SetString(PyExc_TypeError, "expected a callable");
539 return NULL;
540 }
541 xx = rpmtsSetSolveCallback(s->ts, rpmts_SolveCallback, (void *)&cbInfo);
542 }
543
544 if (_rpmts_debug)
545 fprintf(stderr, "*** rpmts_Check(%p) ts %p cb %p\n", s, s->ts, cbInfo.cb);
546
547 cbInfo.tso = s;
548 cbInfo.dso = NULL; /* XXX perhaps persistent? */
549 cbInfo._save = PyEval_SaveThread();
550
551 xx = rpmtsCheck(s->ts);
552 ps = rpmtsProblems(s->ts);
553
554 if (cbInfo.cb)
555 xx = rpmtsSetSolveCallback(s->ts, rpmtsSolve, NULL);
556
557 PyEval_RestoreThread(cbInfo._save);
558
559 if (ps != NULL) {
560 list = PyList_New(0);
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! */
585 if (rpmProblemGetType(p) == RPMPROB_BADRELOCATE)
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')
601 ? RPMDEP_SENSE_CONFLICTS : RPMDEP_SENSE_REQUIRES;
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_DECREF(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 *
642 rpmts_Order(rpmtsObject * s)
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 *
662 rpmts_Clean(rpmtsObject * s)
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;
684 rpmTag tag = RPMTAG_INSTALLTID;
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_DECREF(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_DECREF(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
800 ia->qva_flags = (VERIFY_DIGEST|VERIFY_SIGNATURE|VERIFY_HDRCHK);
801 ia->transFlags |= (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL);
802 ia->transFlags |= RPMTRANS_FLAG_NOFDIGESTS;
803 ia->installInterfaceFlags = (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL);
804 ia->rbtid = rbtid;
805 ia->relocations = NULL;
806 ia->probFilter |= RPMPROB_FILTER_OLDPACKAGE;
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 *
820 rpmts_OpenDB(rpmtsObject * s)
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 *
838 rpmts_CloseDB(rpmtsObject * s)
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 *
856 rpmts_InitDB(rpmtsObject * s)
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 *
876 rpmts_RebuildDB(rpmtsObject * s)
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 *
896 rpmts_VerifyDB(rpmtsObject * s)
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));
1001 rpmrc = headerCheck(dig, uh, uc, &msg);
1002 dig = pgpDigFree(dig, "rpmts_HdrCheck");
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 *
1032 rpmts_GetVSFlags(rpmtsObject * s)
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 {
1044 rpmVSFlags vsflags;
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 = 0;
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 *
1226 rpmts_Problems(rpmtsObject * s)
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 psi = rpmpsInitIterator(ps);
1287 while (rpmpsNextIterator(psi) >= 0) {
1288 rpmProblem p = rpmpsProblem(psi);
1289 PyObject * prob = Py_BuildValue("s(isN)", rpmProblemString(p),
1290 rpmProblemGetType(p),
1291 rpmProblemGetStr(p),
1292 PyLong_FromLongLong(rpmProblemGetDiskNeed(p)));
1293 PyList_Append(list, prob);
1294 Py_DECREF(prob);
1295 }
1296 psi = rpmpsFreeIterator(psi);
1297
1298 ps = rpmpsFree(ps);
1299
1300 return list;
1301 }
1302
1306 static PyObject *
1307 rpmts_Next(rpmtsObject * s)
1308 /*@globals _Py_NoneStruct @*/
1309 /*@modifies s, _Py_NoneStruct @*/
1310 {
1311 PyObject * result;
1312
1313 if (_rpmts_debug)
1314 fprintf(stderr, "*** rpmts_Next(%p) ts %p\n", s, s->ts);
1315
1316 result = rpmts_iternext(s);
1317
1318 if (result == NULL) {
1319 Py_INCREF(Py_None);
1320 return Py_None;
1321 }
1322
1323 return result;
1324 }
1325
1328 /*@null@*/
1329 static specObject *
1330 spec_Parse(rpmtsObject * s, PyObject * args, PyObject * kwds)
1331 /*@globals rpmGlobalMacroContext @*/
1332 /*@modifies s, rpmGlobalMacroContext @*/
1333 {
1334 const char * specfile;
1335 Spec spec;
1336 int recursing = 0;
1337 char * passPhrase = "";
1338 char *cookie = NULL;
1339 int anyarch = 1;
1340 int verify = 1;
1341 int force = 1;
1342 char * kwlist[] = {"specfile", NULL};
1343
1344 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:Parse", kwlist, &specfile))
1345 return NULL;
1346
1347 if (parseSpec(s->ts, specfile,"/", recursing, passPhrase,
1348 cookie, anyarch, force, verify)!=0) {
1349 PyErr_SetString(pyrpmError, "can't parse specfile\n");
1350 return NULL;
1351 }
1352
1353 spec = rpmtsSpec(s->ts);
1354 return spec_Wrap(spec);
1355 }
1356
1359 /*@null@*/
1360 static rpmmiObject *
1361 rpmts_Match(rpmtsObject * s, PyObject * args, PyObject * kwds)
1362 /*@globals rpmGlobalMacroContext @*/
1363 /*@modifies s, rpmGlobalMacroContext @*/
1364 {
1365 PyObject *TagN = NULL;
1366 PyObject *Key = NULL;
1367 char *key = NULL;
1368 /* XXX lkey *must* be a 32 bit integer, int "works" on all known platforms. */
1369 int lkey = 0;
1370 int len = 0;
1371 int tag = RPMDBI_PACKAGES;
1372 char * kwlist[] = {"tagNumber", "key", NULL};
1373
1374 if (_rpmts_debug)
1375 fprintf(stderr, "*** rpmts_Match(%p) ts %p\n", s, s->ts);
1376
1377 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:Match", kwlist,
1378 &TagN, &Key))
1379 return NULL;
1380
1381 if (TagN && (tag = tagNumFromPyObject (TagN)) == -1) {
1382 PyErr_SetString(PyExc_TypeError, "unknown tag type");
1383 return NULL;
1384 }
1385
1386 if (Key) {
1387 /*@-branchstate@*/
1388 if (PyString_Check(Key) || PyUnicode_Check(Key)) {
1389 key = PyString_AsString(Key);
1390 len = PyString_Size(Key);
1391 } else if (PyInt_Check(Key)) {
1392 lkey = PyInt_AsLong(Key);
1393 key = (char *)&lkey;
1394 len = sizeof(lkey);
1395 } else {
1396 PyErr_SetString(PyExc_TypeError, "unknown key type");
1397 return NULL;
1398 }
1399 /*@=branchstate@*/
1400 }
1401
1402 /* XXX If not already opened, open the database O_RDONLY now. */
1403 /* XXX FIXME: lazy default rdonly open also done by rpmtsInitIterator(). */
1404 if (rpmtsGetRdb(s->ts) == NULL) {
1405 int rc = rpmtsOpenDB(s->ts, O_RDONLY);
1406 if (rc || rpmtsGetRdb(s->ts) == NULL) {
1407 PyErr_SetString(PyExc_TypeError, "rpmdb open failed");
1408 return NULL;
1409 }
1410 }
1411
1412 return rpmmi_Wrap( rpmtsInitIterator(s->ts, tag, key, len) );
1413 }
1414
1419 /*@-fullinitblock@*/
1420 /*@unchecked@*/ /*@observer@*/
1421 static struct PyMethodDef rpmts_methods[] = {
1422 {"Debug", (PyCFunction)rpmts_Debug, METH_VARARGS|METH_KEYWORDS,
1423 NULL},
1424
1425 {"addInstall", (PyCFunction) rpmts_AddInstall, METH_VARARGS|METH_KEYWORDS,
1426 NULL },
1427 {"addErase", (PyCFunction) rpmts_AddErase, METH_VARARGS|METH_KEYWORDS,
1428 NULL },
1429 {"setDFlags", (PyCFunction) rpmts_SetDFlags, METH_VARARGS|METH_KEYWORDS,
1430 "ts.setDFlags(depFlags) -> previous depFlags\n\
1431 - Set control bit(s) for executing ts.check() and ts.order().\n" },
1432 {"check", (PyCFunction) rpmts_Check, METH_VARARGS|METH_KEYWORDS,
1433 NULL },
1434 {"order", (PyCFunction) rpmts_Order, METH_NOARGS,
1435 NULL },
1436 {"setFlags", (PyCFunction) rpmts_SetFlags, METH_VARARGS|METH_KEYWORDS,
1437 "ts.setFlags(transFlags) -> previous transFlags\n\
1438 - Set control bit(s) for executing ts.run().\n\
1439 Note: This method replaces the 1st argument to the old ts.run()\n" },
1440 {"setProbFilter", (PyCFunction) rpmts_SetProbFilter, METH_VARARGS|METH_KEYWORDS,
1441 "ts.setProbFilter(ignoreSet) -> previous ignoreSet\n\
1442 - Set control bit(s) for ignoring problems found by ts.run().\n\
1443 Note: This method replaces the 2nd argument to the old ts.run()\n" },
1444 {"problems", (PyCFunction) rpmts_Problems, METH_NOARGS,
1445 "ts.problems() -> ps\n\
1446 - Return current problem set.\n" },
1447 {"run", (PyCFunction) rpmts_Run, METH_VARARGS|METH_KEYWORDS,
1448 "ts.run(callback, data) -> (problems)\n\
1449 - Run a transaction set, returning list of problems found.\n\
1450 Note: The callback may not be None.\n" },
1451 {"clean", (PyCFunction) rpmts_Clean, METH_NOARGS,
1452 NULL },
1453 {"IDTXload", (PyCFunction) rpmts_IDTXload, METH_VARARGS|METH_KEYWORDS,
1454 "ts.IDTXload(rbtid=iid) -> ((tid,hdr,instance)+)\n\
1455 - Return list of installed packages reverse sorted by transaction id.\n" },
1456 {"IDTXglob", (PyCFunction) rpmts_IDTXglob, METH_VARARGS|METH_KEYWORDS,
1457 "ts.IDTXglob(rbtid=rid) -> ((tid,hdr,instance)+)\n\
1458 - Return list of removed packages reverse sorted by transaction id.\n" },
1459 {"rollback", (PyCFunction) rpmts_Rollback, METH_VARARGS|METH_KEYWORDS,
1460 NULL },
1461 {"openDB", (PyCFunction) rpmts_OpenDB, METH_NOARGS,
1462 "ts.openDB() -> None\n\
1463 - Open the default transaction rpmdb.\n\
1464 Note: The transaction rpmdb is lazily opened, so ts.openDB() is seldom needed.\n" },
1465 {"closeDB", (PyCFunction) rpmts_CloseDB, METH_NOARGS,
1466 "ts.closeDB() -> None\n\
1467 - Close the default transaction rpmdb.\n\
1468 Note: ts.closeDB() disables lazy opens, and should hardly ever be used.\n" },
1469 {"initDB", (PyCFunction) rpmts_InitDB, METH_NOARGS,
1470 "ts.initDB() -> None\n\
1471 - Initialize the default transaction rpmdb.\n\
1472 Note: ts.initDB() is seldom needed anymore.\n" },
1473 {"rebuildDB", (PyCFunction) rpmts_RebuildDB, METH_NOARGS,
1474 "ts.rebuildDB() -> None\n\
1475 - Rebuild the default transaction rpmdb.\n" },
1476 {"verifyDB", (PyCFunction) rpmts_VerifyDB, METH_NOARGS,
1477 "ts.verifyDB() -> None\n\
1478 - Verify the default transaction rpmdb.\n" },
1479 {"hdrFromFdno",(PyCFunction) rpmts_HdrFromFdno,METH_VARARGS|METH_KEYWORDS,
1480 "ts.hdrFromFdno(fdno) -> hdr\n\
1481 - Read a package header from a file descriptor.\n" },
1482 {"hdrCheck", (PyCFunction) rpmts_HdrCheck, METH_VARARGS|METH_KEYWORDS,
1483 NULL },
1484 {"getVSFlags",(PyCFunction) rpmts_GetVSFlags, METH_NOARGS,
1485 "ts.getVSFlags() -> vsflags\n\
1486 - Retrieve current signature verification flags from transaction\n" },
1487 {"setVSFlags",(PyCFunction) rpmts_SetVSFlags, METH_VARARGS|METH_KEYWORDS,
1488 "ts.setVSFlags(vsflags) -> ovsflags\n\
1489 - Set signature verification flags. Values for vsflags are:\n\
1490 rpm.RPMVSF_NOHDRCHK if set, don't check rpmdb headers\n\
1491 rpm.RPMVSF_NEEDPAYLOAD if not set, check header+payload (if possible)\n\
1492 rpm.RPMVSF_NOSHA1HEADER if set, don't check header SHA1 digest\n\
1493 rpm.RPMVSF_NODSAHEADER if set, don't check header DSA signature\n\
1494 rpm.RPMVSF_NORSAHEADER if set, don't check header RSA signature\n\
1495 rpm.RPMVSF_NOMD5 if set, don't check header+payload MD5 digest\n\
1496 rpm.RPMVSF_NODSA if set, don't check header+payload DSA signature\n\
1497 rpm.RPMVSF_NORSA if set, don't check header+payload RSA signature\n\
1498 rpm._RPMVSF_NODIGESTS if set, don't check digest(s)\n\
1499 rpm._RPMVSF_NOSIGNATURES if set, don't check signature(s)\n" },
1500 {"setColor",(PyCFunction) rpmts_SetColor, METH_VARARGS|METH_KEYWORDS,
1501 NULL },
1502 {"pgpPrtPkts", (PyCFunction) rpmts_PgpPrtPkts, METH_VARARGS|METH_KEYWORDS,
1503 NULL },
1504 {"pgpImportPubkey", (PyCFunction) rpmts_PgpImportPubkey, METH_VARARGS|METH_KEYWORDS,
1505 NULL },
1506 {"parseSpec", (PyCFunction) spec_Parse, METH_VARARGS|METH_KEYWORDS,
1507 "ts.parseSpec(\"/path/to/foo.spec\") -> spec\n\
1508 - Parse a spec file.\n" },
1509 {"dbMatch", (PyCFunction) rpmts_Match, METH_VARARGS|METH_KEYWORDS,
1510 "ts.dbMatch([TagN, [key, [len]]]) -> mi\n\
1511 - Create a match iterator for the default transaction rpmdb.\n" },
1512 {"next", (PyCFunction)rpmts_Next, METH_NOARGS,
1513 "ts.next() -> te\n\
1514 - Retrieve next transaction set element.\n" },
1515 {NULL, NULL} /* sentinel */
1516 };
1517 /*@=fullinitblock@*/
1518
1521 static void rpmts_dealloc(/*@only@*/ rpmtsObject * s)
1522 /*@modifies *s @*/
1523 {
1524
1525 if (_rpmts_debug)
1526 fprintf(stderr, "%p -- ts %p db %p\n", s, s->ts, rpmtsGetRdb(s->ts));
1527 (void)rpmtsFree(s->ts);
1528 s->ts = NULL;
1529
1530 if (s->scriptFd) Fclose(s->scriptFd);
1531 /* this will free the keyList, and decrement the ref count of all
1532 the items on the list as well :-) */
1533 Py_DECREF(s->keyList);
1534 PyObject_Del((PyObject *)s);
1535 }
1536
1537 static PyObject * rpmts_getattro(PyObject * o, PyObject * n)
1538 /*@*/
1539 {
1540 return PyObject_GenericGetAttr(o, n);
1541 }
1542
1545 static int rpmts_setattro(PyObject * o, PyObject * n, PyObject * v)
1546 /*@*/
1547 {
1548 rpmtsObject *s = (rpmtsObject *)o;
1549 char * name = PyString_AsString(n);
1550 int fdno;
1551
1552 if (!strcmp(name, "scriptFd")) {
1553 if (!PyArg_Parse(v, "i", &fdno)) return 0;
1554 if (fdno < 0) {
1555 PyErr_SetString(PyExc_TypeError, "bad file descriptor");
1556 return -1;
1557 } else {
1558 s->scriptFd = fdDup(fdno);
1559 rpmtsSetScriptFd(s->ts, s->scriptFd);
1560 }
1561 } else {
1562 PyErr_SetString(PyExc_AttributeError, name);
1563 return -1;
1564 }
1565
1566 return 0;
1567 }
1568
1571 static int rpmts_init(rpmtsObject * s, PyObject *args, PyObject *kwds)
1572 /*@globals rpmGlobalMacroContext @*/
1573 /*@modifies s, rpmGlobalMacroContext @*/
1574 {
1575 /* nothing to do atm... */
1576 return 0;
1577 }
1578
1581 static void rpmts_free(/*@only@*/ rpmtsObject * s)
1582 /*@modifies s @*/
1583 {
1584 if (_rpmts_debug)
1585 fprintf(stderr, "%p -- ts %p db %p\n", s, s->ts, rpmtsGetRdb(s->ts));
1586 (void)rpmtsFree(s->ts);
1587 s->ts = NULL;
1588
1589 if (s->scriptFd)
1590 Fclose(s->scriptFd);
1591
1592 /* this will free the keyList, and decrement the ref count of all
1593 the items on the list as well :-) */
1594 Py_DECREF(s->keyList);
1595
1596 PyObject_Del((PyObject *)s);
1597 }
1598
1601 static PyObject * rpmts_alloc(PyTypeObject * subtype, int nitems)
1602 /*@*/
1603 {
1604 PyObject * s = PyType_GenericAlloc(subtype, nitems);
1605
1606 if (_rpmts_debug < 0)
1607 fprintf(stderr, "*** rpmts_alloc(%p,%d) ret %p\n", subtype, nitems, s);
1608 return s;
1609 }
1610
1613 static PyObject * rpmts_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
1614 /*@globals rpmGlobalMacroContext @*/
1615 /*@modifies rpmGlobalMacroContext @*/
1616 {
1617 rpmtsObject * s = (void *) PyObject_New(rpmtsObject, subtype);
1618
1619 char * rootDir = "/";
1620 int vsflags = rpmExpandNumeric("%{?_vsflags}");
1621 char * kwlist[] = {"rootdir", "vsflags", 0};
1622
1623 if (_rpmts_debug < 0)
1624 fprintf(stderr, "*** rpmts_init(%p,%p,%p)\n", s, args, kwds);
1625
1626 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|si:rpmts_init", kwlist,
1627 &rootDir, &vsflags))
1628 return NULL;
1629
1630 s->ts = rpmtsCreate();
1631 /* XXX: Why is there no rpmts_SetRootDir() ? */
1632 (void) rpmtsSetRootDir(s->ts, rootDir);
1633 /* XXX: make this use common code with rpmts_SetVSFlags() to check the
1634 * python objects */
1635 (void) rpmtsSetVSFlags(s->ts, vsflags);
1636 s->keyList = PyList_New(0);
1637 s->ignoreSet = 0;
1638 s->scriptFd = NULL;
1639 s->tsi = NULL;
1640 s->tsiFilter = 0;
1641
1642 if (_rpmts_debug)
1643 fprintf(stderr, "%p ++ ts %p db %p\n", s, s->ts, rpmtsGetRdb(s->ts));
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 (freefunc) rpmts_free, /* tp_free */
1699 0, /* tp_is_gc */
1700 #endif
1701 };
1702 /*@=fullinitblock@*/
1703
1706 PyObject *
1707 rpmts_Create(/*@unused@*/ PyObject * s, PyObject * args,
1708 PyObject * kwds)
1709 {
1710 return PyObject_Call((PyObject *) &rpmts_Type, args, kwds);
1711 }