Main Page   Modules   Compound List   File List   Compound Members   File Members   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 <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 
00015 #include "Python.h"
00016 #include "rpmlib.h"
00017 #include "misc.h"
00018 #include "rpmmacro.h"
00019 #include "upgrade.h"
00020 
00021 extern int _rpmio_debug;
00022 
00023 extern int mdfile(const char *fn, unsigned char *digest);
00024 
00025 void initrpm(void);
00026 
00027 /* from lib/misc.c */
00028 int rpmvercmp(const char * one, const char * two);
00029 
00030 
00033 typedef struct rpmdbObject_s rpmdbObject;
00034 
00037 typedef struct rpmdbMIObject_s rpmdbMIObject;
00038 
00041 typedef struct rpmtransObject_s rpmtransObject;
00042 
00045 typedef struct hdrObject_s hdrObject;
00046 
00049 static PyObject * pyrpmError;
00050 
00100 
00103 struct hdrObject_s {
00104     PyObject_HEAD;
00105     Header h;
00106     Header sigs;
00107     char ** md5list;
00108     char ** fileList;
00109     char ** linkList;
00110     int_32 * fileSizes;
00111     int_32 * mtimes;
00112     int_32 * uids, * gids;
00113     unsigned short * rdevs;
00114     unsigned short * modes;
00115 } ;
00116 
00119 static PyObject * hdrKeyList(hdrObject * s, PyObject * args) {
00120     PyObject * list, *o;
00121     HeaderIterator iter;
00122     int tag, type;
00123 
00124     if (!PyArg_ParseTuple(args, "")) return NULL;
00125 
00126     list = PyList_New(0);
00127 
00128     iter = headerInitIterator(s->h);
00129     while (headerNextIterator(iter, &tag, &type, NULL, NULL)) {
00130         if (tag == HEADER_I18NTABLE) continue;
00131 
00132         switch (type) {
00133           case RPM_BIN_TYPE:
00134           case RPM_INT32_TYPE:
00135           case RPM_CHAR_TYPE:
00136           case RPM_INT8_TYPE:
00137           case RPM_INT16_TYPE:
00138           case RPM_STRING_ARRAY_TYPE:
00139           case RPM_STRING_TYPE:
00140             PyList_Append(list, o=PyInt_FromLong(tag));
00141             Py_DECREF(o);
00142         }
00143     }
00144 
00145     headerFreeIterator(iter);
00146 
00147     return list;
00148 }
00149 
00152 static PyObject * hdrUnload(hdrObject * s, PyObject * args) {
00153     char * buf;
00154     int len;
00155     PyObject * rc;
00156 
00157     len = headerSizeof(s->h, 0);
00158     buf = headerUnload(s->h);
00159 
00160     rc = PyString_FromStringAndSize(buf, len);
00161     free(buf);
00162 
00163     return rc;
00164 }
00165 
00166 /* Returns a list of these tuple for each part which failed:
00167 
00168         (attr_name, correctValue, currentValue)
00169 
00170         It should be passwd the file number to verify.
00171 */
00174 static PyObject * hdrVerifyFile(hdrObject * s, PyObject * args) {
00175     int fileNumber;
00176     rpmVerifyAttrs verifyResult = 0;
00177     PyObject * list, * tuple, * attrName;
00178     int type, count;
00179     struct stat sb;
00180     char buf[2048];
00181     int i;
00182     time_t timeInt;
00183     struct tm * timeStruct;
00184 
00185     if (!PyInt_Check(args)) {
00186         PyErr_SetString(PyExc_TypeError, "integer expected");
00187         return NULL;
00188     }
00189 
00190     fileNumber = (int) PyInt_AsLong(args);
00191 
00192     if (rpmVerifyFile("", s->h, fileNumber, &verifyResult, RPMVERIFY_NONE)) {
00193         Py_INCREF(Py_None);
00194         return Py_None;
00195     }
00196 
00197     list = PyList_New(0);
00198 
00199     if (!verifyResult) return list;
00200 
00201     if (!s->fileList) {
00202         headerGetEntry(s->h, RPMTAG_OLDFILENAMES, &type, (void **) &s->fileList,
00203                  &count);
00204     }
00205 
00206     lstat(s->fileList[fileNumber], &sb);
00207 
00208     if (verifyResult & RPMVERIFY_MD5) {
00209         if (!s->md5list) {
00210             headerGetEntry(s->h, RPMTAG_FILEMD5S, &type, (void **) &s->md5list,
00211                      &count);
00212         }
00213 
00214         if (mdfile(s->fileList[fileNumber], buf)) {
00215             strcpy(buf, "(unknown)");
00216         }
00217 
00218         tuple = PyTuple_New(3);
00219         attrName = PyString_FromString("checksum");
00220         PyTuple_SetItem(tuple, 0, attrName);
00221         PyTuple_SetItem(tuple, 1, PyString_FromString(s->md5list[fileNumber]));
00222         PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00223         PyList_Append(list, tuple);
00224         Py_DECREF(tuple);
00225     }
00226 
00227     if (verifyResult & RPMVERIFY_FILESIZE) {
00228         if (!s->fileSizes) {
00229             headerGetEntry(s->h, RPMTAG_FILESIZES, &type, (void **) &s->fileSizes,
00230                      &count);
00231 
00232         }
00233 
00234         tuple = PyTuple_New(3);
00235         attrName = PyString_FromString("size");
00236         PyTuple_SetItem(tuple, 0, attrName);
00237 
00238         sprintf(buf, "%d", 100);
00239         PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00240         sprintf(buf, "%ld", sb.st_size);
00241         PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00242         PyList_Append(list, tuple);
00243         Py_DECREF(tuple);
00244     }
00245 
00246     if (verifyResult & RPMVERIFY_LINKTO) {
00247         if (!s->linkList) {
00248             headerGetEntry(s->h, RPMTAG_FILELINKTOS, &type, (void **) &s->linkList,
00249                      &count);
00250         }
00251 
00252         i = readlink(s->fileList[fileNumber], buf, sizeof(buf));
00253         if (i <= 0)
00254             strcpy(buf, "(unknown)");
00255         else
00256             buf[i] = '\0';
00257 
00258         tuple = PyTuple_New(3);
00259         attrName = PyString_FromString("link");
00260         PyTuple_SetItem(tuple, 0, attrName);
00261         PyTuple_SetItem(tuple, 1, PyString_FromString(s->linkList[fileNumber]));
00262         PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00263         PyList_Append(list, tuple);
00264         Py_DECREF(tuple);
00265     }
00266 
00267     if (verifyResult & RPMVERIFY_MTIME) {
00268         if (!s->mtimes) {
00269             headerGetEntry(s->h, RPMTAG_FILEMTIMES, &type, (void **) &s->mtimes,
00270                      &count);
00271         }
00272 
00273         tuple = PyTuple_New(3);
00274         attrName = PyString_FromString("time");
00275         PyTuple_SetItem(tuple, 0, attrName);
00276 
00277         timeInt = sb.st_mtime;
00278         timeStruct = localtime(&timeInt);
00279         strftime(buf, sizeof(buf) - 1, "%c", timeStruct);
00280         PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00281 
00282         timeInt = s->mtimes[fileNumber];
00283         timeStruct = localtime(&timeInt);
00284         strftime(buf, sizeof(buf) - 1, "%c", timeStruct);
00285 
00286         PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00287 
00288         PyList_Append(list, tuple);
00289         Py_DECREF(tuple);
00290     }
00291 
00292     if (verifyResult & RPMVERIFY_RDEV) {
00293         if (!s->rdevs) {
00294             headerGetEntry(s->h, RPMTAG_FILERDEVS, &type, (void **) &s->rdevs,
00295                      &count);
00296         }
00297 
00298         tuple = PyTuple_New(3);
00299         attrName = PyString_FromString("device");
00300 
00301         PyTuple_SetItem(tuple, 0, attrName);
00302         sprintf(buf, "0x%-4x", s->rdevs[fileNumber]);
00303         PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00304         sprintf(buf, "0x%-4x", (unsigned int) sb.st_rdev);
00305         PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00306         PyList_Append(list, tuple);
00307         Py_DECREF(tuple);
00308     }
00309 
00310     /* RPMVERIFY_USER and RPM_VERIFY_GROUP are handled wrong here, but rpmlib.a
00311        doesn't do these correctly either. At least this is consisten */
00312     if (verifyResult & RPMVERIFY_USER) {
00313         if (!s->uids) {
00314             headerGetEntry(s->h, RPMTAG_FILEUIDS, &type, (void **) &s->uids,
00315                      &count);
00316         }
00317 
00318         tuple = PyTuple_New(3);
00319         attrName = PyString_FromString("uid");
00320         PyTuple_SetItem(tuple, 0, attrName);
00321         sprintf(buf, "%d", s->uids[fileNumber]);
00322         PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00323         sprintf(buf, "%d", sb.st_uid);
00324         PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00325         PyList_Append(list, tuple);
00326         Py_DECREF(tuple);
00327     }
00328 
00329     if (verifyResult & RPMVERIFY_GROUP) {
00330         if (!s->gids) {
00331             headerGetEntry(s->h, RPMTAG_FILEGIDS, &type, (void **) &s->gids,
00332                      &count);
00333         }
00334 
00335         tuple = PyTuple_New(3);
00336         attrName = PyString_FromString("gid");
00337         PyTuple_SetItem(tuple, 0, attrName);
00338         sprintf(buf, "%d", s->gids[fileNumber]);
00339         PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00340         sprintf(buf, "%d", sb.st_gid);
00341         PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00342         PyList_Append(list, tuple);
00343         Py_DECREF(tuple);
00344     }
00345 
00346     if (verifyResult & RPMVERIFY_MODE) {
00347         if (!s->modes) {
00348             headerGetEntry(s->h, RPMTAG_FILEMODES, &type, (void **) &s->modes,
00349                      &count);
00350         }
00351 
00352         tuple = PyTuple_New(3);
00353         attrName = PyString_FromString("permissions");
00354         PyTuple_SetItem(tuple, 0, attrName);
00355         sprintf(buf, "0%-4o", s->modes[fileNumber]);
00356         PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00357         sprintf(buf, "0%-4o", sb.st_mode);
00358         PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00359         PyList_Append(list, tuple);
00360         Py_DECREF(tuple);
00361     }
00362 
00363     return list;
00364 }
00365 
00368 static PyObject * hdrExpandFilelist(hdrObject * s, PyObject * args) {
00369     expandFilelist (s->h);
00370 
00371     Py_INCREF(Py_None);
00372     return Py_None;
00373 }
00374 
00377 static PyObject * hdrCompressFilelist(hdrObject * s, PyObject * args) {
00378     compressFilelist (s->h);
00379 
00380     Py_INCREF(Py_None);
00381     return Py_None;
00382 }
00383 
00384 /* make a header with _all_ the tags we need */
00387 static void mungeFilelist(Header h)
00388 {
00389     const char ** fileNames = NULL;
00390     int count = 0;
00391 
00392     if (!headerIsEntry (h, RPMTAG_BASENAMES)
00393         || !headerIsEntry (h, RPMTAG_DIRNAMES)
00394         || !headerIsEntry (h, RPMTAG_DIRINDEXES))
00395         compressFilelist(h);
00396     
00397     rpmBuildFileList(h, &fileNames, &count);
00398 
00399     if (fileNames == NULL || count <= 0)
00400         return;
00401 
00402     headerAddEntry(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
00403                         fileNames, count);
00404 
00405     free((void *)fileNames);
00406 }
00407 
00410 static PyObject * hdrFullFilelist(hdrObject * s, PyObject * args) {
00411     mungeFilelist (s->h);
00412 
00413     Py_INCREF(Py_None);
00414     return Py_None;
00415 }
00416 
00419 static struct PyMethodDef hdrMethods[] = {
00420         {"keys",        (PyCFunction) hdrKeyList,       1 },
00421         {"unload",      (PyCFunction) hdrUnload,        1 },
00422         {"verifyFile",  (PyCFunction) hdrVerifyFile,    1 },
00423         {"expandFilelist",      (PyCFunction) hdrExpandFilelist,        1 },
00424         {"compressFilelist",    (PyCFunction) hdrCompressFilelist,      1 },
00425         {"fullFilelist",        (PyCFunction) hdrFullFilelist,  1 },
00426         {NULL,          NULL}           /* sentinel */
00427 };
00428 
00431 static PyObject * hdrGetAttr(hdrObject * s, char * name) {
00432     return Py_FindMethod(hdrMethods, (PyObject * ) s, name);
00433 }
00434 
00437 static void hdrDealloc(hdrObject * s) {
00438     if (s->h) headerFree(s->h);
00439     if (s->sigs) headerFree(s->sigs);
00440     if (s->md5list) free(s->md5list);
00441     if (s->fileList) free(s->fileList);
00442     if (s->linkList) free(s->linkList);
00443     PyMem_DEL(s);
00444 }
00445 
00448 static long tagNumFromPyObject (PyObject *item)
00449 {
00450     char * str;
00451     int i;
00452 
00453     if (PyInt_Check(item)) {
00454         return PyInt_AsLong(item);
00455     } else if (PyString_Check(item)) {
00456         str = PyString_AsString(item);
00457         for (i = 0; i < rpmTagTableSize; i++)
00458             if (!xstrcasecmp(rpmTagTable[i].name + 7, str)) break;
00459         if (i < rpmTagTableSize) return rpmTagTable[i].val;
00460     }
00461     return -1;
00462 }
00463 
00466 static PyObject * hdrSubscript(hdrObject * s, PyObject * item) {
00467     int type, count, i, tag = -1;
00468     void * data;
00469     PyObject * o, * metao;
00470     char ** stringArray;
00471     int forceArray = 0;
00472     int freeData = 0;
00473     char * str;
00474     struct headerSprintfExtension * ext = NULL;
00475     const struct headerSprintfExtension * extensions = rpmHeaderFormats;
00476 
00477     if (PyCObject_Check (item))
00478         ext = PyCObject_AsVoidPtr(item);
00479     else
00480         tag = tagNumFromPyObject (item);
00481     if (tag == -1 && PyString_Check(item)) {
00482         /* if we still don't have the tag, go looking for the header
00483            extensions */
00484         str = PyString_AsString(item);
00485         while (extensions->name) {
00486             if (extensions->type == HEADER_EXT_TAG
00487                 && !xstrcasecmp(extensions->name + 7, str)) {
00488                 (const struct headerSprintfExtension *) ext = extensions;
00489             }
00490             extensions++;
00491         }
00492     }
00493 
00494     if (ext) {
00495         ext->u.tagFunction(s->h, &type, (const void **) &data, &count, &freeData);
00496     } else {
00497         if (tag == -1) {
00498             PyErr_SetString(PyExc_KeyError, "unknown header tag");
00499             return NULL;
00500         }
00501         
00502         if (!rpmPackageGetEntry(NULL, s->sigs, s->h, tag, &type, &data, &count))
00503         {
00504             Py_INCREF(Py_None);
00505             return Py_None;
00506         }
00507     }
00508 
00509     switch (tag) {
00510       case RPMTAG_OLDFILENAMES:
00511       case RPMTAG_FILESIZES:
00512       case RPMTAG_FILESTATES:
00513       case RPMTAG_FILEMODES:
00514       case RPMTAG_FILEUIDS:
00515       case RPMTAG_FILEGIDS:
00516       case RPMTAG_FILERDEVS:
00517       case RPMTAG_FILEMTIMES:
00518       case RPMTAG_FILEMD5S:
00519       case RPMTAG_FILELINKTOS:
00520       case RPMTAG_FILEFLAGS:
00521       case RPMTAG_ROOT:
00522       case RPMTAG_FILEUSERNAME:
00523       case RPMTAG_FILEGROUPNAME:
00524         forceArray = 1;
00525         break;
00526       case RPMTAG_SUMMARY:
00527       case RPMTAG_GROUP:
00528       case RPMTAG_DESCRIPTION:
00529         freeData = 1;
00530         break;
00531       default:
00532         break;
00533     }
00534 
00535     switch (type) {
00536       case RPM_BIN_TYPE:
00537         o = PyString_FromStringAndSize(data, count);
00538         break;
00539 
00540       case RPM_INT32_TYPE:
00541         if (count != 1 || forceArray) {
00542             metao = PyList_New(0);
00543             for (i = 0; i < count; i++) {
00544                 o = PyInt_FromLong(((int *) data)[i]);
00545                 PyList_Append(metao, o);
00546                 Py_DECREF(o);
00547             }
00548             o = metao;
00549         } else {
00550             o = PyInt_FromLong(*((int *) data));
00551         }
00552         break;
00553 
00554       case RPM_CHAR_TYPE:
00555       case RPM_INT8_TYPE:
00556         if (count != 1 || forceArray) {
00557             metao = PyList_New(0);
00558             for (i = 0; i < count; i++) {
00559                 o = PyInt_FromLong(((char *) data)[i]);
00560                 PyList_Append(metao, o);
00561                 Py_DECREF(o);
00562             }
00563             o = metao;
00564         } else {
00565             o = PyInt_FromLong(*((char *) data));
00566         }
00567         break;
00568 
00569       case RPM_INT16_TYPE:
00570         if (count != 1 || forceArray) {
00571             metao = PyList_New(0);
00572             for (i = 0; i < count; i++) {
00573                 o = PyInt_FromLong(((short *) data)[i]);
00574                 PyList_Append(metao, o);
00575                 Py_DECREF(o);
00576             }
00577             o = metao;
00578         } else {
00579             o = PyInt_FromLong(*((short *) data));
00580         }
00581         break;
00582 
00583       case RPM_STRING_ARRAY_TYPE:
00584         stringArray = data;
00585 
00586         metao = PyList_New(0);
00587         for (i = 0; i < count; i++) {
00588             o = PyString_FromString(stringArray[i]);
00589             PyList_Append(metao, o);
00590             Py_DECREF(o);
00591         }
00592         free (stringArray);
00593         o = metao;
00594         break;
00595 
00596       case RPM_STRING_TYPE:
00597         if (count != 1 || forceArray) {
00598             stringArray = data;
00599 
00600             metao = PyList_New(0);
00601             for (i=0; i < count; i++) {
00602                 o = PyString_FromString(stringArray[i]);
00603                 PyList_Append(metao, o);
00604                 Py_DECREF(o);
00605             }
00606             o = metao;
00607         } else {
00608             o = PyString_FromString(data);
00609             if (freeData)
00610                 free (data);
00611         }
00612         break;
00613 
00614       default:
00615         PyErr_SetString(PyExc_TypeError, "unsupported type in header");
00616         return NULL;
00617     }
00618 
00619     return o;
00620 }
00621 
00624 static PyMappingMethods hdrAsMapping = {
00625         (inquiry) 0,                    /* mp_length */
00626         (binaryfunc) hdrSubscript,      /* mp_subscript */
00627         (objobjargproc)0,               /* mp_ass_subscript */
00628 };
00629 
00632 static PyTypeObject hdrType = {
00633         PyObject_HEAD_INIT(&PyType_Type)
00634         0,                              /* ob_size */
00635         "header",                       /* tp_name */
00636         sizeof(hdrObject),              /* tp_size */
00637         0,                              /* tp_itemsize */
00638         (destructor) hdrDealloc,        /* tp_dealloc */
00639         0,                              /* tp_print */
00640         (getattrfunc) hdrGetAttr,       /* tp_getattr */
00641         0,                              /* tp_setattr */
00642         0,                              /* tp_compare */
00643         0,                              /* tp_repr */
00644         0,                              /* tp_as_number */
00645         0,                              /* tp_as_sequence */
00646         &hdrAsMapping,                  /* tp_as_mapping */
00647 };
00648 
00661 
00664 struct rpmdbObject_s {
00665     PyObject_HEAD;
00666     rpmdb db;
00667     int offx;
00668     int noffs;
00669     int *offsets;
00670 } ;
00671 
00674 struct rpmdbMIObject_s {
00675     PyObject_HEAD;
00676     rpmdbObject *db;
00677     rpmdbMatchIterator mi;
00678 } ;
00679 
00682 static PyObject *
00683 rpmdbMINext(rpmdbMIObject * s, PyObject * args) {
00684     /* XXX assume header? */
00685     Header h;
00686     hdrObject * ho;
00687     
00688 
00689     h = rpmdbNextIterator(s->mi);
00690     if (!h) {
00691         Py_INCREF(Py_None);
00692         return Py_None;
00693     }
00694 
00695     ho = PyObject_NEW(hdrObject, &hdrType);
00696     ho->h = headerLink(h);
00697     ho->sigs = NULL;
00698     ho->fileList = ho->linkList = ho->md5list = NULL;
00699     ho->uids = ho->gids = ho->mtimes = ho->fileSizes = NULL;
00700     ho->modes = ho->rdevs = NULL;
00701     
00702     return (PyObject *) ho;
00703 }
00704 
00707 static struct PyMethodDef rpmdbMIMethods[] = {
00708         {"next",            (PyCFunction) rpmdbMINext,  1 },
00709         {NULL,          NULL}           /* sentinel */
00710 };
00711 
00714 static PyObject * rpmdbMIGetAttr (rpmdbObject *s, char *name) {
00715     return Py_FindMethod (rpmdbMIMethods, (PyObject *) s, name);
00716 }
00717 
00720 static void rpmdbMIDealloc(rpmdbMIObject * s) {
00721     if (s && s->mi) {
00722         rpmdbFreeIterator(s->mi);
00723     }
00724     Py_DECREF (s->db);
00725     PyMem_DEL(s);
00726 }
00727 
00730 static PyTypeObject rpmdbMIType = {
00731         PyObject_HEAD_INIT(&PyType_Type)
00732         0,                              /* ob_size */
00733         "rpmdbMatchIterator",           /* tp_name */
00734         sizeof(rpmdbMIObject),  /* tp_size */
00735         0,                              /* tp_itemsize */
00736         (destructor) rpmdbMIDealloc,    /* tp_dealloc */
00737         0,                              /* tp_print */
00738         (getattrfunc) rpmdbMIGetAttr,   /* tp_getattr */
00739         0,                              /* tp_setattr */
00740         0,                              /* tp_compare */
00741         0,                              /* tp_repr */
00742         0,                              /* tp_as_number */
00743         0,                              /* tp_as_sequence */
00744         0,                              /* tp_as_mapping */
00745 };
00746 
00815 
00818 static PyObject * rpmdbFirst(rpmdbObject * s, PyObject * args) {
00819     int first;
00820 
00821     if (!PyArg_ParseTuple (args, "")) return NULL;
00822 
00823     /* Acquire all offsets in one fell swoop. */
00824     if (s->offsets == NULL || s->noffs <= 0) {
00825         rpmdbMatchIterator mi;
00826         Header h;
00827 
00828         if (s->offsets)
00829             free(s->offsets);
00830         s->offsets = NULL;
00831         s->noffs = 0;
00832         mi = rpmdbInitIterator(s->db, RPMDBI_PACKAGES, NULL, 0);
00833         while ((h = rpmdbNextIterator(mi)) != NULL) {
00834             s->noffs++;
00835             s->offsets = realloc(s->offsets, s->noffs * sizeof(s->offsets[0]));
00836             s->offsets[s->noffs-1] = rpmdbGetIteratorOffset(mi);
00837         }
00838         rpmdbFreeIterator(mi);
00839     }
00840 
00841     s->offx = 0;
00842     if (s->offsets != NULL && s->offx < s->noffs)
00843         first = s->offsets[s->offx++];
00844     else
00845         first = 0;
00846 
00847     if (!first) {
00848         PyErr_SetString(pyrpmError, "cannot find first entry in database\n");
00849         return NULL;
00850     }
00851 
00852     return Py_BuildValue("i", first);
00853 }
00854 
00857 static PyObject * rpmdbNext(rpmdbObject * s, PyObject * args) {
00858     int where;
00859 
00860     if (!PyArg_ParseTuple (args, "i", &where)) return NULL;
00861 
00862     if (s->offsets == NULL || s->offx >= s->noffs) {
00863         Py_INCREF(Py_None);
00864         return Py_None;
00865     }
00866 
00867     where = s->offsets[s->offx++];
00868 
00869     if (!where) {
00870         Py_INCREF(Py_None);
00871         return Py_None;
00872     }
00873 
00874     return Py_BuildValue("i", where);
00875 }
00876 
00879 static PyObject * handleDbResult(rpmdbMatchIterator mi) {
00880     PyObject * list, *o;
00881 
00882     list = PyList_New(0);
00883 
00884     /* XXX FIXME: unnecessary header mallocs are side effect here */
00885     if (mi != NULL) {
00886         while (rpmdbNextIterator(mi)) {
00887             PyList_Append(list, o=PyInt_FromLong(rpmdbGetIteratorOffset(mi)));
00888             Py_DECREF(o);
00889         }
00890         rpmdbFreeIterator(mi);
00891     }
00892 
00893     return list;
00894 }
00895 
00898 static PyObject * rpmdbByFile(rpmdbObject * s, PyObject * args) {
00899     char * str;
00900 
00901     if (!PyArg_ParseTuple(args, "s", &str)) return NULL;
00902 
00903     return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_BASENAMES, str, 0));
00904 }
00905 
00908 static PyObject * rpmdbByName(rpmdbObject * s, PyObject * args) {
00909     char * str;
00910 
00911     if (!PyArg_ParseTuple(args, "s", &str)) return NULL;
00912 
00913     return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_NAME, str, 0));
00914 }
00915 
00918 static PyObject * rpmdbByProvides(rpmdbObject * s, PyObject * args) {
00919     char * str;
00920 
00921     if (!PyArg_ParseTuple(args, "s", &str)) return NULL;
00922 
00923     return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_PROVIDENAME, str, 0));
00924 }
00925 
00928 static rpmdbMIObject *
00929 py_rpmdbInitIterator (rpmdbObject * s, PyObject * args) {
00930     PyObject *index = NULL;
00931     char *key = NULL;
00932     int len = 0, tag = -1;
00933     rpmdbMIObject * mio;
00934     
00935     if (!PyArg_ParseTuple(args, "|Ozi", &index, &key, &len))
00936         return NULL;
00937 
00938     if (index == NULL)
00939         tag = 0;
00940     else if ((tag = tagNumFromPyObject (index)) == -1) {
00941         PyErr_SetString(PyExc_TypeError, "unknown tag type");
00942         return NULL;
00943     }
00944     
00945     mio = (rpmdbMIObject *) PyObject_NEW(rpmdbMIObject, &rpmdbMIType);
00946     if (mio == NULL) {
00947         PyErr_SetString(pyrpmError, "out of memory creating rpmdbMIObject");
00948         return NULL;
00949     }
00950     
00951     mio->mi = rpmdbInitIterator(s->db, tag, key, len);
00952     mio->db = s;
00953     Py_INCREF (mio->db);
00954     
00955     return mio;
00956 }
00957 
00960 static struct PyMethodDef rpmdbMethods[] = {
00961         {"firstkey",        (PyCFunction) rpmdbFirst,   1 },
00962         {"nextkey",         (PyCFunction) rpmdbNext,    1 },
00963         {"findbyfile",      (PyCFunction) rpmdbByFile, 1 },
00964         {"findbyname",      (PyCFunction) rpmdbByName, 1 },
00965         {"findbyprovides",  (PyCFunction) rpmdbByProvides, 1 },
00966         {"match",           (PyCFunction) py_rpmdbInitIterator, 1 },
00967         {NULL,          NULL}           /* sentinel */
00968 };
00969 
00972 static PyObject * rpmdbGetAttr(rpmdbObject * s, char * name) {
00973     return Py_FindMethod(rpmdbMethods, (PyObject * ) s, name);
00974 }
00975 
00978 static void rpmdbDealloc(rpmdbObject * s) {
00979     if (s->offsets) {
00980         free(s->offsets);
00981     }
00982     if (s->db) {
00983         rpmdbClose(s->db);
00984     }
00985     PyMem_DEL(s);
00986 }
00987 
00988 #ifndef DYINGSOON
00989 
00991 static int
00992 rpmdbLength(rpmdbObject * s) {
00993     int count = 0;
00994 
00995     {   rpmdbMatchIterator mi;
00996 
00997         /* RPMDBI_PACKAGES */
00998         mi = rpmdbInitIterator(s->db, RPMDBI_PACKAGES, NULL, 0);
00999         /* XXX FIXME: unnecessary header mallocs are side effect here */
01000         while (rpmdbNextIterator(mi) != NULL)
01001             count++;
01002         rpmdbFreeIterator(mi);
01003     }
01004 
01005     return count;
01006 }
01007 
01010 static hdrObject *
01011 rpmdbSubscript(rpmdbObject * s, PyObject * key) {
01012     int offset;
01013     hdrObject * h;
01014 
01015     if (!PyInt_Check(key)) {
01016         PyErr_SetString(PyExc_TypeError, "integer expected");
01017         return NULL;
01018     }
01019 
01020     offset = (int) PyInt_AsLong(key);
01021 
01022     h = PyObject_NEW(hdrObject, &hdrType);
01023     h->h = NULL;
01024     h->sigs = NULL;
01025     {   rpmdbMatchIterator mi;
01026         mi = rpmdbInitIterator(s->db, RPMDBI_PACKAGES, &offset, sizeof(offset));
01027         if ((h->h = rpmdbNextIterator(mi)) != NULL)
01028             h->h = headerLink(h->h);
01029         rpmdbFreeIterator(mi);
01030     }
01031     h->fileList = h->linkList = h->md5list = NULL;
01032     h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
01033     h->modes = h->rdevs = NULL;
01034     if (!h->h) {
01035         Py_DECREF(h);
01036         PyErr_SetString(pyrpmError, "cannot read rpmdb entry");
01037         return NULL;
01038     }
01039 
01040     return h;
01041 }
01042 
01045 static PyMappingMethods rpmdbAsMapping = {
01046         (inquiry) rpmdbLength,          /* mp_length */
01047         (binaryfunc) rpmdbSubscript,    /* mp_subscript */
01048         (objobjargproc)0,               /* mp_ass_subscript */
01049 };
01050 #endif
01051 
01054 static PyTypeObject rpmdbType = {
01055         PyObject_HEAD_INIT(&PyType_Type)
01056         0,                              /* ob_size */
01057         "rpmdb",                        /* tp_name */
01058         sizeof(rpmdbObject),            /* tp_size */
01059         0,                              /* tp_itemsize */
01060         (destructor) rpmdbDealloc,      /* tp_dealloc */
01061         0,                              /* tp_print */
01062         (getattrfunc) rpmdbGetAttr,     /* tp_getattr */
01063         0,                              /* tp_setattr */
01064         0,                              /* tp_compare */
01065         0,                              /* tp_repr */
01066         0,                              /* tp_as_number */
01067         0,                              /* tp_as_sequence */
01068 #ifndef DYINGSOON
01069         &rpmdbAsMapping,                /* tp_as_mapping */
01070 #else
01071         0,
01072 #endif
01073 };
01074 
01179 
01182 struct rpmtransObject_s {
01183     PyObject_HEAD;
01184     rpmdbObject * dbo;
01185     rpmTransactionSet ts;
01186     PyObject * keyList;                 /* keeps reference counts correct */
01187     FD_t scriptFd;
01188 } ;
01189 
01192 static PyObject * rpmtransAdd(rpmtransObject * s, PyObject * args) {
01193     hdrObject * h;
01194     PyObject * key;
01195     char * how = NULL;
01196     int isUpgrade = 0;
01197 
01198     if (!PyArg_ParseTuple(args, "OO|s", &h, &key, &how)) return NULL;
01199     if (h->ob_type != &hdrType) {
01200         PyErr_SetString(PyExc_TypeError, "bad type for header argument");
01201         return NULL;
01202     }
01203 
01204     if (how && strcmp(how, "a") && strcmp(how, "u") && strcmp(how, "i")) {
01205         PyErr_SetString(PyExc_TypeError, "how argument must be \"u\", \"a\", or \"i\"");
01206         return NULL;
01207     } else if (how && !strcmp(how, "u"))
01208         isUpgrade = 1;
01209 
01210     if (how && !strcmp(how, "a"))
01211         rpmtransAvailablePackage(s->ts, h->h, key);
01212     else
01213         rpmtransAddPackage(s->ts, h->h, NULL, key, isUpgrade, NULL);
01214 
01215     /* This should increment the usage count for me */
01216     if (key) {
01217         PyList_Append(s->keyList, key);
01218     }
01219 
01220     Py_INCREF(Py_None);
01221     return Py_None;
01222 }
01223 
01226 static PyObject * rpmtransRemove(rpmtransObject * s, PyObject * args) {
01227     char * name;
01228     int count;
01229     rpmdbMatchIterator mi;
01230     
01231     if (!PyArg_ParseTuple(args, "s", &name))
01232         return NULL;
01233 
01234     /* XXX: Copied hack from ../lib/rpminstall.c, rpmErase() */
01235     mi = rpmdbInitIterator(s->dbo->db, RPMDBI_LABEL, name, 0);
01236     count = rpmdbGetIteratorCount(mi);
01237     if (count <= 0) {
01238         PyErr_SetString(pyrpmError, "package not installed");
01239         return NULL;
01240     } else { /* XXX: Note that we automatically choose to remove all matches */
01241         Header h;
01242         while ((h = rpmdbNextIterator(mi)) != NULL) {
01243             unsigned int recOffset = rpmdbGetIteratorOffset(mi);
01244             if (recOffset) {
01245                 rpmtransRemovePackage(s->ts, recOffset);
01246             }
01247         }
01248     }
01249     rpmdbFreeIterator(mi);
01250 
01251     Py_INCREF(Py_None);
01252     return Py_None;
01253 }
01254 
01257 static PyObject * rpmtransDepCheck(rpmtransObject * s, PyObject * args) {
01258     struct rpmDependencyConflict * conflicts;
01259     int numConflicts;
01260     PyObject * list, * cf;
01261     int i;
01262 
01263     if (!PyArg_ParseTuple(args, "")) return NULL;
01264 
01265     rpmdepCheck(s->ts, &conflicts, &numConflicts);
01266     if (numConflicts) {
01267         list = PyList_New(0);
01268 
01269         for (i = 0; i < numConflicts; i++) {
01270             cf = Py_BuildValue("((sss)(ss)iOi)", conflicts[i].byName,
01271                                conflicts[i].byVersion, conflicts[i].byRelease,
01272 
01273                                conflicts[i].needsName,
01274                                conflicts[i].needsVersion,
01275 
01276                                conflicts[i].needsFlags,
01277                                conflicts[i].suggestedPackage ?
01278                                    conflicts[i].suggestedPackage : Py_None,
01279                                conflicts[i].sense);
01280             PyList_Append(list, (PyObject *) cf);
01281             Py_DECREF(cf);
01282         }
01283 
01284         rpmdepFreeConflicts(conflicts, numConflicts);
01285 
01286         return list;
01287     }
01288 
01289     Py_INCREF(Py_None);
01290     return Py_None;
01291 }
01292 
01295 static PyObject * rpmtransOrder(rpmtransObject * s, PyObject * args) {
01296     if (!PyArg_ParseTuple(args, "")) return NULL;
01297 
01298     rpmdepOrder(s->ts);
01299 
01300     Py_INCREF(Py_None);
01301     return Py_None;
01302 }
01303 
01306 static PyObject * py_rpmtransGetKeys(rpmtransObject * s, PyObject * args) {
01307     const void **data = NULL;
01308     int num, i;
01309     PyObject *tuple;
01310 
01311     rpmtransGetKeys(s->ts, &data, &num);
01312     if (data == NULL) {
01313         Py_INCREF(Py_None);
01314         return Py_None;
01315     }
01316 
01317     tuple = PyTuple_New(num);
01318 
01319     for (i = 0; i < num; i++) {
01320         PyObject *obj = (PyObject *) data[i];
01321         Py_INCREF(obj);
01322         PyTuple_SetItem(tuple, i, obj);
01323     }
01324 
01325     free (data);
01326 
01327     return tuple;
01328 }
01329 
01332 struct tsCallbackType {
01333     PyObject * cb;
01334     PyObject * data;
01335     int pythonError;
01336 };
01337 
01340 static Header transactionSetHeader = NULL;
01341 
01344 static void * tsCallback(const void * hd, const rpmCallbackType what,
01345                          const unsigned long amount, const unsigned long total,
01346                          const void * pkgKey, rpmCallbackData data) {
01347     struct tsCallbackType * cbInfo = data;
01348     PyObject * args, * result;
01349     int fd;
01350     static FD_t fdt;
01351     const Header h = (Header) hd;
01352 
01353     if (cbInfo->pythonError) return NULL;
01354 
01355     if (!pkgKey) pkgKey = Py_None;
01356     transactionSetHeader = h;    
01357 
01358     args = Py_BuildValue("(illOO)", what, amount, total, pkgKey, cbInfo->data);
01359     result = PyEval_CallObject(cbInfo->cb, args);
01360     Py_DECREF(args);
01361 
01362     if (!result) {
01363         cbInfo->pythonError = 1;
01364         return NULL;
01365     }
01366 
01367     if (what == RPMCALLBACK_INST_OPEN_FILE) {
01368         if (!PyArg_Parse(result, "i", &fd)) {
01369             cbInfo->pythonError = 1;
01370             return NULL;
01371         }
01372         fdt = fdDup(fd);
01373         
01374         Py_DECREF(result);
01375         return fdt;
01376     }
01377 
01378     if (what == RPMCALLBACK_INST_CLOSE_FILE) {
01379         Fclose (fdt);
01380     }
01381 
01382     Py_DECREF(result);
01383 
01384     return NULL;
01385 }
01386 
01389 static PyObject * rpmtransRun(rpmtransObject * s, PyObject * args) {
01390     int flags, ignoreSet;
01391     int rc, i;
01392     PyObject * list, * prob;
01393     rpmProblemSet probs;
01394     struct tsCallbackType cbInfo;
01395 
01396     if (!PyArg_ParseTuple(args, "iiOO", &flags, &ignoreSet, &cbInfo.cb,
01397                           &cbInfo.data))
01398         return NULL;
01399 
01400     cbInfo.pythonError = 0;
01401 
01402     rc = rpmRunTransactions(s->ts, tsCallback, &cbInfo, NULL, &probs, flags,
01403                             ignoreSet);
01404 
01405     if (cbInfo.pythonError) {
01406         if (rc > 0)
01407             rpmProblemSetFree(probs);
01408         return NULL;
01409     }
01410 
01411     if (rc < 0) {
01412         list = PyList_New(0);
01413         return list;
01414     } else if (!rc) {
01415         Py_INCREF(Py_None);
01416         return Py_None;
01417     }
01418 
01419     list = PyList_New(0);
01420     for (i = 0; i < probs->numProblems; i++) {
01421         rpmProblem myprob = probs->probs + i;
01422         prob = Py_BuildValue("s(isi)", rpmProblemString(myprob),
01423                              myprob->type,
01424                              myprob->str1,
01425                              myprob->ulong1);
01426         PyList_Append(list, prob);
01427         Py_DECREF(prob);
01428     }
01429 
01430     rpmProblemSetFree(probs);
01431 
01432     return list;
01433 }
01434 
01437 static struct PyMethodDef rpmtransMethods[] = {
01438         {"add",         (PyCFunction) rpmtransAdd,      1 },
01439         {"remove",      (PyCFunction) rpmtransRemove,   1 },
01440         {"depcheck",    (PyCFunction) rpmtransDepCheck, 1 },
01441         {"order",       (PyCFunction) rpmtransOrder,    1 },
01442         {"getKeys",     (PyCFunction) py_rpmtransGetKeys, 1 },
01443         {"run",         (PyCFunction) rpmtransRun, 1 },
01444         {NULL,          NULL}           /* sentinel */
01445 };
01446 
01449 static PyObject * rpmtransGetAttr(rpmtransObject * o, char * name) {
01450     return Py_FindMethod(rpmtransMethods, (PyObject *) o, name);
01451 }
01452 
01455 static void rpmtransDealloc(PyObject * o) {
01456     rpmtransObject * trans = (void *) o;
01457 
01458     rpmtransFree(trans->ts);
01459     if (trans->dbo) {
01460         Py_DECREF(trans->dbo);
01461     }
01462     if (trans->scriptFd) Fclose(trans->scriptFd);
01463     /* this will free the keyList, and decrement the ref count of all
01464        the items on the list as well :-) */
01465     Py_DECREF(trans->keyList);
01466     PyMem_DEL(o);
01467 }
01468 
01471 static int rpmtransSetAttr(rpmtransObject * o, char * name,
01472                            PyObject * val) {
01473     int i;
01474 
01475     if (!strcmp(name, "scriptFd")) {
01476         if (!PyArg_Parse(val, "i", &i)) return 0;
01477         if (i < 0) {
01478             PyErr_SetString(PyExc_TypeError, "bad file descriptor");
01479             return -1;
01480         } else {
01481             o->scriptFd = fdDup(i);
01482             rpmtransSetScriptFd(o->ts, o->scriptFd);
01483         }
01484     } else {
01485         PyErr_SetString(PyExc_AttributeError, name);
01486         return -1;
01487     }
01488 
01489     return 0;
01490 }
01491 
01494 static PyTypeObject rpmtransType = {
01495         PyObject_HEAD_INIT(&PyType_Type)
01496         0,                              /* ob_size */
01497         "rpmtrans",                     /* tp_name */
01498         sizeof(rpmtransObject),         /* tp_size */
01499         0,                              /* tp_itemsize */
01500         (destructor) rpmtransDealloc,   /* tp_dealloc */
01501         0,                              /* tp_print */
01502         (getattrfunc) rpmtransGetAttr,  /* tp_getattr */
01503         (setattrfunc) rpmtransSetAttr,  /* tp_setattr */
01504         0,                              /* tp_compare */
01505         0,                              /* tp_repr */
01506         0,                              /* tp_as_number */
01507         0,                              /* tp_as_sequence */
01508         0,                              /* tp_as_mapping */
01509 };
01510 
01517 
01520 static PyObject * rpmtransCreate(PyObject * self, PyObject * args) {
01521     rpmtransObject * o;
01522     rpmdbObject * db = NULL;
01523     char * rootPath = "/";
01524 
01525     if (!PyArg_ParseTuple(args, "|sO", &rootPath, &db)) return NULL;
01526     if (db && db->ob_type != &rpmdbType) {
01527         PyErr_SetString(PyExc_TypeError, "bad type for database argument");
01528         return NULL;
01529     }
01530 
01531     o = (void *) PyObject_NEW(rpmtransObject, &rpmtransType);
01532 
01533     Py_XINCREF(db);
01534     o->dbo = db;
01535     o->scriptFd = NULL;
01536     o->ts = rpmtransCreateSet(db ? db->db : NULL, rootPath);
01537     o->keyList = PyList_New(0);
01538 
01539     return (void *) o;
01540 }
01541 
01544 static PyObject * doAddMacro(PyObject * self, PyObject * args) {
01545     char * name, * val;
01546 
01547     if (!PyArg_ParseTuple(args, "ss", &name, &val))
01548         return NULL;
01549 
01550     addMacro(NULL, name, NULL, val, RMIL_DEFAULT);
01551 
01552     Py_INCREF(Py_None);
01553     return Py_None;
01554 }
01555 
01558 static PyObject * doDelMacro(PyObject * self, PyObject * args) {
01559     char * name;
01560 
01561     if (!PyArg_ParseTuple(args, "s", &name))
01562         return NULL;
01563 
01564     delMacro(NULL, name);
01565 
01566     Py_INCREF(Py_None);
01567     return Py_None;
01568 }
01569 
01572 static PyObject * archScore(PyObject * self, PyObject * args) {
01573     char * arch;
01574     int score;
01575 
01576     if (!PyArg_ParseTuple(args, "s", &arch))
01577         return NULL;
01578 
01579     score = rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch);
01580 
01581     return Py_BuildValue("i", score);
01582 }
01583 
01586 static int psGetArchScore(Header h) {
01587     void * pkgArch;
01588     int type, count;
01589 
01590     if (!headerGetEntry(h, RPMTAG_ARCH, &type, (void **) &pkgArch, &count) ||
01591         type == RPM_INT8_TYPE)
01592        return 150;
01593     else
01594         return rpmMachineScore(RPM_MACHTABLE_INSTARCH, pkgArch);
01595 }
01596 
01599 static int pkgCompareVer(void * first, void * second) {
01600     struct packageInfo ** a = first;
01601     struct packageInfo ** b = second;
01602     int ret, score1, score2;
01603 
01604     /* put packages w/o names at the end */
01605     if (!(*a)->name) return 1;
01606     if (!(*b)->name) return -1;
01607 
01608     ret = xstrcasecmp((*a)->name, (*b)->name);
01609     if (ret) return ret;
01610     score1 = psGetArchScore((*a)->h);
01611     if (!score1) return 1;
01612     score2 = psGetArchScore((*b)->h);
01613     if (!score2) return -1;
01614     if (score1 < score2) return -1;
01615     if (score1 > score2) return 1;
01616     return rpmVersionCompare((*b)->h, (*a)->h);
01617 }
01618 
01621 static void pkgSort(struct pkgSet * psp) {
01622     int i;
01623     char *name;
01624 
01625     qsort(psp->packages, psp->numPackages, sizeof(*psp->packages),
01626          (void *) pkgCompareVer);
01627 
01628     name = psp->packages[0]->name;
01629     if (!name) {
01630        psp->numPackages = 0;
01631        return;
01632     }
01633     for (i = 1; i < psp->numPackages; i++) {
01634        if (!psp->packages[i]->name) break;
01635        if (!strcmp(psp->packages[i]->name, name))
01636            psp->packages[i]->name = NULL;
01637        else
01638            name = psp->packages[i]->name;
01639     }
01640 
01641     qsort(psp->packages, psp->numPackages, sizeof(*psp->packages),
01642          (void *) pkgCompareVer);
01643 
01644     for (i = 0; i < psp->numPackages; i++)
01645        if (!psp->packages[i]->name) break;
01646     psp->numPackages = i;
01647 }
01648 
01651 static PyObject * findUpgradeSet(PyObject * self, PyObject * args) {
01652     PyObject * hdrList, * result;
01653     char * root = "/";
01654     int i;
01655     struct pkgSet list;
01656     hdrObject * hdr;
01657 
01658     if (!PyArg_ParseTuple(args, "O|s", &hdrList, &root)) return NULL;
01659 
01660     if (!PyList_Check(hdrList)) {
01661         PyErr_SetString(PyExc_TypeError, "list of headers expected");
01662         return NULL;
01663     }
01664 
01665     list.numPackages = PyList_Size(hdrList);
01666     list.packages = alloca(sizeof(list.packages) * list.numPackages);
01667     for (i = 0; i < list.numPackages; i++) {
01668         hdr = (hdrObject *) PyList_GetItem(hdrList, i);
01669         if (hdr->ob_type != &hdrType) {
01670             PyErr_SetString(PyExc_TypeError, "list of headers expected");
01671             return NULL;
01672         }
01673         list.packages[i] = alloca(sizeof(struct packageInfo));
01674         list.packages[i]->h = hdr->h;
01675         list.packages[i]->selected = 0;
01676         list.packages[i]->data = hdr;
01677 
01678         headerGetEntry(hdr->h, RPMTAG_NAME, NULL,
01679                       (void **) &list.packages[i]->name, NULL);
01680     }
01681 
01682     pkgSort (&list);
01683 
01684     if (ugFindUpgradePackages(&list, root)) {
01685         PyErr_SetString(pyrpmError, "error during upgrade check");
01686         return NULL;
01687     }
01688 
01689     result = PyList_New(0);
01690     for (i = 0; i < list.numPackages; i++) {
01691         if (list.packages[i]->selected) {
01692             PyList_Append(result, list.packages[i]->data);
01693 /*          Py_DECREF(list.packages[i]->data); */
01694         }
01695     }
01696 
01697     return result;
01698 }
01699 
01702 static PyObject * rpmHeaderFromPackage(PyObject * self, PyObject * args) {
01703     hdrObject * h;
01704     Header header;
01705     Header sigs;
01706     int rc;
01707     FD_t fd;
01708     int rawFd;
01709     int isSource = 0;
01710 
01711     if (!PyArg_ParseTuple(args, "i", &rawFd)) return NULL;
01712     fd = fdDup(rawFd);
01713 
01714     rc = rpmReadPackageInfo(fd, &sigs, &header);
01715     Fclose(fd);
01716 
01717     switch (rc) {
01718       case 0:
01719         h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
01720         h->h = header;
01721         h->sigs = sigs;
01722         h->fileList = h->linkList = h->md5list = NULL;
01723         h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
01724         h->modes = h->rdevs = NULL;
01725         if (headerIsEntry(header, RPMTAG_SOURCEPACKAGE))
01726             isSource = 1;
01727         break;
01728 
01729       case 1:
01730         Py_INCREF(Py_None);
01731         h = (hdrObject *) Py_None;
01732         break;
01733 
01734       default:
01735         PyErr_SetString(pyrpmError, "error reading package");
01736         return NULL;
01737     }
01738 
01739     return Py_BuildValue("(Ni)", h, isSource);
01740 }
01741 
01744 static PyObject * hdrLoad(PyObject * self, PyObject * args) {
01745     char * obj, * copy=NULL;
01746     Header hdr;
01747     hdrObject * h;
01748     int len;
01749 
01750     if (!PyArg_ParseTuple(args, "s#", &obj, &len)) return NULL;
01751     
01752     copy = malloc(len);
01753     if (copy == NULL) {
01754         PyErr_SetString(pyrpmError, "out of memory");
01755         return NULL;
01756     }
01757 
01758     memcpy (copy, obj, len);
01759 
01760     hdr = headerLoad(copy);
01761     if (!hdr) {
01762         PyErr_SetString(pyrpmError, "bad header");
01763         return NULL;
01764     }
01765     compressFilelist (hdr);
01766     providePackageNVR (hdr);
01767 
01768     h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
01769     h->h = hdr;
01770     h->sigs = NULL;
01771     h->fileList = h->linkList = h->md5list = NULL;
01772     h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
01773     h->modes = h->rdevs = NULL;
01774 
01775     return (PyObject *) h;
01776 }
01777 
01780 static PyObject * rpmInitDB(PyObject * self, PyObject * args) {
01781     char *root;
01782     int forWrite = 0;
01783 
01784     if (!PyArg_ParseTuple(args, "i|s", &forWrite, &root)) return NULL;
01785 
01786     if (rpmdbInit(root, forWrite ? O_RDWR | O_CREAT: O_RDONLY)) {
01787         char * errmsg = "cannot initialize database in %s";
01788         char * errstr = NULL;
01789         int errsize;
01790 
01791         errsize = strlen(errmsg) + strlen(root);
01792         errstr = alloca(errsize);
01793         snprintf(errstr, errsize, errmsg, root);
01794         PyErr_SetString(pyrpmError, errstr);
01795         return NULL;
01796     }
01797 
01798     Py_INCREF(Py_None);
01799     return(Py_None);
01800 }
01801 
01804 static rpmdbObject * rpmOpenDB(PyObject * self, PyObject * args) {
01805     rpmdbObject * o;
01806     char * root = "";
01807     int forWrite = 0;
01808 
01809     if (!PyArg_ParseTuple(args, "|is", &forWrite, &root)) return NULL;
01810 
01811     o = PyObject_NEW(rpmdbObject, &rpmdbType);
01812     o->db = NULL;
01813     o->offx = 0;
01814     o->noffs = 0;
01815     o->offsets = NULL;
01816 
01817     if (rpmdbOpen(root, &o->db, forWrite ? O_RDWR | O_CREAT: O_RDONLY, 0644)) {
01818         char * errmsg = "cannot open database in %s";
01819         char * errstr = NULL;
01820         int errsize;
01821 
01822         Py_DECREF(o);
01823         /* PyErr_SetString should take varargs... */
01824         errsize = strlen(errmsg) + *root == '\0' ? 15 /* "/var/lib/rpm" */ : strlen(root);
01825         errstr = alloca(errsize);
01826         snprintf(errstr, errsize, errmsg, *root == '\0' ? "/var/lib/rpm" : root);
01827         PyErr_SetString(pyrpmError, errstr);
01828         return NULL;
01829     }
01830 
01831     return o;
01832 }
01833 
01836 static PyObject * rebuildDB (PyObject * self, PyObject * args) {
01837     char * root = "";
01838 
01839     if (!PyArg_ParseTuple(args, "s", &root)) return NULL;
01840 
01841     return Py_BuildValue("i", rpmdbRebuild(root));
01842 }
01843 
01846 static PyObject * rpmReadHeaders (FD_t fd) {
01847     PyObject * list;
01848     Header header;
01849     hdrObject * h;
01850 
01851     if (!fd) {
01852         PyErr_SetFromErrno(pyrpmError);
01853         return NULL;
01854     }
01855 
01856     list = PyList_New(0);
01857     Py_BEGIN_ALLOW_THREADS
01858     header = headerRead(fd, HEADER_MAGIC_YES);
01859 
01860     Py_END_ALLOW_THREADS
01861     while (header) {
01862         compressFilelist (header);
01863         providePackageNVR (header);
01864         h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
01865         h->h = header;
01866         h->sigs = NULL;
01867         h->fileList = h->linkList = h->md5list = NULL;
01868         h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
01869         h->modes = h->rdevs = NULL;
01870         if (PyList_Append(list, (PyObject *) h)) {
01871             Py_DECREF(list);
01872             Py_DECREF(h);
01873             return NULL;
01874         }
01875 
01876         Py_DECREF(h);
01877 
01878         Py_BEGIN_ALLOW_THREADS
01879         header = headerRead(fd, HEADER_MAGIC_YES);
01880         Py_END_ALLOW_THREADS
01881     }
01882 
01883     return list;
01884 }
01885 
01888 static PyObject * rpmHeaderFromFD(PyObject * self, PyObject * args) {
01889     FD_t fd;
01890     int fileno;
01891     PyObject * list;
01892 
01893     if (!PyArg_ParseTuple(args, "i", &fileno)) return NULL;
01894     fd = fdDup(fileno);
01895 
01896     list = rpmReadHeaders (fd);
01897     Fclose(fd);
01898 
01899     return list;
01900 }
01901 
01904 static PyObject * rpmHeaderFromFile(PyObject * self, PyObject * args) {
01905     char * filespec;
01906     FD_t fd;
01907     PyObject * list;
01908 
01909     if (!PyArg_ParseTuple(args, "s", &filespec)) return NULL;
01910     fd = Fopen(filespec, "r.fdio");
01911 
01912     if (!fd) {
01913         PyErr_SetFromErrno(pyrpmError);
01914         return NULL;
01915     }
01916 
01917     list = rpmReadHeaders (fd);
01918     Fclose(fd);
01919 
01920     return list;
01921 }
01922 
01926 /* this assumes the order of list matches the order of the new headers, and
01927    throws an exception if that isn't true */
01928 static int rpmMergeHeaders(PyObject * list, FD_t fd, int matchTag) {
01929     Header newH;
01930     HeaderIterator iter;
01931     int_32 * newMatch, * oldMatch;
01932     hdrObject * ho;
01933     int count = 0;
01934     int type, c, tag;
01935     void * p;
01936 
01937     Py_BEGIN_ALLOW_THREADS
01938     newH = headerRead(fd, HEADER_MAGIC_YES);
01939 
01940     Py_END_ALLOW_THREADS
01941     while (newH) {
01942         if (!headerGetEntry(newH, matchTag, NULL, (void **) &newMatch, NULL)) {
01943             PyErr_SetString(pyrpmError, "match tag missing in new header");
01944             return 1;
01945         }
01946 
01947         ho = (hdrObject *) PyList_GetItem(list, count++);
01948         if (!ho) return 1;
01949 
01950         if (!headerGetEntry(ho->h, matchTag, NULL, (void **) &oldMatch, NULL)) {
01951             PyErr_SetString(pyrpmError, "match tag missing in new header");
01952             return 1;
01953         }
01954 
01955         if (*newMatch != *oldMatch) {
01956             PyErr_SetString(pyrpmError, "match tag mismatch");
01957             return 1;
01958         }
01959 
01960         if (ho->sigs) headerFree(ho->sigs);
01961         if (ho->md5list) free(ho->md5list);
01962         if (ho->fileList) free(ho->fileList);
01963         if (ho->linkList) free(ho->linkList);
01964 
01965         ho->sigs = NULL;
01966         ho->md5list = NULL;
01967         ho->fileList = NULL;
01968         ho->linkList = NULL;
01969 
01970         iter = headerInitIterator(newH);
01971 
01972         while (headerNextIterator(iter, &tag, &type, (void *) &p, &c)) {
01973             /* could be dupes */
01974             headerRemoveEntry(ho->h, tag);
01975             headerAddEntry(ho->h, tag, type, p, c);
01976             headerFreeData(p, type);
01977         }
01978 
01979         headerFreeIterator(iter);
01980 
01981         Py_BEGIN_ALLOW_THREADS
01982         newH = headerRead(fd, HEADER_MAGIC_YES);
01983         Py_END_ALLOW_THREADS
01984     }
01985 
01986     return 0;
01987 }
01988 
01989 static PyObject * rpmMergeHeadersFromFD(PyObject * self, PyObject * args) {
01990     FD_t fd;
01991     int fileno;
01992     PyObject * list;
01993     int rc;
01994     int matchTag;
01995 
01996     if (!PyArg_ParseTuple(args, "Oii", &list, &fileno, &matchTag)) return NULL;
01997 
01998     if (!PyList_Check(list)) {
01999         PyErr_SetString(PyExc_TypeError, "first parameter must be a list");
02000         return NULL;
02001     }
02002 
02003     fd = fdDup(fileno);
02004 
02005     rc = rpmMergeHeaders (list, fd, matchTag);
02006     Fclose(fd);
02007 
02008     if (rc) {
02009         return NULL;
02010     }
02011 
02012     Py_INCREF(Py_None);
02013     return Py_None;
02014 }
02015 
02018 static PyObject * errorCB = NULL, * errorData = NULL;
02019 
02022 static void errorcb (void)
02023 {
02024     PyObject * result, * args = NULL;
02025 
02026     if (errorData)
02027         args = Py_BuildValue("(O)", errorData);
02028 
02029     result = PyEval_CallObject(errorCB, args);
02030     Py_XDECREF(args);
02031 
02032     if (result == NULL) {
02033         PyErr_Print();
02034         PyErr_Clear();
02035     }
02036     Py_DECREF (result);
02037 }
02038 
02041 static PyObject * errorSetCallback (PyObject * self, PyObject * args) {
02042     if (errorCB != NULL) {
02043         Py_DECREF (errorCB);
02044         errorCB = NULL;
02045     }
02046 
02047     if (errorData != NULL) {
02048         Py_DECREF (errorData);
02049         errorData = NULL;
02050     }
02051 
02052     if (!PyArg_ParseTuple(args, "O|O", &errorCB, &errorData)) return NULL;
02053 
02054     /* if we're getting a void*, set the error callback to this. */
02055     /* also, we can possibly decref any python callbacks we had  */
02056     /* and set them to NULL.                                     */
02057     if (PyCObject_Check (errorCB)) {
02058         rpmErrorSetCallback (PyCObject_AsVoidPtr(errorCB));
02059 
02060         Py_XDECREF (errorCB);
02061         Py_XDECREF (errorData);
02062 
02063         errorCB   = NULL;
02064         errorData = NULL;
02065         
02066         Py_INCREF(Py_None);
02067         return Py_None;
02068     }
02069     
02070     if (!PyCallable_Check (errorCB)) {
02071         PyErr_SetString(PyExc_TypeError, "parameter must be callable");
02072         return NULL;
02073     }
02074 
02075     Py_INCREF (errorCB);
02076     Py_XINCREF (errorData);
02077 
02078     return PyCObject_FromVoidPtr(rpmErrorSetCallback (errorcb), NULL);
02079 }
02080 
02083 static PyObject * errorString (PyObject * self, PyObject * args) {
02084     return PyString_FromString(rpmErrorString ());
02085 }
02086 
02089 static PyObject * versionCompare (PyObject * self, PyObject * args) {
02090     hdrObject * h1, * h2;
02091 
02092     if (!PyArg_ParseTuple(args, "O!O!", &hdrType, &h1, &hdrType, &h2)) return NULL;
02093 
02094     return Py_BuildValue("i", rpmVersionCompare(h1->h, h2->h));
02095 }
02096 
02099 static PyObject * labelCompare (PyObject * self, PyObject * args) {
02100     char *v1, *r1, *e1, *v2, *r2, *e2;
02101     int rc;
02102 
02103     if (!PyArg_ParseTuple(args, "(zzz)(zzz)",
02104                           &e1, &v1, &r1,
02105                           &e2, &v2, &r2)) return NULL;
02106 
02107     if (e1 && !e2)
02108         return Py_BuildValue("i", 1);
02109     else if (!e1 && e2)
02110         return Py_BuildValue("i", -1);
02111     else if (e1 && e2) {
02112         int ep1, ep2;
02113         ep1 = atoi (e1);
02114         ep2 = atoi (e2);
02115         if (ep1 < ep2)
02116             return Py_BuildValue("i", -1);
02117         else if (ep1 > ep2)
02118             return Py_BuildValue("i", 1);
02119     }
02120 
02121     rc = rpmvercmp(v1, v2);
02122     if (rc)
02123         return Py_BuildValue("i", rc);
02124 
02125     return Py_BuildValue("i", rpmvercmp(r1, r2));
02126 }
02127 
02130 static PyObject * checkSig (PyObject * self, PyObject * args) {
02131     char * filename;
02132     int flags;
02133     int rc = 255;
02134 
02135     if (PyArg_ParseTuple(args, "si", &filename, &flags)) {
02136         const char *av[2];
02137         av[0] = filename;
02138         av[1] = NULL;
02139         rc = rpmCheckSig(flags, av);
02140     }
02141     return Py_BuildValue("i", rc);
02142 }
02143 
02144 /* hack to get the current header that's in the transaction set */
02147 static PyObject * getTsHeader (PyObject * self, PyObject * args) {
02148     hdrObject * h;
02149     
02150     if (transactionSetHeader) {
02151         h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
02152         h->h = headerLink(transactionSetHeader);
02153         h->sigs = NULL;
02154         h->fileList = h->linkList = h->md5list = NULL;
02155         h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
02156         h->modes = h->rdevs = NULL;
02157         return (PyObject *) h;
02158     }
02159     Py_INCREF(Py_None);
02160     return (PyObject *) Py_None;
02161 }
02162 
02165 typedef struct FDlist_t FDlist;
02166 
02169 struct FDlist_t {
02170     FILE *f;
02171     FD_t fd;
02172     char *note;
02173     FDlist *next;
02174 } ;
02175 
02178 static FDlist *fdhead = NULL;
02179 
02182 static FDlist *fdtail = NULL;
02183 
02186 static int closeCallback(FILE * f) {
02187     FDlist *node, *last;
02188 
02189     printf ("close callback on %p\n", f);
02190     
02191     node = fdhead;
02192     last = NULL;
02193     while (node) {
02194         if (node->f == f)
02195             break;
02196         last = node;
02197         node = node->next;
02198     }
02199     if (node) {
02200         if (last)
02201             last->next = node->next;
02202         else
02203             fdhead = node->next;
02204         printf ("closing %s %p\n", node->note, node->fd);
02205         free (node->note);
02206         node->fd = fdLink(node->fd, "closeCallback");
02207         Fclose (node->fd);
02208         while (node->fd)
02209             node->fd = fdFree(node->fd, "closeCallback");
02210         free (node);
02211     }
02212     return 0; 
02213 }
02214 
02215 #if 0
02216 
02218 static PyObject * doFopen(PyObject * self, PyObject * args) {
02219     char * path, * mode;
02220     FDlist *node;
02221     
02222     if (!PyArg_ParseTuple(args, "ss", &path, &mode))
02223         return NULL;
02224     
02225     node = malloc (sizeof(FDlist));
02226     
02227     node->fd = Fopen(path, mode);
02228     node->fd = fdLink(node->fd, "doFopen");
02229     node->note = strdup (path);
02230 
02231     if (!node->fd) {
02232         PyErr_SetFromErrno(pyrpmError);
02233         free (node);
02234         return NULL;
02235     }
02236     
02237     if (Ferror(node->fd)) {
02238         const char *err = Fstrerror(node->fd);
02239         free(node);
02240         if (err) {
02241             PyErr_SetString(pyrpmError, err);
02242             return NULL;
02243         }
02244     }
02245     node->f = fdGetFp(node->fd);
02246     printf ("opening %s fd = %p f = %p\n", node->note, node->fd, node->f);
02247     if (!node->f) {
02248         PyErr_SetString(pyrpmError, "FD_t has no FILE*");
02249         free(node);
02250         return NULL;
02251     }
02252 
02253     node->next = NULL;
02254     if (!fdhead) {
02255         fdhead = fdtail = node;
02256     } else if (fdtail) {
02257         fdtail->next = node;
02258     } else {
02259         fdhead = node;
02260     }
02261     fdtail = node;
02262     
02263     return PyFile_FromFile (node->f, path, mode, closeCallback);
02264 }
02265 #endif
02266 
02269 static PyMethodDef rpmModuleMethods[] = {
02270     { "TransactionSet", (PyCFunction) rpmtransCreate, METH_VARARGS, NULL },
02271     { "addMacro", (PyCFunction) doAddMacro, METH_VARARGS, NULL },
02272     { "delMacro", (PyCFunction) doDelMacro, METH_VARARGS, NULL },
02273     { "archscore", (PyCFunction) archScore, METH_VARARGS, NULL },
02274     { "findUpgradeSet", (PyCFunction) findUpgradeSet, METH_VARARGS, NULL },
02275     { "headerFromPackage", (PyCFunction) rpmHeaderFromPackage, METH_VARARGS, NULL },
02276     { "headerLoad", (PyCFunction) hdrLoad, METH_VARARGS, NULL },
02277     { "initdb", (PyCFunction) rpmInitDB, METH_VARARGS, NULL },
02278     { "opendb", (PyCFunction) rpmOpenDB, METH_VARARGS, NULL },
02279     { "rebuilddb", (PyCFunction) rebuildDB, METH_VARARGS, NULL },
02280     { "readHeaderListFromFD", (PyCFunction) rpmHeaderFromFD, METH_VARARGS, NULL },
02281     { "mergeHeaderListFromFD", (PyCFunction) rpmMergeHeadersFromFD, METH_VARARGS, NULL },
02282     { "readHeaderListFromFile", (PyCFunction) rpmHeaderFromFile, METH_VARARGS, NULL },
02283     { "errorSetCallback", (PyCFunction) errorSetCallback, METH_VARARGS, NULL },
02284     { "errorString", (PyCFunction) errorString, METH_VARARGS, NULL },
02285     { "versionCompare", (PyCFunction) versionCompare, METH_VARARGS, NULL },
02286     { "labelCompare", (PyCFunction) labelCompare, METH_VARARGS, NULL },
02287     { "checksig", (PyCFunction) checkSig, METH_VARARGS, NULL },
02288     { "getTransactionCallbackHeader", (PyCFunction) getTsHeader, METH_VARARGS, NULL },
02289 /*      { "Fopen", (PyCFunction) doFopen, METH_VARARGS, NULL }, */
02290     { NULL }
02291 } ;
02292 
02295 void initrpm(void) {
02296     PyObject * m, * d, *o, * tag = NULL, * dict;
02297     int i;
02298     const struct headerSprintfExtension * extensions = rpmHeaderFormats;
02299     struct headerSprintfExtension * ext;
02300 
02301 /*      _rpmio_debug = -1; */
02302     rpmReadConfigFiles(NULL, NULL);
02303 
02304     m = Py_InitModule("rpm", rpmModuleMethods);
02305     d = PyModule_GetDict(m);
02306 
02307     pyrpmError = PyString_FromString("rpm.error");
02308     PyDict_SetItemString(d, "error", pyrpmError);
02309     Py_DECREF(pyrpmError);
02310 
02311     dict = PyDict_New();
02312 
02313     for (i = 0; i < rpmTagTableSize; i++) {
02314         tag = PyInt_FromLong(rpmTagTable[i].val);
02315         PyDict_SetItemString(d, (char *) rpmTagTable[i].name, tag);
02316         Py_DECREF(tag);
02317         PyDict_SetItem(dict, tag, o=PyString_FromString(rpmTagTable[i].name + 7));
02318         Py_DECREF(o);
02319     }
02320 
02321     while (extensions->name) {
02322         if (extensions->type == HEADER_EXT_TAG) {
02323             (const struct headerSprintfExtension *) ext = extensions;
02324             PyDict_SetItemString(d, extensions->name, o=PyCObject_FromVoidPtr(ext, NULL));
02325             Py_DECREF(o);
02326             PyDict_SetItem(dict, tag, o=PyString_FromString(ext->name + 7));
02327             Py_DECREF(o);    
02328         }
02329         extensions++;
02330     }
02331 
02332     PyDict_SetItemString(d, "tagnames", dict);
02333     Py_DECREF(dict);
02334 
02335 
02336 #define REGISTER_ENUM(val) \
02337     PyDict_SetItemString(d, #val, o=PyInt_FromLong(## val)); \
02338     Py_DECREF(o);
02339     
02340     REGISTER_ENUM(RPMFILE_STATE_NORMAL);
02341     REGISTER_ENUM(RPMFILE_STATE_REPLACED);
02342     REGISTER_ENUM(RPMFILE_STATE_NOTINSTALLED);
02343     REGISTER_ENUM(RPMFILE_STATE_NETSHARED);
02344 
02345     REGISTER_ENUM(RPMFILE_CONFIG);
02346     REGISTER_ENUM(RPMFILE_DOC);
02347     REGISTER_ENUM(RPMFILE_MISSINGOK);
02348     REGISTER_ENUM(RPMFILE_NOREPLACE);
02349     REGISTER_ENUM(RPMFILE_GHOST);
02350     REGISTER_ENUM(RPMFILE_LICENSE);
02351     REGISTER_ENUM(RPMFILE_README);
02352 
02353     REGISTER_ENUM(RPMDEP_SENSE_REQUIRES);
02354     REGISTER_ENUM(RPMDEP_SENSE_CONFLICTS);
02355 
02356     REGISTER_ENUM(RPMSENSE_SERIAL);
02357     REGISTER_ENUM(RPMSENSE_LESS);
02358     REGISTER_ENUM(RPMSENSE_GREATER);
02359     REGISTER_ENUM(RPMSENSE_EQUAL);
02360     REGISTER_ENUM(RPMSENSE_PREREQ);
02361     REGISTER_ENUM(RPMSENSE_INTERP);
02362     REGISTER_ENUM(RPMSENSE_SCRIPT_PRE);
02363     REGISTER_ENUM(RPMSENSE_SCRIPT_POST);
02364     REGISTER_ENUM(RPMSENSE_SCRIPT_PREUN);
02365     REGISTER_ENUM(RPMSENSE_SCRIPT_POSTUN);
02366     REGISTER_ENUM(RPMSENSE_SCRIPT_VERIFY);
02367     REGISTER_ENUM(RPMSENSE_FIND_REQUIRES);
02368     REGISTER_ENUM(RPMSENSE_FIND_PROVIDES);
02369     REGISTER_ENUM(RPMSENSE_TRIGGERIN);
02370     REGISTER_ENUM(RPMSENSE_TRIGGERUN);
02371     REGISTER_ENUM(RPMSENSE_TRIGGERPOSTUN);
02372     REGISTER_ENUM(RPMSENSE_MULTILIB);
02373     REGISTER_ENUM(RPMSENSE_SCRIPT_PREP);
02374     REGISTER_ENUM(RPMSENSE_SCRIPT_BUILD);
02375     REGISTER_ENUM(RPMSENSE_SCRIPT_INSTALL);
02376     REGISTER_ENUM(RPMSENSE_SCRIPT_CLEAN);
02377     REGISTER_ENUM(RPMSENSE_RPMLIB);
02378     REGISTER_ENUM(RPMSENSE_TRIGGERPREIN);
02379 
02380     REGISTER_ENUM(RPMTRANS_FLAG_TEST);
02381     REGISTER_ENUM(RPMTRANS_FLAG_BUILD_PROBS);
02382     REGISTER_ENUM(RPMTRANS_FLAG_NOSCRIPTS);
02383     REGISTER_ENUM(RPMTRANS_FLAG_JUSTDB);
02384     REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERS);
02385     REGISTER_ENUM(RPMTRANS_FLAG_NODOCS);
02386     REGISTER_ENUM(RPMTRANS_FLAG_ALLFILES);
02387     REGISTER_ENUM(RPMTRANS_FLAG_KEEPOBSOLETE);
02388     REGISTER_ENUM(RPMTRANS_FLAG_MULTILIB);
02389 
02390     REGISTER_ENUM(RPMPROB_FILTER_IGNOREOS);
02391     REGISTER_ENUM(RPMPROB_FILTER_IGNOREARCH);
02392     REGISTER_ENUM(RPMPROB_FILTER_REPLACEPKG);
02393     REGISTER_ENUM(RPMPROB_FILTER_FORCERELOCATE);
02394     REGISTER_ENUM(RPMPROB_FILTER_REPLACENEWFILES);
02395     REGISTER_ENUM(RPMPROB_FILTER_REPLACEOLDFILES);
02396     REGISTER_ENUM(RPMPROB_FILTER_OLDPACKAGE);
02397     REGISTER_ENUM(RPMPROB_FILTER_DISKSPACE);
02398     REGISTER_ENUM(RPMPROB_FILTER_DISKNODES);
02399 
02400     REGISTER_ENUM(RPMCALLBACK_INST_PROGRESS);
02401     REGISTER_ENUM(RPMCALLBACK_INST_START);
02402     REGISTER_ENUM(RPMCALLBACK_INST_OPEN_FILE);
02403     REGISTER_ENUM(RPMCALLBACK_INST_CLOSE_FILE);
02404     REGISTER_ENUM(RPMCALLBACK_TRANS_PROGRESS);
02405     REGISTER_ENUM(RPMCALLBACK_TRANS_START);
02406     REGISTER_ENUM(RPMCALLBACK_TRANS_STOP);
02407     REGISTER_ENUM(RPMCALLBACK_UNINST_PROGRESS);
02408     REGISTER_ENUM(RPMCALLBACK_UNINST_START);
02409     REGISTER_ENUM(RPMCALLBACK_UNINST_STOP);
02410 
02411     REGISTER_ENUM(RPMPROB_BADARCH);
02412     REGISTER_ENUM(RPMPROB_BADOS);
02413     REGISTER_ENUM(RPMPROB_PKG_INSTALLED);
02414     REGISTER_ENUM(RPMPROB_BADRELOCATE);
02415     REGISTER_ENUM(RPMPROB_REQUIRES);
02416     REGISTER_ENUM(RPMPROB_CONFLICT);
02417     REGISTER_ENUM(RPMPROB_NEW_FILE_CONFLICT);
02418     REGISTER_ENUM(RPMPROB_FILE_CONFLICT);
02419     REGISTER_ENUM(RPMPROB_OLDPACKAGE);
02420     REGISTER_ENUM(RPMPROB_DISKSPACE);
02421     REGISTER_ENUM(RPMPROB_DISKNODES);
02422     REGISTER_ENUM(RPMPROB_BADPRETRANS);
02423 
02424     REGISTER_ENUM(CHECKSIG_PGP);
02425     REGISTER_ENUM(CHECKSIG_GPG);
02426     REGISTER_ENUM(CHECKSIG_MD5);
02427 }
02428 

Generated at Mon May 21 08:53:40 2001 for rpm by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001