python/header-py.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 
00007 #include "rpmio_internal.h"
00008 #include "rpmcli.h"     /* XXX for rpmCheckSig */
00009 
00010 #include "legacy.h"
00011 #include "misc.h"
00012 #include "header_internal.h"
00013 
00014 #include "rpmts.h"      /* XXX rpmtsCreate/rpmtsFree */
00015 #define _RPMEVR_INTERNAL
00016 #include "rpmevr.h"
00017 
00018 #include "header-py.h"
00019 #include "rpmds-py.h"
00020 #include "rpmfi-py.h"
00021 
00022 #include "debug.h"
00023 
00135 struct hdrObject_s {
00136     PyObject_HEAD
00137     Header h;
00138     char ** md5list;
00139     char ** fileList;
00140     char ** linkList;
00141     int_32 * fileSizes;
00142     int_32 * mtimes;
00143     int_32 * uids, * gids;      /* XXX these tags are not used anymore */
00144     unsigned short * rdevs;
00145     unsigned short * modes;
00146 } ;
00147 
00150 /*@unused@*/ static inline Header headerAllocated(Header h)
00151         /*@modifies h @*/
00152 {
00153     h->flags |= HEADERFLAG_ALLOCATED;
00154     return 0;
00155 }
00156 
00157 /*@-boundsread@*/
00158 static int dncmp(const void * a, const void * b)
00159         /*@*/
00160 {
00161     const char *const * first = a;
00162     const char *const * second = b;
00163     return strcmp(*first, *second);
00164 }
00165 /*@=boundsread@*/
00166 
00171 static void expandFilelist(Header h)
00172         /*@modifies h @*/
00173 {
00174     HAE_t hae = (HAE_t)headerAddEntry;
00175     HRE_t hre = (HRE_t)headerRemoveEntry;
00176     const char ** fileNames = NULL;
00177     int count = 0;
00178     int xx;
00179 
00180     /*@-branchstate@*/
00181     if (!headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
00182         rpmfiBuildFNames(h, RPMTAG_BASENAMES, &fileNames, &count);
00183         if (fileNames == NULL || count <= 0)
00184             return;
00185         xx = hae(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
00186                         fileNames, count);
00187         fileNames = _free(fileNames);
00188     }
00189     /*@=branchstate@*/
00190 
00191     xx = hre(h, RPMTAG_DIRNAMES);
00192     xx = hre(h, RPMTAG_BASENAMES);
00193     xx = hre(h, RPMTAG_DIRINDEXES);
00194 }
00195 
00196 /*@-bounds@*/
00201 static void compressFilelist(Header h)
00202         /*@modifies h @*/
00203 {
00204     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00205     HAE_t hae = (HAE_t)headerAddEntry;
00206     HRE_t hre = (HRE_t)headerRemoveEntry;
00207     HFD_t hfd = headerFreeData;
00208     char ** fileNames;
00209     const char ** dirNames;
00210     const char ** baseNames;
00211     int_32 * dirIndexes;
00212     rpmTagType fnt;
00213     int count;
00214     int i, xx;
00215     int dirIndex = -1;
00216 
00217     /*
00218      * This assumes the file list is already sorted, and begins with a
00219      * single '/'. That assumption isn't critical, but it makes things go
00220      * a bit faster.
00221      */
00222 
00223     if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
00224         xx = hre(h, RPMTAG_OLDFILENAMES);
00225         return;         /* Already converted. */
00226     }
00227 
00228     if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &fileNames, &count))
00229         return;         /* no file list */
00230     if (fileNames == NULL || count <= 0)
00231         return;
00232 
00233     dirNames = alloca(sizeof(*dirNames) * count);       /* worst case */
00234     baseNames = alloca(sizeof(*dirNames) * count);
00235     dirIndexes = alloca(sizeof(*dirIndexes) * count);
00236 
00237     if (fileNames[0][0] != '/') {
00238         /* HACK. Source RPM, so just do things differently */
00239         dirIndex = 0;
00240         dirNames[dirIndex] = "";
00241         for (i = 0; i < count; i++) {
00242             dirIndexes[i] = dirIndex;
00243             baseNames[i] = fileNames[i];
00244         }
00245         goto exit;
00246     }
00247 
00248     /*@-branchstate@*/
00249     for (i = 0; i < count; i++) {
00250         const char ** needle;
00251         char savechar;
00252         char * baseName;
00253         int len;
00254 
00255         if (fileNames[i] == NULL)       /* XXX can't happen */
00256             continue;
00257         baseName = strrchr(fileNames[i], '/') + 1;
00258         len = baseName - fileNames[i];
00259         needle = dirNames;
00260         savechar = *baseName;
00261         *baseName = '\0';
00262 /*@-compdef@*/
00263         if (dirIndex < 0 ||
00264             (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
00265             char *s = alloca(len + 1);
00266             memcpy(s, fileNames[i], len + 1);
00267             s[len] = '\0';
00268             dirIndexes[i] = ++dirIndex;
00269             dirNames[dirIndex] = s;
00270         } else
00271             dirIndexes[i] = needle - dirNames;
00272 /*@=compdef@*/
00273 
00274         *baseName = savechar;
00275         baseNames[i] = baseName;
00276     }
00277     /*@=branchstate@*/
00278 
00279 exit:
00280     if (count > 0) {
00281         xx = hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
00282         xx = hae(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
00283                         baseNames, count);
00284         xx = hae(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
00285                         dirNames, dirIndex + 1);
00286     }
00287 
00288     fileNames = hfd(fileNames, fnt);
00289 
00290     xx = hre(h, RPMTAG_OLDFILENAMES);
00291 }
00292 /*@=bounds@*/
00293 /* make a header with _all_ the tags we need */
00296 static void mungeFilelist(Header h)
00297         /*@*/
00298 {
00299     const char ** fileNames = NULL;
00300     int count = 0;
00301 
00302     if (!headerIsEntry (h, RPMTAG_BASENAMES)
00303         || !headerIsEntry (h, RPMTAG_DIRNAMES)
00304         || !headerIsEntry (h, RPMTAG_DIRINDEXES))
00305         compressFilelist(h);
00306 
00307     rpmfiBuildFNames(h, RPMTAG_BASENAMES, &fileNames, &count);
00308 
00309     if (fileNames == NULL || count <= 0)
00310         return;
00311 
00312     /* XXX Legacy tag needs to go away. */
00313     headerAddEntry(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
00314                         fileNames, count);
00315 
00316     fileNames = _free(fileNames);
00317 }
00318 
00324 static void providePackageNVR(Header h)
00325 {
00326     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00327     HFD_t hfd = headerFreeData;
00328     const char *name, *version, *release;
00329     int_32 * epoch;
00330     const char *pEVR;
00331     char *p;
00332     int_32 pFlags = RPMSENSE_EQUAL;
00333     const char ** provides = NULL;
00334     const char ** providesEVR = NULL;
00335     rpmTagType pnt, pvt;
00336     int_32 * provideFlags = NULL;
00337     int providesCount;
00338     int i, xx;
00339     int bingo = 1;
00340 
00341     /* Generate provides for this package name-version-release. */
00342     xx = headerNVR(h, &name, &version, &release);
00343     if (!(name && version && release))
00344         return;
00345     pEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
00346     *p = '\0';
00347     if (hge(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
00348         sprintf(p, "%d:", *epoch);
00349         while (*p != '\0')
00350             p++;
00351     }
00352     (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
00353 
00354     /*
00355      * Rpm prior to 3.0.3 does not have versioned provides.
00356      * If no provides at all are available, we can just add.
00357      */
00358     if (!hge(h, RPMTAG_PROVIDENAME, &pnt, (void **) &provides, &providesCount))
00359         goto exit;
00360 
00361     /*
00362      * Otherwise, fill in entries on legacy packages.
00363      */
00364     if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt, (void **) &providesEVR, NULL)) {
00365         for (i = 0; i < providesCount; i++) {
00366             char * vdummy = "";
00367             int_32 fdummy = RPMSENSE_ANY;
00368             xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
00369                         &vdummy, 1);
00370             xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
00371                         &fdummy, 1);
00372         }
00373         goto exit;
00374     }
00375 
00376     xx = hge(h, RPMTAG_PROVIDEFLAGS, NULL, (void **) &provideFlags, NULL);
00377 
00378     /*@-nullderef@*/    /* LCL: providesEVR is not NULL */
00379     if (provides && providesEVR && provideFlags)
00380     for (i = 0; i < providesCount; i++) {
00381         if (!(provides[i] && providesEVR[i]))
00382             continue;
00383         if (!(provideFlags[i] == RPMSENSE_EQUAL &&
00384             !strcmp(name, provides[i]) && !strcmp(pEVR, providesEVR[i])))
00385             continue;
00386         bingo = 0;
00387         break;
00388     }
00389     /*@=nullderef@*/
00390 
00391 exit:
00392     provides = hfd(provides, pnt);
00393     providesEVR = hfd(providesEVR, pvt);
00394 
00395     if (bingo) {
00396         xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE,
00397                 &name, 1);
00398         xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
00399                 &pFlags, 1);
00400         xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
00401                 &pEVR, 1);
00402     }
00403 }
00404 
00409 
00412 static PyObject * hdrKeyList(hdrObject * s)
00413         /*@*/
00414 {
00415     PyObject * list, *o;
00416     HeaderIterator hi;
00417     int tag, type;
00418 
00419     list = PyList_New(0);
00420 
00421     hi = headerInitIterator(s->h);
00422     while (headerNextIterator(hi, &tag, &type, NULL, NULL)) {
00423         if (tag == HEADER_I18NTABLE) continue;
00424 
00425         switch (type) {
00426         case RPM_OPENPGP_TYPE:
00427         case RPM_ASN1_TYPE:
00428         case RPM_BIN_TYPE:
00429         case RPM_INT64_TYPE:
00430         case RPM_INT32_TYPE:
00431         case RPM_INT16_TYPE:
00432         case RPM_INT8_TYPE:
00433         case RPM_CHAR_TYPE:
00434         case RPM_STRING_ARRAY_TYPE:
00435         case RPM_STRING_TYPE:
00436             PyList_Append(list, o=PyInt_FromLong(tag));
00437             Py_DECREF(o);
00438         }
00439     }
00440     headerFreeIterator(hi);
00441 
00442     return list;
00443 }
00444 
00447 static PyObject * hdrUnload(hdrObject * s, PyObject * args, PyObject *keywords)
00448         /*@*/
00449 {
00450     char * buf;
00451     PyObject * rc;
00452     int len, legacy = 0;
00453     Header h;
00454     static char *kwlist[] = { "legacyHeader", NULL};
00455 
00456     if (!PyArg_ParseTupleAndKeywords(args, keywords, "|i", kwlist, &legacy))
00457         return NULL;
00458 
00459     h = headerLink(s->h);
00460     /* XXX this legacy switch is a hack, needs to be removed. */
00461     if (legacy) {
00462         h = headerCopy(s->h);   /* XXX strip region tags, etc */
00463         headerFree(s->h);
00464     }
00465     len = headerSizeof(h, 0);
00466     buf = headerUnload(h);
00467     h = headerFree(h);
00468 
00469     if (buf == NULL || len == 0) {
00470         PyErr_SetString(pyrpmError, "can't unload bad header\n");
00471         return NULL;
00472     }
00473 
00474     rc = PyString_FromStringAndSize(buf, len);
00475     buf = _free(buf);
00476 
00477     return rc;
00478 }
00479 
00482 static PyObject * hdrExpandFilelist(hdrObject * s)
00483         /*@*/
00484 {
00485     expandFilelist (s->h);
00486 
00487     Py_INCREF(Py_None);
00488     return Py_None;
00489 }
00490 
00493 static PyObject * hdrCompressFilelist(hdrObject * s)
00494         /*@*/
00495 {
00496     compressFilelist (s->h);
00497 
00498     Py_INCREF(Py_None);
00499     return Py_None;
00500 }
00501 
00504 static PyObject * hdrGetOrigin(hdrObject * s)
00505         /*@*/
00506 {
00507     const char * origin = NULL;
00508     if (s->h != NULL)
00509 
00510         origin = headerGetOrigin(s->h);
00511     if (origin != NULL)
00512         return Py_BuildValue("s", origin);
00513     Py_INCREF(Py_None);
00514     return Py_None;
00515 }
00516 
00519 static PyObject * hdrSetOrigin(hdrObject * s, PyObject * args, PyObject * kwds)
00520         /*@*/
00521 {
00522     char * kwlist[] = {"origin", NULL};
00523     const char * origin = NULL;
00524 
00525     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:SetOrigin", kwlist, &origin))
00526         return NULL;
00527 
00528     if (s->h != NULL && origin != NULL)
00529         headerSetOrigin(s->h, origin);
00530 
00531     Py_INCREF(Py_None);
00532     return Py_None;
00533 }
00534 
00537 static PyObject * hdrFullFilelist(hdrObject * s)
00538         /*@*/
00539 {
00540     mungeFilelist (s->h);
00541 
00542     Py_INCREF(Py_None);
00543     return Py_None;
00544 }
00545 
00548 static PyObject * hdrSprintf(hdrObject * s, PyObject * args, PyObject * kwds)
00549         /*@*/
00550 {
00551     char * fmt;
00552     char * r;
00553     errmsg_t err;
00554     PyObject * result;
00555     char * kwlist[] = {"format", NULL};
00556 
00557     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &fmt))
00558         return NULL;
00559 
00560     r = headerSprintf(s->h, fmt, rpmTagTable, rpmHeaderFormats, &err);
00561     if (!r) {
00562         PyErr_SetString(pyrpmError, err);
00563         return NULL;
00564     }
00565 
00566     result = Py_BuildValue("s", r);
00567     r = _free(r);
00568 
00569     return result;
00570 }
00571 
00576 /*@unchecked@*/ /*@observer@*/
00577 static struct PyMethodDef hdr_methods[] = {
00578     {"keys",            (PyCFunction) hdrKeyList,       METH_NOARGS,
00579         NULL },
00580     {"unload",          (PyCFunction) hdrUnload,        METH_VARARGS|METH_KEYWORDS,
00581         NULL },
00582     {"expandFilelist",  (PyCFunction) hdrExpandFilelist,METH_NOARGS,
00583         NULL },
00584     {"compressFilelist",(PyCFunction) hdrCompressFilelist,METH_NOARGS,
00585         NULL },
00586     {"fullFilelist",    (PyCFunction) hdrFullFilelist,  METH_NOARGS,
00587         NULL },
00588     {"getorigin",       (PyCFunction) hdrGetOrigin,     METH_NOARGS,
00589         NULL },
00590     {"setorigin",       (PyCFunction) hdrSetOrigin,     METH_NOARGS,
00591         NULL },
00592     {"sprintf",         (PyCFunction) hdrSprintf,       METH_VARARGS|METH_KEYWORDS,
00593         NULL },
00594 
00595     {"dsOfHeader",      (PyCFunction)hdr_dsOfHeader,    METH_NOARGS,
00596         NULL},
00597     {"dsFromHeader",    (PyCFunction)hdr_dsFromHeader,  METH_VARARGS|METH_KEYWORDS,
00598         NULL},
00599     {"fiFromHeader",    (PyCFunction)hdr_fiFromHeader,  METH_VARARGS|METH_KEYWORDS,
00600         NULL},
00601 
00602     {NULL,              NULL}           /* sentinel */
00603 };
00604 
00607 static int hdr_compare(hdrObject * a, hdrObject * b)
00608         /*@*/
00609 {
00610     return rpmVersionCompare(a->h, b->h);
00611 }
00612 
00613 static long hdr_hash(PyObject * h)
00614 {
00615     return (long) h;
00616 }
00617 
00618 static PyObject * hdr_getattro(PyObject * o, PyObject * n)
00619         /*@*/
00620 {
00621     return PyObject_GenericGetAttr(o, n);
00622 }
00623 
00624 static int hdr_setattro(PyObject * o, PyObject * n, PyObject * v)
00625         /*@*/
00626 {
00627     return PyObject_GenericSetAttr(o, n, v);
00628 }
00629 
00630 
00633 static void hdr_dealloc(hdrObject * s)
00634         /*@*/
00635 {
00636     if (s->h) headerFree(s->h);
00637     s->md5list = _free(s->md5list);
00638     s->fileList = _free(s->fileList);
00639     s->linkList = _free(s->linkList);
00640     PyObject_Del(s);
00641 }
00642 
00645 long tagNumFromPyObject (PyObject *item)
00646 {
00647     char * str;
00648     int i;
00649 
00650     if (PyInt_Check(item)) {
00651         return PyInt_AsLong(item);
00652     } else if (PyString_Check(item) || PyUnicode_Check(item)) {
00653         str = PyString_AsString(item);
00654         for (i = 0; i < rpmTagTableSize; i++)
00655             if (!xstrcasecmp(rpmTagTable[i].name + 7, str)) break;
00656         if (i < rpmTagTableSize) return rpmTagTable[i].val;
00657     }
00658     return -1;
00659 }
00660 
00674 static int rpmHeaderGetEntry(Header h, int_32 tag, /*@out@*/ int_32 *type,
00675                 /*@out@*/ void **p, /*@out@*/ int_32 *c)
00676         /*@modifies *type, *p, *c @*/
00677 {
00678     switch (tag) {
00679     case RPMTAG_OLDFILENAMES:
00680     {   const char ** fl = NULL;
00681         int count;
00682         rpmfiBuildFNames(h, RPMTAG_BASENAMES, &fl, &count);
00683         if (count > 0) {
00684             *p = fl;
00685             if (c)      *c = count;
00686             if (type)   *type = RPM_STRING_ARRAY_TYPE;
00687             return 1;
00688         }
00689         if (c)  *c = 0;
00690         return 0;
00691     }   /*@notreached@*/ break;
00692 
00693     case RPMTAG_GROUP:
00694     case RPMTAG_DESCRIPTION:
00695     case RPMTAG_SUMMARY:
00696     {   char fmt[128];
00697         const char * msgstr;
00698         const char * errstr;
00699 
00700         fmt[0] = '\0';
00701         (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tagName(tag)), "}\n");
00702 
00703         /* XXX FIXME: memory leak. */
00704         msgstr = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
00705         if (msgstr) {
00706             *p = (void *) msgstr;
00707             if (type)   *type = RPM_STRING_TYPE;
00708             if (c)      *c = 1;
00709             return 1;
00710         } else {
00711             if (c)      *c = 0;
00712             return 0;
00713         }
00714     }   /*@notreached@*/ break;
00715 
00716     default:
00717         return headerGetEntry(h, tag, type, p, c);
00718         /*@notreached@*/ break;
00719     }
00720     /*@notreached@*/
00721 }
00722 
00725 static PyObject * hdr_subscript(hdrObject * s, PyObject * item)
00726         /*@*/
00727 {
00728     int type, count, i, tag = -1;
00729     void * data;
00730     PyObject * o, * metao;
00731     char ** stringArray;
00732     int forceArray = 0;
00733     int freeData = 0;
00734     char * str;
00735     const struct headerSprintfExtension_s * ext = NULL;
00736     const struct headerSprintfExtension_s * extensions = rpmHeaderFormats;
00737 
00738     if (PyCObject_Check (item))
00739         ext = PyCObject_AsVoidPtr(item);
00740     else
00741         tag = tagNumFromPyObject (item);
00742     if (tag == -1 && (PyString_Check(item) || PyUnicode_Check(item))) {
00743         /* if we still don't have the tag, go looking for the header
00744            extensions */
00745         str = PyString_AsString(item);
00746         while (extensions->name) {
00747             if (extensions->type == HEADER_EXT_TAG
00748              && !xstrcasecmp(extensions->name + 7, str)) {
00749                 ext = extensions;
00750             }
00751             extensions++;
00752         }
00753     }
00754 
00755     /* Retrieve data from extension or header. */
00756     if (ext) {
00757         ext->u.tagFunction(s->h, &type, (const void **) &data, &count, &freeData);
00758     } else {
00759         if (tag == -1) {
00760             PyErr_SetString(PyExc_KeyError, "unknown header tag");
00761             return NULL;
00762         }
00763         
00764         if (!rpmHeaderGetEntry(s->h, tag, &type, &data, &count)) {
00765             switch (tag) {
00766             case RPMTAG_EPOCH:
00767             case RPMTAG_NAME:
00768             case RPMTAG_VERSION:
00769             case RPMTAG_RELEASE:
00770             case RPMTAG_ARCH:
00771             case RPMTAG_OS:
00772                 Py_INCREF(Py_None);
00773                 return Py_None;
00774                 break;
00775             default:
00776                 return PyList_New(0);
00777                 break;
00778             }
00779         }
00780     }
00781 
00782     switch (tag) {
00783     case RPMTAG_OLDFILENAMES:
00784     case RPMTAG_FILESIZES:
00785     case RPMTAG_FILESTATES:
00786     case RPMTAG_FILEMODES:
00787     case RPMTAG_FILEUIDS:
00788     case RPMTAG_FILEGIDS:
00789     case RPMTAG_FILERDEVS:
00790     case RPMTAG_FILEMTIMES:
00791     case RPMTAG_FILEMD5S:
00792     case RPMTAG_FILELINKTOS:
00793     case RPMTAG_FILEFLAGS:
00794     case RPMTAG_ROOT:
00795     case RPMTAG_FILEUSERNAME:
00796     case RPMTAG_FILEGROUPNAME:
00797     case RPMTAG_REQUIRENAME:
00798     case RPMTAG_REQUIREFLAGS:
00799     case RPMTAG_REQUIREVERSION:
00800     case RPMTAG_PROVIDENAME:
00801     case RPMTAG_PROVIDEFLAGS:
00802     case RPMTAG_PROVIDEVERSION:
00803     case RPMTAG_OBSOLETENAME:
00804     case RPMTAG_OBSOLETEFLAGS:
00805     case RPMTAG_OBSOLETEVERSION:
00806     case RPMTAG_CONFLICTNAME:
00807     case RPMTAG_CONFLICTFLAGS:
00808     case RPMTAG_CONFLICTVERSION:
00809     case RPMTAG_CHANGELOGTIME:
00810         forceArray = 1;
00811         break;
00812     case RPMTAG_SUMMARY:
00813     case RPMTAG_GROUP:
00814     case RPMTAG_DESCRIPTION:
00815         freeData = 1;
00816         break;
00817     default:
00818         break;
00819     }
00820 
00821     switch (type) {
00822     case RPM_OPENPGP_TYPE:
00823     case RPM_ASN1_TYPE:
00824     case RPM_BIN_TYPE:
00825         o = PyString_FromStringAndSize(data, count);
00826         break;
00827 
00828     case RPM_INT64_TYPE:
00829         if (count != 1 || forceArray) {
00830             metao = PyList_New(0);
00831             for (i = 0; i < count; i++) {
00832                 o = PyInt_FromLong(((long long *) data)[i]);
00833                 PyList_Append(metao, o);
00834                 Py_DECREF(o);
00835             }
00836             o = metao;
00837         } else {
00838             o = PyInt_FromLong(*((long long *) data));
00839         }
00840         break;
00841     case RPM_INT32_TYPE:
00842         if (count != 1 || forceArray) {
00843             metao = PyList_New(0);
00844             for (i = 0; i < count; i++) {
00845                 o = PyInt_FromLong(((int *) data)[i]);
00846                 PyList_Append(metao, o);
00847                 Py_DECREF(o);
00848             }
00849             o = metao;
00850         } else {
00851             o = PyInt_FromLong(*((int *) data));
00852         }
00853         break;
00854 
00855     case RPM_CHAR_TYPE:
00856     case RPM_INT8_TYPE:
00857         if (count != 1 || forceArray) {
00858             metao = PyList_New(0);
00859             for (i = 0; i < count; i++) {
00860                 o = PyInt_FromLong(((char *) data)[i]);
00861                 PyList_Append(metao, o);
00862                 Py_DECREF(o);
00863             }
00864             o = metao;
00865         } else {
00866             o = PyInt_FromLong(*((char *) data));
00867         }
00868         break;
00869 
00870     case RPM_INT16_TYPE:
00871         if (count != 1 || forceArray) {
00872             metao = PyList_New(0);
00873             for (i = 0; i < count; i++) {
00874                 o = PyInt_FromLong(((short *) data)[i]);
00875                 PyList_Append(metao, o);
00876                 Py_DECREF(o);
00877             }
00878             o = metao;
00879         } else {
00880             o = PyInt_FromLong(*((short *) data));
00881         }
00882         break;
00883 
00884     case RPM_STRING_ARRAY_TYPE:
00885         stringArray = data;
00886 
00887         metao = PyList_New(0);
00888         for (i = 0; i < count; i++) {
00889             o = PyString_FromString(stringArray[i]);
00890             PyList_Append(metao, o);
00891             Py_DECREF(o);
00892         }
00893         free (stringArray);
00894         o = metao;
00895         break;
00896 
00897     case RPM_STRING_TYPE:
00898         if (count != 1 || forceArray) {
00899             stringArray = data;
00900 
00901             metao = PyList_New(0);
00902             for (i=0; i < count; i++) {
00903                 o = PyString_FromString(stringArray[i]);
00904                 PyList_Append(metao, o);
00905                 Py_DECREF(o);
00906             }
00907             o = metao;
00908         } else {
00909             o = PyString_FromString(data);
00910             if (freeData)
00911                 free (data);
00912         }
00913         break;
00914 
00915     default:
00916         PyErr_SetString(PyExc_TypeError, "unsupported type in header");
00917         return NULL;
00918     }
00919 
00920     return o;
00921 }
00922 
00925 /*@unchecked@*/ /*@observer@*/
00926 static PyMappingMethods hdr_as_mapping = {
00927         (inquiry) 0,                    /* mp_length */
00928         (binaryfunc) hdr_subscript,     /* mp_subscript */
00929         (objobjargproc)0,               /* mp_ass_subscript */
00930 };
00931 
00934 static char hdr_doc[] =
00935 "";
00936 
00939 /*@unchecked@*/ /*@observer@*/
00940 PyTypeObject hdr_Type = {
00941         PyObject_HEAD_INIT(&PyType_Type)
00942         0,                              /* ob_size */
00943         "rpm.hdr",                      /* tp_name */
00944         sizeof(hdrObject),              /* tp_size */
00945         0,                              /* tp_itemsize */
00946         (destructor) hdr_dealloc,       /* tp_dealloc */
00947         0,                              /* tp_print */
00948         (getattrfunc) 0,                /* tp_getattr */
00949         0,                              /* tp_setattr */
00950         (cmpfunc) hdr_compare,          /* tp_compare */
00951         0,                              /* tp_repr */
00952         0,                              /* tp_as_number */
00953         0,                              /* tp_as_sequence */
00954         &hdr_as_mapping,                /* tp_as_mapping */
00955         hdr_hash,                       /* tp_hash */
00956         0,                              /* tp_call */
00957         0,                              /* tp_str */
00958         (getattrofunc) hdr_getattro,    /* tp_getattro */
00959         (setattrofunc) hdr_setattro,    /* tp_setattro */
00960         0,                              /* tp_as_buffer */
00961         Py_TPFLAGS_DEFAULT,             /* tp_flags */
00962         hdr_doc,                        /* tp_doc */
00963 #if Py_TPFLAGS_HAVE_ITER
00964         0,                              /* tp_traverse */
00965         0,                              /* tp_clear */
00966         0,                              /* tp_richcompare */
00967         0,                              /* tp_weaklistoffset */
00968         0,                              /* tp_iter */
00969         0,                              /* tp_iternext */
00970         hdr_methods,                    /* tp_methods */
00971         0,                              /* tp_members */
00972         0,                              /* tp_getset */
00973         0,                              /* tp_base */
00974         0,                              /* tp_dict */
00975         0,                              /* tp_descr_get */
00976         0,                              /* tp_descr_set */
00977         0,                              /* tp_dictoffset */
00978         0,                              /* tp_init */
00979         0,                              /* tp_alloc */
00980         0,                              /* tp_new */
00981         0,                              /* tp_free */
00982         0,                              /* tp_is_gc */
00983 #endif
00984 };
00985 
00986 hdrObject * hdr_Wrap(Header h)
00987 {
00988     hdrObject * hdr = PyObject_New(hdrObject, &hdr_Type);
00989     hdr->h = headerLink(h);
00990     hdr->fileList = hdr->linkList = hdr->md5list = NULL;
00991     hdr->uids = hdr->gids = hdr->mtimes = hdr->fileSizes = NULL;
00992     hdr->modes = hdr->rdevs = NULL;
00993     return hdr;
00994 }
00995 
00996 Header hdrGetHeader(hdrObject * s)
00997 {
00998     return s->h;
00999 }
01000 
01003 PyObject * hdrLoad(PyObject * self, PyObject * args, PyObject * kwds)
01004 {
01005     hdrObject * hdr;
01006     char * copy = NULL;
01007     char * obj;
01008     Header h;
01009     int len;
01010     char * kwlist[] = {"headers", NULL};
01011 
01012     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#", kwlist, &obj, &len))
01013         return NULL;
01014 
01015     /* malloc is needed to avoid surprises from data swab in headerLoad(). */
01016     copy = malloc(len);
01017     if (copy == NULL) {
01018         PyErr_SetString(pyrpmError, "out of memory");
01019         return NULL;
01020     }
01021     memcpy (copy, obj, len);
01022 
01023     h = headerLoad(copy);
01024     if (!h) {
01025         PyErr_SetString(pyrpmError, "bad header");
01026         return NULL;
01027     }
01028     headerAllocated(h);
01029     compressFilelist (h);
01030     providePackageNVR (h);
01031 
01032     hdr = hdr_Wrap(h);
01033     h = headerFree(h);  /* XXX ref held by hdr */
01034 
01035     return (PyObject *) hdr;
01036 }
01037 
01040 PyObject * rpmReadHeaders (FD_t fd)
01041 {
01042     PyObject * list;
01043     Header h;
01044     hdrObject * hdr;
01045 
01046     if (!fd) {
01047         PyErr_SetFromErrno(pyrpmError);
01048         return NULL;
01049     }
01050 
01051     list = PyList_New(0);
01052     Py_BEGIN_ALLOW_THREADS
01053     h = headerRead(fd, HEADER_MAGIC_YES);
01054     Py_END_ALLOW_THREADS
01055 
01056     while (h) {
01057         compressFilelist(h);
01058         providePackageNVR(h);
01059         hdr = hdr_Wrap(h);
01060         if (PyList_Append(list, (PyObject *) hdr)) {
01061             Py_DECREF(list);
01062             Py_DECREF(hdr);
01063             return NULL;
01064         }
01065         Py_DECREF(hdr);
01066 
01067         h = headerFree(h);      /* XXX ref held by hdr */
01068 
01069         Py_BEGIN_ALLOW_THREADS
01070         h = headerRead(fd, HEADER_MAGIC_YES);
01071         Py_END_ALLOW_THREADS
01072     }
01073 
01074     return list;
01075 }
01076 
01079 PyObject * rpmHeaderFromFD(PyObject * self, PyObject * args, PyObject * kwds)
01080 {
01081     FD_t fd;
01082     int fileno;
01083     PyObject * list;
01084     char * kwlist[] = {"fd", NULL};
01085 
01086     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &fileno))
01087         return NULL;
01088 
01089     fd = fdDup(fileno);
01090 
01091     list = rpmReadHeaders (fd);
01092     Fclose(fd);
01093 
01094     return list;
01095 }
01096 
01099 PyObject * rpmHeaderFromFile(PyObject * self, PyObject * args, PyObject *kwds)
01100 {
01101     char * filespec;
01102     FD_t fd;
01103     PyObject * list;
01104     char * kwlist[] = {"file", NULL};
01105 
01106     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &filespec))
01107         return NULL;
01108 
01109     fd = Fopen(filespec, "r.fdio");
01110 
01111     if (!fd) {
01112         PyErr_SetFromErrno(pyrpmError);
01113         return NULL;
01114     }
01115 
01116     list = rpmReadHeaders (fd);
01117     Fclose(fd);
01118 
01119     return list;
01120 }
01121 
01126 int rpmMergeHeaders(PyObject * list, FD_t fd, int matchTag)
01127 {
01128     Header h;
01129     HeaderIterator hi;
01130     int_32 * newMatch;
01131     int_32 * oldMatch;
01132     hdrObject * hdr;
01133     int count = 0;
01134     int type, c, tag;
01135     void * p;
01136 
01137     Py_BEGIN_ALLOW_THREADS
01138     h = headerRead(fd, HEADER_MAGIC_YES);
01139     Py_END_ALLOW_THREADS
01140 
01141     while (h) {
01142         if (!headerGetEntry(h, matchTag, NULL, (void **) &newMatch, NULL)) {
01143             PyErr_SetString(pyrpmError, "match tag missing in new header");
01144             return 1;
01145         }
01146 
01147         hdr = (hdrObject *) PyList_GetItem(list, count++);
01148         if (!hdr) return 1;
01149 
01150         if (!headerGetEntry(hdr->h, matchTag, NULL, (void **) &oldMatch, NULL)) {
01151             PyErr_SetString(pyrpmError, "match tag missing in new header");
01152             return 1;
01153         }
01154 
01155         if (*newMatch != *oldMatch) {
01156             PyErr_SetString(pyrpmError, "match tag mismatch");
01157             return 1;
01158         }
01159 
01160         hdr->md5list = _free(hdr->md5list);
01161         hdr->fileList = _free(hdr->fileList);
01162         hdr->linkList = _free(hdr->linkList);
01163 
01164         for (hi = headerInitIterator(h);
01165             headerNextIterator(hi, &tag, &type, (void *) &p, &c);
01166             p = headerFreeData(p, type))
01167         {
01168             /* could be dupes */
01169             headerRemoveEntry(hdr->h, tag);
01170             headerAddEntry(hdr->h, tag, type, p, c);
01171         }
01172 
01173         headerFreeIterator(hi);
01174         h = headerFree(h);
01175 
01176         Py_BEGIN_ALLOW_THREADS
01177         h = headerRead(fd, HEADER_MAGIC_YES);
01178         Py_END_ALLOW_THREADS
01179     }
01180 
01181     return 0;
01182 }
01183 
01184 PyObject *
01185 rpmMergeHeadersFromFD(PyObject * self, PyObject * args, PyObject * kwds)
01186 {
01187     FD_t fd;
01188     int fileno;
01189     PyObject * list;
01190     int rc;
01191     int matchTag;
01192     char * kwlist[] = {"list", "fd", "matchTag", NULL};
01193 
01194     if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oii", kwlist, &list,
01195             &fileno, &matchTag))
01196         return NULL;
01197 
01198     if (!PyList_Check(list)) {
01199         PyErr_SetString(PyExc_TypeError, "first parameter must be a list");
01200         return NULL;
01201     }
01202 
01203     fd = fdDup(fileno);
01204 
01205     rc = rpmMergeHeaders (list, fd, matchTag);
01206     Fclose(fd);
01207 
01208     if (rc) {
01209         return NULL;
01210     }
01211 
01212     Py_INCREF(Py_None);
01213     return Py_None;
01214 }
01215 
01218 PyObject *
01219 rpmSingleHeaderFromFD(PyObject * self, PyObject * args, PyObject * kwds)
01220 {
01221     FD_t fd;
01222     int fileno;
01223     off_t offset;
01224     PyObject * tuple;
01225     Header h;
01226     char * kwlist[] = {"fd", NULL};
01227 
01228     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &fileno))
01229         return NULL;
01230 
01231     offset = lseek(fileno, 0, SEEK_CUR);
01232 
01233     fd = fdDup(fileno);
01234 
01235     if (!fd) {
01236         PyErr_SetFromErrno(pyrpmError);
01237         return NULL;
01238     }
01239 
01240     Py_BEGIN_ALLOW_THREADS
01241     h = headerRead(fd, HEADER_MAGIC_YES);
01242     Py_END_ALLOW_THREADS
01243 
01244     Fclose(fd);
01245 
01246     tuple = PyTuple_New(2);
01247 
01248     if (h && tuple) {
01249         PyTuple_SET_ITEM(tuple, 0, (PyObject *) hdr_Wrap(h));
01250         PyTuple_SET_ITEM(tuple, 1, PyLong_FromLong(offset));
01251         h = headerFree(h);
01252     } else {
01253         Py_INCREF(Py_None);
01254         Py_INCREF(Py_None);
01255         PyTuple_SET_ITEM(tuple, 0, Py_None);
01256         PyTuple_SET_ITEM(tuple, 1, Py_None);
01257     }
01258 
01259     return tuple;
01260 }
01261 
01264 PyObject * versionCompare (PyObject * self, PyObject * args, PyObject * kwds)
01265 {
01266     hdrObject * h1, * h2;
01267     char * kwlist[] = {"version0", "version1", NULL};
01268 
01269     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", kwlist, &hdr_Type,
01270             &h1, &hdr_Type, &h2))
01271         return NULL;
01272 
01273     return Py_BuildValue("i", hdr_compare(h1, h2));
01274 }
01275 
01276 PyObject * labelCompare (PyObject * self, PyObject * args)
01277 {
01278     EVR_t A = memset(alloca(sizeof(*A)), 0, sizeof(*A));
01279     EVR_t B = memset(alloca(sizeof(*B)), 0, sizeof(*B));
01280     int rc;
01281 
01282     if (!PyArg_ParseTuple(args, "(zzz)(zzz)",
01283                         &A->E, &A->V, &A->R, &B->E, &B->V, &B->R))
01284         return NULL;
01285 
01286     if (A->E == NULL)   A->E = "0";
01287     if (B->E == NULL)   B->E = "0";
01288     if (A->V == NULL)   A->E = "";
01289     if (B->V == NULL)   B->E = "";
01290     if (A->R == NULL)   A->E = "";
01291     if (B->R == NULL)   B->E = "";
01292 
01293     rc = rpmEVRcompare(A, B);
01294 
01295     return Py_BuildValue("i", rc);
01296 }

Generated on Wed Feb 6 22:32:31 2008 for rpm by  doxygen 1.5.1