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     /* Legacy headers are forced into immutable region. */
00462     if (!headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) {
00463         Header nh = headerReload(h, RPMTAG_HEADERIMMUTABLE);
00464         /* XXX Another unload/load cycle to "seal" the immutable region. */
00465         uh = headerUnload(nh);
00466         headerFree(nh);
00467         h = headerLoad(uh);
00468         headerAllocated(h);
00469     }
00470 
00471     /* All headers have SHA1 digest, compute and add if necessary. */
00472     if (!headerIsEntry(h, RPMTAG_SHA1HEADER)) {
00473         int_32 uht, uhc;
00474         const char * digest;
00475         size_t digestlen;
00476         DIGEST_CTX ctx;
00477 
00478         headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, (void **)&uh, &uhc);
00479 
00480         ctx = rpmDigestInit(RPMDIGEST_SHA1);
00481         rpmDigestUpdate(ctx, uh, uhc);
00482         rpmDigestFinal(ctx, (void **)&digest, &digestlen, 1);
00483 
00484         headerAddEntry(h, RPMTAG_SHA1RHN, RPM_STRING_TYPE, digest, 1);
00485 
00486         uh = headerFreeData(uh, uht);
00487         digest = _free(digest);
00488     }
00489 
00490     len = headerSizeof(h, 0);
00491     uh = headerUnload(h);
00492     headerFree(h);
00493 
00494     rc = PyString_FromStringAndSize(uh, len);
00495     free(uh);
00496 
00497     return rc;
00498 }
00499 
00502 static PyObject * hdrFullFilelist(hdrObject * s, PyObject * args) {
00503     mungeFilelist (s->h);
00504 
00505     Py_INCREF(Py_None);
00506     return Py_None;
00507 }
00508 
00511 static struct PyMethodDef hdrMethods[] = {
00512         {"keys",        (PyCFunction) hdrKeyList,       1 },
00513         {"unload",      (PyCFunction) hdrUnload,        METH_VARARGS|METH_KEYWORDS },
00514         {"verifyFile",  (PyCFunction) hdrVerifyFile,    1 },
00515         {"expandFilelist",      (PyCFunction) hdrExpandFilelist,        1 },
00516         {"compressFilelist",    (PyCFunction) hdrCompressFilelist,      1 },
00517         {"fullFilelist",        (PyCFunction) hdrFullFilelist,  1 },
00518         {"rhnUnload",   (PyCFunction) rhnUnload, METH_VARARGS },
00519         {NULL,          NULL}           /* sentinel */
00520 };
00521 
00524 static PyObject * hdrGetAttr(hdrObject * s, char * name) {
00525     return Py_FindMethod(hdrMethods, (PyObject * ) s, name);
00526 }
00527 
00530 static void hdrDealloc(hdrObject * s) {
00531     if (s->h) headerFree(s->h);
00532     if (s->sigs) headerFree(s->sigs);
00533     if (s->md5list) free(s->md5list);
00534     if (s->fileList) free(s->fileList);
00535     if (s->linkList) free(s->linkList);
00536     PyMem_DEL(s);
00537 }
00538 
00541 static long tagNumFromPyObject (PyObject *item)
00542 {
00543     char * str;
00544     int i;
00545 
00546     if (PyInt_Check(item)) {
00547         return PyInt_AsLong(item);
00548     } else if (PyString_Check(item)) {
00549         str = PyString_AsString(item);
00550         for (i = 0; i < rpmTagTableSize; i++)
00551             if (!xstrcasecmp(rpmTagTable[i].name + 7, str)) break;
00552         if (i < rpmTagTableSize) return rpmTagTable[i].val;
00553     }
00554     return -1;
00555 }
00556 
00559 static PyObject * hdrSubscript(hdrObject * s, PyObject * item) {
00560     int type, count, i, tag = -1;
00561     void * data;
00562     PyObject * o, * metao;
00563     char ** stringArray;
00564     int forceArray = 0;
00565     int freeData = 0;
00566     char * str;
00567     struct headerSprintfExtension_s * ext = NULL;
00568     const struct headerSprintfExtension_s * extensions = rpmHeaderFormats;
00569 
00570     if (PyCObject_Check (item))
00571         ext = PyCObject_AsVoidPtr(item);
00572     else
00573         tag = tagNumFromPyObject (item);
00574     if (tag == -1 && PyString_Check(item)) {
00575         /* if we still don't have the tag, go looking for the header
00576            extensions */
00577         str = PyString_AsString(item);
00578         while (extensions->name) {
00579             if (extensions->type == HEADER_EXT_TAG
00580                 && !xstrcasecmp(extensions->name + 7, str)) {
00581                 (const struct headerSprintfExtension *) ext = extensions;
00582             }
00583             extensions++;
00584         }
00585     }
00586 
00587     if (ext) {
00588         ext->u.tagFunction(s->h, &type, (const void **) &data, &count, &freeData);
00589     } else {
00590         if (tag == -1) {
00591             PyErr_SetString(PyExc_KeyError, "unknown header tag");
00592             return NULL;
00593         }
00594         
00595         /* XXX signature tags are appended to header, this API is gonna die */
00596         if (!rpmPackageGetEntry(NULL, s->sigs, s->h, tag, &type, &data, &count))
00597         {
00598             Py_INCREF(Py_None);
00599             return Py_None;
00600         }
00601     }
00602 
00603     switch (tag) {
00604       case RPMTAG_OLDFILENAMES:
00605       case RPMTAG_FILESIZES:
00606       case RPMTAG_FILESTATES:
00607       case RPMTAG_FILEMODES:
00608       case RPMTAG_FILEUIDS:
00609       case RPMTAG_FILEGIDS:
00610       case RPMTAG_FILERDEVS:
00611       case RPMTAG_FILEMTIMES:
00612       case RPMTAG_FILEMD5S:
00613       case RPMTAG_FILELINKTOS:
00614       case RPMTAG_FILEFLAGS:
00615       case RPMTAG_ROOT:
00616       case RPMTAG_FILEUSERNAME:
00617       case RPMTAG_FILEGROUPNAME:
00618         forceArray = 1;
00619         break;
00620       case RPMTAG_SUMMARY:
00621       case RPMTAG_GROUP:
00622       case RPMTAG_DESCRIPTION:
00623         freeData = 1;
00624         break;
00625       default:
00626         break;
00627     }
00628 
00629     switch (type) {
00630       case RPM_BIN_TYPE:
00631         o = PyString_FromStringAndSize(data, count);
00632         break;
00633 
00634       case RPM_INT32_TYPE:
00635         if (count != 1 || forceArray) {
00636             metao = PyList_New(0);
00637             for (i = 0; i < count; i++) {
00638                 o = PyInt_FromLong(((int *) data)[i]);
00639                 PyList_Append(metao, o);
00640                 Py_DECREF(o);
00641             }
00642             o = metao;
00643         } else {
00644             o = PyInt_FromLong(*((int *) data));
00645         }
00646         break;
00647 
00648       case RPM_CHAR_TYPE:
00649       case RPM_INT8_TYPE:
00650         if (count != 1 || forceArray) {
00651             metao = PyList_New(0);
00652             for (i = 0; i < count; i++) {
00653                 o = PyInt_FromLong(((char *) data)[i]);
00654                 PyList_Append(metao, o);
00655                 Py_DECREF(o);
00656             }
00657             o = metao;
00658         } else {
00659             o = PyInt_FromLong(*((char *) data));
00660         }
00661         break;
00662 
00663       case RPM_INT16_TYPE:
00664         if (count != 1 || forceArray) {
00665             metao = PyList_New(0);
00666             for (i = 0; i < count; i++) {
00667                 o = PyInt_FromLong(((short *) data)[i]);
00668                 PyList_Append(metao, o);
00669                 Py_DECREF(o);
00670             }
00671             o = metao;
00672         } else {
00673             o = PyInt_FromLong(*((short *) data));
00674         }
00675         break;
00676 
00677       case RPM_STRING_ARRAY_TYPE:
00678         stringArray = data;
00679 
00680         metao = PyList_New(0);
00681         for (i = 0; i < count; i++) {
00682             o = PyString_FromString(stringArray[i]);
00683             PyList_Append(metao, o);
00684             Py_DECREF(o);
00685         }
00686         free (stringArray);
00687         o = metao;
00688         break;
00689 
00690       case RPM_STRING_TYPE:
00691         if (count != 1 || forceArray) {
00692             stringArray = data;
00693 
00694             metao = PyList_New(0);
00695             for (i=0; i < count; i++) {
00696                 o = PyString_FromString(stringArray[i]);
00697                 PyList_Append(metao, o);
00698                 Py_DECREF(o);
00699             }
00700             o = metao;
00701         } else {
00702             o = PyString_FromString(data);
00703             if (freeData)
00704                 free (data);
00705         }
00706         break;
00707 
00708       default:
00709         PyErr_SetString(PyExc_TypeError, "unsupported type in header");
00710         return NULL;
00711     }
00712 
00713     return o;
00714 }
00715 
00718 static PyMappingMethods hdrAsMapping = {
00719         (inquiry) 0,                    /* mp_length */
00720         (binaryfunc) hdrSubscript,      /* mp_subscript */
00721         (objobjargproc)0,               /* mp_ass_subscript */
00722 };
00723 
00726 static PyTypeObject hdrType = {
00727         PyObject_HEAD_INIT(NULL)
00728         0,                              /* ob_size */
00729         "header",                       /* tp_name */
00730         sizeof(hdrObject),              /* tp_size */
00731         0,                              /* tp_itemsize */
00732         (destructor) hdrDealloc,        /* tp_dealloc */
00733         0,                              /* tp_print */
00734         (getattrfunc) hdrGetAttr,       /* tp_getattr */
00735         0,                              /* tp_setattr */
00736         0,                              /* tp_compare */
00737         0,                              /* tp_repr */
00738         0,                              /* tp_as_number */
00739         0,                              /* tp_as_sequence */
00740         &hdrAsMapping,                  /* tp_as_mapping */
00741 };
00742 
00755 
00758 struct rpmdbObject_s {
00759     PyObject_HEAD;
00760     rpmdb db;
00761     int offx;
00762     int noffs;
00763     int *offsets;
00764 } ;
00765 
00768 struct rpmdbMIObject_s {
00769     PyObject_HEAD;
00770     rpmdbObject *db;
00771     rpmdbMatchIterator mi;
00772 } ;
00773 
00776 static PyObject *
00777 rpmdbMINext(rpmdbMIObject * s, PyObject * args) {
00778     /* XXX assume header? */
00779     Header h;
00780     hdrObject * ho;
00781     
00782 
00783     h = rpmdbNextIterator(s->mi);
00784     if (!h) {
00785         Py_INCREF(Py_None);
00786         return Py_None;
00787     }
00788 
00789     ho = PyObject_NEW(hdrObject, &hdrType);
00790     ho->h = headerLink(h);
00791     ho->sigs = NULL;
00792     ho->fileList = ho->linkList = ho->md5list = NULL;
00793     ho->uids = ho->gids = ho->mtimes = ho->fileSizes = NULL;
00794     ho->modes = ho->rdevs = NULL;
00795     
00796     return (PyObject *) ho;
00797 }
00798 
00801 static struct PyMethodDef rpmdbMIMethods[] = {
00802         {"next",            (PyCFunction) rpmdbMINext,  1 },
00803         {NULL,          NULL}           /* sentinel */
00804 };
00805 
00808 static PyObject * rpmdbMIGetAttr (rpmdbObject *s, char *name) {
00809     return Py_FindMethod (rpmdbMIMethods, (PyObject *) s, name);
00810 }
00811 
00814 static void rpmdbMIDealloc(rpmdbMIObject * s) {
00815     if (s && s->mi) {
00816         rpmdbFreeIterator(s->mi);
00817     }
00818     Py_DECREF (s->db);
00819     PyMem_DEL(s);
00820 }
00821 
00824 static PyTypeObject rpmdbMIType = {
00825         PyObject_HEAD_INIT(NULL)
00826         0,                              /* ob_size */
00827         "rpmdbMatchIterator",           /* tp_name */
00828         sizeof(rpmdbMIObject),  /* tp_size */
00829         0,                              /* tp_itemsize */
00830         (destructor) rpmdbMIDealloc,    /* tp_dealloc */
00831         0,                              /* tp_print */
00832         (getattrfunc) rpmdbMIGetAttr,   /* tp_getattr */
00833         0,                              /* tp_setattr */
00834         0,                              /* tp_compare */
00835         0,                              /* tp_repr */
00836         0,                              /* tp_as_number */
00837         0,                              /* tp_as_sequence */
00838         0,                              /* tp_as_mapping */
00839 };
00840 
00909 
00912 static PyObject * rpmdbFirst(rpmdbObject * s, PyObject * args) {
00913     int first;
00914 
00915     if (!PyArg_ParseTuple (args, "")) return NULL;
00916 
00917     /* Acquire all offsets in one fell swoop. */
00918     if (s->offsets == NULL || s->noffs <= 0) {
00919         rpmdbMatchIterator mi;
00920         Header h;
00921 
00922         if (s->offsets)
00923             free(s->offsets);
00924         s->offsets = NULL;
00925         s->noffs = 0;
00926         mi = rpmdbInitIterator(s->db, RPMDBI_PACKAGES, NULL, 0);
00927         while ((h = rpmdbNextIterator(mi)) != NULL) {
00928             s->noffs++;
00929             s->offsets = realloc(s->offsets, s->noffs * sizeof(s->offsets[0]));
00930             s->offsets[s->noffs-1] = rpmdbGetIteratorOffset(mi);
00931         }
00932         rpmdbFreeIterator(mi);
00933     }
00934 
00935     s->offx = 0;
00936     if (s->offsets != NULL && s->offx < s->noffs)
00937         first = s->offsets[s->offx++];
00938     else
00939         first = 0;
00940 
00941     if (!first) {
00942         PyErr_SetString(pyrpmError, "cannot find first entry in database\n");
00943         return NULL;
00944     }
00945 
00946     return Py_BuildValue("i", first);
00947 }
00948 
00951 static PyObject * rpmdbNext(rpmdbObject * s, PyObject * args) {
00952     int where;
00953 
00954     if (!PyArg_ParseTuple (args, "i", &where)) return NULL;
00955 
00956     if (s->offsets == NULL || s->offx >= s->noffs) {
00957         Py_INCREF(Py_None);
00958         return Py_None;
00959     }
00960 
00961     where = s->offsets[s->offx++];
00962 
00963     if (!where) {
00964         Py_INCREF(Py_None);
00965         return Py_None;
00966     }
00967 
00968     return Py_BuildValue("i", where);
00969 }
00970 
00973 static PyObject * handleDbResult(rpmdbMatchIterator mi) {
00974     PyObject * list, *o;
00975 
00976     list = PyList_New(0);
00977 
00978     /* XXX FIXME: unnecessary header mallocs are side effect here */
00979     if (mi != NULL) {
00980         while (rpmdbNextIterator(mi)) {
00981             PyList_Append(list, o=PyInt_FromLong(rpmdbGetIteratorOffset(mi)));
00982             Py_DECREF(o);
00983         }
00984         rpmdbFreeIterator(mi);
00985     }
00986 
00987     return list;
00988 }
00989 
00992 static PyObject * rpmdbByFile(rpmdbObject * s, PyObject * args) {
00993     char * str;
00994 
00995     if (!PyArg_ParseTuple(args, "s", &str)) return NULL;
00996 
00997     return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_BASENAMES, str, 0));
00998 }
00999 
01002 static PyObject * rpmdbByName(rpmdbObject * s, PyObject * args) {
01003     char * str;
01004 
01005     if (!PyArg_ParseTuple(args, "s", &str)) return NULL;
01006 
01007     return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_NAME, str, 0));
01008 }
01009 
01012 static PyObject * rpmdbByProvides(rpmdbObject * s, PyObject * args) {
01013     char * str;
01014 
01015     if (!PyArg_ParseTuple(args, "s", &str)) return NULL;
01016 
01017     return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_PROVIDENAME, str, 0));
01018 }
01019 
01022 static rpmdbMIObject *
01023 py_rpmdbInitIterator (rpmdbObject * s, PyObject * args) {
01024     PyObject *index = NULL;
01025     char *key = NULL;
01026     int len = 0, tag = -1;
01027     rpmdbMIObject * mio;
01028     
01029     if (!PyArg_ParseTuple(args, "|Ozi", &index, &key, &len))
01030         return NULL;
01031 
01032     if (index == NULL)
01033         tag = 0;
01034     else if ((tag = tagNumFromPyObject (index)) == -1) {
01035         PyErr_SetString(PyExc_TypeError, "unknown tag type");
01036         return NULL;
01037     }
01038     
01039     mio = (rpmdbMIObject *) PyObject_NEW(rpmdbMIObject, &rpmdbMIType);
01040     if (mio == NULL) {
01041         PyErr_SetString(pyrpmError, "out of memory creating rpmdbMIObject");
01042         return NULL;
01043     }
01044     
01045     mio->mi = rpmdbInitIterator(s->db, tag, key, len);
01046     mio->db = s;
01047     Py_INCREF (mio->db);
01048     
01049     return mio;
01050 }
01051 
01054 static struct PyMethodDef rpmdbMethods[] = {
01055         {"firstkey",        (PyCFunction) rpmdbFirst,   1 },
01056         {"nextkey",         (PyCFunction) rpmdbNext,    1 },
01057         {"findbyfile",      (PyCFunction) rpmdbByFile, 1 },
01058         {"findbyname",      (PyCFunction) rpmdbByName, 1 },
01059         {"findbyprovides",  (PyCFunction) rpmdbByProvides, 1 },
01060         {"match",           (PyCFunction) py_rpmdbInitIterator, 1 },
01061         {NULL,          NULL}           /* sentinel */
01062 };
01063 
01066 static PyObject * rpmdbGetAttr(rpmdbObject * s, char * name) {
01067     return Py_FindMethod(rpmdbMethods, (PyObject * ) s, name);
01068 }
01069 
01072 static void rpmdbDealloc(rpmdbObject * s) {
01073     if (s->offsets) {
01074         free(s->offsets);
01075     }
01076     if (s->db) {
01077         rpmdbClose(s->db);
01078     }
01079     PyMem_DEL(s);
01080 }
01081 
01082 #ifndef DYINGSOON       /* XXX OK, when? */
01083 
01085 static int
01086 rpmdbLength(rpmdbObject * s) {
01087     int count = 0;
01088 
01089     {   rpmdbMatchIterator mi;
01090 
01091         /* RPMDBI_PACKAGES */
01092         mi = rpmdbInitIterator(s->db, RPMDBI_PACKAGES, NULL, 0);
01093         while (rpmdbNextIterator(mi) != NULL)
01094             count++;
01095         rpmdbFreeIterator(mi);
01096     }
01097 
01098     return count;
01099 }
01100 
01103 static hdrObject *
01104 rpmdbSubscript(rpmdbObject * s, PyObject * key) {
01105     int offset;
01106     hdrObject * h;
01107 
01108     if (!PyInt_Check(key)) {
01109         PyErr_SetString(PyExc_TypeError, "integer expected");
01110         return NULL;
01111     }
01112 
01113     offset = (int) PyInt_AsLong(key);
01114 
01115     h = PyObject_NEW(hdrObject, &hdrType);
01116     h->h = NULL;
01117     h->sigs = NULL;
01118     {   rpmdbMatchIterator mi;
01119         mi = rpmdbInitIterator(s->db, RPMDBI_PACKAGES, &offset, sizeof(offset));
01120         if ((h->h = rpmdbNextIterator(mi)) != NULL)
01121             h->h = headerLink(h->h);
01122         rpmdbFreeIterator(mi);
01123     }
01124     h->fileList = h->linkList = h->md5list = NULL;
01125     h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
01126     h->modes = h->rdevs = NULL;
01127     if (!h->h) {
01128         Py_DECREF(h);
01129         PyErr_SetString(pyrpmError, "cannot read rpmdb entry");
01130         return NULL;
01131     }
01132 
01133     return h;
01134 }
01135 
01138 static PyMappingMethods rpmdbAsMapping = {
01139         (inquiry) rpmdbLength,          /* mp_length */
01140         (binaryfunc) rpmdbSubscript,    /* mp_subscript */
01141         (objobjargproc)0,               /* mp_ass_subscript */
01142 };
01143 #endif
01144 
01147 static PyTypeObject rpmdbType = {
01148         PyObject_HEAD_INIT(NULL)
01149         0,                              /* ob_size */
01150         "rpmdb",                        /* tp_name */
01151         sizeof(rpmdbObject),            /* tp_size */
01152         0,                              /* tp_itemsize */
01153         (destructor) rpmdbDealloc,      /* tp_dealloc */
01154         0,                              /* tp_print */
01155         (getattrfunc) rpmdbGetAttr,     /* tp_getattr */
01156         0,                              /* tp_setattr */
01157         0,                              /* tp_compare */
01158         0,                              /* tp_repr */
01159         0,                              /* tp_as_number */
01160         0,                              /* tp_as_sequence */
01161 #ifndef DYINGSOON
01162         &rpmdbAsMapping,                /* tp_as_mapping */
01163 #else
01164         0,
01165 #endif
01166 };
01167 
01272 
01275 struct rpmtransObject_s {
01276     PyObject_HEAD;
01277     rpmdbObject * dbo;
01278     rpmTransactionSet ts;
01279     PyObject * keyList;                 /* keeps reference counts correct */
01280     FD_t scriptFd;
01281 } ;
01282 
01285 static PyObject * rpmtransAdd(rpmtransObject * s, PyObject * args) {
01286     hdrObject * h;
01287     PyObject * key;
01288     char * how = NULL;
01289     int isUpgrade = 0;
01290 
01291     if (!PyArg_ParseTuple(args, "OO|s", &h, &key, &how)) return NULL;
01292     if (h->ob_type != &hdrType) {
01293         PyErr_SetString(PyExc_TypeError, "bad type for header argument");
01294         return NULL;
01295     }
01296 
01297     if (how && strcmp(how, "a") && strcmp(how, "u") && strcmp(how, "i")) {
01298         PyErr_SetString(PyExc_TypeError, "how argument must be \"u\", \"a\", or \"i\"");
01299         return NULL;
01300     } else if (how && !strcmp(how, "u"))
01301         isUpgrade = 1;
01302 
01303     if (how && !strcmp(how, "a"))
01304         rpmtransAvailablePackage(s->ts, h->h, key);
01305     else
01306         rpmtransAddPackage(s->ts, h->h, NULL, key, isUpgrade, NULL);
01307 
01308     /* This should increment the usage count for me */
01309     if (key) {
01310         PyList_Append(s->keyList, key);
01311     }
01312 
01313     Py_INCREF(Py_None);
01314     return Py_None;
01315 }
01316 
01319 static PyObject * rpmtransRemove(rpmtransObject * s, PyObject * args) {
01320     char * name;
01321     int count;
01322     rpmdbMatchIterator mi;
01323     
01324     if (!PyArg_ParseTuple(args, "s", &name))
01325         return NULL;
01326 
01327     /* XXX: Copied hack from ../lib/rpminstall.c, rpmErase() */
01328     mi = rpmdbInitIterator(s->dbo->db, RPMDBI_LABEL, name, 0);
01329     count = rpmdbGetIteratorCount(mi);
01330     if (count <= 0) {
01331         PyErr_SetString(pyrpmError, "package not installed");
01332         return NULL;
01333     } else { /* XXX: Note that we automatically choose to remove all matches */
01334         Header h;
01335         while ((h = rpmdbNextIterator(mi)) != NULL) {
01336             unsigned int recOffset = rpmdbGetIteratorOffset(mi);
01337             if (recOffset) {
01338                 rpmtransRemovePackage(s->ts, recOffset);
01339             }
01340         }
01341     }
01342     rpmdbFreeIterator(mi);
01343 
01344     Py_INCREF(Py_None);
01345     return Py_None;
01346 }
01347 
01350 static PyObject * rpmtransDepCheck(rpmtransObject * s, PyObject * args) {
01351     rpmDependencyConflict conflicts;
01352     int numConflicts;
01353     PyObject * list, * cf;
01354     int i;
01355 
01356     if (!PyArg_ParseTuple(args, "")) return NULL;
01357 
01358     rpmdepCheck(s->ts, &conflicts, &numConflicts);
01359     if (numConflicts) {
01360         list = PyList_New(0);
01361 
01362         /* XXX TODO: rpmlib-4.0.3 can return multiple suggested packages. */
01363         for (i = 0; i < numConflicts; i++) {
01364             cf = Py_BuildValue("((sss)(ss)iOi)", conflicts[i].byName,
01365                                conflicts[i].byVersion, conflicts[i].byRelease,
01366 
01367                                conflicts[i].needsName,
01368                                conflicts[i].needsVersion,
01369 
01370                                conflicts[i].needsFlags,
01371                                conflicts[i].suggestedPackages ?
01372                                    conflicts[i].suggestedPackages[0] : Py_None,
01373                                conflicts[i].sense);
01374             PyList_Append(list, (PyObject *) cf);
01375             Py_DECREF(cf);
01376         }
01377 
01378         conflicts = rpmdepFreeConflicts(conflicts, numConflicts);
01379 
01380         return list;
01381     }
01382 
01383     Py_INCREF(Py_None);
01384     return Py_None;
01385 }
01386 
01389 static PyObject * rpmtransOrder(rpmtransObject * s, PyObject * args) {
01390     if (!PyArg_ParseTuple(args, "")) return NULL;
01391 
01392     rpmdepOrder(s->ts);
01393 
01394     Py_INCREF(Py_None);
01395     return Py_None;
01396 }
01397 
01400 static PyObject * py_rpmtransGetKeys(rpmtransObject * s, PyObject * args) {
01401     const void **data = NULL;
01402     int num, i;
01403     PyObject *tuple;
01404 
01405     rpmtransGetKeys(s->ts, &data, &num);
01406     if (data == NULL) {
01407         Py_INCREF(Py_None);
01408         return Py_None;
01409     }
01410 
01411     tuple = PyTuple_New(num);
01412 
01413     for (i = 0; i < num; i++) {
01414         PyObject *obj = (PyObject *) data[i];
01415         Py_INCREF(obj);
01416         PyTuple_SetItem(tuple, i, obj);
01417     }
01418 
01419     free (data);
01420 
01421     return tuple;
01422 }
01423 
01426 struct tsCallbackType {
01427     PyObject * cb;
01428     PyObject * data;
01429     int pythonError;
01430 };
01431 
01435 static Header transactionSetHeader = NULL;
01436 
01439 static void * tsCallback(const void * hd, const rpmCallbackType what,
01440                          const unsigned long amount, const unsigned long total,
01441                          const void * pkgKey, rpmCallbackData data) {
01442     struct tsCallbackType * cbInfo = data;
01443     PyObject * args, * result;
01444     int fd;
01445     static FD_t fdt;
01446     const Header h = (Header) hd;
01447 
01448     if (cbInfo->pythonError) return NULL;
01449 
01450     if (!pkgKey) pkgKey = Py_None;
01451     transactionSetHeader = h;    
01452 
01453     args = Py_BuildValue("(illOO)", what, amount, total, pkgKey, cbInfo->data);
01454     result = PyEval_CallObject(cbInfo->cb, args);
01455     Py_DECREF(args);
01456 
01457     if (!result) {
01458         cbInfo->pythonError = 1;
01459         return NULL;
01460     }
01461 
01462     if (what == RPMCALLBACK_INST_OPEN_FILE) {
01463         if (!PyArg_Parse(result, "i", &fd)) {
01464             cbInfo->pythonError = 1;
01465             return NULL;
01466         }
01467         fdt = fdDup(fd);
01468         
01469         Py_DECREF(result);
01470         return fdt;
01471     }
01472 
01473     if (what == RPMCALLBACK_INST_CLOSE_FILE) {
01474         Fclose (fdt);
01475     }
01476 
01477     Py_DECREF(result);
01478 
01479     return NULL;
01480 }
01481 
01484 static PyObject * rpmtransRun(rpmtransObject * s, PyObject * args) {
01485     int flags, ignoreSet;
01486     int rc, i;
01487     PyObject * list, * prob;
01488     rpmProblemSet probs;
01489     struct tsCallbackType cbInfo;
01490 
01491     if (!PyArg_ParseTuple(args, "iiOO", &flags, &ignoreSet, &cbInfo.cb,
01492                           &cbInfo.data))
01493         return NULL;
01494 
01495     cbInfo.pythonError = 0;
01496 
01497     rc = rpmRunTransactions(s->ts, tsCallback, &cbInfo, NULL, &probs, flags,
01498                             ignoreSet);
01499 
01500     if (cbInfo.pythonError) {
01501         if (rc > 0)
01502             rpmProblemSetFree(probs);
01503         return NULL;
01504     }
01505 
01506     if (rc < 0) {
01507         list = PyList_New(0);
01508         return list;
01509     } else if (!rc) {
01510         Py_INCREF(Py_None);
01511         return Py_None;
01512     }
01513 
01514     list = PyList_New(0);
01515     for (i = 0; i < probs->numProblems; i++) {
01516         rpmProblem myprob = probs->probs + i;
01517         prob = Py_BuildValue("s(isi)", rpmProblemString(myprob),
01518                              myprob->type,
01519                              myprob->str1,
01520                              myprob->ulong1);
01521         PyList_Append(list, prob);
01522         Py_DECREF(prob);
01523     }
01524 
01525     rpmProblemSetFree(probs);
01526 
01527     return list;
01528 }
01529 
01532 static struct PyMethodDef rpmtransMethods[] = {
01533         {"add",         (PyCFunction) rpmtransAdd,      1 },
01534         {"remove",      (PyCFunction) rpmtransRemove,   1 },
01535         {"depcheck",    (PyCFunction) rpmtransDepCheck, 1 },
01536         {"order",       (PyCFunction) rpmtransOrder,    1 },
01537         {"getKeys",     (PyCFunction) py_rpmtransGetKeys, 1 },
01538         {"run",         (PyCFunction) rpmtransRun, 1 },
01539         {NULL,          NULL}           /* sentinel */
01540 };
01541 
01544 static PyObject * rpmtransGetAttr(rpmtransObject * o, char * name) {
01545     return Py_FindMethod(rpmtransMethods, (PyObject *) o, name);
01546 }
01547 
01550 static void rpmtransDealloc(PyObject * o) {
01551     rpmtransObject * trans = (void *) o;
01552 
01553     rpmtransFree(trans->ts);
01554     if (trans->dbo) {
01555         Py_DECREF(trans->dbo);
01556     }
01557     if (trans->scriptFd) Fclose(trans->scriptFd);
01558     /* this will free the keyList, and decrement the ref count of all
01559        the items on the list as well :-) */
01560     Py_DECREF(trans->keyList);
01561     PyMem_DEL(o);
01562 }
01563 
01566 static int rpmtransSetAttr(rpmtransObject * o, char * name,
01567                            PyObject * val) {
01568     int i;
01569 
01570     if (!strcmp(name, "scriptFd")) {
01571         if (!PyArg_Parse(val, "i", &i)) return 0;
01572         if (i < 0) {
01573             PyErr_SetString(PyExc_TypeError, "bad file descriptor");
01574             return -1;
01575         } else {
01576             o->scriptFd = fdDup(i);
01577             rpmtransSetScriptFd(o->ts, o->scriptFd);
01578         }
01579     } else {
01580         PyErr_SetString(PyExc_AttributeError, name);
01581         return -1;
01582     }
01583 
01584     return 0;
01585 }
01586 
01589 static PyTypeObject rpmtransType = {
01590         PyObject_HEAD_INIT(NULL)
01591         0,                              /* ob_size */
01592         "rpmtrans",                     /* tp_name */
01593         sizeof(rpmtransObject),         /* tp_size */
01594         0,                              /* tp_itemsize */
01595         (destructor) rpmtransDealloc,   /* tp_dealloc */
01596         0,                              /* tp_print */
01597         (getattrfunc) rpmtransGetAttr,  /* tp_getattr */
01598         (setattrfunc) rpmtransSetAttr,  /* tp_setattr */
01599         0,                              /* tp_compare */
01600         0,                              /* tp_repr */
01601         0,                              /* tp_as_number */
01602         0,                              /* tp_as_sequence */
01603         0,                              /* tp_as_mapping */
01604 };
01605 
01612 
01615 static PyObject * rpmtransCreate(PyObject * self, PyObject * args) {
01616     rpmtransObject * o;
01617     rpmdbObject * db = NULL;
01618     char * rootPath = "/";
01619 
01620     if (!PyArg_ParseTuple(args, "|sO", &rootPath, &db)) return NULL;
01621     if (db && db->ob_type != &rpmdbType) {
01622         PyErr_SetString(PyExc_TypeError, "bad type for database argument");
01623         return NULL;
01624     }
01625 
01626     o = (void *) PyObject_NEW(rpmtransObject, &rpmtransType);
01627 
01628     Py_XINCREF(db);
01629     o->dbo = db;
01630     o->scriptFd = NULL;
01631     o->ts = rpmtransCreateSet(db ? db->db : NULL, rootPath);
01632     o->keyList = PyList_New(0);
01633 
01634     return (void *) o;
01635 }
01636 
01639 static PyObject * doAddMacro(PyObject * self, PyObject * args) {
01640     char * name, * val;
01641 
01642     if (!PyArg_ParseTuple(args, "ss", &name, &val))
01643         return NULL;
01644 
01645     addMacro(NULL, name, NULL, val, RMIL_DEFAULT);
01646 
01647     Py_INCREF(Py_None);
01648     return Py_None;
01649 }
01650 
01653 static PyObject * doDelMacro(PyObject * self, PyObject * args) {
01654     char * name;
01655 
01656     if (!PyArg_ParseTuple(args, "s", &name))
01657         return NULL;
01658 
01659     delMacro(NULL, name);
01660 
01661     Py_INCREF(Py_None);
01662     return Py_None;
01663 }
01664 
01667 static PyObject * archScore(PyObject * self, PyObject * args) {
01668     char * arch;
01669     int score;
01670 
01671     if (!PyArg_ParseTuple(args, "s", &arch))
01672         return NULL;
01673 
01674     score = rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch);
01675 
01676     return Py_BuildValue("i", score);
01677 }
01678 
01681 static int psGetArchScore(Header h) {
01682     void * pkgArch;
01683     int type, count;
01684 
01685     if (!headerGetEntry(h, RPMTAG_ARCH, &type, (void **) &pkgArch, &count) ||
01686         type == RPM_INT8_TYPE)
01687        return 150;
01688     else
01689         return rpmMachineScore(RPM_MACHTABLE_INSTARCH, pkgArch);
01690 }
01691 
01694 static int pkgCompareVer(void * first, void * second) {
01695     struct packageInfo ** a = first;
01696     struct packageInfo ** b = second;
01697     int ret, score1, score2;
01698 
01699     /* put packages w/o names at the end */
01700     if (!(*a)->name) return 1;
01701     if (!(*b)->name) return -1;
01702 
01703     ret = xstrcasecmp((*a)->name, (*b)->name);
01704     if (ret) return ret;
01705     score1 = psGetArchScore((*a)->h);
01706     if (!score1) return 1;
01707     score2 = psGetArchScore((*b)->h);
01708     if (!score2) return -1;
01709     if (score1 < score2) return -1;
01710     if (score1 > score2) return 1;
01711     return rpmVersionCompare((*b)->h, (*a)->h);
01712 }
01713 
01716 static void pkgSort(struct pkgSet * psp) {
01717     int i;
01718     char *name;
01719 
01720     if (psp->numPackages <= 0)
01721         return;
01722 
01723     qsort(psp->packages, psp->numPackages, sizeof(*psp->packages),
01724          (void *) pkgCompareVer);
01725 
01726     name = psp->packages[0]->name;
01727     if (!name) {
01728        psp->numPackages = 0;
01729        return;
01730     }
01731     for (i = 1; i < psp->numPackages; i++) {
01732        if (!psp->packages[i]->name) break;
01733        if (!strcmp(psp->packages[i]->name, name))
01734            psp->packages[i]->name = NULL;
01735        else
01736            name = psp->packages[i]->name;
01737     }
01738 
01739     qsort(psp->packages, psp->numPackages, sizeof(*psp->packages),
01740          (void *) pkgCompareVer);
01741 
01742     for (i = 0; i < psp->numPackages; i++)
01743        if (!psp->packages[i]->name) break;
01744     psp->numPackages = i;
01745 }
01746 
01749 static PyObject * findUpgradeSet(PyObject * self, PyObject * args) {
01750     PyObject * hdrList, * result;
01751     char * root = "/";
01752     int i;
01753     struct pkgSet list;
01754     hdrObject * hdr;
01755 
01756     if (!PyArg_ParseTuple(args, "O|s", &hdrList, &root)) return NULL;
01757 
01758     if (!PyList_Check(hdrList)) {
01759         PyErr_SetString(PyExc_TypeError, "list of headers expected");
01760         return NULL;
01761     }
01762 
01763     list.numPackages = PyList_Size(hdrList);
01764     list.packages = alloca(sizeof(list.packages) * list.numPackages);
01765     for (i = 0; i < list.numPackages; i++) {
01766         hdr = (hdrObject *) PyList_GetItem(hdrList, i);
01767         if (hdr->ob_type != &hdrType) {
01768             PyErr_SetString(PyExc_TypeError, "list of headers expected");
01769             return NULL;
01770         }
01771         list.packages[i] = alloca(sizeof(struct packageInfo));
01772         list.packages[i]->h = hdr->h;
01773         list.packages[i]->selected = 0;
01774         list.packages[i]->data = hdr;
01775 
01776         headerGetEntry(hdr->h, RPMTAG_NAME, NULL,
01777                       (void **) &list.packages[i]->name, NULL);
01778     }
01779 
01780     pkgSort (&list);
01781 
01782     if (ugFindUpgradePackages(&list, root)) {
01783         PyErr_SetString(pyrpmError, "error during upgrade check");
01784         return NULL;
01785     }
01786 
01787     result = PyList_New(0);
01788     for (i = 0; i < list.numPackages; i++) {
01789         if (list.packages[i]->selected) {
01790             PyList_Append(result, list.packages[i]->data);
01791 /*          Py_DECREF(list.packages[i]->data); */
01792         }
01793     }
01794 
01795     return result;
01796 }
01797 
01800 static PyObject * rpmHeaderFromPackage(PyObject * self, PyObject * args) {
01801     hdrObject * h;
01802     Header header;
01803     Header sigs;
01804     FD_t fd;
01805     int rawFd;
01806     int isSource = 0;
01807     rpmRC rc;
01808 
01809     if (!PyArg_ParseTuple(args, "i", &rawFd)) return NULL;
01810     fd = fdDup(rawFd);
01811 
01812     rc = rpmReadPackageInfo(fd, &sigs, &header);
01813     Fclose(fd);
01814 
01815     switch (rc) {
01816     case RPMRC_BADSIZE:
01817     case RPMRC_OK:
01818         h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
01819         h->h = header;
01820         h->sigs = sigs;
01821         h->fileList = h->linkList = h->md5list = NULL;
01822         h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
01823         h->modes = h->rdevs = NULL;
01824         if (headerIsEntry(header, RPMTAG_SOURCEPACKAGE))
01825             isSource = 1;
01826         break;
01827 
01828     case RPMRC_BADMAGIC:
01829         Py_INCREF(Py_None);
01830         h = (hdrObject *) Py_None;
01831         break;
01832 
01833     case RPMRC_FAIL:
01834     case RPMRC_SHORTREAD:
01835     default:
01836         PyErr_SetString(pyrpmError, "error reading package");
01837         return NULL;
01838     }
01839 
01840     return Py_BuildValue("(Ni)", h, isSource);
01841 }
01842 
01845 static PyObject * hdrLoad(PyObject * self, PyObject * args) {
01846     char * obj, * copy=NULL;
01847     Header hdr;
01848     hdrObject * h;
01849     int len;
01850 
01851     if (!PyArg_ParseTuple(args, "s#", &obj, &len)) return NULL;
01852     
01853     /* malloc is needed to avoid surprises from data swab in headerLoad(). */
01854     copy = malloc(len);
01855     if (copy == NULL) {
01856         PyErr_SetString(pyrpmError, "out of memory");
01857         return NULL;
01858     }
01859     memcpy (copy, obj, len);
01860 
01861     hdr = headerLoad(copy);
01862     if (!hdr) {
01863         PyErr_SetString(pyrpmError, "bad header");
01864         return NULL;
01865     }
01866     headerAllocated(hdr);
01867     compressFilelist (hdr);
01868     providePackageNVR (hdr);
01869 
01870     h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
01871     h->h = hdr;
01872     h->sigs = NULL;
01873     h->fileList = h->linkList = h->md5list = NULL;
01874     h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
01875     h->modes = h->rdevs = NULL;
01876 
01877     return (PyObject *) h;
01878 }
01879 
01882 static PyObject * rhnLoad(PyObject * self, PyObject * args) {
01883     char * obj, * copy=NULL;
01884     Header hdr;
01885     hdrObject * h;
01886     int len;
01887 
01888     if (!PyArg_ParseTuple(args, "s#", &obj, &len)) return NULL;
01889     
01890     /* malloc is needed to avoid surprises from data swab in headerLoad(). */
01891     copy = malloc(len);
01892     if (copy == NULL) {
01893         PyErr_SetString(pyrpmError, "out of memory");
01894         return NULL;
01895     }
01896     memcpy (copy, obj, len);
01897 
01898     hdr = headerLoad(copy);
01899     if (!hdr) {
01900         PyErr_SetString(pyrpmError, "bad header");
01901         return NULL;
01902     }
01903     headerAllocated(hdr);
01904 
01905     /* XXX avoid the false OK's from rpmverifyDigest() with missing tags. */
01906     if (!headerIsEntry(hdr, RPMTAG_HEADERIMMUTABLE)) {
01907         PyErr_SetString(pyrpmError, "bad header, not immutable");
01908         headerFree(hdr);
01909         return NULL;
01910     }
01911 
01912     /* XXX avoid the false OK's from rpmverifyDigest() with missing tags. */
01913     if (!headerIsEntry(hdr, RPMTAG_SHA1HEADER)
01914     &&  !headerIsEntry(hdr, RPMTAG_SHA1RHN)) {
01915         PyErr_SetString(pyrpmError, "bad header, no digest");
01916         headerFree(hdr);
01917         return NULL;
01918     }
01919 
01920     if (rpmVerifyDigest(hdr)) {
01921         PyErr_SetString(pyrpmError, "bad header, digest check failed");
01922         headerFree(hdr);
01923         return NULL;
01924     }
01925 
01926     h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
01927     h->h = hdr;
01928     h->sigs = NULL;
01929     h->fileList = h->linkList = h->md5list = NULL;
01930     h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
01931     h->modes = h->rdevs = NULL;
01932 
01933     return (PyObject *) h;
01934 }
01935 
01938 static PyObject * rpmInitDB(PyObject * self, PyObject * args) {
01939     char *root;
01940     int forWrite = 0;
01941 
01942     if (!PyArg_ParseTuple(args, "i|s", &forWrite, &root)) return NULL;
01943 
01944     if (rpmdbInit(root, forWrite ? O_RDWR | O_CREAT: O_RDONLY)) {
01945         char * errmsg = "cannot initialize database in %s";
01946         char * errstr = NULL;
01947         int errsize;
01948 
01949         errsize = strlen(errmsg) + strlen(root);
01950         errstr = alloca(errsize);
01951         snprintf(errstr, errsize, errmsg, root);
01952         PyErr_SetString(pyrpmError, errstr);
01953         return NULL;
01954     }
01955 
01956     Py_INCREF(Py_None);
01957     return(Py_None);
01958 }
01959 
01962 static rpmdbObject * rpmOpenDB(PyObject * self, PyObject * args) {
01963     rpmdbObject * o;
01964     char * root = "";
01965     int forWrite = 0;
01966 
01967     if (!PyArg_ParseTuple(args, "|is", &forWrite, &root)) return NULL;
01968 
01969     o = PyObject_NEW(rpmdbObject, &rpmdbType);
01970     o->db = NULL;
01971     o->offx = 0;
01972     o->noffs = 0;
01973     o->offsets = NULL;
01974 
01975     if (rpmdbOpen(root, &o->db, forWrite ? O_RDWR | O_CREAT: O_RDONLY, 0644)) {
01976         char * errmsg = "cannot open database in %s";
01977         char * errstr = NULL;
01978         int errsize;
01979 
01980         Py_DECREF(o);
01981         /* PyErr_SetString should take varargs... */
01982         errsize = strlen(errmsg) + *root == '\0' ? 15 /* "/var/lib/rpm" */ : strlen(root);
01983         errstr = alloca(errsize);
01984         snprintf(errstr, errsize, errmsg, *root == '\0' ? "/var/lib/rpm" : root);
01985         PyErr_SetString(pyrpmError, errstr);
01986         return NULL;
01987     }
01988 
01989     return o;
01990 }
01991 
01994 static PyObject * rebuildDB (PyObject * self, PyObject * args) {
01995     char * root = "";
01996 
01997     if (!PyArg_ParseTuple(args, "s", &root)) return NULL;
01998 
01999     return Py_BuildValue("i", rpmdbRebuild(root));
02000 }
02001 
02004 static PyObject * rpmReadHeaders (FD_t fd) {
02005     PyObject * list;
02006     Header header;
02007     hdrObject * h;
02008 
02009     if (!fd) {
02010         PyErr_SetFromErrno(pyrpmError);
02011         return NULL;
02012     }
02013 
02014     list = PyList_New(0);
02015     Py_BEGIN_ALLOW_THREADS
02016     header = headerRead(fd, HEADER_MAGIC_YES);
02017 
02018     Py_END_ALLOW_THREADS
02019     while (header) {
02020         compressFilelist (header);
02021         providePackageNVR (header);
02022         h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
02023         h->h = header;
02024         h->sigs = NULL;
02025         h->fileList = h->linkList = h->md5list = NULL;
02026         h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
02027         h->modes = h->rdevs = NULL;
02028         if (PyList_Append(list, (PyObject *) h)) {
02029             Py_DECREF(list);
02030             Py_DECREF(h);
02031             return NULL;
02032         }
02033 
02034         Py_DECREF(h);
02035 
02036         Py_BEGIN_ALLOW_THREADS
02037         header = headerRead(fd, HEADER_MAGIC_YES);
02038         Py_END_ALLOW_THREADS
02039     }
02040 
02041     return list;
02042 }
02043 
02046 static PyObject * rpmHeaderFromFD(PyObject * self, PyObject * args) {
02047     FD_t fd;
02048     int fileno;
02049     PyObject * list;
02050 
02051     if (!PyArg_ParseTuple(args, "i", &fileno)) return NULL;
02052     fd = fdDup(fileno);
02053 
02054     list = rpmReadHeaders (fd);
02055     Fclose(fd);
02056 
02057     return list;
02058 }
02059 
02062 static PyObject * rpmHeaderFromFile(PyObject * self, PyObject * args) {
02063     char * filespec;
02064     FD_t fd;
02065     PyObject * list;
02066 
02067     if (!PyArg_ParseTuple(args, "s", &filespec)) return NULL;
02068     fd = Fopen(filespec, "r.fdio");
02069 
02070     if (!fd) {
02071         PyErr_SetFromErrno(pyrpmError);
02072         return NULL;
02073     }
02074 
02075     list = rpmReadHeaders (fd);
02076     Fclose(fd);
02077 
02078     return list;
02079 }
02080 
02085 static int rpmMergeHeaders(PyObject * list, FD_t fd, int matchTag) {
02086     Header newH;
02087     HeaderIterator iter;
02088     int_32 * newMatch, * oldMatch;
02089     hdrObject * ho;
02090     int count = 0;
02091     int type, c, tag;
02092     void * p;
02093 
02094     Py_BEGIN_ALLOW_THREADS
02095     newH = headerRead(fd, HEADER_MAGIC_YES);
02096 
02097     Py_END_ALLOW_THREADS
02098     while (newH) {
02099         if (!headerGetEntry(newH, matchTag, NULL, (void **) &newMatch, NULL)) {
02100             PyErr_SetString(pyrpmError, "match tag missing in new header");
02101             return 1;
02102         }
02103 
02104         ho = (hdrObject *) PyList_GetItem(list, count++);
02105         if (!ho) return 1;
02106 
02107         if (!headerGetEntry(ho->h, matchTag, NULL, (void **) &oldMatch, NULL)) {
02108             PyErr_SetString(pyrpmError, "match tag missing in new header");
02109             return 1;
02110         }
02111 
02112         if (*newMatch != *oldMatch) {
02113             PyErr_SetString(pyrpmError, "match tag mismatch");
02114             return 1;
02115         }
02116 
02117         if (ho->sigs) headerFree(ho->sigs);
02118         if (ho->md5list) free(ho->md5list);
02119         if (ho->fileList) free(ho->fileList);
02120         if (ho->linkList) free(ho->linkList);
02121 
02122         ho->sigs = NULL;
02123         ho->md5list = NULL;
02124         ho->fileList = NULL;
02125         ho->linkList = NULL;
02126 
02127         iter = headerInitIterator(newH);
02128 
02129         while (headerNextIterator(iter, &tag, &type, (void *) &p, &c)) {
02130             /* could be dupes */
02131             headerRemoveEntry(ho->h, tag);
02132             headerAddEntry(ho->h, tag, type, p, c);
02133             headerFreeData(p, type);
02134         }
02135 
02136         headerFreeIterator(iter);
02137 
02138         Py_BEGIN_ALLOW_THREADS
02139         newH = headerRead(fd, HEADER_MAGIC_YES);
02140         Py_END_ALLOW_THREADS
02141     }
02142 
02143     return 0;
02144 }
02145 
02146 static PyObject * rpmMergeHeadersFromFD(PyObject * self, PyObject * args) {
02147     FD_t fd;
02148     int fileno;
02149     PyObject * list;
02150     int rc;
02151     int matchTag;
02152 
02153     if (!PyArg_ParseTuple(args, "Oii", &list, &fileno, &matchTag)) return NULL;
02154 
02155     if (!PyList_Check(list)) {
02156         PyErr_SetString(PyExc_TypeError, "first parameter must be a list");
02157         return NULL;
02158     }
02159 
02160     fd = fdDup(fileno);
02161 
02162     rc = rpmMergeHeaders (list, fd, matchTag);
02163     Fclose(fd);
02164 
02165     if (rc) {
02166         return NULL;
02167     }
02168 
02169     Py_INCREF(Py_None);
02170     return Py_None;
02171 }
02172 
02173 
02176 static PyObject * errorCB = NULL, * errorData = NULL;
02177 
02180 static void errorcb (void)
02181 {
02182     PyObject * result, * args = NULL;
02183 
02184     if (errorData)
02185         args = Py_BuildValue("(O)", errorData);
02186 
02187     result = PyEval_CallObject(errorCB, args);
02188     Py_XDECREF(args);
02189 
02190     if (result == NULL) {
02191         PyErr_Print();
02192         PyErr_Clear();
02193     }
02194     Py_DECREF (result);
02195 }
02196 
02199 static PyObject * errorSetCallback (PyObject * self, PyObject * args) {
02200     PyObject *newCB = NULL, *newData = NULL;
02201 
02202     if (!PyArg_ParseTuple(args, "O|O", &newCB, &newData)) return NULL;
02203 
02204     /* if we're getting a void*, set the error callback to this. */
02205     /* also, we can possibly decref any python callbacks we had  */
02206     /* and set them to NULL.                                     */
02207     if (PyCObject_Check (newCB)) {
02208         rpmErrorSetCallback (PyCObject_AsVoidPtr(newCB));
02209 
02210         Py_XDECREF (errorCB);
02211         Py_XDECREF (errorData);
02212 
02213         errorCB   = NULL;
02214         errorData = NULL;
02215         
02216         Py_INCREF(Py_None);
02217         return Py_None;
02218     }
02219     
02220     if (!PyCallable_Check (newCB)) {
02221         PyErr_SetString(PyExc_TypeError, "parameter must be callable");
02222         return NULL;
02223     }
02224 
02225     Py_XDECREF(errorCB);
02226     Py_XDECREF(errorData);
02227 
02228     errorCB = newCB;
02229     errorData = newData;
02230     
02231     Py_INCREF (errorCB);
02232     Py_XINCREF (errorData);
02233 
02234     return PyCObject_FromVoidPtr(rpmErrorSetCallback (errorcb), NULL);
02235 }
02236 
02239 static PyObject * errorString (PyObject * self, PyObject * args) {
02240     return PyString_FromString(rpmErrorString ());
02241 }
02242 
02245 static PyObject * versionCompare (PyObject * self, PyObject * args) {
02246     hdrObject * h1, * h2;
02247 
02248     if (!PyArg_ParseTuple(args, "O!O!", &hdrType, &h1, &hdrType, &h2)) return NULL;
02249 
02250     return Py_BuildValue("i", rpmVersionCompare(h1->h, h2->h));
02251 }
02252 
02255 static PyObject * labelCompare (PyObject * self, PyObject * args) {
02256     char *v1, *r1, *e1, *v2, *r2, *e2;
02257     int rc;
02258 
02259     if (!PyArg_ParseTuple(args, "(zzz)(zzz)",
02260                           &e1, &v1, &r1,
02261                           &e2, &v2, &r2)) return NULL;
02262 
02263     if (e1 && !e2)
02264         return Py_BuildValue("i", 1);
02265     else if (!e1 && e2)
02266         return Py_BuildValue("i", -1);
02267     else if (e1 && e2) {
02268         int ep1, ep2;
02269         ep1 = atoi (e1);
02270         ep2 = atoi (e2);
02271         if (ep1 < ep2)
02272             return Py_BuildValue("i", -1);
02273         else if (ep1 > ep2)
02274             return Py_BuildValue("i", 1);
02275     }
02276 
02277     rc = rpmvercmp(v1, v2);
02278     if (rc)
02279         return Py_BuildValue("i", rc);
02280 
02281     return Py_BuildValue("i", rpmvercmp(r1, r2));
02282 }
02283 
02286 static PyObject * checkSig (PyObject * self, PyObject * args) {
02287     char * filename;
02288     int flags;
02289     int rc = 255;
02290 
02291     if (PyArg_ParseTuple(args, "si", &filename, &flags)) {
02292         const char *av[2];
02293         av[0] = filename;
02294         av[1] = NULL;
02295         rc = rpmCheckSig(flags, av);
02296     }
02297     return Py_BuildValue("i", rc);
02298 }
02299 
02300 /* hack to get the current header that's in the transaction set */
02303 static PyObject * getTsHeader (PyObject * self, PyObject * args) {
02304     hdrObject * h;
02305     
02306     if (transactionSetHeader) {
02307         h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
02308         h->h = headerLink(transactionSetHeader);
02309         h->sigs = NULL;
02310         h->fileList = h->linkList = h->md5list = NULL;
02311         h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
02312         h->modes = h->rdevs = NULL;
02313         return (PyObject *) h;
02314     }
02315     Py_INCREF(Py_None);
02316     return (PyObject *) Py_None;
02317 }
02318 
02321 typedef struct FDlist_t FDlist;
02322 
02325 struct FDlist_t {
02326     FILE *f;
02327     FD_t fd;
02328     char *note;
02329     FDlist *next;
02330 } ;
02331 
02334 static FDlist *fdhead = NULL;
02335 
02338 static FDlist *fdtail = NULL;
02339 
02342 static int closeCallback(FILE * f) {
02343     FDlist *node, *last;
02344 
02345     printf ("close callback on %p\n", f);
02346     
02347     node = fdhead;
02348     last = NULL;
02349     while (node) {
02350         if (node->f == f)
02351             break;
02352         last = node;
02353         node = node->next;
02354     }
02355     if (node) {
02356         if (last)
02357             last->next = node->next;
02358         else
02359             fdhead = node->next;
02360         printf ("closing %s %p\n", node->note, node->fd);
02361         free (node->note);
02362         node->fd = fdLink(node->fd, "closeCallback");
02363         Fclose (node->fd);
02364         while (node->fd)
02365             node->fd = fdFree(node->fd, "closeCallback");
02366         free (node);
02367     }
02368     return 0; 
02369 }
02370 
02373 static PyObject * doFopen(PyObject * self, PyObject * args) {
02374     char * path, * mode;
02375     FDlist *node;
02376     
02377     if (!PyArg_ParseTuple(args, "ss", &path, &mode))
02378         return NULL;
02379     
02380     node = malloc (sizeof(FDlist));
02381     
02382     node->fd = Fopen(path, mode);
02383     node->fd = fdLink(node->fd, "doFopen");
02384     node->note = strdup (path);
02385 
02386     if (!node->fd) {
02387         PyErr_SetFromErrno(pyrpmError);
02388         free (node);
02389         return NULL;
02390     }
02391     
02392     if (Ferror(node->fd)) {
02393         const char *err = Fstrerror(node->fd);
02394         free(node);
02395         if (err) {
02396             PyErr_SetString(pyrpmError, err);
02397             return NULL;
02398         }
02399     }
02400     node->f = fdGetFp(node->fd);
02401     printf ("opening %s fd = %p f = %p\n", node->note, node->fd, node->f);
02402     if (!node->f) {
02403         PyErr_SetString(pyrpmError, "FD_t has no FILE*");
02404         free(node);
02405         return NULL;
02406     }
02407 
02408     node->next = NULL;
02409     if (!fdhead) {
02410         fdhead = fdtail = node;
02411     } else if (fdtail) {
02412         fdtail->next = node;
02413     } else {
02414         fdhead = node;
02415     }
02416     fdtail = node;
02417     
02418     return PyFile_FromFile (node->f, path, mode, closeCallback);
02419 }
02420 
02423 static PyMethodDef rpmModuleMethods[] = {
02424     { "TransactionSet", (PyCFunction) rpmtransCreate, METH_VARARGS, NULL },
02425     { "addMacro", (PyCFunction) doAddMacro, METH_VARARGS, NULL },
02426     { "delMacro", (PyCFunction) doDelMacro, METH_VARARGS, NULL },
02427     { "archscore", (PyCFunction) archScore, METH_VARARGS, NULL },
02428     { "findUpgradeSet", (PyCFunction) findUpgradeSet, METH_VARARGS, NULL },
02429     { "headerFromPackage", (PyCFunction) rpmHeaderFromPackage, METH_VARARGS, NULL },
02430     { "headerLoad", (PyCFunction) hdrLoad, METH_VARARGS, NULL },
02431     { "rhnLoad", (PyCFunction) rhnLoad, METH_VARARGS, NULL },
02432     { "initdb", (PyCFunction) rpmInitDB, METH_VARARGS, NULL },
02433     { "opendb", (PyCFunction) rpmOpenDB, METH_VARARGS, NULL },
02434     { "rebuilddb", (PyCFunction) rebuildDB, METH_VARARGS, NULL },
02435     { "mergeHeaderListFromFD", (PyCFunction) rpmMergeHeadersFromFD, METH_VARARGS, NULL },
02436     { "readHeaderListFromFD", (PyCFunction) rpmHeaderFromFD, METH_VARARGS, NULL },
02437     { "readHeaderListFromFile", (PyCFunction) rpmHeaderFromFile, METH_VARARGS, NULL },
02438     { "errorSetCallback", (PyCFunction) errorSetCallback, METH_VARARGS, NULL },
02439     { "errorString", (PyCFunction) errorString, METH_VARARGS, NULL },
02440     { "versionCompare", (PyCFunction) versionCompare, METH_VARARGS, NULL },
02441     { "labelCompare", (PyCFunction) labelCompare, METH_VARARGS, NULL },
02442     { "checksig", (PyCFunction) checkSig, METH_VARARGS, NULL },
02443     { "getTransactionCallbackHeader", (PyCFunction) getTsHeader, METH_VARARGS, NULL },
02444 /*      { "Fopen", (PyCFunction) doFopen, METH_VARARGS, NULL }, */
02445     { NULL }
02446 } ;
02447 
02450 void initrpm(void) {
02451     PyObject * m, * d, *o, * tag = NULL, * dict;
02452     int i;
02453     const struct headerSprintfExtension_s * extensions = rpmHeaderFormats;
02454     struct headerSprintfExtension_s * ext;
02455 
02456     m = Py_InitModule("rpm", rpmModuleMethods);
02457 
02458     hdrType.ob_type = &PyType_Type;
02459     rpmdbMIType.ob_type = &PyType_Type;
02460     rpmdbType.ob_type = &PyType_Type;
02461     rpmtransType.ob_type = &PyType_Type;
02462 
02463     if(!m)
02464         return;
02465 
02466 /*      _rpmio_debug = -1; */
02467     rpmReadConfigFiles(NULL, NULL);
02468 
02469     d = PyModule_GetDict(m);
02470 
02471     pyrpmError = PyString_FromString("rpm.error");
02472     PyDict_SetItemString(d, "error", pyrpmError);
02473     Py_DECREF(pyrpmError);
02474 
02475     dict = PyDict_New();
02476 
02477     for (i = 0; i < rpmTagTableSize; i++) {
02478         tag = PyInt_FromLong(rpmTagTable[i].val);
02479         PyDict_SetItemString(d, (char *) rpmTagTable[i].name, tag);
02480         Py_DECREF(tag);
02481         PyDict_SetItem(dict, tag, o=PyString_FromString(rpmTagTable[i].name + 7));
02482         Py_DECREF(o);
02483     }
02484 
02485     while (extensions->name) {
02486         if (extensions->type == HEADER_EXT_TAG) {
02487             (const struct headerSprintfExtension *) ext = extensions;
02488             PyDict_SetItemString(d, extensions->name, o=PyCObject_FromVoidPtr(ext, NULL));
02489             Py_DECREF(o);
02490             PyDict_SetItem(dict, tag, o=PyString_FromString(ext->name + 7));
02491             Py_DECREF(o);    
02492         }
02493         extensions++;
02494     }
02495 
02496     PyDict_SetItemString(d, "tagnames", dict);
02497     Py_DECREF(dict);
02498 
02499 
02500 #define REGISTER_ENUM(val) \
02501     PyDict_SetItemString(d, #val, o=PyInt_FromLong( val )); \
02502     Py_DECREF(o);
02503     
02504     REGISTER_ENUM(RPMFILE_STATE_NORMAL);
02505     REGISTER_ENUM(RPMFILE_STATE_REPLACED);
02506     REGISTER_ENUM(RPMFILE_STATE_NOTINSTALLED);
02507     REGISTER_ENUM(RPMFILE_STATE_NETSHARED);
02508 
02509     REGISTER_ENUM(RPMFILE_CONFIG);
02510     REGISTER_ENUM(RPMFILE_DOC);
02511     REGISTER_ENUM(RPMFILE_MISSINGOK);
02512     REGISTER_ENUM(RPMFILE_NOREPLACE);
02513     REGISTER_ENUM(RPMFILE_GHOST);
02514     REGISTER_ENUM(RPMFILE_LICENSE);
02515     REGISTER_ENUM(RPMFILE_README);
02516 
02517     REGISTER_ENUM(RPMDEP_SENSE_REQUIRES);
02518     REGISTER_ENUM(RPMDEP_SENSE_CONFLICTS);
02519 
02520     REGISTER_ENUM(RPMSENSE_SERIAL);
02521     REGISTER_ENUM(RPMSENSE_LESS);
02522     REGISTER_ENUM(RPMSENSE_GREATER);
02523     REGISTER_ENUM(RPMSENSE_EQUAL);
02524     REGISTER_ENUM(RPMSENSE_PREREQ);
02525     REGISTER_ENUM(RPMSENSE_INTERP);
02526     REGISTER_ENUM(RPMSENSE_SCRIPT_PRE);
02527     REGISTER_ENUM(RPMSENSE_SCRIPT_POST);
02528     REGISTER_ENUM(RPMSENSE_SCRIPT_PREUN);
02529     REGISTER_ENUM(RPMSENSE_SCRIPT_POSTUN);
02530     REGISTER_ENUM(RPMSENSE_SCRIPT_VERIFY);
02531     REGISTER_ENUM(RPMSENSE_FIND_REQUIRES);
02532     REGISTER_ENUM(RPMSENSE_FIND_PROVIDES);
02533     REGISTER_ENUM(RPMSENSE_TRIGGERIN);
02534     REGISTER_ENUM(RPMSENSE_TRIGGERUN);
02535     REGISTER_ENUM(RPMSENSE_TRIGGERPOSTUN);
02536     REGISTER_ENUM(RPMSENSE_MULTILIB);
02537     REGISTER_ENUM(RPMSENSE_SCRIPT_PREP);
02538     REGISTER_ENUM(RPMSENSE_SCRIPT_BUILD);
02539     REGISTER_ENUM(RPMSENSE_SCRIPT_INSTALL);
02540     REGISTER_ENUM(RPMSENSE_SCRIPT_CLEAN);
02541     REGISTER_ENUM(RPMSENSE_RPMLIB);
02542     REGISTER_ENUM(RPMSENSE_TRIGGERPREIN);
02543 
02544     REGISTER_ENUM(RPMTRANS_FLAG_TEST);
02545     REGISTER_ENUM(RPMTRANS_FLAG_BUILD_PROBS);
02546     REGISTER_ENUM(RPMTRANS_FLAG_NOSCRIPTS);
02547     REGISTER_ENUM(RPMTRANS_FLAG_JUSTDB);
02548     REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERS);
02549     REGISTER_ENUM(RPMTRANS_FLAG_NODOCS);
02550     REGISTER_ENUM(RPMTRANS_FLAG_ALLFILES);
02551     REGISTER_ENUM(RPMTRANS_FLAG_KEEPOBSOLETE);
02552     REGISTER_ENUM(RPMTRANS_FLAG_MULTILIB);
02553 
02554     REGISTER_ENUM(RPMPROB_FILTER_IGNOREOS);
02555     REGISTER_ENUM(RPMPROB_FILTER_IGNOREARCH);
02556     REGISTER_ENUM(RPMPROB_FILTER_REPLACEPKG);
02557     REGISTER_ENUM(RPMPROB_FILTER_FORCERELOCATE);
02558     REGISTER_ENUM(RPMPROB_FILTER_REPLACENEWFILES);
02559     REGISTER_ENUM(RPMPROB_FILTER_REPLACEOLDFILES);
02560     REGISTER_ENUM(RPMPROB_FILTER_OLDPACKAGE);
02561     REGISTER_ENUM(RPMPROB_FILTER_DISKSPACE);
02562     REGISTER_ENUM(RPMPROB_FILTER_DISKNODES);
02563 
02564     REGISTER_ENUM(RPMCALLBACK_INST_PROGRESS);
02565     REGISTER_ENUM(RPMCALLBACK_INST_START);
02566     REGISTER_ENUM(RPMCALLBACK_INST_OPEN_FILE);
02567     REGISTER_ENUM(RPMCALLBACK_INST_CLOSE_FILE);
02568     REGISTER_ENUM(RPMCALLBACK_TRANS_PROGRESS);
02569     REGISTER_ENUM(RPMCALLBACK_TRANS_START);
02570     REGISTER_ENUM(RPMCALLBACK_TRANS_STOP);
02571     REGISTER_ENUM(RPMCALLBACK_UNINST_PROGRESS);
02572     REGISTER_ENUM(RPMCALLBACK_UNINST_START);
02573     REGISTER_ENUM(RPMCALLBACK_UNINST_STOP);
02574 
02575     REGISTER_ENUM(RPMPROB_BADARCH);
02576     REGISTER_ENUM(RPMPROB_BADOS);
02577     REGISTER_ENUM(RPMPROB_PKG_INSTALLED);
02578     REGISTER_ENUM(RPMPROB_BADRELOCATE);
02579     REGISTER_ENUM(RPMPROB_REQUIRES);
02580     REGISTER_ENUM(RPMPROB_CONFLICT);
02581     REGISTER_ENUM(RPMPROB_NEW_FILE_CONFLICT);
02582     REGISTER_ENUM(RPMPROB_FILE_CONFLICT);
02583     REGISTER_ENUM(RPMPROB_OLDPACKAGE);
02584     REGISTER_ENUM(RPMPROB_DISKSPACE);
02585     REGISTER_ENUM(RPMPROB_DISKNODES);
02586     REGISTER_ENUM(RPMPROB_BADPRETRANS);
02587 
02588     REGISTER_ENUM(CHECKSIG_PGP);
02589     REGISTER_ENUM(CHECKSIG_GPG);
02590     REGISTER_ENUM(CHECKSIG_MD5);
02591 }
02592 

Generated at Wed Mar 27 03:56:52 2002 for rpm by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001