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

# python/header-py.c

Go to the documentation of this file.

    00001
    00005 #include "system.h"
    00006
    00007 #include "rpmio_internal.h"
    00008
    00009 #include "legacy.h"
    00010 #define _RPMTAG_INTERNAL
    00011 #include "header_internal.h"    /* XXX HEADERFLAG_ALLOCATED */
    00012 #include "rpmcli.h"     /* XXX for rpmCheckSig */
    00013 #include "pkgio.h"              /* XXX rpmpkgRead */
    00014
    00015 #include "rpmts.h"      /* XXX rpmtsCreate/rpmtsFree */
    00016 #define _RPMEVR_INTERNAL
    00017 #include "rpmevr.h"
    00018
    00019 #include "header-py.h"
    00020 #include "rpmds-py.h"
    00021 #include "rpmfi-py.h"
    00022
    00023 #include "debug.h"
    00024
    00135 struct hdrObject_s {
    00136     PyObject_HEAD
    00137     Header h;
    00138 } ;
    00139
    00142 /*@unused@*/ static inline Header headerAllocated(Header h)
    00143         /*@modifies h @*/
    00144 {
    00145     h->flags |= HEADERFLAG_ALLOCATED;
    00146     return 0;
    00147 }
    00148
    00153
    00156 static PyObject * hdrKeyList(hdrObject * s)
    00157         /*@*/
    00158 {
    00159     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00160     PyObject * list, *o;
    00161     HeaderIterator hi;
    00162
    00163     list = PyList_New(0);
    00164
    00165     for (hi = headerInit(s->h);
    00166         headerNext(hi, he, 0);
    00167         he->p.ptr = _free(he->p.ptr))
    00168     {
    00169         if (he->tag == HEADER_I18NTABLE) continue;
    00170         switch (he->t) {
    00171         case RPM_I18NSTRING_TYPE:
    00172             break;
    00173         case RPM_BIN_TYPE:
    00174         case RPM_UINT64_TYPE:
    00175         case RPM_UINT32_TYPE:
    00176         case RPM_UINT16_TYPE:
    00177         case RPM_UINT8_TYPE:
    00178         case RPM_STRING_ARRAY_TYPE:
    00179         case RPM_STRING_TYPE:
    00180             PyList_Append(list, o=PyInt_FromLong(he->tag));
    00181             Py_DECREF(o);
    00182             break;
    00183         }
    00184     }
    00185     hi = headerFini(hi);
    00186
    00187     return list;
    00188 }
    00189
    00192 static PyObject * hdrUnload(hdrObject * s, PyObject * args, PyObject *keywords)
    00193         /*@*/
    00194 {
    00195     char * buf;
    00196     PyObject * rc;
    00197     int legacy = 0;
    00198     int nb;
    00199     Header h;
    00200     static char *kwlist[] = { "legacyHeader", NULL};
    00201
    00202     if (!PyArg_ParseTupleAndKeywords(args, keywords, "|i", kwlist, &legacy))
    00203         return NULL;
    00204
    00205     h = headerLink(s->h);
    00206     /* XXX this legacy switch is a hack, needs to be removed. */
    00207     if (legacy) {
    00208         h = headerCopy(s->h);   /* XXX strip region tags, etc */
    00209         headerFree(s->h);
    00210     }
    00211     {   size_t len;
    00212         buf = headerUnload(h, &len);
    00213         nb = len;
    00214         nb -= 8;        /* XXX HEADER_MAGIC_NO */
    00215     }
    00216     h = headerFree(h);
    00217
    00218     if (buf == NULL || nb == 0) {
    00219         PyErr_SetString(pyrpmError, "can't unload bad header\n");
    00220         return NULL;
    00221     }
    00222
    00223     rc = PyString_FromStringAndSize(buf, nb);
    00224     buf = _free(buf);
    00225
    00226     return rc;
    00227 }
    00228
    00231 static PyObject * hdrGetOrigin(hdrObject * s)
    00232         /*@*/
    00233 {
    00234     const char * origin = NULL;
    00235     if (s->h != NULL)
    00236
    00237         origin = headerGetOrigin(s->h);
    00238     if (origin != NULL)
    00239         return Py_BuildValue("s", origin);
    00240     Py_INCREF(Py_None);
    00241     return Py_None;
    00242 }
    00243
    00246 static PyObject * hdrSetOrigin(hdrObject * s, PyObject * args, PyObject * kwds)
    00247         /*@*/
    00248 {
    00249     char * kwlist[] = {"origin", NULL};
    00250     const char * origin = NULL;
    00251
    00252     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:SetOrigin", kwlist, &origin))
    00253         return NULL;
    00254
    00255     if (s->h != NULL && origin != NULL)
    00256         headerSetOrigin(s->h, origin);
    00257
    00258     Py_INCREF(Py_None);
    00259     return Py_None;
    00260 }
    00261
    00264 static PyObject * hdrSprintf(hdrObject * s, PyObject * args, PyObject * kwds)
    00265         /*@*/
    00266 {
    00267     char * fmt;
    00268     char * r;
    00269     errmsg_t err;
    00270     PyObject * result;
    00271     char * kwlist[] = {"format", NULL};
    00272
    00273     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &fmt))
    00274         return NULL;
    00275
    00276     r = headerSprintf(s->h, fmt, NULL, rpmHeaderFormats, &err);
    00277     if (!r) {
    00278         PyErr_SetString(pyrpmError, err);
    00279         return NULL;
    00280     }
    00281
    00282     result = Py_BuildValue("s", r);
    00283     r = _free(r);
    00284
    00285     return result;
    00286 }
    00287
    00292 /*@unchecked@*/ /*@observer@*/
    00293 static struct PyMethodDef hdr_methods[] = {
    00294     {"keys",            (PyCFunction) hdrKeyList,       METH_NOARGS,
    00295         NULL },
    00296     {"unload",          (PyCFunction) hdrUnload,        METH_VARARGS|METH_KEYWORDS,
    00297         NULL },
    00298     {"getorigin",       (PyCFunction) hdrGetOrigin,     METH_NOARGS,
    00299         NULL },
    00300     {"setorigin",       (PyCFunction) hdrSetOrigin,     METH_NOARGS,
    00301         NULL },
    00302     {"sprintf",         (PyCFunction) hdrSprintf,       METH_VARARGS|METH_KEYWORDS,
    00303         NULL },
    00304
    00305     {"dsOfHeader",      (PyCFunction)hdr_dsOfHeader,    METH_NOARGS,
    00306         NULL},
    00307     {"dsFromHeader",    (PyCFunction)hdr_dsFromHeader,  METH_VARARGS|METH_KEYWORDS,
    00308         NULL},
    00309     {"fiFromHeader",    (PyCFunction)hdr_fiFromHeader,  METH_VARARGS|METH_KEYWORDS,
    00310         NULL},
    00311
    00312     {NULL,              NULL}           /* sentinel */
    00313 };
    00314
    00317 static int hdr_compare(hdrObject * a, hdrObject * b)
    00318         /*@*/
    00319 {
    00320     return rpmVersionCompare(a->h, b->h);
    00321 }
    00322
    00323 static long hdr_hash(PyObject * h)
    00324 {
    00325     return (long) h;
    00326 }
    00327
    00330 static void hdr_dealloc(hdrObject * s)
    00331         /*@*/
    00332 {
    00333     if (s->h) headerFree(s->h);
    00334     PyObject_Del(s);
    00335 }
    00336
    00339 long tagNumFromPyObject (PyObject *item)
    00340 {
    00341     char * str;
    00342
    00343     if (PyInt_Check(item)) {
    00344         return PyInt_AsLong(item);
    00345     } else if (PyString_Check(item) || PyUnicode_Check(item)) {
    00346         str = PyString_AsString(item);
    00347         return tagValue(str);
    00348     }
    00349     return -1;
    00350 }
    00351
    00354 static PyObject * hdr_subscript(hdrObject * s, PyObject * item)
    00355         /*@*/
    00356 {
    00357     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00358     uint32_t tag = 0xffffffff;
    00359     int i;
    00360     PyObject * o, * metao;
    00361     int forceArray = 0;
    00362     const struct headerSprintfExtension_s * ext = NULL;
    00363     int xx;
    00364
    00365     if (PyCObject_Check (item))
    00366         ext = PyCObject_AsVoidPtr(item);
    00367     else
    00368         tag = tagNumFromPyObject (item);
    00369
    00370     if (tag == 0xffffffff && (PyString_Check(item) || PyUnicode_Check(item))) {
    00371         const struct headerSprintfExtension_s * extensions = rpmHeaderFormats;
    00372         char * str;
    00373         /* if we still don't have the tag, go looking for the header
    00374            extensions */
    00375         str = PyString_AsString(item);
    00376         while (extensions->name) {
    00377             if (extensions->type == HEADER_EXT_TAG
    00378              && !xstrcasecmp(extensions->name + 7, str)) {
    00379                 ext = extensions;
    00380             }
    00381             extensions++;
    00382             if (extensions->type == HEADER_EXT_MORE)
    00383                 extensions = *extensions->u.more;
    00384         }
    00385     }
    00386
    00387     /* Retrieve data from extension or header. */
    00388     if (ext) {
    00389         ext->u.tagFunction(s->h, he);
    00390     } else {
    00391         if (tag == 0xffffffff) {
    00392             PyErr_SetString(PyExc_KeyError, "unknown header tag");
    00393             return NULL;
    00394         }
    00395
    00396         he->tag = tag;
    00397         xx = headerGet(s->h, he, 0);
    00398         if (!xx) {
    00399             he->p.ptr = _free(he->p.ptr);
    00400             switch (tag) {
    00401             case RPMTAG_EPOCH:
    00402             case RPMTAG_NAME:
    00403             case RPMTAG_VERSION:
    00404             case RPMTAG_RELEASE:
    00405             case RPMTAG_ARCH:
    00406             case RPMTAG_OS:
    00407                 Py_INCREF(Py_None);
    00408                 return Py_None;
    00409                 break;
    00410             default:
    00411                 return PyList_New(0);
    00412                 break;
    00413             }
    00414         }
    00415     }
    00416
    00417     switch (tag) {
    00418     case RPMTAG_FILEPATHS:
    00419     case RPMTAG_ORIGPATHS:
    00420     case RPMTAG_OLDFILENAMES:
    00421     case RPMTAG_FILESIZES:
    00422     case RPMTAG_FILESTATES:
    00423     case RPMTAG_FILEMODES:
    00424     case RPMTAG_FILEUIDS:
    00425     case RPMTAG_FILEGIDS:
    00426     case RPMTAG_FILERDEVS:
    00427     case RPMTAG_FILEMTIMES:
    00428     case RPMTAG_FILEMD5S:
    00429     case RPMTAG_FILELINKTOS:
    00430     case RPMTAG_FILEFLAGS:
    00431     case RPMTAG_ROOT:
    00432     case RPMTAG_FILEUSERNAME:
    00433     case RPMTAG_FILEGROUPNAME:
    00434     case RPMTAG_REQUIRENAME:
    00435     case RPMTAG_REQUIREFLAGS:
    00436     case RPMTAG_REQUIREVERSION:
    00437     case RPMTAG_PROVIDENAME:
    00438     case RPMTAG_PROVIDEFLAGS:
    00439     case RPMTAG_PROVIDEVERSION:
    00440     case RPMTAG_OBSOLETENAME:
    00441     case RPMTAG_OBSOLETEFLAGS:
    00442     case RPMTAG_OBSOLETEVERSION:
    00443     case RPMTAG_CONFLICTNAME:
    00444     case RPMTAG_CONFLICTFLAGS:
    00445     case RPMTAG_CONFLICTVERSION:
    00446     case RPMTAG_CHANGELOGTIME:
    00447     case RPMTAG_FILEVERIFYFLAGS:
    00448         forceArray = 1;
    00449         break;
    00450     default:
    00451         break;
    00452     }
    00453
    00454     switch (he->t) {
    00455     case RPM_BIN_TYPE:
    00456         o = PyString_FromStringAndSize(he->p.str, he->c);
    00457         break;
    00458
    00459     case RPM_UINT8_TYPE:
    00460         if (he->c != 1 || forceArray) {
    00461             metao = PyList_New(0);
    00462             for (i = 0; i < he->c; i++) {
    00463                 o = PyInt_FromLong(he->p.ui8p[i]);
    00464                 PyList_Append(metao, o);
    00465                 Py_DECREF(o);
    00466             }
    00467             o = metao;
    00468         } else {
    00469             o = PyInt_FromLong(he->p.ui8p[0]);
    00470         }
    00471         break;
    00472
    00473     case RPM_UINT16_TYPE:
    00474         if (he->c != 1 || forceArray) {
    00475             metao = PyList_New(0);
    00476             for (i = 0; i < he->c; i++) {
    00477                 o = PyInt_FromLong(he->p.ui16p[i]);
    00478                 PyList_Append(metao, o);
    00479                 Py_DECREF(o);
    00480             }
    00481             o = metao;
    00482         } else {
    00483             o = PyInt_FromLong(he->p.ui16p[0]);
    00484         }
    00485         break;
    00486
    00487     case RPM_UINT32_TYPE:
    00488         if (he->c != 1 || forceArray) {
    00489             metao = PyList_New(0);
    00490             for (i = 0; i < he->c; i++) {
    00491                 o = PyInt_FromLong(he->p.ui32p[i]);
    00492                 PyList_Append(metao, o);
    00493                 Py_DECREF(o);
    00494             }
    00495             o = metao;
    00496         } else {
    00497             o = PyInt_FromLong(he->p.ui32p[0]);
    00498         }
    00499         break;
    00500
    00501     case RPM_UINT64_TYPE:
    00502         if (he->c != 1 || forceArray) {
    00503             metao = PyList_New(0);
    00504             for (i = 0; i < he->c; i++) {
    00505                 o = PyInt_FromLong(he->p.ui64p[i]);
    00506                 PyList_Append(metao, o);
    00507                 Py_DECREF(o);
    00508             }
    00509             o = metao;
    00510         } else {
    00511             o = PyInt_FromLong(he->p.ui64p[0]);
    00512         }
    00513         break;
    00514
    00515     case RPM_STRING_ARRAY_TYPE:
    00516         metao = PyList_New(0);
    00517         for (i = 0; i < he->c; i++) {
    00518             o = PyString_FromString(he->p.argv[i]);
    00519             PyList_Append(metao, o);
    00520             Py_DECREF(o);
    00521         }
    00522         o = metao;
    00523         break;
    00524
    00525     case RPM_STRING_TYPE:
    00526         o = PyString_FromString(he->p.str);
    00527         break;
    00528
    00529     default:
    00530         PyErr_SetString(PyExc_TypeError, "unsupported type in header");
    00531         return NULL;
    00532     }
    00533     if (he->freeData)
    00534         he->p.ptr = _free(he->p.ptr);
    00535
    00536     return o;
    00537 }
    00538
    00541 /*@unchecked@*/ /*@observer@*/
    00542 static PyMappingMethods hdr_as_mapping = {
    00543         (inquiry) 0,                    /* mp_length */
    00544         (binaryfunc) hdr_subscript,     /* mp_subscript */
    00545         (objobjargproc)0,               /* mp_ass_subscript */
    00546 };
    00547
    00548 static PyObject * hdr_getattro(hdrObject * o, PyObject * n)
    00549         /*@*/
    00550 {
    00551     PyObject * res;
    00552     res = PyObject_GenericGetAttr((PyObject *)o, n);
    00553     if (res == NULL)
    00554         res = hdr_subscript(o, n);
    00555     return res;
    00556 }
    00557
    00558 static int hdr_setattro(hdrObject * o, PyObject * n, PyObject * v)
    00559         /*@*/
    00560 {
    00561     return PyObject_GenericSetAttr((PyObject *)o, n, v);
    00562 }
    00563
    00566 static char hdr_doc[] =
    00567 "";
    00568
    00571 /*@unchecked@*/ /*@observer@*/
    00572 PyTypeObject hdr_Type = {
    00573         PyObject_HEAD_INIT(&PyType_Type)
    00574         0,                              /* ob_size */
    00575         "rpm.hdr",                      /* tp_name */
    00576         sizeof(hdrObject),              /* tp_size */
    00577         0,                              /* tp_itemsize */
    00578         (destructor) hdr_dealloc,       /* tp_dealloc */
    00579         0,                              /* tp_print */
    00580         (getattrfunc) 0,                /* tp_getattr */
    00581         0,                              /* tp_setattr */
    00582         (cmpfunc) hdr_compare,          /* tp_compare */
    00583         0,                              /* tp_repr */
    00584         0,                              /* tp_as_number */
    00585         0,                              /* tp_as_sequence */
    00586         &hdr_as_mapping,                /* tp_as_mapping */
    00587         hdr_hash,                       /* tp_hash */
    00588         0,                              /* tp_call */
    00589         0,                              /* tp_str */
    00590         (getattrofunc) hdr_getattro,    /* tp_getattro */
    00591         (setattrofunc) hdr_setattro,    /* tp_setattro */
    00592         0,                              /* tp_as_buffer */
    00593         Py_TPFLAGS_DEFAULT,             /* tp_flags */
    00594         hdr_doc,                        /* tp_doc */
    00595 #if Py_TPFLAGS_HAVE_ITER
    00596         0,                              /* tp_traverse */
    00597         0,                              /* tp_clear */
    00598         0,                              /* tp_richcompare */
    00599         0,                              /* tp_weaklistoffset */
    00600         0,                              /* tp_iter */
    00601         0,                              /* tp_iternext */
    00602         hdr_methods,                    /* tp_methods */
    00603         0,                              /* tp_members */
    00604         0,                              /* tp_getset */
    00605         0,                              /* tp_base */
    00606         0,                              /* tp_dict */
    00607         0,                              /* tp_descr_get */
    00608         0,                              /* tp_descr_set */
    00609         0,                              /* tp_dictoffset */
    00610         0,                              /* tp_init */
    00611         0,                              /* tp_alloc */
    00612         0,                              /* tp_new */
    00613         0,                              /* tp_free */
    00614         0,                              /* tp_is_gc */
    00615 #endif
    00616 };
    00617
    00618 hdrObject * hdr_Wrap(Header h)
    00619 {
    00620     hdrObject * hdr = PyObject_New(hdrObject, &hdr_Type);
    00621     hdr->h = headerLink(h);
    00622     return hdr;
    00623 }
    00624
    00625 Header hdrGetHeader(hdrObject * s)
    00626 {
    00627     return s->h;
    00628 }
    00629
    00632 PyObject * hdrLoad(PyObject * self, PyObject * args, PyObject * kwds)
    00633 {
    00634     hdrObject * hdr;
    00635     char * copy = NULL;
    00636     char * obj;
    00637     Header h;
    00638     int len;
    00639     char * kwlist[] = {"headers", NULL};
    00640
    00641     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#", kwlist, &obj, &len))
    00642         return NULL;
    00643
    00644     /* malloc is needed to avoid surprises from data swab in headerLoad(). */
    00645     copy = malloc(len);
    00646     if (copy == NULL) {
    00647         PyErr_SetString(pyrpmError, "out of memory");
    00648         return NULL;
    00649     }
    00650     memcpy (copy, obj, len);
    00651
    00652     h = headerLoad(copy);
    00653     if (!h) {
    00654         PyErr_SetString(pyrpmError, "bad header");
    00655         return NULL;
    00656     }
    00657     headerAllocated(h);
    00658
    00659     hdr = hdr_Wrap(h);
    00660     h = headerFree(h);  /* XXX ref held by hdr */
    00661
    00662     return (PyObject *) hdr;
    00663 }
    00664
    00667 PyObject * rpmReadHeaders (FD_t fd)
    00668 {
    00669     PyObject * list;
    00670     Header h;
    00671     hdrObject * hdr;
    00672
    00673     if (!fd) {
    00674         PyErr_SetFromErrno(pyrpmError);
    00675         return NULL;
    00676     }
    00677
    00678     list = PyList_New(0);
    00679     Py_BEGIN_ALLOW_THREADS
    00680     {   const char item[] = "Header";
    00681         const char * msg = NULL;
    00682         rpmRC rc = rpmpkgRead(item, fd, &h, &msg);
    00683         if (rc != RPMRC_OK)
    00684             rpmlog(RPMLOG_ERR, "%s: %s: %s\n", "rpmpkgRead", item, msg);
    00685         msg = _free(msg);
    00686     }
    00687     Py_END_ALLOW_THREADS
    00688
    00689     while (h) {
    00690         hdr = hdr_Wrap(h);
    00691         if (PyList_Append(list, (PyObject *) hdr)) {
    00692             Py_DECREF(list);
    00693             Py_DECREF(hdr);
    00694             return NULL;
    00695         }
    00696         Py_DECREF(hdr);
    00697
    00698         h = headerFree(h);      /* XXX ref held by hdr */
    00699
    00700         Py_BEGIN_ALLOW_THREADS
    00701         {   const char item[] = "Header";
    00702             const char * msg = NULL;
    00703             rpmRC rc = rpmpkgRead(item, fd, &h, &msg);
    00704             if (rc != RPMRC_OK && rc != RPMRC_NOTFOUND)
    00705                 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", "rpmpkgRead", item, msg);
    00706             msg = _free(msg);
    00707         }
    00708         Py_END_ALLOW_THREADS
    00709     }
    00710
    00711     return list;
    00712 }
    00713
    00716 PyObject * rpmHeaderFromFD(PyObject * self, PyObject * args, PyObject * kwds)
    00717 {
    00718     FD_t fd;
    00719     int fileno;
    00720     PyObject * list;
    00721     char * kwlist[] = {"fd", NULL};
    00722
    00723     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &fileno))
    00724         return NULL;
    00725
    00726     fd = fdDup(fileno);
    00727
    00728     list = rpmReadHeaders (fd);
    00729     Fclose(fd);
    00730
    00731     return list;
    00732 }
    00733
    00736 PyObject * rpmHeaderFromFile(PyObject * self, PyObject * args, PyObject *kwds)
    00737 {
    00738     char * filespec;
    00739     FD_t fd;
    00740     PyObject * list;
    00741     char * kwlist[] = {"file", NULL};
    00742
    00743     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &filespec))
    00744         return NULL;
    00745
    00746     fd = Fopen(filespec, "r.fdio");
    00747
    00748     if (!fd) {
    00749         PyErr_SetFromErrno(pyrpmError);
    00750         return NULL;
    00751     }
    00752
    00753     list = rpmReadHeaders (fd);
    00754     Fclose(fd);
    00755
    00756     return list;
    00757 }
    00758
    00761 PyObject *
    00762 rpmSingleHeaderFromFD(PyObject * self, PyObject * args, PyObject * kwds)
    00763 {
    00764     FD_t fd;
    00765     int fileno;
    00766     off_t offset;
    00767     PyObject * tuple;
    00768     Header h;
    00769     char * kwlist[] = {"fd", NULL};
    00770
    00771     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &fileno))
    00772         return NULL;
    00773
    00774     offset = lseek(fileno, 0, SEEK_CUR);
    00775
    00776     fd = fdDup(fileno);
    00777
    00778     if (!fd) {
    00779         PyErr_SetFromErrno(pyrpmError);
    00780         return NULL;
    00781     }
    00782
    00783     Py_BEGIN_ALLOW_THREADS
    00784     {   const char item[] = "Header";
    00785         const char * msg = NULL;
    00786         rpmRC rc = rpmpkgRead(item, fd, &h, &msg);
    00787         if (rc != RPMRC_OK)
    00788             rpmlog(RPMLOG_ERR, "%s: %s: %s\n", "rpmpkgRead", item, msg);
    00789         msg = _free(msg);
    00790     }
    00791     Py_END_ALLOW_THREADS
    00792
    00793     Fclose(fd);
    00794
    00795     tuple = PyTuple_New(2);
    00796
    00797     if (h && tuple) {
    00798         PyTuple_SET_ITEM(tuple, 0, (PyObject *) hdr_Wrap(h));
    00799         PyTuple_SET_ITEM(tuple, 1, PyLong_FromLong(offset));
    00800         h = headerFree(h);
    00801     } else {
    00802         Py_INCREF(Py_None);
    00803         Py_INCREF(Py_None);
    00804         PyTuple_SET_ITEM(tuple, 0, Py_None);
    00805         PyTuple_SET_ITEM(tuple, 1, Py_None);
    00806     }
    00807
    00808     return tuple;
    00809 }
    00810
    00813 PyObject * versionCompare (PyObject * self, PyObject * args, PyObject * kwds)
    00814 {
    00815     hdrObject * h1, * h2;
    00816     char * kwlist[] = {"version0", "version1", NULL};
    00817
    00818     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", kwlist, &hdr_Type,
    00819             &h1, &hdr_Type, &h2))
    00820         return NULL;
    00821
    00822     return Py_BuildValue("i", hdr_compare(h1, h2));
    00823 }
    00824
    00825 PyObject * labelCompare (PyObject * self, PyObject * args)
    00826 {
    00827     EVR_t A = memset(alloca(sizeof(*A)), 0, sizeof(*A));
    00828     EVR_t B = memset(alloca(sizeof(*B)), 0, sizeof(*B));
    00829     int rc;
    00830
    00831     if (!PyArg_ParseTuple(args, "(zzz)(zzz)",
    00832                         &A->E, &A->V, &A->R, &B->E, &B->V, &B->R))
    00833         return NULL;
    00834
    00835     if (A->E == NULL)   A->E = "0";
    00836     if (B->E == NULL)   B->E = "0";
    00837     if (A->V == NULL)   A->E = "";
    00838     if (B->V == NULL)   B->E = "";
    00839     if (A->R == NULL)   A->E = "";
    00840     if (B->R == NULL)   B->E = "";
    00841
    00842     rc = rpmEVRcompare(A, B);
    00843
    00844     return Py_BuildValue("i", rc);
    00845 }