python/rpmmodule.c

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

Generated on Wed Feb 13 14:05:38 2008 for rpm by  doxygen 1.5.2