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 */
17 * \brief START HERE / RPM base module for the Python API
19 * The rpm base module provides the main starting point for
20 * accessing RPM from Python. For most usage, call
21 * the TransactionSet method to get a transaction set (rpmts).
27 * ts = rpm.TransactionSet()
30 * The transaction set will open the RPM database as needed, so
31 * in most cases, you do not need to explicitly open the
32 * database. The transaction set is the workhorse of RPM.
34 * You can open another RPM database, such as one that holds
35 * all packages for a given Linux distribution, to provide
36 * packages used to solve dependencies. To do this, use
40 * rpm.addMacro('_dbpath', '/path/to/alternate/database')
41 * solvets = rpm.TransactionSet()
43 * rpm.delMacro('_dbpath')
45 * # Open default database
46 * ts = rpm.TransactionSet()
49 * This code gives you access to two RPM databases through
50 * two transaction sets (rpmts): ts is a transaction set
51 * associated with the default RPM database and solvets
52 * is a transaction set tied to an alternate database, which
53 * is very useful for resolving dependencies.
55 * The rpm methods used here are:
57 * - addMacro(macro, value)
58 * @param macro Name of macro to add
59 * @param value Value for the macro
62 * @param macro Name of macro to delete
68 * \brief A python header object represents an RPM package header.
70 * All RPM packages have headers that provide metadata for the package.
71 * Header objects can be returned by database queries or loaded from a
72 * binary package on disk.
74 * The ts.hdrFromFdno() function returns the package header from a
75 * package on disk, verifying package signatures and digests of the
76 * package while reading.
78 * Note: The older method rpm.headerFromPackage() which has been replaced
79 * by ts.hdrFromFdno() used to return a (hdr, isSource) tuple.
81 * If you need to distinguish source/binary headers, do:
85 * ts = rpm.TransactionSet()
86 * fdno = os.open("/tmp/foo-1.0-1.i386.rpm", os.O_RDONLY)
87 * hdr = ts.hdrFromFdno(fdno)
89 * if hdr[rpm.RPMTAG_SOURCEPACKAGE]:
90 * print "header is from a source package"
92 * print "header is from a binary package"
95 * The Python interface to the header data is quite elegant. It
96 * presents the data in a dictionary form. We'll take the header we
97 * just loaded and access the data within it:
99 * print hdr[rpm.RPMTAG_NAME]
100 * print hdr[rpm.RPMTAG_VERSION]
101 * print hdr[rpm.RPMTAG_RELEASE]
103 * in the case of our "foo-1.0-1.i386.rpm" package, this code would
111 * You make also access the header data by string name:
114 * print hdr['version']
115 * print hdr['release']
118 * This method of access is a teensy bit slower because the name must be
119 * translated into the tag number dynamically. You also must make sure
120 * the strings in header lookups don't get translated, or the lookups
125 * \name Class: rpm.hdr
128 #define DEPRECATED_METHOD \
129 static int _warn = 0; \
130 if (!_warn) PyErr_Warn(PyExc_DeprecationWarning, "method is deprecated"); \
138 static PyObject * hdrKeyList(hdrObject * s)
142 rpmtd td = rpmtdNew();
144 list = PyList_New(0);
146 hi = headerInitIterator(s->h);
147 while (headerNext(hi, td)) {
148 rpmTag tag = rpmtdTag(td);
149 if (tag == HEADER_I18NTABLE) continue;
151 switch (rpmtdType(td)) {
157 case RPM_STRING_ARRAY_TYPE:
158 case RPM_STRING_TYPE:
159 PyList_Append(list, o=PyInt_FromLong(tag));
162 case RPM_I18NSTRING_TYPE: /* hum.. ?`*/
169 headerFreeIterator(hi);
175 static PyObject * hdrUnload(hdrObject * s, PyObject * args, PyObject *keywords)
181 static char *kwlist[] = { "legacyHeader", NULL};
183 if (!PyArg_ParseTupleAndKeywords(args, keywords, "|i", kwlist, &legacy))
186 h = headerLink(s->h);
187 /* XXX this legacy switch is a hack, needs to be removed. */
189 h = headerCopy(s->h); /* XXX strip region tags, etc */
192 len = headerSizeof(h, 0);
193 buf = headerUnload(h);
196 if (buf == NULL || len == 0) {
197 PyErr_SetString(pyrpmError, "can't unload bad header\n");
201 rc = PyString_FromStringAndSize(buf, len);
207 static PyObject * hdrExpandFilelist(hdrObject * s)
210 headerConvert(s->h, HEADERCONV_EXPANDFILELIST);
215 static PyObject * hdrCompressFilelist(hdrObject * s)
218 headerConvert(s->h, HEADERCONV_COMPRESSFILELIST);
223 /* make a header with _all_ the tags we need */
224 static PyObject * hdrFullFilelist(hdrObject * s)
226 rpmtd fileNames = rpmtdNew();
230 if (!headerIsEntry (h, RPMTAG_BASENAMES)
231 || !headerIsEntry (h, RPMTAG_DIRNAMES)
232 || !headerIsEntry (h, RPMTAG_DIRINDEXES))
233 headerConvert(h, HEADERCONV_COMPRESSFILELIST);
235 if (headerGet(h, RPMTAG_FILENAMES, fileNames, HEADERGET_EXT)) {
236 rpmtdSetTag(fileNames, RPMTAG_OLDFILENAMES);
237 headerPut(h, fileNames, HEADERPUT_DEFAULT);
238 rpmtdFreeData(fileNames);
240 rpmtdFree(fileNames);
245 static PyObject * hdrFormat(hdrObject * s, PyObject * args, PyObject * kwds)
251 char * kwlist[] = {"format", NULL};
253 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &fmt))
256 r = headerFormat(s->h, fmt, &err);
258 PyErr_SetString(pyrpmError, err);
262 result = Py_BuildValue("s", r);
268 static PyObject * hdrSprintf(hdrObject * s, PyObject * args, PyObject * kwds)
271 return hdrFormat(s, args, kwds);
274 static PyObject *hdrIsSource(hdrObject *s)
276 return PyBool_FromLong(headerIsSource(s->h));
279 static PyObject *hdrHasKey(hdrObject *s, PyObject *pytag)
281 rpmTag tag = tagNumFromPyObject(pytag);
282 if (tag == RPMTAG_NOT_FOUND) {
285 return PyBool_FromLong(headerIsEntry(s->h, tag));
288 static PyObject *hdrConvert(hdrObject *self, PyObject *args, PyObject *kwds)
290 char *kwlist[] = {"op", NULL};
291 headerConvOps op = -1;
293 if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &op)) {
296 return PyBool_FromLong(headerConvert(self->h, op));
299 static PyObject * hdrWrite(hdrObject *s, PyObject *args, PyObject *kwds)
301 char *kwlist[] = { "file", "magic", NULL };
306 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|i", kwlist,
307 rpmFdFromPyObject, &fd, &magic))
310 Py_BEGIN_ALLOW_THREADS;
311 rc = headerWrite(fd, s->h, magic ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
312 Py_END_ALLOW_THREADS;
314 if (rc) PyErr_SetFromErrno(PyExc_IOError);
315 Fclose(fd); /* avoid messing up errno wrt above */
321 static PyObject * hdr_fiFromHeader(PyObject * s, PyObject * args, PyObject * kwds)
324 return PyObject_Call((PyObject *) &rpmfi_Type,
325 Py_BuildValue("(O)", s), kwds);
328 static int hdr_compare(hdrObject * a, hdrObject * b)
330 return rpmVersionCompare(a->h, b->h);
333 static long hdr_hash(PyObject * h)
338 static struct PyMethodDef hdr_methods[] = {
339 {"keys", (PyCFunction) hdrKeyList, METH_NOARGS,
341 {"unload", (PyCFunction) hdrUnload, METH_VARARGS|METH_KEYWORDS,
343 {"expandFilelist", (PyCFunction) hdrExpandFilelist,METH_NOARGS,
345 {"compressFilelist",(PyCFunction) hdrCompressFilelist,METH_NOARGS,
347 {"fullFilelist", (PyCFunction) hdrFullFilelist, METH_NOARGS,
349 {"convert", (PyCFunction) hdrConvert, METH_VARARGS|METH_KEYWORDS,
351 {"format", (PyCFunction) hdrFormat, METH_VARARGS|METH_KEYWORDS,
353 {"has_key", (PyCFunction) hdrHasKey, METH_O,
355 {"sprintf", (PyCFunction) hdrSprintf, METH_VARARGS|METH_KEYWORDS,
357 {"isSource", (PyCFunction)hdrIsSource, METH_NOARGS,
359 {"write", (PyCFunction)hdrWrite, METH_VARARGS|METH_KEYWORDS,
361 {"dsOfHeader", (PyCFunction)hdr_dsOfHeader, METH_NOARGS,
363 {"dsFromHeader", (PyCFunction)hdr_dsFromHeader, METH_VARARGS|METH_KEYWORDS,
365 {"fiFromHeader", (PyCFunction)hdr_fiFromHeader, METH_VARARGS|METH_KEYWORDS,
368 {NULL, NULL} /* sentinel */
371 /* TODO: permit keyring check + retrofits on copy/load */
372 static PyObject *hdr_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
374 PyObject *obj = NULL;
377 char *kwlist[] = { "obj", NULL };
379 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &obj)) {
385 } else if (hdrObject_Check(obj)) {
386 h = headerCopy(hdrGetHeader((hdrObject*) obj));
387 } else if (PyString_Check(obj)) {
388 h = headerCopyLoad(PyString_AsString(obj));
389 } else if (rpmFdFromPyObject(obj, &fd)) {
390 Py_BEGIN_ALLOW_THREADS;
391 h = headerRead(fd, HEADER_MAGIC_YES);
393 Py_END_ALLOW_THREADS;
395 PyErr_SetString(PyExc_TypeError, "header, blob or file expected");
400 PyErr_SetString(pyrpmError, "bad header");
407 static void hdr_dealloc(hdrObject * s)
409 if (s->h) headerFree(s->h);
413 rpmTag tagNumFromPyObject (PyObject *item)
415 rpmTag tag = RPMTAG_NOT_FOUND;
417 if (PyInt_Check(item)) {
418 /* XXX we should probably validate tag numbers too */
419 tag = PyInt_AsLong(item);
420 } else if (PyString_Check(item)) {
421 tag = rpmTagGetValue(PyString_AsString(item));
423 if (tag == RPMTAG_NOT_FOUND) {
424 PyErr_SetString(PyExc_ValueError, "unknown header tag");
430 static PyObject * hdr_subscript(hdrObject * s, PyObject * item)
432 rpmTagType tagtype, type;
433 rpmTag tag = RPMTAG_NOT_FOUND;
434 rpm_count_t count, i;
436 PyObject * o, * metao;
441 tag = tagNumFromPyObject (item);
442 if (tag == RPMTAG_NOT_FOUND) return NULL;
444 tagtype = rpmTagGetType(tag);
445 forceArray = (tagtype & RPM_MASK_RETURN_TYPE) == RPM_ARRAY_RETURN_TYPE;
447 /* Retrieve data from extension or header. */
448 if (!headerGet(s->h, tag, &td, HEADERGET_EXT)) {
464 o = PyString_FromStringAndSize(data, count);
468 if (count != 1 || forceArray) {
469 metao = PyList_New(0);
470 for (i = 0; i < count; i++) {
471 o = PyInt_FromLong(((int *) data)[i]);
472 PyList_Append(metao, o);
477 o = PyInt_FromLong(*((int *) data));
483 if (count != 1 || forceArray) {
484 metao = PyList_New(0);
485 for (i = 0; i < count; i++) {
486 o = PyInt_FromLong(((char *) data)[i]);
487 PyList_Append(metao, o);
492 o = PyInt_FromLong(*((char *) data));
497 if (count != 1 || forceArray) {
498 metao = PyList_New(0);
499 for (i = 0; i < count; i++) {
500 o = PyInt_FromLong(((short *) data)[i]);
501 PyList_Append(metao, o);
506 o = PyInt_FromLong(*((short *) data));
510 case RPM_STRING_ARRAY_TYPE:
513 metao = PyList_New(0);
514 for (i = 0; i < count; i++) {
515 o = PyString_FromString(stringArray[i]);
516 PyList_Append(metao, o);
522 case RPM_STRING_TYPE:
523 case RPM_I18NSTRING_TYPE:
524 if (count != 1 || forceArray) {
527 metao = PyList_New(0);
528 for (i=0; i < count; i++) {
529 o = PyString_FromString(stringArray[i]);
530 PyList_Append(metao, o);
535 o = PyString_FromString(data);
540 PyErr_SetString(PyExc_TypeError, "unsupported type in header");
548 static PyObject * hdr_getattro(PyObject * o, PyObject * n)
551 res = PyObject_GenericGetAttr(o, n);
553 res = hdr_subscript((hdrObject *)o, n);
557 static int hdr_setattro(PyObject * o, PyObject * n, PyObject * v)
559 return PyObject_GenericSetAttr(o, n, v);
562 static PyMappingMethods hdr_as_mapping = {
563 (lenfunc) 0, /* mp_length */
564 (binaryfunc) hdr_subscript, /* mp_subscript */
565 (objobjargproc)0, /* mp_ass_subscript */
568 static char hdr_doc[] =
571 PyTypeObject hdr_Type = {
572 PyObject_HEAD_INIT(&PyType_Type)
574 "rpm.hdr", /* tp_name */
575 sizeof(hdrObject), /* tp_size */
577 (destructor) hdr_dealloc, /* tp_dealloc */
579 (getattrfunc) 0, /* tp_getattr */
581 (cmpfunc) hdr_compare, /* tp_compare */
583 0, /* tp_as_number */
584 0, /* tp_as_sequence */
585 &hdr_as_mapping, /* tp_as_mapping */
586 hdr_hash, /* tp_hash */
589 (getattrofunc) hdr_getattro, /* tp_getattro */
590 (setattrofunc) hdr_setattro, /* tp_setattro */
591 0, /* tp_as_buffer */
592 Py_TPFLAGS_DEFAULT, /* tp_flags */
593 hdr_doc, /* tp_doc */
596 0, /* tp_richcompare */
597 0, /* tp_weaklistoffset */
600 hdr_methods, /* tp_methods */
605 0, /* tp_descr_get */
606 0, /* tp_descr_set */
607 0, /* tp_dictoffset */
610 hdr_new, /* tp_new */
615 PyObject * hdr_Wrap(Header h)
617 hdrObject * hdr = PyObject_New(hdrObject, &hdr_Type);
618 if (hdr == NULL) return PyErr_NoMemory();
620 hdr->h = headerLink(h);
621 return (PyObject *) hdr;
624 Header hdrGetHeader(hdrObject * s)
629 PyObject * hdrLoad(PyObject * s, PyObject * args, PyObject * kwds)
632 return PyObject_Call((PyObject *) &hdr_Type, args, kwds);
635 PyObject * rpmReadHeaders (FD_t fd)
642 PyErr_SetFromErrno(pyrpmError);
646 list = PyList_New(0);
647 Py_BEGIN_ALLOW_THREADS
648 h = headerRead(fd, HEADER_MAGIC_YES);
652 headerConvert(h, HEADERCONV_RETROFIT_V3);
654 if (PyList_Append(list, (PyObject *) hdr)) {
661 h = headerFree(h); /* XXX ref held by hdr */
663 Py_BEGIN_ALLOW_THREADS
664 h = headerRead(fd, HEADER_MAGIC_YES);
671 PyObject * rpmHeaderFromFD(PyObject * self, PyObject * args, PyObject * kwds)
675 char * kwlist[] = {"fd", NULL};
677 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kwlist,
678 rpmFdFromPyObject, &fd))
681 list = rpmReadHeaders (fd);
687 PyObject * rpmHeaderFromFile(PyObject * self, PyObject * args, PyObject *kwds)
692 char * kwlist[] = {"file", NULL};
694 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &filespec))
697 fd = Fopen(filespec, "r.fdio");
700 PyErr_SetFromErrno(pyrpmError);
704 list = rpmReadHeaders (fd);
711 * This assumes the order of list matches the order of the new headers, and
712 * throws an exception if that isn't true.
714 int rpmMergeHeaders(PyObject * list, FD_t fd, int matchTag)
718 rpmTag newMatch, oldMatch;
720 rpm_count_t count = 0;
721 int rc = 1; /* assume failure */
722 rpmtd td = rpmtdNew();
724 Py_BEGIN_ALLOW_THREADS
725 h = headerRead(fd, HEADER_MAGIC_YES);
729 if (!headerGet(h, matchTag, td, HEADERGET_MINMEM)) {
730 PyErr_SetString(pyrpmError, "match tag missing in new header");
733 newMatch = rpmtdTag(td);
736 hdr = (hdrObject *) PyList_GetItem(list, count++);
739 if (!headerGet(hdr->h, matchTag, td, HEADERGET_MINMEM)) {
740 PyErr_SetString(pyrpmError, "match tag missing in new header");
743 oldMatch = rpmtdTag(td);
746 if (newMatch != oldMatch) {
747 PyErr_SetString(pyrpmError, "match tag mismatch");
751 for (hi = headerInitIterator(h); headerNext(hi, td); rpmtdFreeData(td))
754 headerDel(hdr->h, rpmtdTag(td));
755 headerPut(hdr->h, td, HEADERPUT_DEFAULT);
758 headerFreeIterator(hi);
761 Py_BEGIN_ALLOW_THREADS
762 h = headerRead(fd, HEADER_MAGIC_YES);
773 rpmMergeHeadersFromFD(PyObject * self, PyObject * args, PyObject * kwds)
780 char * kwlist[] = {"list", "fd", "matchTag", NULL};
782 if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oii", kwlist, &list,
786 if (!PyList_Check(list)) {
787 PyErr_SetString(PyExc_TypeError, "first parameter must be a list");
793 rc = rpmMergeHeaders (list, fd, matchTag);
804 rpmSingleHeaderFromFD(PyObject * self, PyObject * args, PyObject * kwds)
811 char * kwlist[] = {"fd", NULL};
813 if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &fileno))
816 offset = lseek(fileno, 0, SEEK_CUR);
821 PyErr_SetFromErrno(pyrpmError);
825 Py_BEGIN_ALLOW_THREADS
826 h = headerRead(fd, HEADER_MAGIC_YES);
831 tuple = PyTuple_New(2);
834 PyTuple_SET_ITEM(tuple, 0, hdr_Wrap(h));
835 PyTuple_SET_ITEM(tuple, 1, PyLong_FromLong(offset));
840 PyTuple_SET_ITEM(tuple, 0, Py_None);
841 PyTuple_SET_ITEM(tuple, 1, Py_None);
847 PyObject * versionCompare (PyObject * self, PyObject * args, PyObject * kwds)
849 hdrObject * h1, * h2;
850 char * kwlist[] = {"version0", "version1", NULL};
852 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", kwlist, &hdr_Type,
853 &h1, &hdr_Type, &h2))
856 return Py_BuildValue("i", hdr_compare(h1, h2));
859 static int compare_values(const char *str1, const char *str2)
863 else if (str1 && !str2)
865 else if (!str1 && str2)
867 return rpmvercmp(str1, str2);
870 PyObject * labelCompare (PyObject * self, PyObject * args)
872 char *v1, *r1, *v2, *r2;
876 if (!PyArg_ParseTuple(args, "(zzz)(zzz)",
877 &e1, &v1, &r1, &e2, &v2, &r2))
880 if (e1 == NULL) e1 = "0";
881 if (e2 == NULL) e2 = "0";
883 rc = compare_values(e1, e2);
885 rc = compare_values(v1, v2);
887 rc = compare_values(r1, r2);
889 return Py_BuildValue("i", rc);