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

Generated at Fri Feb 15 10:35:59 2002 for rpm by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001