1 #include "rpmsystem-py.h"
3 #include <rpm/rpmlib.h> /* rpmvercmp */
4 #include <rpm/rpmtag.h>
5 #include <rpm/rpmstring.h>
6 #include <rpm/rpmts.h> /* XXX rpmtsCreate/rpmtsFree */
18 * \brief START HERE / RPM base module for the Python API
20 * The rpm base module provides the main starting point for
21 * accessing RPM from Python. For most usage, call
22 * the TransactionSet method to get a transaction set (rpmts).
28 * ts = rpm.TransactionSet()
31 * The transaction set will open the RPM database as needed, so
32 * in most cases, you do not need to explicitly open the
33 * database. The transaction set is the workhorse of RPM.
35 * You can open another RPM database, such as one that holds
36 * all packages for a given Linux distribution, to provide
37 * packages used to solve dependencies. To do this, use
41 * rpm.addMacro('_dbpath', '/path/to/alternate/database')
42 * solvets = rpm.TransactionSet()
44 * rpm.delMacro('_dbpath')
46 * # Open default database
47 * ts = rpm.TransactionSet()
50 * This code gives you access to two RPM databases through
51 * two transaction sets (rpmts): ts is a transaction set
52 * associated with the default RPM database and solvets
53 * is a transaction set tied to an alternate database, which
54 * is very useful for resolving dependencies.
56 * The rpm methods used here are:
58 * - addMacro(macro, value)
59 * @param macro Name of macro to add
60 * @param value Value for the macro
63 * @param macro Name of macro to delete
69 * \brief A python header object represents an RPM package header.
71 * All RPM packages have headers that provide metadata for the package.
72 * Header objects can be returned by database queries or loaded from a
73 * binary package on disk.
75 * The ts.hdrFromFdno() function returns the package header from a
76 * package on disk, verifying package signatures and digests of the
77 * package while reading.
79 * Note: The older method rpm.headerFromPackage() which has been replaced
80 * by ts.hdrFromFdno() used to return a (hdr, isSource) tuple.
82 * If you need to distinguish source/binary headers, do:
86 * ts = rpm.TransactionSet()
87 * fdno = os.open("/tmp/foo-1.0-1.i386.rpm", os.O_RDONLY)
88 * hdr = ts.hdrFromFdno(fdno)
90 * if hdr[rpm.RPMTAG_SOURCEPACKAGE]:
91 * print "header is from a source package"
93 * print "header is from a binary package"
96 * The Python interface to the header data is quite elegant. It
97 * presents the data in a dictionary form. We'll take the header we
98 * just loaded and access the data within it:
100 * print hdr[rpm.RPMTAG_NAME]
101 * print hdr[rpm.RPMTAG_VERSION]
102 * print hdr[rpm.RPMTAG_RELEASE]
104 * in the case of our "foo-1.0-1.i386.rpm" package, this code would
112 * You make also access the header data by string name:
115 * print hdr['version']
116 * print hdr['release']
119 * This method of access is a teensy bit slower because the name must be
120 * translated into the tag number dynamically. You also must make sure
121 * the strings in header lookups don't get translated, or the lookups
126 * \name Class: rpm.hdr
134 static PyObject * hdrKeyList(hdrObject * s)
138 rpmtd td = rpmtdNew();
140 list = PyList_New(0);
142 hi = headerInitIterator(s->h);
143 while (headerNext(hi, td)) {
144 rpmTag tag = rpmtdTag(td);
145 if (tag == HEADER_I18NTABLE) continue;
147 switch (rpmtdType(td)) {
153 case RPM_STRING_ARRAY_TYPE:
154 case RPM_STRING_TYPE:
155 PyList_Append(list, o=PyInt_FromLong(tag));
158 case RPM_I18NSTRING_TYPE: /* hum.. ?`*/
165 headerFreeIterator(hi);
171 static PyObject * hdrUnload(hdrObject * s, PyObject * args, PyObject *keywords)
177 static char *kwlist[] = { "legacyHeader", NULL};
179 if (!PyArg_ParseTupleAndKeywords(args, keywords, "|i", kwlist, &legacy))
182 h = headerLink(s->h);
183 /* XXX this legacy switch is a hack, needs to be removed. */
185 h = headerCopy(s->h); /* XXX strip region tags, etc */
188 len = headerSizeof(h, 0);
189 buf = headerUnload(h);
192 if (buf == NULL || len == 0) {
193 PyErr_SetString(pyrpmError, "can't unload bad header\n");
197 rc = PyString_FromStringAndSize(buf, len);
203 static PyObject * hdrExpandFilelist(hdrObject * s)
206 headerConvert(s->h, HEADERCONV_EXPANDFILELIST);
211 static PyObject * hdrCompressFilelist(hdrObject * s)
214 headerConvert(s->h, HEADERCONV_COMPRESSFILELIST);
219 /* make a header with _all_ the tags we need */
220 static PyObject * hdrFullFilelist(hdrObject * s)
222 rpmtd fileNames = rpmtdNew();
226 if (!headerIsEntry (h, RPMTAG_BASENAMES)
227 || !headerIsEntry (h, RPMTAG_DIRNAMES)
228 || !headerIsEntry (h, RPMTAG_DIRINDEXES))
229 headerConvert(h, HEADERCONV_COMPRESSFILELIST);
231 if (headerGet(h, RPMTAG_FILENAMES, fileNames, HEADERGET_EXT)) {
232 rpmtdSetTag(fileNames, RPMTAG_OLDFILENAMES);
233 headerPut(h, fileNames, HEADERPUT_DEFAULT);
234 rpmtdFreeData(fileNames);
236 rpmtdFree(fileNames);
241 static PyObject * hdrFormat(hdrObject * s, PyObject * args, PyObject * kwds)
247 char * kwlist[] = {"format", NULL};
249 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &fmt))
252 r = headerFormat(s->h, fmt, &err);
254 PyErr_SetString(pyrpmError, err);
258 result = Py_BuildValue("s", r);
264 static PyObject * hdrSprintf(hdrObject * s, PyObject * args, PyObject * kwds)
267 return hdrFormat(s, args, kwds);
270 static PyObject *hdrIsSource(hdrObject *s)
272 return PyBool_FromLong(headerIsSource(s->h));
275 static PyObject *hdrHasKey(hdrObject *s, PyObject *pytag)
278 if (!tagNumFromPyObject(pytag, &tag)) return NULL;
280 return PyBool_FromLong(headerIsEntry(s->h, tag));
283 static PyObject *hdrConvert(hdrObject *self, PyObject *args, PyObject *kwds)
285 char *kwlist[] = {"op", NULL};
286 headerConvOps op = -1;
288 if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &op)) {
291 return PyBool_FromLong(headerConvert(self->h, op));
294 static PyObject * hdrWrite(hdrObject *s, PyObject *args, PyObject *kwds)
296 char *kwlist[] = { "file", "magic", NULL };
301 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|i", kwlist,
302 rpmFdFromPyObject, &fd, &magic))
305 Py_BEGIN_ALLOW_THREADS;
306 rc = headerWrite(fd, s->h, magic ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
307 Py_END_ALLOW_THREADS;
309 if (rc) PyErr_SetFromErrno(PyExc_IOError);
310 Fclose(fd); /* avoid messing up errno wrt above */
316 static PyObject * hdr_fiFromHeader(PyObject * s, PyObject * args, PyObject * kwds)
319 return PyObject_Call((PyObject *) &rpmfi_Type,
320 Py_BuildValue("(O)", s), kwds);
323 static int hdr_compare(hdrObject * a, hdrObject * b)
325 return rpmVersionCompare(a->h, b->h);
328 static long hdr_hash(PyObject * h)
333 static struct PyMethodDef hdr_methods[] = {
334 {"keys", (PyCFunction) hdrKeyList, METH_NOARGS,
336 {"unload", (PyCFunction) hdrUnload, METH_VARARGS|METH_KEYWORDS,
338 {"expandFilelist", (PyCFunction) hdrExpandFilelist,METH_NOARGS,
340 {"compressFilelist",(PyCFunction) hdrCompressFilelist,METH_NOARGS,
342 {"fullFilelist", (PyCFunction) hdrFullFilelist, METH_NOARGS,
344 {"convert", (PyCFunction) hdrConvert, METH_VARARGS|METH_KEYWORDS,
346 {"format", (PyCFunction) hdrFormat, METH_VARARGS|METH_KEYWORDS,
348 {"has_key", (PyCFunction) hdrHasKey, METH_O,
350 {"sprintf", (PyCFunction) hdrSprintf, METH_VARARGS|METH_KEYWORDS,
352 {"isSource", (PyCFunction)hdrIsSource, METH_NOARGS,
354 {"write", (PyCFunction)hdrWrite, METH_VARARGS|METH_KEYWORDS,
356 {"dsOfHeader", (PyCFunction)hdr_dsOfHeader, METH_NOARGS,
358 {"dsFromHeader", (PyCFunction)hdr_dsFromHeader, METH_VARARGS|METH_KEYWORDS,
360 {"fiFromHeader", (PyCFunction)hdr_fiFromHeader, METH_VARARGS|METH_KEYWORDS,
363 {NULL, NULL} /* sentinel */
366 /* TODO: permit keyring check + retrofits on copy/load */
367 static PyObject *hdr_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
369 PyObject *obj = NULL;
372 char *kwlist[] = { "obj", NULL };
374 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &obj)) {
380 } else if (hdrObject_Check(obj)) {
381 h = headerCopy(hdrGetHeader((hdrObject*) obj));
382 } else if (PyString_Check(obj)) {
383 h = headerCopyLoad(PyString_AsString(obj));
384 } else if (rpmFdFromPyObject(obj, &fd)) {
385 Py_BEGIN_ALLOW_THREADS;
386 h = headerRead(fd, HEADER_MAGIC_YES);
388 Py_END_ALLOW_THREADS;
390 PyErr_SetString(PyExc_TypeError, "header, blob or file expected");
395 PyErr_SetString(pyrpmError, "bad header");
399 return hdr_Wrap(subtype, h);
402 static void hdr_dealloc(hdrObject * s)
404 if (s->h) headerFree(s->h);
405 s->ob_type->tp_free((PyObject *)s);
408 int tagNumFromPyObject (PyObject *item, rpmTag *tagp)
410 rpmTag tag = RPMTAG_NOT_FOUND;
412 if (PyInt_Check(item)) {
413 /* XXX we should probably validate tag numbers too */
414 tag = PyInt_AsLong(item);
415 } else if (PyString_Check(item)) {
416 tag = rpmTagGetValue(PyString_AsString(item));
418 PyErr_SetString(PyExc_TypeError, "expected a string or integer");
421 if (tag == RPMTAG_NOT_FOUND) {
422 PyErr_SetString(PyExc_ValueError, "unknown header tag");
430 static PyObject * hdr_subscript(hdrObject * s, PyObject * item)
432 rpmTag tag = RPMTAG_NOT_FOUND;
434 PyObject *res = NULL;
436 if (!tagNumFromPyObject(item, &tag)) return NULL;
438 /* rpmtd_AsPyObj() knows how to handle empty containers and all */
439 (void) headerGet(s->h, tag, &td, HEADERGET_EXT);
440 res = rpmtd_AsPyobj(&td);
446 static PyObject * hdr_getattro(PyObject * o, PyObject * n)
449 res = PyObject_GenericGetAttr(o, n);
451 res = hdr_subscript((hdrObject *)o, n);
455 static int hdr_setattro(PyObject * o, PyObject * n, PyObject * v)
457 return PyObject_GenericSetAttr(o, n, v);
460 static PyMappingMethods hdr_as_mapping = {
461 (lenfunc) 0, /* mp_length */
462 (binaryfunc) hdr_subscript, /* mp_subscript */
463 (objobjargproc)0, /* mp_ass_subscript */
466 static char hdr_doc[] =
469 PyTypeObject hdr_Type = {
470 PyObject_HEAD_INIT(&PyType_Type)
472 "rpm.hdr", /* tp_name */
473 sizeof(hdrObject), /* tp_size */
475 (destructor) hdr_dealloc, /* tp_dealloc */
477 (getattrfunc) 0, /* tp_getattr */
479 (cmpfunc) hdr_compare, /* tp_compare */
481 0, /* tp_as_number */
482 0, /* tp_as_sequence */
483 &hdr_as_mapping, /* tp_as_mapping */
484 hdr_hash, /* tp_hash */
487 (getattrofunc) hdr_getattro, /* tp_getattro */
488 (setattrofunc) hdr_setattro, /* tp_setattro */
489 0, /* tp_as_buffer */
490 Py_TPFLAGS_DEFAULT, /* tp_flags */
491 hdr_doc, /* tp_doc */
494 0, /* tp_richcompare */
495 0, /* tp_weaklistoffset */
498 hdr_methods, /* tp_methods */
503 0, /* tp_descr_get */
504 0, /* tp_descr_set */
505 0, /* tp_dictoffset */
508 hdr_new, /* tp_new */
513 PyObject * hdr_Wrap(PyTypeObject *subtype, Header h)
515 hdrObject * hdr = (hdrObject *)subtype->tp_alloc(subtype, 0);
516 if (hdr == NULL) return PyErr_NoMemory();
518 hdr->h = headerLink(h);
519 return (PyObject *) hdr;
522 Header hdrGetHeader(hdrObject * s)
527 PyObject * hdrLoad(PyObject * s, PyObject * args, PyObject * kwds)
530 return PyObject_Call((PyObject *) &hdr_Type, args, kwds);
533 PyObject * rpmReadHeaders (FD_t fd)
540 PyErr_SetFromErrno(pyrpmError);
544 list = PyList_New(0);
545 Py_BEGIN_ALLOW_THREADS
546 h = headerRead(fd, HEADER_MAGIC_YES);
550 headerConvert(h, HEADERCONV_RETROFIT_V3);
551 hdr = hdr_Wrap(&hdr_Type, h);
552 if (PyList_Append(list, (PyObject *) hdr)) {
559 h = headerFree(h); /* XXX ref held by hdr */
561 Py_BEGIN_ALLOW_THREADS
562 h = headerRead(fd, HEADER_MAGIC_YES);
569 PyObject * rpmHeaderFromFD(PyObject * self, PyObject * args, PyObject * kwds)
573 char * kwlist[] = {"fd", NULL};
575 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kwlist,
576 rpmFdFromPyObject, &fd))
579 list = rpmReadHeaders (fd);
585 PyObject * rpmHeaderFromFile(PyObject * self, PyObject * args, PyObject *kwds)
590 char * kwlist[] = {"file", NULL};
592 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &filespec))
595 fd = Fopen(filespec, "r.fdio");
598 PyErr_SetFromErrno(pyrpmError);
602 list = rpmReadHeaders (fd);
609 * This assumes the order of list matches the order of the new headers, and
610 * throws an exception if that isn't true.
612 int rpmMergeHeaders(PyObject * list, FD_t fd, int matchTag)
616 rpmTag newMatch, oldMatch;
618 rpm_count_t count = 0;
619 int rc = 1; /* assume failure */
620 rpmtd td = rpmtdNew();
622 Py_BEGIN_ALLOW_THREADS
623 h = headerRead(fd, HEADER_MAGIC_YES);
627 if (!headerGet(h, matchTag, td, HEADERGET_MINMEM)) {
628 PyErr_SetString(pyrpmError, "match tag missing in new header");
631 newMatch = rpmtdTag(td);
634 hdr = (hdrObject *) PyList_GetItem(list, count++);
637 if (!headerGet(hdr->h, matchTag, td, HEADERGET_MINMEM)) {
638 PyErr_SetString(pyrpmError, "match tag missing in new header");
641 oldMatch = rpmtdTag(td);
644 if (newMatch != oldMatch) {
645 PyErr_SetString(pyrpmError, "match tag mismatch");
649 for (hi = headerInitIterator(h); headerNext(hi, td); rpmtdFreeData(td))
652 headerDel(hdr->h, rpmtdTag(td));
653 headerPut(hdr->h, td, HEADERPUT_DEFAULT);
656 headerFreeIterator(hi);
659 Py_BEGIN_ALLOW_THREADS
660 h = headerRead(fd, HEADER_MAGIC_YES);
671 rpmMergeHeadersFromFD(PyObject * self, PyObject * args, PyObject * kwds)
678 char * kwlist[] = {"list", "fd", "matchTag", NULL};
680 if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oii", kwlist, &list,
684 if (!PyList_Check(list)) {
685 PyErr_SetString(PyExc_TypeError, "first parameter must be a list");
691 rc = rpmMergeHeaders (list, fd, matchTag);
702 rpmSingleHeaderFromFD(PyObject * self, PyObject * args, PyObject * kwds)
709 char * kwlist[] = {"fd", NULL};
711 if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &fileno))
714 offset = lseek(fileno, 0, SEEK_CUR);
719 PyErr_SetFromErrno(pyrpmError);
723 Py_BEGIN_ALLOW_THREADS
724 h = headerRead(fd, HEADER_MAGIC_YES);
729 tuple = PyTuple_New(2);
732 PyTuple_SET_ITEM(tuple, 0, hdr_Wrap(&hdr_Type, h));
733 PyTuple_SET_ITEM(tuple, 1, PyLong_FromLong(offset));
738 PyTuple_SET_ITEM(tuple, 0, Py_None);
739 PyTuple_SET_ITEM(tuple, 1, Py_None);
745 PyObject * versionCompare (PyObject * self, PyObject * args, PyObject * kwds)
747 hdrObject * h1, * h2;
748 char * kwlist[] = {"version0", "version1", NULL};
750 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", kwlist, &hdr_Type,
751 &h1, &hdr_Type, &h2))
754 return Py_BuildValue("i", hdr_compare(h1, h2));
757 static int compare_values(const char *str1, const char *str2)
761 else if (str1 && !str2)
763 else if (!str1 && str2)
765 return rpmvercmp(str1, str2);
768 PyObject * labelCompare (PyObject * self, PyObject * args)
770 char *v1, *r1, *v2, *r2;
774 if (!PyArg_ParseTuple(args, "(zzz)(zzz)",
775 &e1, &v1, &r1, &e2, &v2, &r2))
778 if (e1 == NULL) e1 = "0";
779 if (e2 == NULL) e2 = "0";
781 rc = compare_values(e1, e2);
783 rc = compare_values(v1, v2);
785 rc = compare_values(r1, r2);
787 return Py_BuildValue("i", rc);