Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

python/rpmmodule.c

Go to the documentation of this file.
00001 
00005 #include <alloca.h>
00006 #include <errno.h>
00007 #include <fcntl.h>
00008 #include <time.h>
00009 #include <sys/stat.h>
00010 #include <sys/time.h>
00011 #include <unistd.h>
00012 #include <glob.h>       /* XXX rpmio.h */
00013 #include <dirent.h>     /* XXX rpmio.h */
00014 #include <locale.h>
00015 #include <time.h>
00016 
00017 #include "Python.h"
00018 #include "rpmcli.h"     /* XXX for rpmCheckSig */
00019 #include "misc.h"
00020 #include "rpmio_internal.h"
00021 #include "header_internal.h"
00022 #include "upgrade.h"
00023 
00024 extern int _rpmio_debug;
00025 
00026 /*@unused@*/ static inline Header headerAllocated(Header h) {
00027     h->flags |= HEADERFLAG_ALLOCATED;
00028     return 0;
00029 }
00030 
00031 #ifdef __LCLINT__
00032 #undef  PyObject_HEAD
00033 #define PyObject_HEAD   int _PyObjectHead
00034 #endif
00035 
00036 extern int mdfile(const char *fn, unsigned char *digest);
00037 
00038 void initrpm(void);
00039 
00040 /* from lib/misc.c */
00041 int rpmvercmp(const char * one, const char * two);
00042 
00043 
00046 typedef struct rpmdbObject_s rpmdbObject;
00047 
00050 typedef struct rpmdbMIObject_s rpmdbMIObject;
00051 
00054 typedef struct rpmtransObject_s rpmtransObject;
00055 
00058 typedef struct hdrObject_s hdrObject;
00059 
00062 static PyObject * pyrpmError;
00063 
00113 
00116 struct hdrObject_s {
00117     PyObject_HEAD;
00118     Header h;
00119     Header sigs;                /* XXX signature tags are in header */
00120     char ** md5list;
00121     char ** fileList;
00122     char ** linkList;
00123     int_32 * fileSizes;
00124     int_32 * mtimes;
00125     int_32 * uids, * gids;      /* XXX these tags are not used anymore */
00126     unsigned short * rdevs;
00127     unsigned short * modes;
00128 } ;
00129 
00132 static PyObject * hdrKeyList(hdrObject * s, PyObject * args) {
00133     PyObject * list, *o;
00134     HeaderIterator iter;
00135     int tag, type;
00136 
00137     if (!PyArg_ParseTuple(args, "")) return NULL;
00138 
00139     list = PyList_New(0);
00140 
00141     iter = headerInitIterator(s->h);
00142     while (headerNextIterator(iter, &tag, &type, NULL, NULL)) {
00143         if (tag == HEADER_I18NTABLE) continue;
00144 
00145         switch (type) {
00146           case RPM_BIN_TYPE:
00147           case RPM_INT32_TYPE:
00148           case RPM_CHAR_TYPE:
00149           case RPM_INT8_TYPE:
00150           case RPM_INT16_TYPE:
00151           case RPM_STRING_ARRAY_TYPE:
00152           case RPM_STRING_TYPE:
00153             PyList_Append(list, o=PyInt_FromLong(tag));
00154             Py_DECREF(o);
00155         }
00156     }
00157 
00158     headerFreeIterator(iter);
00159 
00160     return list;
00161 }
00162 
00165 static PyObject * hdrUnload(hdrObject * s, PyObject * args, PyObject *keywords) {
00166     char * buf;
00167     PyObject * rc;
00168     int len, legacy = 0;
00169     Header h;
00170     static char *kwlist[] = { "legacyHeader", NULL};
00171 
00172     if (!PyArg_ParseTupleAndKeywords(args, keywords, "|i", kwlist, &legacy))
00173         return NULL; 
00174 
00175     h = headerLink(s->h);
00176     /* XXX this legacy switch is a hack, needs to be removed. */
00177     if (legacy) {
00178         h = headerCopy(s->h);   /* XXX strip region tags, etc */
00179         headerFree(s->h);
00180     }
00181     len = headerSizeof(h, 0);
00182     buf = headerUnload(h);
00183     h = headerFree(h);
00184 
00185     if (buf == NULL || len == 0) {
00186         PyErr_SetString(pyrpmError, "can't unload bad header\n");
00187         return NULL;
00188     }
00189 
00190     rc = PyString_FromStringAndSize(buf, len);
00191     free(buf);
00192 
00193     return rc;
00194 }
00195 
00201 static PyObject * hdrVerifyFile(hdrObject * s, PyObject * args) {
00202     int fileNumber;
00203     rpmVerifyAttrs verifyResult = 0;
00204     PyObject * list, * tuple, * attrName;
00205     int type, count;
00206     struct stat sb;
00207     char buf[2048];
00208     int i;
00209     time_t timeInt;
00210     struct tm * timeStruct;
00211 
00212     if (!PyInt_Check(args)) {
00213         PyErr_SetString(PyExc_TypeError, "integer expected");
00214         return NULL;
00215     }
00216 
00217     fileNumber = (int) PyInt_AsLong(args);
00218 
00219     /* XXX this routine might use callbacks intelligently. */
00220     if (rpmVerifyFile("", s->h, fileNumber, &verifyResult, RPMVERIFY_NONE)) {
00221         Py_INCREF(Py_None);
00222         return Py_None;
00223     }
00224 
00225     list = PyList_New(0);
00226 
00227     if (!verifyResult) return list;
00228 
00229     /* XXX Legacy tag needs to go away. */
00230     if (!s->fileList) {
00231         headerGetEntry(s->h, RPMTAG_OLDFILENAMES, &type, (void **) &s->fileList,
00232                  &count);
00233     }
00234 
00235     lstat(s->fileList[fileNumber], &sb);
00236 
00237     if (verifyResult & RPMVERIFY_MD5) {
00238         if (!s->md5list) {
00239             headerGetEntry(s->h, RPMTAG_FILEMD5S, &type, (void **) &s->md5list,
00240                      &count);
00241         }
00242 
00243         if (mdfile(s->fileList[fileNumber], buf)) {
00244             strcpy(buf, "(unknown)");
00245         }
00246 
00247         tuple = PyTuple_New(3);
00248         attrName = PyString_FromString("checksum");
00249         PyTuple_SetItem(tuple, 0, attrName);
00250         PyTuple_SetItem(tuple, 1, PyString_FromString(s->md5list[fileNumber]));
00251         PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00252         PyList_Append(list, tuple);
00253         Py_DECREF(tuple);
00254     }
00255 
00256     if (verifyResult & RPMVERIFY_FILESIZE) {
00257         if (!s->fileSizes) {
00258             headerGetEntry(s->h, RPMTAG_FILESIZES, &type, (void **) &s->fileSizes,
00259                      &count);
00260 
00261         }
00262 
00263         tuple = PyTuple_New(3);
00264         attrName = PyString_FromString("size");
00265         PyTuple_SetItem(tuple, 0, attrName);
00266 
00267         sprintf(buf, "%d", 100);
00268         PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00269         sprintf(buf, "%ld", sb.st_size);
00270         PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00271         PyList_Append(list, tuple);
00272         Py_DECREF(tuple);
00273     }
00274 
00275     if (verifyResult & RPMVERIFY_LINKTO) {
00276         if (!s->linkList) {
00277             headerGetEntry(s->h, RPMTAG_FILELINKTOS, &type, (void **) &s->linkList,
00278                      &count);
00279         }
00280 
00281         i = readlink(s->fileList[fileNumber], buf, sizeof(buf));
00282         if (i <= 0)
00283             strcpy(buf, "(unknown)");
00284         else
00285             buf[i] = '\0';
00286 
00287         tuple = PyTuple_New(3);
00288         attrName = PyString_FromString("link");
00289         PyTuple_SetItem(tuple, 0, attrName);
00290         PyTuple_SetItem(tuple, 1, PyString_FromString(s->linkList[fileNumber]));
00291         PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00292         PyList_Append(list, tuple);
00293         Py_DECREF(tuple);
00294     }
00295 
00296     if (verifyResult & RPMVERIFY_MTIME) {
00297         if (!s->mtimes) {
00298             headerGetEntry(s->h, RPMTAG_FILEMTIMES, &type, (void **) &s->mtimes,
00299                      &count);
00300         }
00301 
00302         tuple = PyTuple_New(3);
00303         attrName = PyString_FromString("time");
00304         PyTuple_SetItem(tuple, 0, attrName);
00305 
00306         timeInt = sb.st_mtime;
00307         timeStruct = localtime(&timeInt);
00308         strftime(buf, sizeof(buf) - 1, "%c", timeStruct);
00309         PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00310 
00311         timeInt = s->mtimes[fileNumber];
00312         timeStruct = localtime(&timeInt);
00313         strftime(buf, sizeof(buf) - 1, "%c", timeStruct);
00314 
00315         PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00316 
00317         PyList_Append(list, tuple);
00318         Py_DECREF(tuple);
00319     }
00320 
00321     if (verifyResult & RPMVERIFY_RDEV) {
00322         if (!s->rdevs) {
00323             headerGetEntry(s->h, RPMTAG_FILERDEVS, &type, (void **) &s->rdevs,
00324                      &count);
00325         }
00326 
00327         tuple = PyTuple_New(3);
00328         attrName = PyString_FromString("device");
00329 
00330         PyTuple_SetItem(tuple, 0, attrName);
00331         sprintf(buf, "0x%-4x", s->rdevs[fileNumber]);
00332         PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00333         sprintf(buf, "0x%-4x", (unsigned int) sb.st_rdev);
00334         PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00335         PyList_Append(list, tuple);
00336         Py_DECREF(tuple);
00337     }
00338 
00339     /*
00340      * RPMVERIFY_USER and RPM_VERIFY_GROUP are handled wrong here, but rpmlib.a
00341      * doesn't do these correctly either. At least this is consistent.
00342      *
00343      * XXX Consistent? rpmlib.a verifies user/group quite well, thank you.
00344      * XXX The code below does nothing useful. FILEUSERNAME needs to be
00345      * XXX retrieved and looked up.
00346      */
00347     if (verifyResult & RPMVERIFY_USER) {
00348         if (!s->uids) {
00349             headerGetEntry(s->h, RPMTAG_FILEUIDS, &type, (void **) &s->uids,
00350                      &count);
00351         }
00352 
00353         tuple = PyTuple_New(3);
00354         attrName = PyString_FromString("uid");
00355         PyTuple_SetItem(tuple, 0, attrName);
00356         sprintf(buf, "%d", s->uids[fileNumber]);
00357         PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00358         sprintf(buf, "%d", sb.st_uid);
00359         PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00360         PyList_Append(list, tuple);
00361         Py_DECREF(tuple);
00362     }
00363 
00364     /*
00365      * XXX The code below does nothing useful. FILEGROUPNAME needs to be
00366      * XXX retrieved and looked up.
00367      */
00368     if (verifyResult & RPMVERIFY_GROUP) {
00369         if (!s->gids) {
00370             headerGetEntry(s->h, RPMTAG_FILEGIDS, &type, (void **) &s->gids,
00371                      &count);
00372         }
00373 
00374         tuple = PyTuple_New(3);
00375         attrName = PyString_FromString("gid");
00376         PyTuple_SetItem(tuple, 0, attrName);
00377         sprintf(buf, "%d", s->gids[fileNumber]);
00378         PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00379         sprintf(buf, "%d", sb.st_gid);
00380         PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00381         PyList_Append(list, tuple);
00382         Py_DECREF(tuple);
00383     }
00384 
00385     if (verifyResult & RPMVERIFY_MODE) {
00386         if (!s->modes) {
00387             headerGetEntry(s->h, RPMTAG_FILEMODES, &type, (void **) &s->modes,
00388                      &count);
00389         }
00390 
00391         tuple = PyTuple_New(3);
00392         attrName = PyString_FromString("permissions");
00393         PyTuple_SetItem(tuple, 0, attrName);
00394         sprintf(buf, "0%-4o", s->modes[fileNumber]);
00395         PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00396         sprintf(buf, "0%-4o", sb.st_mode);
00397         PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00398         PyList_Append(list, tuple);
00399         Py_DECREF(tuple);
00400     }
00401 
00402     return list;
00403 }
00404 
00407 static PyObject * hdrExpandFilelist(hdrObject * s, PyObject * args) {
00408     expandFilelist (s->h);
00409 
00410     Py_INCREF(Py_None);
00411     return Py_None;
00412 }
00413 
00416 static PyObject * hdrCompressFilelist(hdrObject * s, PyObject * args) {
00417     compressFilelist (s->h);
00418 
00419     Py_INCREF(Py_None);
00420     return Py_None;
00421 }
00422 
00423 /* make a header with _all_ the tags we need */
00426 static void mungeFilelist(Header h)
00427 {
00428     const char ** fileNames = NULL;
00429     int count = 0;
00430 
00431     if (!headerIsEntry (h, RPMTAG_BASENAMES)
00432         || !headerIsEntry (h, RPMTAG_DIRNAMES)
00433         || !headerIsEntry (h, RPMTAG_DIRINDEXES))
00434         compressFilelist(h);
00435     
00436     rpmBuildFileList(h, &fileNames, &count);
00437 
00438     if (fileNames == NULL || count <= 0)
00439         return;
00440 
00441     /* XXX Legacy tag needs to go away. */
00442     headerAddEntry(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
00443                         fileNames, count);
00444 
00445     free((void *)fileNames);
00446 }
00447 
00450 static PyObject * rhnUnload(hdrObject * s, PyObject * args) {
00451     int len;
00452     char * uh;
00453     PyObject * rc;
00454     Header h;
00455 
00456     if (!PyArg_ParseTuple(args, ""))
00457         return NULL;
00458 
00459     h = headerLink(s->h);
00460 
00461     /* Retrofit a RHNPlatform: tag. */
00462     if (!headerIsEntry(h, RPMTAG_RHNPLATFORM)) {
00463         const char * arch;
00464         int_32 at;
00465         if (headerGetEntry(h, RPMTAG_ARCH, &at, (void **)&arch, NULL))
00466             headerAddEntry(h, RPMTAG_RHNPLATFORM, at, arch, 1);
00467     }
00468 
00469     /* Legacy headers are forced into immutable region. */
00470     if (!headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) {
00471         Header nh = headerReload(h, RPMTAG_HEADERIMMUTABLE);
00472         /* XXX Another unload/load cycle to "seal" the immutable region. */
00473         uh = headerUnload(nh);
00474         headerFree(nh);
00475         h = headerLoad(uh);
00476         headerAllocated(h);
00477     }
00478 
00479     /* All headers have SHA1 digest, compute and add if necessary. */
00480     if (!headerIsEntry(h, RPMTAG_SHA1HEADER)) {
00481         int_32 uht, uhc;
00482         const char * digest;
00483         size_t digestlen;
00484         DIGEST_CTX ctx;
00485 
00486         headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, (void **)&uh, &uhc);
00487 
00488         ctx = rpmDigestInit(RPMDIGEST_SHA1);
00489         rpmDigestUpdate(ctx, uh, uhc);
00490         rpmDigestFinal(ctx, (void **)&digest, &digestlen, 1);
00491 
00492         headerAddEntry(h, RPMTAG_SHA1RHN, RPM_STRING_TYPE, digest, 1);
00493 
00494         uh = headerFreeData(uh, uht);
00495         digest = _free(digest);
00496     }
00497 
00498     len = headerSizeof(h, 0);
00499     uh = headerUnload(h);
00500     headerFree(h);
00501 
00502     rc = PyString_FromStringAndSize(uh, len);
00503     free(uh);
00504 
00505     return rc;
00506 }
00507 
00510 static PyObject * hdrFullFilelist(hdrObject * s, PyObject * args) {
00511     mungeFilelist (s->h);
00512 
00513     Py_INCREF(Py_None);
00514     return Py_None;
00515 }
00516 
00519 static struct PyMethodDef hdrMethods[] = {
00520         {"keys",        (PyCFunction) hdrKeyList,       1 },
00521         {"unload",      (PyCFunction) hdrUnload,        METH_VARARGS|METH_KEYWORDS },
00522         {"verifyFile",  (PyCFunction) hdrVerifyFile,    1 },
00523         {"expandFilelist",      (PyCFunction) hdrExpandFilelist,        1 },
00524         {"compressFilelist",    (PyCFunction) hdrCompressFilelist,      1 },
00525         {"fullFilelist",        (PyCFunction) hdrFullFilelist,  1 },
00526         {"rhnUnload",   (PyCFunction) rhnUnload, METH_VARARGS },
00527         {NULL,          NULL}           /* sentinel */
00528 };
00529 
00532 static PyObject * hdrGetAttr(hdrObject * s, char * name) {
00533     return Py_FindMethod(hdrMethods, (PyObject * ) s, name);
00534 }
00535 
00538 static void hdrDealloc(hdrObject * s) {
00539     if (s->h) headerFree(s->h);
00540     if (s->sigs) headerFree(s->sigs);
00541     if (s->md5list) free(s->md5list);
00542     if (s->fileList) free(s->fileList);
00543     if (s->linkList) free(s->linkList);
00544     PyMem_DEL(s);
00545 }
00546 
00549 static long tagNumFromPyObject (PyObject *item)
00550 {
00551     char * str;
00552     int i;
00553 
00554     if (PyInt_Check(item)) {
00555         return PyInt_AsLong(item);
00556     } else if (PyString_Check(item)) {
00557         str = PyString_AsString(item);
00558         for (i = 0; i < rpmTagTableSize; i++)
00559             if (!xstrcasecmp(rpmTagTable[i].name + 7, str)) break;
00560         if (i < rpmTagTableSize) return rpmTagTable[i].val;
00561     }
00562     return -1;
00563 }
00564 
00567 static PyObject * hdrSubscript(hdrObject * s, PyObject * item) {
00568     int type, count, i, tag = -1;
00569     void * data;
00570     PyObject * o, * metao;
00571     char ** stringArray;
00572     int forceArray = 0;
00573     int freeData = 0;
00574     char * str;
00575     struct headerSprintfExtension_s * ext = NULL;
00576     const struct headerSprintfExtension_s * extensions = rpmHeaderFormats;
00577 
00578     if (PyCObject_Check (item))
00579         ext = PyCObject_AsVoidPtr(item);
00580     else
00581         tag = tagNumFromPyObject (item);
00582     if (tag == -1 && PyString_Check(item)) {
00583         /* if we still don't have the tag, go looking for the header
00584            extensions */
00585         str = PyString_AsString(item);
00586         while (extensions->name) {
00587             if (extensions->type == HEADER_EXT_TAG
00588                 && !xstrcasecmp(extensions->name + 7, str)) {
00589                 (const struct headerSprintfExtension *) ext = extensions;
00590             }
00591             extensions++;
00592         }
00593     }
00594 
00595     if (ext) {
00596         ext->u.tagFunction(s->h, &type, (const void **) &data, &count, &freeData);
00597     } else {
00598         if (tag == -1) {
00599             PyErr_SetString(PyExc_KeyError, "unknown header tag");
00600             return NULL;
00601         }
00602         
00603         /* XXX signature tags are appended to header, this API is gonna die */
00604         if (!rpmPackageGetEntry(NULL, s->sigs, s->h, tag, &type, &data, &count))
00605         {
00606             Py_INCREF(Py_None);
00607             return Py_None;
00608         }
00609     }
00610 
00611     switch (tag) {
00612       case RPMTAG_OLDFILENAMES:
00613       case RPMTAG_FILESIZES:
00614       case RPMTAG_FILESTATES:
00615       case RPMTAG_FILEMODES:
00616       case RPMTAG_FILEUIDS:
00617       case RPMTAG_FILEGIDS:
00618       case RPMTAG_FILERDEVS:
00619       case RPMTAG_FILEMTIMES:
00620       case RPMTAG_FILEMD5S:
00621       case RPMTAG_FILELINKTOS:
00622       case RPMTAG_FILEFLAGS:
00623       case RPMTAG_ROOT:
00624       case RPMTAG_FILEUSERNAME:
00625       case RPMTAG_FILEGROUPNAME:
00626         forceArray = 1;
00627         break;
00628       case RPMTAG_SUMMARY:
00629       case RPMTAG_GROUP:
00630       case RPMTAG_DESCRIPTION:
00631         freeData = 1;
00632         break;
00633       default:
00634         break;
00635     }
00636 
00637     switch (type) {
00638       case RPM_BIN_TYPE:
00639         o = PyString_FromStringAndSize(data, count);
00640         break;
00641 
00642       case RPM_INT32_TYPE:
00643         if (count != 1 || forceArray) {
00644             metao = PyList_New(0);
00645             for (i = 0; i < count; i++) {
00646                 o = PyInt_FromLong(((int *) data)[i]);
00647                 PyList_Append(metao, o);
00648                 Py_DECREF(o);
00649             }
00650             o = metao;
00651         } else {
00652             o = PyInt_FromLong(*((int *) data));
00653         }
00654         break;
00655 
00656       case RPM_CHAR_TYPE:
00657       case RPM_INT8_TYPE:
00658         if (count != 1 || forceArray) {
00659             metao = PyList_New(0);
00660             for (i = 0; i < count; i++) {
00661                 o = PyInt_FromLong(((char *) data)[i]);
00662                 PyList_Append(metao, o);
00663                 Py_DECREF(o);
00664             }
00665             o = metao;
00666         } else {
00667             o = PyInt_FromLong(*((char *) data));
00668         }
00669         break;
00670 
00671       case RPM_INT16_TYPE:
00672         if (count != 1 || forceArray) {
00673             metao = PyList_New(0);
00674             for (i = 0; i < count; i++) {
00675                 o = PyInt_FromLong(((short *) data)[i]);
00676                 PyList_Append(metao, o);
00677                 Py_DECREF(o);
00678             }
00679             o = metao;
00680         } else {
00681             o = PyInt_FromLong(*((short *) data));
00682         }
00683         break;
00684 
00685       case RPM_STRING_ARRAY_TYPE:
00686         stringArray = data;
00687 
00688         metao = PyList_New(0);
00689         for (i = 0; i < count; i++) {
00690             o = PyString_FromString(stringArray[i]);
00691             PyList_Append(metao, o);
00692             Py_DECREF(o);
00693         }
00694         free (stringArray);
00695         o = metao;
00696         break;
00697 
00698       case RPM_STRING_TYPE:
00699         if (count != 1 || forceArray) {
00700             stringArray = data;
00701 
00702             metao = PyList_New(0);
00703             for (i=0; i < count; i++) {
00704                 o = PyString_FromString(stringArray[i]);
00705                 PyList_Append(metao, o);
00706                 Py_DECREF(o);
00707             }
00708             o = metao;
00709         } else {
00710             o = PyString_FromString(data);
00711             if (freeData)
00712                 free (data);
00713         }
00714         break;
00715 
00716       default:
00717         PyErr_SetString(PyExc_TypeError, "unsupported type in header");
00718         return NULL;
00719     }
00720 
00721     return o;
00722 }
00723 
00726 static PyMappingMethods hdrAsMapping = {
00727         (inquiry) 0,                    /* mp_length */
00728         (binaryfunc) hdrSubscript,      /* mp_subscript */
00729         (objobjargproc)0,               /* mp_ass_subscript */
00730 };
00731 
00734 static PyTypeObject hdrType = {
00735         PyObject_HEAD_INIT(NULL)
00736         0,                              /* ob_size */
00737         "header",                       /* tp_name */
00738         sizeof(hdrObject),              /* tp_size */
00739         0,                              /* tp_itemsize */
00740         (destructor) hdrDealloc,        /* tp_dealloc */
00741         0,                              /* tp_print */
00742         (getattrfunc) hdrGetAttr,       /* tp_getattr */
00743         0,                              /* tp_setattr */
00744         0,                              /* tp_compare */
00745         0,                              /* tp_repr */
00746         0,                              /* tp_as_number */
00747         0,                              /* tp_as_sequence */
00748         &hdrAsMapping,                  /* tp_as_mapping */
00749 };
00750 
00763 
00766 struct rpmdbObject_s {
00767     PyObject_HEAD;
00768     rpmdb db;
00769     int offx;
00770     int noffs;
00771     int *offsets;
00772 } ;
00773 
00776 struct rpmdbMIObject_s {
00777     PyObject_HEAD;
00778     rpmdbObject *db;
00779     rpmdbMatchIterator mi;
00780 } ;
00781 
00784 static PyObject *
00785 rpmdbMINext(rpmdbMIObject * s, PyObject * args) {
00786     /* XXX assume header? */
00787     Header h;
00788     hdrObject * ho;
00789     
00790 
00791     h = rpmdbNextIterator(s->mi);
00792     if (!h) {
00793         Py_INCREF(Py_None);
00794         return Py_None;
00795     }
00796 
00797     ho = PyObject_NEW(hdrObject, &hdrType);
00798     ho->h = headerLink(h);
00799     ho->sigs = NULL;
00800     ho->fileList = ho->linkList = ho->md5list = NULL;
00801     ho->uids = ho->gids = ho->mtimes = ho->fileSizes = NULL;
00802     ho->modes = ho->rdevs = NULL;
00803     
00804     return (PyObject *) ho;
00805 }
00806 
00809 static struct PyMethodDef rpmdbMIMethods[] = {
00810         {"next",            (PyCFunction) rpmdbMINext,  1 },
00811         {NULL,          NULL}           /* sentinel */
00812 };
00813 
00816 static PyObject * rpmdbMIGetAttr (rpmdbObject *s, char *name) {
00817     return Py_FindMethod (rpmdbMIMethods, (PyObject *) s, name);
00818 }
00819 
00822 static void rpmdbMIDealloc(rpmdbMIObject * s) {
00823     if (s && s->mi) {
00824         rpmdbFreeIterator(s->mi);
00825     }
00826     Py_DECREF (s->db);
00827     PyMem_DEL(s);
00828 }
00829 
00832 static PyTypeObject rpmdbMIType = {
00833         PyObject_HEAD_INIT(NULL)
00834         0,                              /* ob_size */
00835         "rpmdbMatchIterator",           /* tp_name */
00836         sizeof(rpmdbMIObject),  /* tp_size */
00837         0,                              /* tp_itemsize */
00838         (destructor) rpmdbMIDealloc,    /* tp_dealloc */
00839         0,                              /* tp_print */
00840         (getattrfunc) rpmdbMIGetAttr,   /* tp_getattr */
00841         0,                              /* tp_setattr */
00842         0,                              /* tp_compare */
00843         0,                              /* tp_repr */
00844         0,                              /* tp_as_number */
00845         0,                              /* tp_as_sequence */
00846         0,                              /* tp_as_mapping */
00847 };
00848 
00917 
00920 static PyObject * rpmdbFirst(rpmdbObject * s, PyObject * args) {
00921     int first;
00922 
00923     if (!PyArg_ParseTuple (args, "")) return NULL;
00924 
00925     /* Acquire all offsets in one fell swoop. */
00926     if (s->offsets == NULL || s->noffs <= 0) {
00927         rpmdbMatchIterator mi;
00928         Header h;
00929 
00930         if (s->offsets)
00931             free(s->offsets);
00932         s->offsets = NULL;
00933         s->noffs = 0;
00934         mi = rpmdbInitIterator(s->db, RPMDBI_PACKAGES, NULL, 0);
00935         while ((h = rpmdbNextIterator(mi)) != NULL) {
00936             s->noffs++;
00937             s->offsets = realloc(s->offsets, s->noffs * sizeof(s->offsets[0]));
00938             s->offsets[s->noffs-1] = rpmdbGetIteratorOffset(mi);
00939         }
00940         rpmdbFreeIterator(mi);
00941     }
00942 
00943     s->offx = 0;
00944     if (s->offsets != NULL && s->offx < s->noffs)
00945         first = s->offsets[s->offx++];
00946     else
00947         first = 0;
00948 
00949     if (!first) {
00950         PyErr_SetString(pyrpmError, "cannot find first entry in database\n");
00951         return NULL;
00952     }
00953 
00954     return Py_BuildValue("i", first);
00955 }
00956 
00959 static PyObject * rpmdbNext(rpmdbObject * s, PyObject * args) {
00960     int where;
00961 
00962     if (!PyArg_ParseTuple (args, "i", &where)) return NULL;
00963 
00964     if (s->offsets == NULL || s->offx >= s->noffs) {
00965         Py_INCREF(Py_None);
00966         return Py_None;
00967     }
00968 
00969     where = s->offsets[s->offx++];
00970 
00971     if (!where) {
00972         Py_INCREF(Py_None);
00973         return Py_None;
00974     }
00975 
00976     return Py_BuildValue("i", where);
00977 }
00978 
00981 static PyObject * handleDbResult(rpmdbMatchIterator mi) {
00982     PyObject * list, *o;
00983 
00984     list = PyList_New(0);
00985 
00986     /* XXX FIXME: unnecessary header mallocs are side effect here */
00987     if (mi != NULL) {
00988         while (rpmdbNextIterator(mi)) {
00989             PyList_Append(list, o=PyInt_FromLong(rpmdbGetIteratorOffset(mi)));
00990             Py_DECREF(o);
00991         }
00992         rpmdbFreeIterator(mi);
00993     }
00994 
00995     return list;
00996 }
00997 
01000 static PyObject * rpmdbByFile(rpmdbObject * s, PyObject * args) {
01001     char * str;
01002 
01003     if (!PyArg_ParseTuple(args, "s", &str)) return NULL;
01004 
01005     return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_BASENAMES, str, 0));
01006 }
01007 
01010 static PyObject * rpmdbByName(rpmdbObject * s, PyObject * args) {
01011     char * str;
01012 
01013     if (!PyArg_ParseTuple(args, "s", &str)) return NULL;
01014 
01015     return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_NAME, str, 0));
01016 }
01017 
01020 static PyObject * rpmdbByProvides(rpmdbObject * s, PyObject * args) {
01021     char * str;
01022 
01023     if (!PyArg_ParseTuple(args, "s", &str)) return NULL;
01024 
01025     return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_PROVIDENAME, str, 0));
01026 }
01027 
01030 static rpmdbMIObject *
01031 py_rpmdbInitIterator (rpmdbObject * s, PyObject * args) {
01032     PyObject *index = NULL;
01033     char *key = NULL;
01034     int len = 0, tag = -1;
01035     rpmdbMIObject * mio;
01036     
01037     if (!PyArg_ParseTuple(args, "|Ozi", &index, &key, &len))
01038         return NULL;
01039 
01040     if (index == NULL)
01041         tag = 0;
01042     else if ((tag = tagNumFromPyObject (index)) == -1) {
01043         PyErr_SetString(PyExc_TypeError, "unknown tag type");
01044         return NULL;
01045     }
01046     
01047     mio = (rpmdbMIObject *) PyObject_NEW(rpmdbMIObject, &rpmdbMIType);
01048     if (mio == NULL) {
01049         PyErr_SetString(pyrpmError, "out of memory creating rpmdbMIObject");
01050         return NULL;
01051     }
01052     
01053     mio->mi = rpmdbInitIterator(s->db, tag, key, len);
01054     mio->db = s;
01055     Py_INCREF (mio->db);
01056     
01057     return mio;
01058 }
01059 
01062 static struct PyMethodDef rpmdbMethods[] = {
01063         {"firstkey",        (PyCFunction) rpmdbFirst,   1 },
01064         {"nextkey",         (PyCFunction) rpmdbNext,    1 },
01065         {"findbyfile",      (PyCFunction) rpmdbByFile, 1 },
01066         {"findbyname",      (PyCFunction) rpmdbByName, 1 },
01067         {"findbyprovides",  (PyCFunction) rpmdbByProvides, 1 },
01068         {"match",           (PyCFunction) py_rpmdbInitIterator, 1 },
01069         {NULL,          NULL}           /* sentinel */
01070 };
01071 
01074 static PyObject * rpmdbGetAttr(rpmdbObject * s, char * name) {
01075     return Py_FindMethod(rpmdbMethods, (PyObject * ) s, name);
01076 }
01077 
01080 static void rpmdbDealloc(rpmdbObject * s) {
01081     if (s->offsets) {
01082         free(s->offsets);
01083     }
01084     if (s->db) {
01085         rpmdbClose(s->db);
01086     }
01087     PyMem_DEL(s);
01088 }
01089 
01090 #ifndef DYINGSOON       /* XXX OK, when? */
01091 
01093 static int
01094 rpmdbLength(rpmdbObject * s) {
01095     int count = 0;
01096 
01097     {   rpmdbMatchIterator mi;
01098 
01099         /* RPMDBI_PACKAGES */
01100         mi = rpmdbInitIterator(s->db, RPMDBI_PACKAGES, NULL, 0);
01101         while (rpmdbNextIterator(mi) != NULL)
01102             count++;
01103         rpmdbFreeIterator(mi);
01104     }
01105 
01106     return count;
01107 }
01108 
01111 static hdrObject *
01112 rpmdbSubscript(rpmdbObject * s, PyObject * key) {
01113     int offset;
01114     hdrObject * h;
01115 
01116     if (!PyInt_Check(key)) {
01117         PyErr_SetString(PyExc_TypeError, "integer expected");
01118         return NULL;
01119     }
01120 
01121     offset = (int) PyInt_AsLong(key);
01122 
01123     h = PyObject_NEW(hdrObject, &hdrType);
01124     h->h = NULL;
01125     h->sigs = NULL;
01126     {   rpmdbMatchIterator mi;
01127         mi = rpmdbInitIterator(s->db, RPMDBI_PACKAGES, &offset, sizeof(offset));
01128         if ((h->h = rpmdbNextIterator(mi)) != NULL)
01129             h->h = headerLink(h->h);
01130         rpmdbFreeIterator(mi);
01131     }
01132     h->fileList = h->linkList = h->md5list = NULL;
01133     h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
01134     h->modes = h->rdevs = NULL;
01135     if (!h->h) {
01136         Py_DECREF(h);
01137         PyErr_SetString(pyrpmError, "cannot read rpmdb entry");
01138         return NULL;
01139     }
01140 
01141     return h;
01142 }
01143 
01146 static PyMappingMethods rpmdbAsMapping = {
01147         (inquiry) rpmdbLength,          /* mp_length */
01148         (binaryfunc) rpmdbSubscript,    /* mp_subscript */
01149         (objobjargproc)0,               /* mp_ass_subscript */
01150 };
01151 #endif
01152 
01155 static PyTypeObject rpmdbType = {
01156         PyObject_HEAD_INIT(NULL)
01157         0,                              /* ob_size */
01158         "rpmdb",                        /* tp_name */
01159         sizeof(rpmdbObject),            /* tp_size */
01160         0,                              /* tp_itemsize */
01161         (destructor) rpmdbDealloc,      /* tp_dealloc */
01162         0,                              /* tp_print */
01163         (getattrfunc) rpmdbGetAttr,     /* tp_getattr */
01164         0,                              /* tp_setattr */
01165         0,                              /* tp_compare */
01166         0,                              /* tp_repr */
01167         0,                              /* tp_as_number */
01168         0,                              /* tp_as_sequence */
01169 #ifndef DYINGSOON
01170         &rpmdbAsMapping,                /* tp_as_mapping */
01171 #else
01172         0,
01173 #endif
01174 };
01175 
01280 
01283 struct rpmtransObject_s {
01284     PyObject_HEAD;
01285     rpmdbObject * dbo;
01286     rpmTransactionSet ts;
01287     PyObject * keyList;                 /* keeps reference counts correct */
01288     FD_t scriptFd;
01289 } ;
01290 
01293 static PyObject * rpmtransAdd(rpmtransObject * s, PyObject * args) {
01294     hdrObject * h;
01295     PyObject * key;
01296     char * how = NULL;
01297     int isUpgrade = 0;
01298 
01299     if (!PyArg_ParseTuple(args, "OO|s", &h, &key, &how)) return NULL;
01300     if (h->ob_type != &hdrType) {
01301         PyErr_SetString(PyExc_TypeError, "bad type for header argument");
01302         return NULL;
01303     }
01304 
01305     if (how && strcmp(how, "a") && strcmp(how, "u") && strcmp(how, "i")) {
01306         PyErr_SetString(PyExc_TypeError, "how argument must be \"u\", \"a\", or \"i\"");
01307         return NULL;
01308     } else if (how && !strcmp(how, "u"))
01309         isUpgrade = 1;
01310 
01311     if (how && !strcmp(how, "a"))
01312         rpmtransAvailablePackage(s->ts, h->h, key);
01313     else
01314         rpmtransAddPackage(s->ts, h->h, NULL, key, isUpgrade, NULL);
01315 
01316     /* This should increment the usage count for me */
01317     if (key) {
01318         PyList_Append(s->keyList, key);
01319     }
01320 
01321     Py_INCREF(Py_None);
01322     return Py_None;
01323 }
01324 
01327 static PyObject * rpmtransRemove(rpmtransObject * s, PyObject * args) {
01328     char * name;
01329     int count;
01330     rpmdbMatchIterator mi;
01331     
01332     if (!PyArg_ParseTuple(args, "s", &name))
01333         return NULL;
01334 
01335     /* XXX: Copied hack from ../lib/rpminstall.c, rpmErase() */
01336     mi = rpmdbInitIterator(s->dbo->db, RPMDBI_LABEL, name, 0);
01337     count = rpmdbGetIteratorCount(mi);
01338     if (count <= 0) {
01339         PyErr_SetString(pyrpmError, "package not installed");
01340         return NULL;
01341     } else { /* XXX: Note that we automatically choose to remove all matches */
01342         Header h;
01343         while ((h = rpmdbNextIterator(mi)) != NULL) {
01344             unsigned int recOffset = rpmdbGetIteratorOffset(mi);
01345             if (recOffset) {
01346                 rpmtransRemovePackage(s->ts, recOffset);
01347             }
01348         }
01349     }
01350     rpmdbFreeIterator(mi);
01351 
01352     Py_INCREF(Py_None);
01353     return Py_None;
01354 }
01355 
01358 static PyObject * rpmtransDepCheck(rpmtransObject * s, PyObject * args) {
01359     rpmDependencyConflict conflicts;
01360     int numConflicts;
01361     PyObject * list, * cf;
01362     int i;
01363 
01364     if (!PyArg_ParseTuple(args, "")) return NULL;
01365 
01366     rpmdepCheck(s->ts, &conflicts, &numConflicts);
01367     if (numConflicts) {
01368         list = PyList_New(0);
01369 
01370         /* XXX TODO: rpmlib-4.0.3 can return multiple suggested packages. */
01371         for (i = 0; i < numConflicts; i++) {
01372             cf = Py_BuildValue("((sss)(ss)iOi)", conflicts[i].byName,
01373                                conflicts[i].byVersion, conflicts[i].byRelease,
01374 
01375                                conflicts[i].needsName,
01376                                conflicts[i].needsVersion,
01377 
01378                                conflicts[i].needsFlags,
01379                                conflicts[i].suggestedPackages ?
01380                                    conflicts[i].suggestedPackages[0] : Py_None,
01381                                conflicts[i].sense);
01382             PyList_Append(list, (PyObject *) cf);
01383             Py_DECREF(cf);
01384         }
01385 
01386         conflicts = rpmdepFreeConflicts(conflicts, numConflicts);
01387 
01388         return list;
01389     }
01390 
01391     Py_INCREF(Py_None);
01392     return Py_None;
01393 }
01394 
01397 static PyObject * rpmtransOrder(rpmtransObject * s, PyObject * args) {
01398     if (!PyArg_ParseTuple(args, "")) return NULL;
01399 
01400     rpmdepOrder(s->ts);
01401 
01402     Py_INCREF(Py_None);
01403     return Py_None;
01404 }
01405 
01408 static PyObject * py_rpmtransGetKeys(rpmtransObject * s, PyObject * args) {
01409     const void **data = NULL;
01410     int num, i;
01411     PyObject *tuple;
01412 
01413     rpmtransGetKeys(s->ts, &data, &num);
01414     if (data == NULL) {
01415         Py_INCREF(Py_None);
01416         return Py_None;
01417     }
01418 
01419     tuple = PyTuple_New(num);
01420 
01421     for (i = 0; i < num; i++) {
01422         PyObject *obj = (PyObject *) data[i];
01423         Py_INCREF(obj);
01424         PyTuple_SetItem(tuple, i, obj);
01425     }
01426 
01427     free (data);
01428 
01429     return tuple;
01430 }
01431 
01434 struct tsCallbackType {
01435     PyObject * cb;
01436     PyObject * data;
01437     int pythonError;
01438 };
01439 
01443 static Header transactionSetHeader = NULL;
01444 
01447 static void * tsCallback(const void * hd, const rpmCallbackType what,
01448                          const unsigned long amount, const unsigned long total,
01449                          const void * pkgKey, rpmCallbackData data) {
01450     struct tsCallbackType * cbInfo = data;
01451     PyObject * args, * result;
01452     int fd;
01453     static FD_t fdt;
01454     const Header h = (Header) hd;
01455 
01456     if (cbInfo->pythonError) return NULL;
01457 
01458     if (!pkgKey) pkgKey = Py_None;
01459     transactionSetHeader = h;    
01460 
01461     args = Py_BuildValue("(illOO)", what, amount, total, pkgKey, cbInfo->data);
01462     result = PyEval_CallObject(cbInfo->cb, args);
01463     Py_DECREF(args);
01464 
01465     if (!result) {
01466         cbInfo->pythonError = 1;
01467         return NULL;
01468     }
01469 
01470     if (what == RPMCALLBACK_INST_OPEN_FILE) {
01471         if (!PyArg_Parse(result, "i", &fd)) {
01472             cbInfo->pythonError = 1;
01473             return NULL;
01474         }
01475         fdt = fdDup(fd);
01476         
01477         Py_DECREF(result);
01478         return fdt;
01479     }
01480 
01481     if (what == RPMCALLBACK_INST_CLOSE_FILE) {
01482         Fclose (fdt);
01483     }
01484 
01485     Py_DECREF(result);
01486 
01487     return NULL;
01488 }
01489 
01492 static PyObject * rpmtransRun(rpmtransObject * s, PyObject * args) {
01493     int flags, ignoreSet;
01494     int rc, i;
01495     PyObject * list, * prob;
01496     rpmProblemSet probs;
01497     struct tsCallbackType cbInfo;
01498 
01499     if (!PyArg_ParseTuple(args, "iiOO", &flags, &ignoreSet, &cbInfo.cb,
01500                           &cbInfo.data))
01501         return NULL;
01502 
01503     cbInfo.pythonError = 0;
01504 
01505     rc = rpmRunTransactions(s->ts, tsCallback, &cbInfo, NULL, &probs, flags,
01506                             ignoreSet);
01507 
01508     if (cbInfo.pythonError) {
01509         if (rc > 0)
01510             rpmProblemSetFree(probs);
01511         return NULL;
01512     }
01513 
01514     if (rc < 0) {
01515         list = PyList_New(0);
01516         return list;
01517     } else if (!rc) {
01518         Py_INCREF(Py_None);
01519         return Py_None;
01520     }
01521 
01522     list = PyList_New(0);
01523     for (i = 0; i < probs->numProblems; i++) {
01524         rpmProblem myprob = probs->probs + i;
01525         prob = Py_BuildValue("s(isi)", rpmProblemString(myprob),
01526                              myprob->type,
01527                              myprob->str1,
01528                              myprob->ulong1);
01529         PyList_Append(list, prob);
01530         Py_DECREF(prob);
01531     }
01532 
01533     rpmProblemSetFree(probs);
01534 
01535     return list;
01536 }
01537 
01540 static struct PyMethodDef rpmtransMethods[] = {
01541         {"add",         (PyCFunction) rpmtransAdd,      1 },
01542         {"remove",      (PyCFunction) rpmtransRemove,   1 },
01543         {"depcheck",    (PyCFunction) rpmtransDepCheck, 1 },
01544         {"order",       (PyCFunction) rpmtransOrder,    1 },
01545         {"getKeys",     (PyCFunction) py_rpmtransGetKeys, 1 },
01546         {"run",         (PyCFunction) rpmtransRun, 1 },
01547         {NULL,          NULL}           /* sentinel */
01548 };
01549 
01552 static PyObject * rpmtransGetAttr(rpmtransObject * o, char * name) {
01553     return Py_FindMethod(rpmtransMethods, (PyObject *) o, name);
01554 }
01555 
01558 static void rpmtransDealloc(PyObject * o) {
01559     rpmtransObject * trans = (void *) o;
01560 
01561     rpmtransFree(trans->ts);
01562     if (trans->dbo) {
01563         Py_DECREF(trans->dbo);
01564     }
01565     if (trans->scriptFd) Fclose(trans->scriptFd);
01566     /* this will free the keyList, and decrement the ref count of all
01567        the items on the list as well :-) */
01568     Py_DECREF(trans->keyList);
01569     PyMem_DEL(o);
01570 }
01571 
01574 static int rpmtransSetAttr(rpmtransObject * o, char * name,
01575                            PyObject * val) {
01576     int i;
01577 
01578     if (!strcmp(name, "scriptFd")) {
01579         if (!PyArg_Parse(val, "i", &i)) return 0;
01580         if (i < 0) {
01581             PyErr_SetString(PyExc_TypeError, "bad file descriptor");
01582             return -1;
01583         } else {
01584             o->scriptFd = fdDup(i);
01585             rpmtransSetScriptFd(o->ts, o->scriptFd);
01586         }
01587     } else {
01588         PyErr_SetString(PyExc_AttributeError, name);
01589         return -1;
01590     }
01591 
01592     return 0;
01593 }
01594 
01597 static PyTypeObject rpmtransType = {
01598         PyObject_HEAD_INIT(NULL)
01599         0,                              /* ob_size */
01600         "rpmtrans",                     /* tp_name */
01601         sizeof(rpmtransObject),         /* tp_size */
01602         0,                              /* tp_itemsize */
01603         (destructor) rpmtransDealloc,   /* tp_dealloc */
01604         0,                              /* tp_print */
01605         (getattrfunc) rpmtransGetAttr,  /* tp_getattr */
01606         (setattrfunc) rpmtransSetAttr,  /* tp_setattr */
01607         0,                              /* tp_compare */
01608         0,                              /* tp_repr */
01609         0,                              /* tp_as_number */
01610         0,                              /* tp_as_sequence */
01611         0,                              /* tp_as_mapping */
01612 };
01613 
01620 
01623 static PyObject * rpmtransCreate(PyObject * self, PyObject * args) {
01624     rpmtransObject * o;
01625     rpmdbObject * db = NULL;
01626     char * rootPath = "/";
01627 
01628     if (!PyArg_ParseTuple(args, "|sO", &rootPath, &db)) return NULL;
01629     if (db && db->ob_type != &rpmdbType) {
01630         PyErr_SetString(PyExc_TypeError, "bad type for database argument");
01631         return NULL;
01632     }
01633 
01634     o = (void *) PyObject_NEW(rpmtransObject, &rpmtransType);
01635 
01636     Py_XINCREF(db);
01637     o->dbo = db;
01638     o->scriptFd = NULL;
01639     o->ts = rpmtransCreateSet(db ? db->db : NULL, rootPath);
01640     o->keyList = PyList_New(0);
01641 
01642     return (void *) o;
01643 }
01644 
01647 static PyObject * doAddMacro(PyObject * self, PyObject * args) {
01648     char * name, * val;
01649 
01650     if (!PyArg_ParseTuple(args, "ss", &name, &val))
01651         return NULL;
01652 
01653     addMacro(NULL, name, NULL, val, RMIL_DEFAULT);
01654 
01655     Py_INCREF(Py_None);
01656     return Py_None;
01657 }
01658 
01661 static PyObject * doDelMacro(PyObject * self, PyObject * args) {
01662     char * name;
01663 
01664     if (!PyArg_ParseTuple(args, "s", &name))
01665         return NULL;
01666 
01667     delMacro(NULL, name);
01668 
01669     Py_INCREF(Py_None);
01670     return Py_None;
01671 }
01672 
01675 static PyObject * archScore(PyObject * self, PyObject * args) {
01676     char * arch;
01677     int score;
01678 
01679     if (!PyArg_ParseTuple(args, "s", &arch))
01680         return NULL;
01681 
01682     score = rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch);
01683 
01684     return Py_BuildValue("i", score);
01685 }
01686 
01689 static int psGetArchScore(Header h) {
01690     void * pkgArch;
01691     int type, count;
01692 
01693     if (!headerGetEntry(h, RPMTAG_ARCH, &type, (void **) &pkgArch, &count) ||
01694         type == RPM_INT8_TYPE)
01695        return 150;
01696     else
01697         return rpmMachineScore(RPM_MACHTABLE_INSTARCH, pkgArch);
01698 }
01699 
01702 static int pkgCompareVer(void * first, void * second) {
01703     struct packageInfo ** a = first;
01704     struct packageInfo ** b = second;
01705     int ret, score1, score2;
01706 
01707     /* put packages w/o names at the end */
01708     if (!(*a)->name) return 1;
01709     if (!(*b)->name) return -1;
01710 
01711     ret = xstrcasecmp((*a)->name, (*b)->name);
01712     if (ret) return ret;
01713     score1 = psGetArchScore((*a)->h);
01714     if (!score1) return 1;
01715     score2 = psGetArchScore((*b)->h);
01716     if (!score2) return -1;
01717     if (score1 < score2) return -1;
01718     if (score1 > score2) return 1;
01719     return rpmVersionCompare((*b)->h, (*a)->h);
01720 }
01721 
01724 static void pkgSort(struct pkgSet * psp) {
01725     int i;
01726     char *name;
01727 
01728     if (psp->numPackages <= 0)
01729         return;
01730 
01731     qsort(psp->packages, psp->numPackages, sizeof(*psp->packages),
01732          (void *) pkgCompareVer);
01733 
01734     name = psp->packages[0]->name;
01735     if (!name) {
01736        psp->numPackages = 0;
01737        return;
01738     }
01739     for (i = 1; i < psp->numPackages; i++) {
01740        if (!psp->packages[i]->name) break;
01741        if (!strcmp(psp->packages[i]->name, name))
01742            psp->packages[i]->name = NULL;
01743        else
01744            name = psp->packages[i]->name;
01745     }
01746 
01747     qsort(psp->packages, psp->numPackages, sizeof(*psp->packages),
01748          (void *) pkgCompareVer);
01749 
01750     for (i = 0; i < psp->numPackages; i++)
01751        if (!psp->packages[i]->name) break;
01752     psp->numPackages = i;
01753 }
01754 
01757 static PyObject * findUpgradeSet(PyObject * self, PyObject * args) {
01758     PyObject * hdrList, * result;
01759     char * root = "/";
01760     int i;
01761     struct pkgSet list;
01762     hdrObject * hdr;
01763 
01764     if (!PyArg_ParseTuple(args, "O|s", &hdrList, &root)) return NULL;
01765 
01766     if (!PyList_Check(hdrList)) {
01767         PyErr_SetString(PyExc_TypeError, "list of headers expected");
01768         return NULL;
01769     }
01770 
01771     list.numPackages = PyList_Size(hdrList);
01772     list.packages = alloca(sizeof(list.packages) * list.numPackages);
01773     for (i = 0; i < list.numPackages; i++) {
01774         hdr = (hdrObject *) PyList_GetItem(hdrList, i);
01775         if (hdr->ob_type != &hdrType) {
01776             PyErr_SetString(PyExc_TypeError, "list of headers expected");
01777             return NULL;
01778         }
01779         list.packages[i] = alloca(sizeof(struct packageInfo));
01780         list.packages[i]->h = hdr->h;
01781         list.packages[i]->selected = 0;
01782         list.packages[i]->data = hdr;
01783 
01784         headerGetEntry(hdr->h, RPMTAG_NAME, NULL,
01785                       (void **) &list.packages[i]->name, NULL);
01786     }
01787 
01788     pkgSort (&list);
01789 
01790     if (ugFindUpgradePackages(&list, root)) {
01791         PyErr_SetString(pyrpmError, "error during upgrade check");
01792         return NULL;
01793     }
01794 
01795     result = PyList_New(0);
01796     for (i = 0; i < list.numPackages; i++) {
01797         if (list.packages[i]->selected) {
01798             PyList_Append(result, list.packages[i]->data);
01799 /*          Py_DECREF(list.packages[i]->data); */
01800         }
01801     }
01802 
01803     return result;
01804 }
01805 
01808 static PyObject * rpmHeaderFromPackage(PyObject * self, PyObject * args) {
01809     hdrObject * h;
01810     Header header;
01811     Header sigs;
01812     FD_t fd;
01813     int rawFd;
01814     int isSource = 0;
01815     rpmRC rc;
01816 
01817     if (!PyArg_ParseTuple(args, "i", &rawFd)) return NULL;
01818     fd = fdDup(rawFd);
01819 
01820     rc = rpmReadPackageInfo(fd, &sigs, &header);
01821     Fclose(fd);
01822 
01823     switch (rc) {
01824     case RPMRC_BADSIZE:
01825     case RPMRC_OK:
01826         h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
01827         h->h = header;
01828         h->sigs = sigs;
01829         h->fileList = h->linkList = h->md5list = NULL;
01830         h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
01831         h->modes = h->rdevs = NULL;
01832         if (headerIsEntry(header, RPMTAG_SOURCEPACKAGE))
01833             isSource = 1;
01834         break;
01835 
01836     case RPMRC_BADMAGIC:
01837         Py_INCREF(Py_None);
01838         h = (hdrObject *) Py_None;
01839         break;
01840 
01841     case RPMRC_FAIL:
01842     case RPMRC_SHORTREAD:
01843     default:
01844         PyErr_SetString(pyrpmError, "error reading package");
01845         return NULL;
01846     }
01847 
01848     return Py_BuildValue("(Ni)", h, isSource);
01849 }
01850 
01853 static PyObject * hdrLoad(PyObject * self, PyObject * args) {
01854     char * obj, * copy=NULL;
01855     Header hdr;
01856     hdrObject * h;
01857     int len;
01858 
01859     if (!PyArg_ParseTuple(args, "s#", &obj, &len)) return NULL;
01860     
01861     /* malloc is needed to avoid surprises from data swab in headerLoad(). */
01862     copy = malloc(len);
01863     if (copy == NULL) {
01864         PyErr_SetString(pyrpmError, "out of memory");
01865         return NULL;
01866     }
01867     memcpy (copy, obj, len);
01868 
01869     hdr = headerLoad(copy);
01870     if (!hdr) {
01871         PyErr_SetString(pyrpmError, "bad header");
01872         return NULL;
01873     }
01874     headerAllocated(hdr);
01875     compressFilelist (hdr);
01876     providePackageNVR (hdr);
01877 
01878     h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
01879     h->h = hdr;
01880     h->sigs = NULL;
01881     h->fileList = h->linkList = h->md5list = NULL;
01882     h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
01883     h->modes = h->rdevs = NULL;
01884 
01885     return (PyObject *) h;
01886 }
01887 
01890 static PyObject * rhnLoad(PyObject * self, PyObject * args) {
01891     char * obj, * copy=NULL;
01892     Header hdr;
01893     hdrObject * h;
01894     int len;
01895 
01896     if (!PyArg_ParseTuple(args, "s#", &obj, &len)) return NULL;
01897     
01898     /* malloc is needed to avoid surprises from data swab in headerLoad(). */
01899     copy = malloc(len);
01900     if (copy == NULL) {
01901         PyErr_SetString(pyrpmError, "out of memory");
01902         return NULL;
01903     }
01904     memcpy (copy, obj, len);
01905 
01906     hdr = headerLoad(copy);
01907     if (!hdr) {
01908         PyErr_SetString(pyrpmError, "bad header");
01909         return NULL;
01910     }
01911     headerAllocated(hdr);
01912 
01913     /* XXX avoid the false OK's from rpmverifyDigest() with missing tags. */
01914     if (!headerIsEntry(hdr, RPMTAG_HEADERIMMUTABLE)) {
01915         PyErr_SetString(pyrpmError, "bad header, not immutable");
01916         headerFree(hdr);
01917         return NULL;
01918     }
01919 
01920     /* XXX avoid the false OK's from rpmverifyDigest() with missing tags. */
01921     if (!headerIsEntry(hdr, RPMTAG_SHA1HEADER)
01922     &&  !headerIsEntry(hdr, RPMTAG_SHA1RHN)) {
01923         PyErr_SetString(pyrpmError, "bad header, no digest");
01924         headerFree(hdr);
01925         return NULL;
01926     }
01927 
01928     if (rpmVerifyDigest(hdr)) {
01929         PyErr_SetString(pyrpmError, "bad header, digest check failed");
01930         headerFree(hdr);
01931         return NULL;
01932     }
01933 
01934     /* Retrofit a RHNPlatform: tag. */
01935     if (!headerIsEntry(hdr, RPMTAG_RHNPLATFORM)) {
01936         const char * arch;
01937         int_32 at;
01938         if (headerGetEntry(hdr, RPMTAG_ARCH, &at, (void **)&arch, NULL))
01939             headerAddEntry(hdr, RPMTAG_RHNPLATFORM, at, arch, 1);
01940     }
01941 
01942     h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
01943     h->h = hdr;
01944     h->sigs = NULL;
01945     h->fileList = h->linkList = h->md5list = NULL;
01946     h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
01947     h->modes = h->rdevs = NULL;
01948 
01949     return (PyObject *) h;
01950 }
01951 
01954 static PyObject * rpmInitDB(PyObject * self, PyObject * args) {
01955     char *root;
01956     int forWrite = 0;
01957 
01958     if (!PyArg_ParseTuple(args, "i|s", &forWrite, &root)) return NULL;
01959 
01960     if (rpmdbInit(root, forWrite ? O_RDWR | O_CREAT: O_RDONLY)) {
01961         char * errmsg = "cannot initialize database in %s";
01962         char * errstr = NULL;
01963         int errsize;
01964 
01965         errsize = strlen(errmsg) + strlen(root);
01966         errstr = alloca(errsize);
01967         snprintf(errstr, errsize, errmsg, root);
01968         PyErr_SetString(pyrpmError, errstr);
01969         return NULL;
01970     }
01971 
01972     Py_INCREF(Py_None);
01973     return(Py_None);
01974 }
01975 
01978 static rpmdbObject * rpmOpenDB(PyObject * self, PyObject * args) {
01979     rpmdbObject * o;
01980     char * root = "";
01981     int forWrite = 0;
01982 
01983     if (!PyArg_ParseTuple(args, "|is", &forWrite, &root)) return NULL;
01984 
01985     o = PyObject_NEW(rpmdbObject, &rpmdbType);
01986     o->db = NULL;
01987     o->offx = 0;
01988     o->noffs = 0;
01989     o->offsets = NULL;
01990 
01991     if (rpmdbOpen(root, &o->db, forWrite ? O_RDWR | O_CREAT: O_RDONLY, 0644)) {
01992         char * errmsg = "cannot open database in %s";
01993         char * errstr = NULL;
01994         int errsize;
01995 
01996         Py_DECREF(o);
01997         /* PyErr_SetString should take varargs... */
01998         errsize = strlen(errmsg) + *root == '\0' ? 15 /* "/var/lib/rpm" */ : strlen(root);
01999         errstr = alloca(errsize);
02000         snprintf(errstr, errsize, errmsg, *root == '\0' ? "/var/lib/rpm" : root);
02001         PyErr_SetString(pyrpmError, errstr);
02002         return NULL;
02003     }
02004 
02005     return o;
02006 }
02007 
02010 static PyObject * rebuildDB (PyObject * self, PyObject * args) {
02011     char * root = "";
02012 
02013     if (!PyArg_ParseTuple(args, "s", &root)) return NULL;
02014 
02015     return Py_BuildValue("i", rpmdbRebuild(root));
02016 }
02017 
02020 static PyObject * rpmReadHeaders (FD_t fd) {
02021     PyObject * list;
02022     Header header;
02023     hdrObject * h;
02024 
02025     if (!fd) {
02026         PyErr_SetFromErrno(pyrpmError);
02027         return NULL;
02028     }
02029 
02030     list = PyList_New(0);
02031     Py_BEGIN_ALLOW_THREADS
02032     header = headerRead(fd, HEADER_MAGIC_YES);
02033 
02034     Py_END_ALLOW_THREADS
02035     while (header) {
02036         compressFilelist (header);
02037         providePackageNVR (header);
02038         h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
02039         h->h = header;
02040         h->sigs = NULL;
02041         h->fileList = h->linkList = h->md5list = NULL;
02042         h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
02043         h->modes = h->rdevs = NULL;
02044         if (PyList_Append(list, (PyObject *) h)) {
02045             Py_DECREF(list);
02046             Py_DECREF(h);
02047             return NULL;
02048         }
02049 
02050         Py_DECREF(h);
02051 
02052         Py_BEGIN_ALLOW_THREADS
02053         header = headerRead(fd, HEADER_MAGIC_YES);
02054         Py_END_ALLOW_THREADS
02055     }
02056 
02057     return list;
02058 }
02059 
02062 static PyObject * rpmHeaderFromFD(PyObject * self, PyObject * args) {
02063     FD_t fd;
02064     int fileno;
02065     PyObject * list;
02066 
02067     if (!PyArg_ParseTuple(args, "i", &fileno)) return NULL;
02068     fd = fdDup(fileno);
02069 
02070     list = rpmReadHeaders (fd);
02071     Fclose(fd);
02072 
02073     return list;
02074 }
02075 
02078 static PyObject * rpmHeaderFromFile(PyObject * self, PyObject * args) {
02079     char * filespec;
02080     FD_t fd;
02081     PyObject * list;
02082 
02083     if (!PyArg_ParseTuple(args, "s", &filespec)) return NULL;
02084     fd = Fopen(filespec, "r.fdio");
02085 
02086     if (!fd) {
02087         PyErr_SetFromErrno(pyrpmError);
02088         return NULL;
02089     }
02090 
02091     list = rpmReadHeaders (fd);
02092     Fclose(fd);
02093 
02094     return list;
02095 }
02096 
02101 static int rpmMergeHeaders(PyObject * list, FD_t fd, int matchTag) {
02102     Header newH;
02103     HeaderIterator iter;
02104     int_32 * newMatch, * oldMatch;
02105     hdrObject * ho;
02106     int count = 0;
02107     int type, c, tag;
02108     void * p;
02109 
02110     Py_BEGIN_ALLOW_THREADS
02111     newH = headerRead(fd, HEADER_MAGIC_YES);
02112 
02113     Py_END_ALLOW_THREADS
02114     while (newH) {
02115         if (!headerGetEntry(newH, matchTag, NULL, (void **) &newMatch, NULL)) {
02116             PyErr_SetString(pyrpmError, "match tag missing in new header");
02117             return 1;
02118         }
02119 
02120         ho = (hdrObject *) PyList_GetItem(list, count++);
02121         if (!ho) return 1;
02122 
02123         if (!headerGetEntry(ho->h, matchTag, NULL, (void **) &oldMatch, NULL)) {
02124             PyErr_SetString(pyrpmError, "match tag missing in new header");
02125             return 1;
02126         }
02127 
02128         if (*newMatch != *oldMatch) {
02129             PyErr_SetString(pyrpmError, "match tag mismatch");
02130             return 1;
02131         }
02132 
02133         if (ho->sigs) headerFree(ho->sigs);
02134         if (ho->md5list) free(ho->md5list);
02135         if (ho->fileList) free(ho->fileList);
02136         if (ho->linkList) free(ho->linkList);
02137 
02138         ho->sigs = NULL;
02139         ho->md5list = NULL;
02140         ho->fileList = NULL;
02141         ho->linkList = NULL;
02142 
02143         iter = headerInitIterator(newH);
02144 
02145         while (headerNextIterator(iter, &tag, &type, (void *) &p, &c)) {
02146             /* could be dupes */
02147             headerRemoveEntry(ho->h, tag);
02148             headerAddEntry(ho->h, tag, type, p, c);
02149             headerFreeData(p, type);
02150         }
02151 
02152         headerFreeIterator(iter);
02153 
02154         Py_BEGIN_ALLOW_THREADS
02155         newH = headerRead(fd, HEADER_MAGIC_YES);
02156         Py_END_ALLOW_THREADS
02157     }
02158 
02159     return 0;
02160 }
02161 
02162 static PyObject * rpmMergeHeadersFromFD(PyObject * self, PyObject * args) {
02163     FD_t fd;
02164     int fileno;
02165     PyObject * list;
02166     int rc;
02167     int matchTag;
02168 
02169     if (!PyArg_ParseTuple(args, "Oii", &list, &fileno, &matchTag)) return NULL;
02170 
02171     if (!PyList_Check(list)) {
02172         PyErr_SetString(PyExc_TypeError, "first parameter must be a list");
02173         return NULL;
02174     }
02175 
02176     fd = fdDup(fileno);
02177 
02178     rc = rpmMergeHeaders (list, fd, matchTag);
02179     Fclose(fd);
02180 
02181     if (rc) {
02182         return NULL;
02183     }
02184 
02185     Py_INCREF(Py_None);
02186     return Py_None;
02187 }
02188 
02189 
02192 static PyObject * errorCB = NULL, * errorData = NULL;
02193 
02196 static void errorcb (void)
02197 {
02198     PyObject * result, * args = NULL;
02199 
02200     if (errorData)
02201         args = Py_BuildValue("(O)", errorData);
02202 
02203     result = PyEval_CallObject(errorCB, args);
02204     Py_XDECREF(args);
02205 
02206     if (result == NULL) {
02207         PyErr_Print();
02208         PyErr_Clear();
02209     }
02210     Py_DECREF (result);
02211 }
02212 
02215 static PyObject * errorSetCallback (PyObject * self, PyObject * args) {
02216     PyObject *newCB = NULL, *newData = NULL;
02217 
02218     if (!PyArg_ParseTuple(args, "O|O", &newCB, &newData)) return NULL;
02219 
02220     /* if we're getting a void*, set the error callback to this. */
02221     /* also, we can possibly decref any python callbacks we had  */
02222     /* and set them to NULL.                                     */
02223     if (PyCObject_Check (newCB)) {
02224         rpmErrorSetCallback (PyCObject_AsVoidPtr(newCB));
02225 
02226         Py_XDECREF (errorCB);
02227         Py_XDECREF (errorData);
02228 
02229         errorCB   = NULL;
02230         errorData = NULL;
02231         
02232         Py_INCREF(Py_None);
02233         return Py_None;
02234     }
02235     
02236     if (!PyCallable_Check (newCB)) {
02237         PyErr_SetString(PyExc_TypeError, "parameter must be callable");
02238         return NULL;
02239     }
02240 
02241     Py_XDECREF(errorCB);
02242     Py_XDECREF(errorData);
02243 
02244     errorCB = newCB;
02245     errorData = newData;
02246     
02247     Py_INCREF (errorCB);
02248     Py_XINCREF (errorData);
02249 
02250     return PyCObject_FromVoidPtr(rpmErrorSetCallback (errorcb), NULL);
02251 }
02252 
02255 static PyObject * errorString (PyObject * self, PyObject * args) {
02256     return PyString_FromString(rpmErrorString ());
02257 }
02258 
02261 static PyObject * versionCompare (PyObject * self, PyObject * args) {
02262     hdrObject * h1, * h2;
02263 
02264     if (!PyArg_ParseTuple(args, "O!O!", &hdrType, &h1, &hdrType, &h2)) return NULL;
02265 
02266     return Py_BuildValue("i", rpmVersionCompare(h1->h, h2->h));
02267 }
02268 
02271 static PyObject * labelCompare (PyObject * self, PyObject * args) {
02272     char *v1, *r1, *e1, *v2, *r2, *e2;
02273     int rc;
02274 
02275     if (!PyArg_ParseTuple(args, "(zzz)(zzz)",
02276                           &e1, &v1, &r1,
02277                           &e2, &v2, &r2)) return NULL;
02278 
02279     if (e1 && !e2)
02280         return Py_BuildValue("i", 1);
02281     else if (!e1 && e2)
02282         return Py_BuildValue("i", -1);
02283     else if (e1 && e2) {
02284         int ep1, ep2;
02285         ep1 = atoi (e1);
02286         ep2 = atoi (e2);
02287         if (ep1 < ep2)
02288             return Py_BuildValue("i", -1);
02289         else if (ep1 > ep2)
02290             return Py_BuildValue("i", 1);
02291     }
02292 
02293     rc = rpmvercmp(v1, v2);
02294     if (rc)
02295         return Py_BuildValue("i", rc);
02296 
02297     return Py_BuildValue("i", rpmvercmp(r1, r2));
02298 }
02299 
02302 static PyObject * checkSig (PyObject * self, PyObject * args) {
02303     char * filename;
02304     int flags;
02305     int rc = 255;
02306 
02307     if (PyArg_ParseTuple(args, "si", &filename, &flags)) {
02308         const char *av[2];
02309         av[0] = filename;
02310         av[1] = NULL;
02311         rc = rpmCheckSig(flags, av);
02312     }
02313     return Py_BuildValue("i", rc);
02314 }
02315 
02316 /* hack to get the current header that's in the transaction set */
02319 static PyObject * getTsHeader (PyObject * self, PyObject * args) {
02320     hdrObject * h;
02321     
02322     if (transactionSetHeader) {
02323         h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
02324         h->h = headerLink(transactionSetHeader);
02325         h->sigs = NULL;
02326         h->fileList = h->linkList = h->md5list = NULL;
02327         h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
02328         h->modes = h->rdevs = NULL;
02329         return (PyObject *) h;
02330     }
02331     Py_INCREF(Py_None);
02332     return (PyObject *) Py_None;
02333 }
02334 
02337 typedef struct FDlist_t FDlist;
02338 
02341 struct FDlist_t {
02342     FILE *f;
02343     FD_t fd;
02344     char *note;
02345     FDlist *next;
02346 } ;
02347 
02350 static FDlist *fdhead = NULL;
02351 
02354 static FDlist *fdtail = NULL;
02355 
02358 static int closeCallback(FILE * f) {
02359     FDlist *node, *last;
02360 
02361     printf ("close callback on %p\n", f);
02362     
02363     node = fdhead;
02364     last = NULL;
02365     while (node) {
02366         if (node->f == f)
02367             break;
02368         last = node;
02369         node = node->next;
02370     }
02371     if (node) {
02372         if (last)
02373             last->next = node->next;
02374         else
02375             fdhead = node->next;
02376         printf ("closing %s %p\n", node->note, node->fd);
02377         free (node->note);
02378         node->fd = fdLink(node->fd, "closeCallback");
02379         Fclose (node->fd);
02380         while (node->fd)
02381             node->fd = fdFree(node->fd, "closeCallback");
02382         free (node);
02383     }
02384     return 0; 
02385 }
02386 
02389 static PyObject * doFopen(PyObject * self, PyObject * args) {
02390     char * path, * mode;
02391     FDlist *node;
02392     
02393     if (!PyArg_ParseTuple(args, "ss", &path, &mode))
02394         return NULL;
02395     
02396     node = malloc (sizeof(FDlist));
02397     
02398     node->fd = Fopen(path, mode);
02399     node->fd = fdLink(node->fd, "doFopen");
02400     node->note = strdup (path);
02401 
02402     if (!node->fd) {
02403         PyErr_SetFromErrno(pyrpmError);
02404         free (node);
02405         return NULL;
02406     }
02407     
02408     if (Ferror(node->fd)) {
02409         const char *err = Fstrerror(node->fd);
02410         free(node);
02411         if (err) {
02412             PyErr_SetString(pyrpmError, err);
02413             return NULL;
02414         }
02415     }
02416     node->f = fdGetFp(node->fd);
02417     printf ("opening %s fd = %p f = %p\n", node->note, node->fd, node->f);
02418     if (!node->f) {
02419         PyErr_SetString(pyrpmError, "FD_t has no FILE*");
02420         free(node);
02421         return NULL;
02422     }
02423 
02424     node->next = NULL;
02425     if (!fdhead) {
02426         fdhead = fdtail = node;
02427     } else if (fdtail) {
02428         fdtail->next = node;
02429     } else {
02430         fdhead = node;
02431     }
02432     fdtail = node;
02433     
02434     return PyFile_FromFile (node->f, path, mode, closeCallback);
02435 }
02436 
02439 static PyMethodDef rpmModuleMethods[] = {
02440     { "TransactionSet", (PyCFunction) rpmtransCreate, METH_VARARGS, NULL },
02441     { "addMacro", (PyCFunction) doAddMacro, METH_VARARGS, NULL },
02442     { "delMacro", (PyCFunction) doDelMacro, METH_VARARGS, NULL },
02443     { "archscore", (PyCFunction) archScore, METH_VARARGS, NULL },
02444     { "findUpgradeSet", (PyCFunction) findUpgradeSet, METH_VARARGS, NULL },
02445     { "headerFromPackage", (PyCFunction) rpmHeaderFromPackage, METH_VARARGS, NULL },
02446     { "headerLoad", (PyCFunction) hdrLoad, METH_VARARGS, NULL },
02447     { "rhnLoad", (PyCFunction) rhnLoad, METH_VARARGS, NULL },
02448     { "initdb", (PyCFunction) rpmInitDB, METH_VARARGS, NULL },
02449     { "opendb", (PyCFunction) rpmOpenDB, METH_VARARGS, NULL },
02450     { "rebuilddb", (PyCFunction) rebuildDB, METH_VARARGS, NULL },
02451     { "mergeHeaderListFromFD", (PyCFunction) rpmMergeHeadersFromFD, METH_VARARGS, NULL },
02452     { "readHeaderListFromFD", (PyCFunction) rpmHeaderFromFD, METH_VARARGS, NULL },
02453     { "readHeaderListFromFile", (PyCFunction) rpmHeaderFromFile, METH_VARARGS, NULL },
02454     { "errorSetCallback", (PyCFunction) errorSetCallback, METH_VARARGS, NULL },
02455     { "errorString", (PyCFunction) errorString, METH_VARARGS, NULL },
02456     { "versionCompare", (PyCFunction) versionCompare, METH_VARARGS, NULL },
02457     { "labelCompare", (PyCFunction) labelCompare, METH_VARARGS, NULL },
02458     { "checksig", (PyCFunction) checkSig, METH_VARARGS, NULL },
02459     { "getTransactionCallbackHeader", (PyCFunction) getTsHeader, METH_VARARGS, NULL },
02460 /*      { "Fopen", (PyCFunction) doFopen, METH_VARARGS, NULL }, */
02461     { NULL }
02462 } ;
02463 
02466 void initrpm(void) {
02467     PyObject * m, * d, *o, * tag = NULL, * dict;
02468     int i;
02469     const struct headerSprintfExtension_s * extensions = rpmHeaderFormats;
02470     struct headerSprintfExtension_s * ext;
02471 
02472     m = Py_InitModule("rpm", rpmModuleMethods);
02473 
02474     hdrType.ob_type = &PyType_Type;
02475     rpmdbMIType.ob_type = &PyType_Type;
02476     rpmdbType.ob_type = &PyType_Type;
02477     rpmtransType.ob_type = &PyType_Type;
02478 
02479     if(!m)
02480         return;
02481 
02482 /*      _rpmio_debug = -1; */
02483     rpmReadConfigFiles(NULL, NULL);
02484 
02485     d = PyModule_GetDict(m);
02486 
02487     pyrpmError = PyString_FromString("rpm.error");
02488     PyDict_SetItemString(d, "error", pyrpmError);
02489     Py_DECREF(pyrpmError);
02490 
02491     dict = PyDict_New();
02492 
02493     for (i = 0; i < rpmTagTableSize; i++) {
02494         tag = PyInt_FromLong(rpmTagTable[i].val);
02495         PyDict_SetItemString(d, (char *) rpmTagTable[i].name, tag);
02496         Py_DECREF(tag);
02497         PyDict_SetItem(dict, tag, o=PyString_FromString(rpmTagTable[i].name + 7));
02498         Py_DECREF(o);
02499     }
02500 
02501     while (extensions->name) {
02502         if (extensions->type == HEADER_EXT_TAG) {
02503             (const struct headerSprintfExtension *) ext = extensions;
02504             PyDict_SetItemString(d, extensions->name, o=PyCObject_FromVoidPtr(ext, NULL));
02505             Py_DECREF(o);
02506             PyDict_SetItem(dict, tag, o=PyString_FromString(ext->name + 7));
02507             Py_DECREF(o);    
02508         }
02509         extensions++;
02510     }
02511 
02512     PyDict_SetItemString(d, "tagnames", dict);
02513     Py_DECREF(dict);
02514 
02515 
02516 #define REGISTER_ENUM(val) \
02517     PyDict_SetItemString(d, #val, o=PyInt_FromLong( val )); \
02518     Py_DECREF(o);
02519     
02520     REGISTER_ENUM(RPMFILE_STATE_NORMAL);
02521     REGISTER_ENUM(RPMFILE_STATE_REPLACED);
02522     REGISTER_ENUM(RPMFILE_STATE_NOTINSTALLED);
02523     REGISTER_ENUM(RPMFILE_STATE_NETSHARED);
02524 
02525     REGISTER_ENUM(RPMFILE_CONFIG);
02526     REGISTER_ENUM(RPMFILE_DOC);
02527     REGISTER_ENUM(RPMFILE_MISSINGOK);
02528     REGISTER_ENUM(RPMFILE_NOREPLACE);
02529     REGISTER_ENUM(RPMFILE_GHOST);
02530     REGISTER_ENUM(RPMFILE_LICENSE);
02531     REGISTER_ENUM(RPMFILE_README);
02532 
02533     REGISTER_ENUM(RPMDEP_SENSE_REQUIRES);
02534     REGISTER_ENUM(RPMDEP_SENSE_CONFLICTS);
02535 
02536     REGISTER_ENUM(RPMSENSE_SERIAL);
02537     REGISTER_ENUM(RPMSENSE_LESS);
02538     REGISTER_ENUM(RPMSENSE_GREATER);
02539     REGISTER_ENUM(RPMSENSE_EQUAL);
02540     REGISTER_ENUM(RPMSENSE_PREREQ);
02541     REGISTER_ENUM(RPMSENSE_INTERP);
02542     REGISTER_ENUM(RPMSENSE_SCRIPT_PRE);
02543     REGISTER_ENUM(RPMSENSE_SCRIPT_POST);
02544     REGISTER_ENUM(RPMSENSE_SCRIPT_PREUN);
02545     REGISTER_ENUM(RPMSENSE_SCRIPT_POSTUN);
02546     REGISTER_ENUM(RPMSENSE_SCRIPT_VERIFY);
02547     REGISTER_ENUM(RPMSENSE_FIND_REQUIRES);
02548     REGISTER_ENUM(RPMSENSE_FIND_PROVIDES);
02549     REGISTER_ENUM(RPMSENSE_TRIGGERIN);
02550     REGISTER_ENUM(RPMSENSE_TRIGGERUN);
02551     REGISTER_ENUM(RPMSENSE_TRIGGERPOSTUN);
02552     REGISTER_ENUM(RPMSENSE_MULTILIB);
02553     REGISTER_ENUM(RPMSENSE_SCRIPT_PREP);
02554     REGISTER_ENUM(RPMSENSE_SCRIPT_BUILD);
02555     REGISTER_ENUM(RPMSENSE_SCRIPT_INSTALL);
02556     REGISTER_ENUM(RPMSENSE_SCRIPT_CLEAN);
02557     REGISTER_ENUM(RPMSENSE_RPMLIB);
02558     REGISTER_ENUM(RPMSENSE_TRIGGERPREIN);
02559 
02560     REGISTER_ENUM(RPMTRANS_FLAG_TEST);
02561     REGISTER_ENUM(RPMTRANS_FLAG_BUILD_PROBS);
02562     REGISTER_ENUM(RPMTRANS_FLAG_NOSCRIPTS);
02563     REGISTER_ENUM(RPMTRANS_FLAG_JUSTDB);
02564     REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERS);
02565     REGISTER_ENUM(RPMTRANS_FLAG_NODOCS);
02566     REGISTER_ENUM(RPMTRANS_FLAG_ALLFILES);
02567     REGISTER_ENUM(RPMTRANS_FLAG_KEEPOBSOLETE);
02568     REGISTER_ENUM(RPMTRANS_FLAG_MULTILIB);
02569 
02570     REGISTER_ENUM(RPMPROB_FILTER_IGNOREOS);
02571     REGISTER_ENUM(RPMPROB_FILTER_IGNOREARCH);
02572     REGISTER_ENUM(RPMPROB_FILTER_REPLACEPKG);
02573     REGISTER_ENUM(RPMPROB_FILTER_FORCERELOCATE);
02574     REGISTER_ENUM(RPMPROB_FILTER_REPLACENEWFILES);
02575     REGISTER_ENUM(RPMPROB_FILTER_REPLACEOLDFILES);
02576     REGISTER_ENUM(RPMPROB_FILTER_OLDPACKAGE);
02577     REGISTER_ENUM(RPMPROB_FILTER_DISKSPACE);
02578     REGISTER_ENUM(RPMPROB_FILTER_DISKNODES);
02579 
02580     REGISTER_ENUM(RPMCALLBACK_INST_PROGRESS);
02581     REGISTER_ENUM(RPMCALLBACK_INST_START);
02582     REGISTER_ENUM(RPMCALLBACK_INST_OPEN_FILE);
02583     REGISTER_ENUM(RPMCALLBACK_INST_CLOSE_FILE);
02584     REGISTER_ENUM(RPMCALLBACK_TRANS_PROGRESS);
02585     REGISTER_ENUM(RPMCALLBACK_TRANS_START);
02586     REGISTER_ENUM(RPMCALLBACK_TRANS_STOP);
02587     REGISTER_ENUM(RPMCALLBACK_UNINST_PROGRESS);
02588     REGISTER_ENUM(RPMCALLBACK_UNINST_START);
02589     REGISTER_ENUM(RPMCALLBACK_UNINST_STOP);
02590 
02591     REGISTER_ENUM(RPMPROB_BADARCH);
02592     REGISTER_ENUM(RPMPROB_BADOS);
02593     REGISTER_ENUM(RPMPROB_PKG_INSTALLED);
02594     REGISTER_ENUM(RPMPROB_BADRELOCATE);
02595     REGISTER_ENUM(RPMPROB_REQUIRES);
02596     REGISTER_ENUM(RPMPROB_CONFLICT);
02597     REGISTER_ENUM(RPMPROB_NEW_FILE_CONFLICT);
02598     REGISTER_ENUM(RPMPROB_FILE_CONFLICT);
02599     REGISTER_ENUM(RPMPROB_OLDPACKAGE);
02600     REGISTER_ENUM(RPMPROB_DISKSPACE);
02601     REGISTER_ENUM(RPMPROB_DISKNODES);
02602     REGISTER_ENUM(RPMPROB_BADPRETRANS);
02603 
02604     REGISTER_ENUM(CHECKSIG_PGP);
02605     REGISTER_ENUM(CHECKSIG_GPG);
02606     REGISTER_ENUM(CHECKSIG_MD5);
02607 }
02608 

Generated on Wed Mar 13 15:34:49 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002