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, &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, &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, &provides, &providesCount))
00359         goto exit;
00360 
00361     /*
00362      * Otherwise, fill in entries on legacy packages.
00363      */
00364     if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt, &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, &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 
00621 static void hdr_dealloc(hdrObject * s)
00622         /*@*/
00623 {
00624     if (s->h) headerFree(s->h);
00625     s->md5list = _free(s->md5list);
00626     s->fileList = _free(s->fileList);
00627     s->linkList = _free(s->linkList);
00628     PyObject_Del(s);
00629 }
00630 
00633 long tagNumFromPyObject (PyObject *item)
00634 {
00635     char * str;
00636     int i;
00637 
00638     if (PyInt_Check(item)) {
00639         return PyInt_AsLong(item);
00640     } else if (PyString_Check(item) || PyUnicode_Check(item)) {
00641         str = PyString_AsString(item);
00642         for (i = 0; i < rpmTagTableSize; i++)
00643             if (!xstrcasecmp(rpmTagTable[i].name + 7, str)) break;
00644         if (i < rpmTagTableSize) return rpmTagTable[i].val;
00645     }
00646     return -1;
00647 }
00648 
00662 static int rpmHeaderGetEntry(Header h, int_32 tag, /*@out@*/ int_32 *type,
00663                 /*@out@*/ void **p, /*@out@*/ int_32 *c)
00664         /*@modifies *type, *p, *c @*/
00665 {
00666     switch (tag) {
00667     case RPMTAG_OLDFILENAMES:
00668     {   const char ** fl = NULL;
00669         int count;
00670         rpmfiBuildFNames(h, RPMTAG_BASENAMES, &fl, &count);
00671         if (count > 0) {
00672             *p = fl;
00673             if (c)      *c = count;
00674             if (type)   *type = RPM_STRING_ARRAY_TYPE;
00675             return 1;
00676         }
00677         if (c)  *c = 0;
00678         return 0;
00679     }   /*@notreached@*/ break;
00680 
00681     case RPMTAG_GROUP:
00682     case RPMTAG_DESCRIPTION:
00683     case RPMTAG_SUMMARY:
00684     {   char fmt[128];
00685         const char * msgstr;
00686         const char * errstr;
00687 
00688         fmt[0] = '\0';
00689         (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tagName(tag)), "}\n");
00690 
00691         /* XXX FIXME: memory leak. */
00692         msgstr = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
00693         if (msgstr) {
00694             *p = (void *) msgstr;
00695             if (type)   *type = RPM_STRING_TYPE;
00696             if (c)      *c = 1;
00697             return 1;
00698         } else {
00699             if (c)      *c = 0;
00700             return 0;
00701         }
00702     }   /*@notreached@*/ break;
00703 
00704     default:
00705         return headerGetEntry(h, tag, type, p, c);
00706         /*@notreached@*/ break;
00707     }
00708     /*@notreached@*/
00709 }
00710 
00713 static PyObject * hdr_subscript(hdrObject * s, PyObject * item)
00714         /*@*/
00715 {
00716     int type, count, i, tag = -1;
00717     void * data;
00718     PyObject * o, * metao;
00719     char ** stringArray;
00720     int forceArray = 0;
00721     int freeData = 0;
00722     char * str;
00723     const struct headerSprintfExtension_s * ext = NULL;
00724     const struct headerSprintfExtension_s * extensions = rpmHeaderFormats;
00725 
00726     if (PyCObject_Check (item))
00727         ext = PyCObject_AsVoidPtr(item);
00728     else
00729         tag = tagNumFromPyObject (item);
00730     if (tag == -1 && (PyString_Check(item) || PyUnicode_Check(item))) {
00731         /* if we still don't have the tag, go looking for the header
00732            extensions */
00733         str = PyString_AsString(item);
00734         while (extensions->name) {
00735             if (extensions->type == HEADER_EXT_TAG
00736              && !xstrcasecmp(extensions->name + 7, str)) {
00737                 ext = extensions;
00738             }
00739             extensions++;
00740         }
00741     }
00742 
00743     /* Retrieve data from extension or header. */
00744     if (ext) {
00745         HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00746         ext->u.tagFunction(s->h, he);
00747         type = he->t;
00748         data = he->p.ptr;
00749         count = he->c;
00750         freeData = he->freeData;
00751     } else {
00752         if (tag == -1) {
00753             PyErr_SetString(PyExc_KeyError, "unknown header tag");
00754             return NULL;
00755         }
00756         
00757         if (!rpmHeaderGetEntry(s->h, tag, &type, &data, &count)) {
00758             switch (tag) {
00759             case RPMTAG_EPOCH:
00760             case RPMTAG_NAME:
00761             case RPMTAG_VERSION:
00762             case RPMTAG_RELEASE:
00763             case RPMTAG_ARCH:
00764             case RPMTAG_OS:
00765                 Py_INCREF(Py_None);
00766                 return Py_None;
00767                 break;
00768             default:
00769                 return PyList_New(0);
00770                 break;
00771             }
00772         }
00773     }
00774 
00775     switch (tag) {
00776     case RPMTAG_OLDFILENAMES:
00777     case RPMTAG_FILESIZES:
00778     case RPMTAG_FILESTATES:
00779     case RPMTAG_FILEMODES:
00780     case RPMTAG_FILEUIDS:
00781     case RPMTAG_FILEGIDS:
00782     case RPMTAG_FILERDEVS:
00783     case RPMTAG_FILEMTIMES:
00784     case RPMTAG_FILEMD5S:
00785     case RPMTAG_FILELINKTOS:
00786     case RPMTAG_FILEFLAGS:
00787     case RPMTAG_ROOT:
00788     case RPMTAG_FILEUSERNAME:
00789     case RPMTAG_FILEGROUPNAME:
00790     case RPMTAG_REQUIRENAME:
00791     case RPMTAG_REQUIREFLAGS:
00792     case RPMTAG_REQUIREVERSION:
00793     case RPMTAG_PROVIDENAME:
00794     case RPMTAG_PROVIDEFLAGS:
00795     case RPMTAG_PROVIDEVERSION:
00796     case RPMTAG_OBSOLETENAME:
00797     case RPMTAG_OBSOLETEFLAGS:
00798     case RPMTAG_OBSOLETEVERSION:
00799     case RPMTAG_CONFLICTNAME:
00800     case RPMTAG_CONFLICTFLAGS:
00801     case RPMTAG_CONFLICTVERSION:
00802     case RPMTAG_CHANGELOGTIME:
00803     case RPMTAG_FILEVERIFYFLAGS:
00804         forceArray = 1;
00805         break;
00806     case RPMTAG_SUMMARY:
00807     case RPMTAG_GROUP:
00808     case RPMTAG_DESCRIPTION:
00809         freeData = 1;
00810         break;
00811     default:
00812         break;
00813     }
00814 
00815     switch (type) {
00816     case RPM_OPENPGP_TYPE:
00817     case RPM_ASN1_TYPE:
00818     case RPM_BIN_TYPE:
00819         o = PyString_FromStringAndSize(data, count);
00820         break;
00821 
00822     case RPM_INT64_TYPE:
00823         if (count != 1 || forceArray) {
00824             metao = PyList_New(0);
00825             for (i = 0; i < count; i++) {
00826                 o = PyInt_FromLong(((long long *) data)[i]);
00827                 PyList_Append(metao, o);
00828                 Py_DECREF(o);
00829             }
00830             o = metao;
00831         } else {
00832             o = PyInt_FromLong(*((long long *) data));
00833         }
00834         break;
00835     case RPM_INT32_TYPE:
00836         if (count != 1 || forceArray) {
00837             metao = PyList_New(0);
00838             for (i = 0; i < count; i++) {
00839                 o = PyInt_FromLong(((int *) data)[i]);
00840                 PyList_Append(metao, o);
00841                 Py_DECREF(o);
00842             }
00843             o = metao;
00844         } else {
00845             o = PyInt_FromLong(*((int *) data));
00846         }
00847         break;
00848 
00849     case RPM_CHAR_TYPE:
00850     case RPM_INT8_TYPE:
00851         if (count != 1 || forceArray) {
00852             metao = PyList_New(0);
00853             for (i = 0; i < count; i++) {
00854                 o = PyInt_FromLong(((char *) data)[i]);
00855                 PyList_Append(metao, o);
00856                 Py_DECREF(o);
00857             }
00858             o = metao;
00859         } else {
00860             o = PyInt_FromLong(*((char *) data));
00861         }
00862         break;
00863 
00864     case RPM_INT16_TYPE:
00865         if (count != 1 || forceArray) {
00866             metao = PyList_New(0);
00867             for (i = 0; i < count; i++) {
00868                 o = PyInt_FromLong(((short *) data)[i]);
00869                 PyList_Append(metao, o);
00870                 Py_DECREF(o);
00871             }
00872             o = metao;
00873         } else {
00874             o = PyInt_FromLong(*((short *) data));
00875         }
00876         break;
00877 
00878     case RPM_STRING_ARRAY_TYPE:
00879         stringArray = data;
00880 
00881         metao = PyList_New(0);
00882         for (i = 0; i < count; i++) {
00883             o = PyString_FromString(stringArray[i]);
00884             PyList_Append(metao, o);
00885             Py_DECREF(o);
00886         }
00887         free (stringArray);
00888         o = metao;
00889         break;
00890 
00891     case RPM_STRING_TYPE:
00892         if (count != 1 || forceArray) {
00893             stringArray = data;
00894 
00895             metao = PyList_New(0);
00896             for (i=0; i < count; i++) {
00897                 o = PyString_FromString(stringArray[i]);
00898                 PyList_Append(metao, o);
00899                 Py_DECREF(o);
00900             }
00901             o = metao;
00902         } else {
00903             o = PyString_FromString(data);
00904             if (freeData)
00905                 free (data);
00906         }
00907         break;
00908 
00909     default:
00910         PyErr_SetString(PyExc_TypeError, "unsupported type in header");
00911         return NULL;
00912     }
00913 
00914     return o;
00915 }
00916 
00917 static PyObject * hdr_getattro(PyObject * o, PyObject * n)
00918         /*@*/
00919 {
00920     PyObject * res = PyObject_GenericGetAttr(o, n);
00921     if (res == NULL)
00922         res = hdr_subscript(o, n);
00923     return res;
00924 }
00925 
00926 static int hdr_setattro(PyObject * o, PyObject * n, PyObject * v)
00927         /*@*/
00928 {
00929     return PyObject_GenericSetAttr(o, n, v);
00930 }
00931 
00934 /*@unchecked@*/ /*@observer@*/
00935 static PyMappingMethods hdr_as_mapping = {
00936         (inquiry) 0,                    /* mp_length */
00937         (binaryfunc) hdr_subscript,     /* mp_subscript */
00938         (objobjargproc)0,               /* mp_ass_subscript */
00939 };
00940 
00943 static char hdr_doc[] =
00944 "";
00945 
00948 /*@unchecked@*/ /*@observer@*/
00949 PyTypeObject hdr_Type = {
00950         PyObject_HEAD_INIT(&PyType_Type)
00951         0,                              /* ob_size */
00952         "rpm.hdr",                      /* tp_name */
00953         sizeof(hdrObject),              /* tp_size */
00954         0,                              /* tp_itemsize */
00955         (destructor) hdr_dealloc,       /* tp_dealloc */
00956         0,                              /* tp_print */
00957         (getattrfunc) 0,                /* tp_getattr */
00958         0,                              /* tp_setattr */
00959         (cmpfunc) hdr_compare,          /* tp_compare */
00960         0,                              /* tp_repr */
00961         0,                              /* tp_as_number */
00962         0,                              /* tp_as_sequence */
00963         &hdr_as_mapping,                /* tp_as_mapping */
00964         hdr_hash,                       /* tp_hash */
00965         0,                              /* tp_call */
00966         0,                              /* tp_str */
00967         (getattrofunc) hdr_getattro,    /* tp_getattro */
00968         (setattrofunc) hdr_setattro,    /* tp_setattro */
00969         0,                              /* tp_as_buffer */
00970         Py_TPFLAGS_DEFAULT,             /* tp_flags */
00971         hdr_doc,                        /* tp_doc */
00972 #if Py_TPFLAGS_HAVE_ITER
00973         0,                              /* tp_traverse */
00974         0,                              /* tp_clear */
00975         0,                              /* tp_richcompare */
00976         0,                              /* tp_weaklistoffset */
00977         0,                              /* tp_iter */
00978         0,                              /* tp_iternext */
00979         hdr_methods,                    /* tp_methods */
00980         0,                              /* tp_members */
00981         0,                              /* tp_getset */
00982         0,                              /* tp_base */
00983         0,                              /* tp_dict */
00984         0,                              /* tp_descr_get */
00985         0,                              /* tp_descr_set */
00986         0,                              /* tp_dictoffset */
00987         0,                              /* tp_init */
00988         0,                              /* tp_alloc */
00989         0,                              /* tp_new */
00990         0,                              /* tp_free */
00991         0,                              /* tp_is_gc */
00992 #endif
00993 };
00994 
00995 hdrObject * hdr_Wrap(Header h)
00996 {
00997     hdrObject * hdr = PyObject_New(hdrObject, &hdr_Type);
00998     hdr->h = headerLink(h);
00999     hdr->fileList = hdr->linkList = hdr->md5list = NULL;
01000     hdr->uids = hdr->gids = hdr->mtimes = hdr->fileSizes = NULL;
01001     hdr->modes = hdr->rdevs = NULL;
01002     return hdr;
01003 }
01004 
01005 Header hdrGetHeader(hdrObject * s)
01006 {
01007     return s->h;
01008 }
01009 
01012 PyObject * hdrLoad(PyObject * self, PyObject * args, PyObject * kwds)
01013 {
01014     hdrObject * hdr;
01015     char * copy = NULL;
01016     char * obj;
01017     Header h;
01018     int len;
01019     char * kwlist[] = {"headers", NULL};
01020 
01021     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#", kwlist, &obj, &len))
01022         return NULL;
01023 
01024     /* malloc is needed to avoid surprises from data swab in headerLoad(). */
01025     copy = malloc(len);
01026     if (copy == NULL) {
01027         PyErr_SetString(pyrpmError, "out of memory");
01028         return NULL;
01029     }
01030     memcpy (copy, obj, len);
01031 
01032     h = headerLoad(copy);
01033     if (!h) {
01034         PyErr_SetString(pyrpmError, "bad header");
01035         return NULL;
01036     }
01037     headerAllocated(h);
01038     compressFilelist (h);
01039     providePackageNVR (h);
01040 
01041     hdr = hdr_Wrap(h);
01042     h = headerFree(h);  /* XXX ref held by hdr */
01043 
01044     return (PyObject *) hdr;
01045 }
01046 
01049 PyObject * rpmReadHeaders (FD_t fd)
01050 {
01051     PyObject * list;
01052     Header h;
01053     hdrObject * hdr;
01054 
01055     if (!fd) {
01056         PyErr_SetFromErrno(pyrpmError);
01057         return NULL;
01058     }
01059 
01060     list = PyList_New(0);
01061     Py_BEGIN_ALLOW_THREADS
01062     h = headerRead(fd, HEADER_MAGIC_YES);
01063     Py_END_ALLOW_THREADS
01064 
01065     while (h) {
01066         compressFilelist(h);
01067         providePackageNVR(h);
01068         hdr = hdr_Wrap(h);
01069         if (PyList_Append(list, (PyObject *) hdr)) {
01070             Py_DECREF(list);
01071             Py_DECREF(hdr);
01072             return NULL;
01073         }
01074         Py_DECREF(hdr);
01075 
01076         h = headerFree(h);      /* XXX ref held by hdr */
01077 
01078         Py_BEGIN_ALLOW_THREADS
01079         h = headerRead(fd, HEADER_MAGIC_YES);
01080         Py_END_ALLOW_THREADS
01081     }
01082 
01083     return list;
01084 }
01085 
01088 PyObject * rpmHeaderFromFD(PyObject * self, PyObject * args, PyObject * kwds)
01089 {
01090     FD_t fd;
01091     int fileno;
01092     PyObject * list;
01093     char * kwlist[] = {"fd", NULL};
01094 
01095     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &fileno))
01096         return NULL;
01097 
01098     fd = fdDup(fileno);
01099 
01100     list = rpmReadHeaders (fd);
01101     Fclose(fd);
01102 
01103     return list;
01104 }
01105 
01108 PyObject * rpmHeaderFromFile(PyObject * self, PyObject * args, PyObject *kwds)
01109 {
01110     char * filespec;
01111     FD_t fd;
01112     PyObject * list;
01113     char * kwlist[] = {"file", NULL};
01114 
01115     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &filespec))
01116         return NULL;
01117 
01118     fd = Fopen(filespec, "r.fdio");
01119 
01120     if (!fd) {
01121         PyErr_SetFromErrno(pyrpmError);
01122         return NULL;
01123     }
01124 
01125     list = rpmReadHeaders (fd);
01126     Fclose(fd);
01127 
01128     return list;
01129 }
01130 
01135 int rpmMergeHeaders(PyObject * list, FD_t fd, int matchTag)
01136 {
01137     Header h;
01138     HeaderIterator hi;
01139     int_32 * newMatch;
01140     int_32 * oldMatch;
01141     hdrObject * hdr;
01142     int count = 0;
01143     int type, c, tag;
01144     void * p;
01145 
01146     Py_BEGIN_ALLOW_THREADS
01147     h = headerRead(fd, HEADER_MAGIC_YES);
01148     Py_END_ALLOW_THREADS
01149 
01150     while (h) {
01151         if (!headerGetEntry(h, matchTag, NULL, &newMatch, NULL)) {
01152             PyErr_SetString(pyrpmError, "match tag missing in new header");
01153             return 1;
01154         }
01155 
01156         hdr = (hdrObject *) PyList_GetItem(list, count++);
01157         if (!hdr) return 1;
01158 
01159         if (!headerGetEntry(hdr->h, matchTag, NULL, &oldMatch, NULL)) {
01160             PyErr_SetString(pyrpmError, "match tag missing in new header");
01161             return 1;
01162         }
01163 
01164         if (*newMatch != *oldMatch) {
01165             PyErr_SetString(pyrpmError, "match tag mismatch");
01166             return 1;
01167         }
01168 
01169         hdr->md5list = _free(hdr->md5list);
01170         hdr->fileList = _free(hdr->fileList);
01171         hdr->linkList = _free(hdr->linkList);
01172 
01173         for (hi = headerInitIterator(h);
01174             headerNextIterator(hi, &tag, &type, (void *) &p, &c);
01175             p = headerFreeData(p, type))
01176         {
01177             /* could be dupes */
01178             headerRemoveEntry(hdr->h, tag);
01179             headerAddEntry(hdr->h, tag, type, p, c);
01180         }
01181 
01182         headerFreeIterator(hi);
01183         h = headerFree(h);
01184 
01185         Py_BEGIN_ALLOW_THREADS
01186         h = headerRead(fd, HEADER_MAGIC_YES);
01187         Py_END_ALLOW_THREADS
01188     }
01189 
01190     return 0;
01191 }
01192 
01193 PyObject *
01194 rpmMergeHeadersFromFD(PyObject * self, PyObject * args, PyObject * kwds)
01195 {
01196     FD_t fd;
01197     int fileno;
01198     PyObject * list;
01199     int rc;
01200     int matchTag;
01201     char * kwlist[] = {"list", "fd", "matchTag", NULL};
01202 
01203     if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oii", kwlist, &list,
01204             &fileno, &matchTag))
01205         return NULL;
01206 
01207     if (!PyList_Check(list)) {
01208         PyErr_SetString(PyExc_TypeError, "first parameter must be a list");
01209         return NULL;
01210     }
01211 
01212     fd = fdDup(fileno);
01213 
01214     rc = rpmMergeHeaders (list, fd, matchTag);
01215     Fclose(fd);
01216 
01217     if (rc) {
01218         return NULL;
01219     }
01220 
01221     Py_INCREF(Py_None);
01222     return Py_None;
01223 }
01224 
01227 PyObject *
01228 rpmSingleHeaderFromFD(PyObject * self, PyObject * args, PyObject * kwds)
01229 {
01230     FD_t fd;
01231     int fileno;
01232     off_t offset;
01233     PyObject * tuple;
01234     Header h;
01235     char * kwlist[] = {"fd", NULL};
01236 
01237     if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &fileno))
01238         return NULL;
01239 
01240     offset = lseek(fileno, 0, SEEK_CUR);
01241 
01242     fd = fdDup(fileno);
01243 
01244     if (!fd) {
01245         PyErr_SetFromErrno(pyrpmError);
01246         return NULL;
01247     }
01248 
01249     Py_BEGIN_ALLOW_THREADS
01250     h = headerRead(fd, HEADER_MAGIC_YES);
01251     Py_END_ALLOW_THREADS
01252 
01253     Fclose(fd);
01254 
01255     tuple = PyTuple_New(2);
01256 
01257     if (h && tuple) {
01258         PyTuple_SET_ITEM(tuple, 0, (PyObject *) hdr_Wrap(h));
01259         PyTuple_SET_ITEM(tuple, 1, PyLong_FromLong(offset));
01260         h = headerFree(h);
01261     } else {
01262         Py_INCREF(Py_None);
01263         Py_INCREF(Py_None);
01264         PyTuple_SET_ITEM(tuple, 0, Py_None);
01265         PyTuple_SET_ITEM(tuple, 1, Py_None);
01266     }
01267 
01268     return tuple;
01269 }
01270 
01273 PyObject * versionCompare (PyObject * self, PyObject * args, PyObject * kwds)
01274 {
01275     hdrObject * h1, * h2;
01276     char * kwlist[] = {"version0", "version1", NULL};
01277 
01278     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", kwlist, &hdr_Type,
01279             &h1, &hdr_Type, &h2))
01280         return NULL;
01281 
01282     return Py_BuildValue("i", hdr_compare(h1, h2));
01283 }
01284 
01285 PyObject * labelCompare (PyObject * self, PyObject * args)
01286 {
01287     EVR_t A = memset(alloca(sizeof(*A)), 0, sizeof(*A));
01288     EVR_t B = memset(alloca(sizeof(*B)), 0, sizeof(*B));
01289     int rc;
01290 
01291     if (!PyArg_ParseTuple(args, "(zzz)(zzz)",
01292                         &A->E, &A->V, &A->R, &B->E, &B->V, &B->R))
01293         return NULL;
01294 
01295     if (A->E == NULL)   A->E = "0";
01296     if (B->E == NULL)   B->E = "0";
01297     if (A->V == NULL)   A->E = "";
01298     if (B->V == NULL)   B->E = "";
01299     if (A->R == NULL)   A->E = "";
01300     if (B->R == NULL)   B->E = "";
01301 
01302     rc = rpmEVRcompare(A, B);
01303 
01304     return Py_BuildValue("i", rc);
01305 }

Generated on Mon Aug 23 22:20:33 2010 for rpm by  doxygen 1.5.1