• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

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 }

Generated on Mon Nov 29 2010 05:18:45 for rpm by  doxygen 1.7.2