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>
00012 #include <dirent.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
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, PyObject *keywords) {
00153 char * buf;
00154 PyObject * rc;
00155 int len, legacy = 0;
00156 static char *kwlist[] = { "legacyHeader", NULL};
00157
00158 if (!PyArg_ParseTupleAndKeywords(args, keywords, "|i", kwlist, &legacy))
00159 return NULL;
00160
00161 if (legacy) {
00162 Header h;
00163
00164 h = headerCopy(s->h);
00165 len = headerSizeof(h, 0);
00166 buf = headerUnload(h);
00167 } else {
00168 len = headerSizeof(s->h, 0);
00169 buf = headerUnload(s->h);
00170 }
00171
00172 rc = PyString_FromStringAndSize(buf, len);
00173 free(buf);
00174
00175 return rc;
00176 }
00177
00178
00179
00180
00181
00182
00183
00186 static PyObject * hdrVerifyFile(hdrObject * s, PyObject * args) {
00187 int fileNumber;
00188 rpmVerifyAttrs verifyResult = 0;
00189 PyObject * list, * tuple, * attrName;
00190 int type, count;
00191 struct stat sb;
00192 char buf[2048];
00193 int i;
00194 time_t timeInt;
00195 struct tm * timeStruct;
00196
00197 if (!PyInt_Check(args)) {
00198 PyErr_SetString(PyExc_TypeError, "integer expected");
00199 return NULL;
00200 }
00201
00202 fileNumber = (int) PyInt_AsLong(args);
00203
00204 if (rpmVerifyFile("", s->h, fileNumber, &verifyResult, RPMVERIFY_NONE)) {
00205 Py_INCREF(Py_None);
00206 return Py_None;
00207 }
00208
00209 list = PyList_New(0);
00210
00211 if (!verifyResult) return list;
00212
00213 if (!s->fileList) {
00214 headerGetEntry(s->h, RPMTAG_OLDFILENAMES, &type, (void **) &s->fileList,
00215 &count);
00216 }
00217
00218 lstat(s->fileList[fileNumber], &sb);
00219
00220 if (verifyResult & RPMVERIFY_MD5) {
00221 if (!s->md5list) {
00222 headerGetEntry(s->h, RPMTAG_FILEMD5S, &type, (void **) &s->md5list,
00223 &count);
00224 }
00225
00226 if (mdfile(s->fileList[fileNumber], buf)) {
00227 strcpy(buf, "(unknown)");
00228 }
00229
00230 tuple = PyTuple_New(3);
00231 attrName = PyString_FromString("checksum");
00232 PyTuple_SetItem(tuple, 0, attrName);
00233 PyTuple_SetItem(tuple, 1, PyString_FromString(s->md5list[fileNumber]));
00234 PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00235 PyList_Append(list, tuple);
00236 Py_DECREF(tuple);
00237 }
00238
00239 if (verifyResult & RPMVERIFY_FILESIZE) {
00240 if (!s->fileSizes) {
00241 headerGetEntry(s->h, RPMTAG_FILESIZES, &type, (void **) &s->fileSizes,
00242 &count);
00243
00244 }
00245
00246 tuple = PyTuple_New(3);
00247 attrName = PyString_FromString("size");
00248 PyTuple_SetItem(tuple, 0, attrName);
00249
00250 sprintf(buf, "%d", 100);
00251 PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00252 sprintf(buf, "%ld", sb.st_size);
00253 PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00254 PyList_Append(list, tuple);
00255 Py_DECREF(tuple);
00256 }
00257
00258 if (verifyResult & RPMVERIFY_LINKTO) {
00259 if (!s->linkList) {
00260 headerGetEntry(s->h, RPMTAG_FILELINKTOS, &type, (void **) &s->linkList,
00261 &count);
00262 }
00263
00264 i = readlink(s->fileList[fileNumber], buf, sizeof(buf));
00265 if (i <= 0)
00266 strcpy(buf, "(unknown)");
00267 else
00268 buf[i] = '\0';
00269
00270 tuple = PyTuple_New(3);
00271 attrName = PyString_FromString("link");
00272 PyTuple_SetItem(tuple, 0, attrName);
00273 PyTuple_SetItem(tuple, 1, PyString_FromString(s->linkList[fileNumber]));
00274 PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00275 PyList_Append(list, tuple);
00276 Py_DECREF(tuple);
00277 }
00278
00279 if (verifyResult & RPMVERIFY_MTIME) {
00280 if (!s->mtimes) {
00281 headerGetEntry(s->h, RPMTAG_FILEMTIMES, &type, (void **) &s->mtimes,
00282 &count);
00283 }
00284
00285 tuple = PyTuple_New(3);
00286 attrName = PyString_FromString("time");
00287 PyTuple_SetItem(tuple, 0, attrName);
00288
00289 timeInt = sb.st_mtime;
00290 timeStruct = localtime(&timeInt);
00291 strftime(buf, sizeof(buf) - 1, "%c", timeStruct);
00292 PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00293
00294 timeInt = s->mtimes[fileNumber];
00295 timeStruct = localtime(&timeInt);
00296 strftime(buf, sizeof(buf) - 1, "%c", timeStruct);
00297
00298 PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00299
00300 PyList_Append(list, tuple);
00301 Py_DECREF(tuple);
00302 }
00303
00304 if (verifyResult & RPMVERIFY_RDEV) {
00305 if (!s->rdevs) {
00306 headerGetEntry(s->h, RPMTAG_FILERDEVS, &type, (void **) &s->rdevs,
00307 &count);
00308 }
00309
00310 tuple = PyTuple_New(3);
00311 attrName = PyString_FromString("device");
00312
00313 PyTuple_SetItem(tuple, 0, attrName);
00314 sprintf(buf, "0x%-4x", s->rdevs[fileNumber]);
00315 PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00316 sprintf(buf, "0x%-4x", (unsigned int) sb.st_rdev);
00317 PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00318 PyList_Append(list, tuple);
00319 Py_DECREF(tuple);
00320 }
00321
00322
00323
00324 if (verifyResult & RPMVERIFY_USER) {
00325 if (!s->uids) {
00326 headerGetEntry(s->h, RPMTAG_FILEUIDS, &type, (void **) &s->uids,
00327 &count);
00328 }
00329
00330 tuple = PyTuple_New(3);
00331 attrName = PyString_FromString("uid");
00332 PyTuple_SetItem(tuple, 0, attrName);
00333 sprintf(buf, "%d", s->uids[fileNumber]);
00334 PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00335 sprintf(buf, "%d", sb.st_uid);
00336 PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00337 PyList_Append(list, tuple);
00338 Py_DECREF(tuple);
00339 }
00340
00341 if (verifyResult & RPMVERIFY_GROUP) {
00342 if (!s->gids) {
00343 headerGetEntry(s->h, RPMTAG_FILEGIDS, &type, (void **) &s->gids,
00344 &count);
00345 }
00346
00347 tuple = PyTuple_New(3);
00348 attrName = PyString_FromString("gid");
00349 PyTuple_SetItem(tuple, 0, attrName);
00350 sprintf(buf, "%d", s->gids[fileNumber]);
00351 PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00352 sprintf(buf, "%d", sb.st_gid);
00353 PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00354 PyList_Append(list, tuple);
00355 Py_DECREF(tuple);
00356 }
00357
00358 if (verifyResult & RPMVERIFY_MODE) {
00359 if (!s->modes) {
00360 headerGetEntry(s->h, RPMTAG_FILEMODES, &type, (void **) &s->modes,
00361 &count);
00362 }
00363
00364 tuple = PyTuple_New(3);
00365 attrName = PyString_FromString("permissions");
00366 PyTuple_SetItem(tuple, 0, attrName);
00367 sprintf(buf, "0%-4o", s->modes[fileNumber]);
00368 PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
00369 sprintf(buf, "0%-4o", sb.st_mode);
00370 PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
00371 PyList_Append(list, tuple);
00372 Py_DECREF(tuple);
00373 }
00374
00375 return list;
00376 }
00377
00380 static PyObject * hdrExpandFilelist(hdrObject * s, PyObject * args) {
00381 expandFilelist (s->h);
00382
00383 Py_INCREF(Py_None);
00384 return Py_None;
00385 }
00386
00389 static PyObject * hdrCompressFilelist(hdrObject * s, PyObject * args) {
00390 compressFilelist (s->h);
00391
00392 Py_INCREF(Py_None);
00393 return Py_None;
00394 }
00395
00396
00399 static void mungeFilelist(Header h)
00400 {
00401 const char ** fileNames = NULL;
00402 int count = 0;
00403
00404 if (!headerIsEntry (h, RPMTAG_BASENAMES)
00405 || !headerIsEntry (h, RPMTAG_DIRNAMES)
00406 || !headerIsEntry (h, RPMTAG_DIRINDEXES))
00407 compressFilelist(h);
00408
00409 rpmBuildFileList(h, &fileNames, &count);
00410
00411 if (fileNames == NULL || count <= 0)
00412 return;
00413
00414 headerAddEntry(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
00415 fileNames, count);
00416
00417 free((void *)fileNames);
00418 }
00419
00422 static PyObject * hdrFullFilelist(hdrObject * s, PyObject * args) {
00423 mungeFilelist (s->h);
00424
00425 Py_INCREF(Py_None);
00426 return Py_None;
00427 }
00428
00431 static struct PyMethodDef hdrMethods[] = {
00432 {"keys", (PyCFunction) hdrKeyList, 1 },
00433 {"unload", (PyCFunction) hdrUnload, METH_VARARGS|METH_KEYWORDS },
00434 {"verifyFile", (PyCFunction) hdrVerifyFile, 1 },
00435 {"expandFilelist", (PyCFunction) hdrExpandFilelist, 1 },
00436 {"compressFilelist", (PyCFunction) hdrCompressFilelist, 1 },
00437 {"fullFilelist", (PyCFunction) hdrFullFilelist, 1 },
00438 {NULL, NULL}
00439 };
00440
00443 static PyObject * hdrGetAttr(hdrObject * s, char * name) {
00444 return Py_FindMethod(hdrMethods, (PyObject * ) s, name);
00445 }
00446
00449 static void hdrDealloc(hdrObject * s) {
00450 if (s->h) headerFree(s->h);
00451 if (s->sigs) headerFree(s->sigs);
00452 if (s->md5list) free(s->md5list);
00453 if (s->fileList) free(s->fileList);
00454 if (s->linkList) free(s->linkList);
00455 PyMem_DEL(s);
00456 }
00457
00460 static long tagNumFromPyObject (PyObject *item)
00461 {
00462 char * str;
00463 int i;
00464
00465 if (PyInt_Check(item)) {
00466 return PyInt_AsLong(item);
00467 } else if (PyString_Check(item)) {
00468 str = PyString_AsString(item);
00469 for (i = 0; i < rpmTagTableSize; i++)
00470 if (!xstrcasecmp(rpmTagTable[i].name + 7, str)) break;
00471 if (i < rpmTagTableSize) return rpmTagTable[i].val;
00472 }
00473 return -1;
00474 }
00475
00478 static PyObject * hdrSubscript(hdrObject * s, PyObject * item) {
00479 int type, count, i, tag = -1;
00480 void * data;
00481 PyObject * o, * metao;
00482 char ** stringArray;
00483 int forceArray = 0;
00484 int freeData = 0;
00485 char * str;
00486 struct headerSprintfExtension * ext = NULL;
00487 const struct headerSprintfExtension * extensions = rpmHeaderFormats;
00488
00489 if (PyCObject_Check (item))
00490 ext = PyCObject_AsVoidPtr(item);
00491 else
00492 tag = tagNumFromPyObject (item);
00493 if (tag == -1 && PyString_Check(item)) {
00494
00495
00496 str = PyString_AsString(item);
00497 while (extensions->name) {
00498 if (extensions->type == HEADER_EXT_TAG
00499 && !xstrcasecmp(extensions->name + 7, str)) {
00500 (const struct headerSprintfExtension *) ext = extensions;
00501 }
00502 extensions++;
00503 }
00504 }
00505
00506 if (ext) {
00507 ext->u.tagFunction(s->h, &type, (const void **) &data, &count, &freeData);
00508 } else {
00509 if (tag == -1) {
00510 PyErr_SetString(PyExc_KeyError, "unknown header tag");
00511 return NULL;
00512 }
00513
00514 if (!rpmPackageGetEntry(NULL, s->sigs, s->h, tag, &type, &data, &count))
00515 {
00516 Py_INCREF(Py_None);
00517 return Py_None;
00518 }
00519 }
00520
00521 switch (tag) {
00522 case RPMTAG_OLDFILENAMES:
00523 case RPMTAG_FILESIZES:
00524 case RPMTAG_FILESTATES:
00525 case RPMTAG_FILEMODES:
00526 case RPMTAG_FILEUIDS:
00527 case RPMTAG_FILEGIDS:
00528 case RPMTAG_FILERDEVS:
00529 case RPMTAG_FILEMTIMES:
00530 case RPMTAG_FILEMD5S:
00531 case RPMTAG_FILELINKTOS:
00532 case RPMTAG_FILEFLAGS:
00533 case RPMTAG_ROOT:
00534 case RPMTAG_FILEUSERNAME:
00535 case RPMTAG_FILEGROUPNAME:
00536 forceArray = 1;
00537 break;
00538 case RPMTAG_SUMMARY:
00539 case RPMTAG_GROUP:
00540 case RPMTAG_DESCRIPTION:
00541 freeData = 1;
00542 break;
00543 default:
00544 break;
00545 }
00546
00547 switch (type) {
00548 case RPM_BIN_TYPE:
00549 o = PyString_FromStringAndSize(data, count);
00550 break;
00551
00552 case RPM_INT32_TYPE:
00553 if (count != 1 || forceArray) {
00554 metao = PyList_New(0);
00555 for (i = 0; i < count; i++) {
00556 o = PyInt_FromLong(((int *) data)[i]);
00557 PyList_Append(metao, o);
00558 Py_DECREF(o);
00559 }
00560 o = metao;
00561 } else {
00562 o = PyInt_FromLong(*((int *) data));
00563 }
00564 break;
00565
00566 case RPM_CHAR_TYPE:
00567 case RPM_INT8_TYPE:
00568 if (count != 1 || forceArray) {
00569 metao = PyList_New(0);
00570 for (i = 0; i < count; i++) {
00571 o = PyInt_FromLong(((char *) data)[i]);
00572 PyList_Append(metao, o);
00573 Py_DECREF(o);
00574 }
00575 o = metao;
00576 } else {
00577 o = PyInt_FromLong(*((char *) data));
00578 }
00579 break;
00580
00581 case RPM_INT16_TYPE:
00582 if (count != 1 || forceArray) {
00583 metao = PyList_New(0);
00584 for (i = 0; i < count; i++) {
00585 o = PyInt_FromLong(((short *) data)[i]);
00586 PyList_Append(metao, o);
00587 Py_DECREF(o);
00588 }
00589 o = metao;
00590 } else {
00591 o = PyInt_FromLong(*((short *) data));
00592 }
00593 break;
00594
00595 case RPM_STRING_ARRAY_TYPE:
00596 stringArray = data;
00597
00598 metao = PyList_New(0);
00599 for (i = 0; i < count; i++) {
00600 o = PyString_FromString(stringArray[i]);
00601 PyList_Append(metao, o);
00602 Py_DECREF(o);
00603 }
00604 free (stringArray);
00605 o = metao;
00606 break;
00607
00608 case RPM_STRING_TYPE:
00609 if (count != 1 || forceArray) {
00610 stringArray = data;
00611
00612 metao = PyList_New(0);
00613 for (i=0; i < count; i++) {
00614 o = PyString_FromString(stringArray[i]);
00615 PyList_Append(metao, o);
00616 Py_DECREF(o);
00617 }
00618 o = metao;
00619 } else {
00620 o = PyString_FromString(data);
00621 if (freeData)
00622 free (data);
00623 }
00624 break;
00625
00626 default:
00627 PyErr_SetString(PyExc_TypeError, "unsupported type in header");
00628 return NULL;
00629 }
00630
00631 return o;
00632 }
00633
00636 static PyMappingMethods hdrAsMapping = {
00637 (inquiry) 0,
00638 (binaryfunc) hdrSubscript,
00639 (objobjargproc)0,
00640 };
00641
00644 static PyTypeObject hdrType = {
00645 PyObject_HEAD_INIT(&PyType_Type)
00646 0,
00647 "header",
00648 sizeof(hdrObject),
00649 0,
00650 (destructor) hdrDealloc,
00651 0,
00652 (getattrfunc) hdrGetAttr,
00653 0,
00654 0,
00655 0,
00656 0,
00657 0,
00658 &hdrAsMapping,
00659 };
00660
00673
00676 struct rpmdbObject_s {
00677 PyObject_HEAD;
00678 rpmdb db;
00679 int offx;
00680 int noffs;
00681 int *offsets;
00682 } ;
00683
00686 struct rpmdbMIObject_s {
00687 PyObject_HEAD;
00688 rpmdbObject *db;
00689 rpmdbMatchIterator mi;
00690 } ;
00691
00694 static PyObject *
00695 rpmdbMINext(rpmdbMIObject * s, PyObject * args) {
00696
00697 Header h;
00698 hdrObject * ho;
00699
00700
00701 h = rpmdbNextIterator(s->mi);
00702 if (!h) {
00703 Py_INCREF(Py_None);
00704 return Py_None;
00705 }
00706
00707 ho = PyObject_NEW(hdrObject, &hdrType);
00708 ho->h = headerLink(h);
00709 ho->sigs = NULL;
00710 ho->fileList = ho->linkList = ho->md5list = NULL;
00711 ho->uids = ho->gids = ho->mtimes = ho->fileSizes = NULL;
00712 ho->modes = ho->rdevs = NULL;
00713
00714 return (PyObject *) ho;
00715 }
00716
00719 static struct PyMethodDef rpmdbMIMethods[] = {
00720 {"next", (PyCFunction) rpmdbMINext, 1 },
00721 {NULL, NULL}
00722 };
00723
00726 static PyObject * rpmdbMIGetAttr (rpmdbObject *s, char *name) {
00727 return Py_FindMethod (rpmdbMIMethods, (PyObject *) s, name);
00728 }
00729
00732 static void rpmdbMIDealloc(rpmdbMIObject * s) {
00733 if (s && s->mi) {
00734 rpmdbFreeIterator(s->mi);
00735 }
00736 Py_DECREF (s->db);
00737 PyMem_DEL(s);
00738 }
00739
00742 static PyTypeObject rpmdbMIType = {
00743 PyObject_HEAD_INIT(&PyType_Type)
00744 0,
00745 "rpmdbMatchIterator",
00746 sizeof(rpmdbMIObject),
00747 0,
00748 (destructor) rpmdbMIDealloc,
00749 0,
00750 (getattrfunc) rpmdbMIGetAttr,
00751 0,
00752 0,
00753 0,
00754 0,
00755 0,
00756 0,
00757 };
00758
00827
00830 static PyObject * rpmdbFirst(rpmdbObject * s, PyObject * args) {
00831 int first;
00832
00833 if (!PyArg_ParseTuple (args, "")) return NULL;
00834
00835
00836 if (s->offsets == NULL || s->noffs <= 0) {
00837 rpmdbMatchIterator mi;
00838 Header h;
00839
00840 if (s->offsets)
00841 free(s->offsets);
00842 s->offsets = NULL;
00843 s->noffs = 0;
00844 mi = rpmdbInitIterator(s->db, RPMDBI_PACKAGES, NULL, 0);
00845 while ((h = rpmdbNextIterator(mi)) != NULL) {
00846 s->noffs++;
00847 s->offsets = realloc(s->offsets, s->noffs * sizeof(s->offsets[0]));
00848 s->offsets[s->noffs-1] = rpmdbGetIteratorOffset(mi);
00849 }
00850 rpmdbFreeIterator(mi);
00851 }
00852
00853 s->offx = 0;
00854 if (s->offsets != NULL && s->offx < s->noffs)
00855 first = s->offsets[s->offx++];
00856 else
00857 first = 0;
00858
00859 if (!first) {
00860 PyErr_SetString(pyrpmError, "cannot find first entry in database\n");
00861 return NULL;
00862 }
00863
00864 return Py_BuildValue("i", first);
00865 }
00866
00869 static PyObject * rpmdbNext(rpmdbObject * s, PyObject * args) {
00870 int where;
00871
00872 if (!PyArg_ParseTuple (args, "i", &where)) return NULL;
00873
00874 if (s->offsets == NULL || s->offx >= s->noffs) {
00875 Py_INCREF(Py_None);
00876 return Py_None;
00877 }
00878
00879 where = s->offsets[s->offx++];
00880
00881 if (!where) {
00882 Py_INCREF(Py_None);
00883 return Py_None;
00884 }
00885
00886 return Py_BuildValue("i", where);
00887 }
00888
00891 static PyObject * handleDbResult(rpmdbMatchIterator mi) {
00892 PyObject * list, *o;
00893
00894 list = PyList_New(0);
00895
00896
00897 if (mi != NULL) {
00898 while (rpmdbNextIterator(mi)) {
00899 PyList_Append(list, o=PyInt_FromLong(rpmdbGetIteratorOffset(mi)));
00900 Py_DECREF(o);
00901 }
00902 rpmdbFreeIterator(mi);
00903 }
00904
00905 return list;
00906 }
00907
00910 static PyObject * rpmdbByFile(rpmdbObject * s, PyObject * args) {
00911 char * str;
00912
00913 if (!PyArg_ParseTuple(args, "s", &str)) return NULL;
00914
00915 return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_BASENAMES, str, 0));
00916 }
00917
00920 static PyObject * rpmdbByName(rpmdbObject * s, PyObject * args) {
00921 char * str;
00922
00923 if (!PyArg_ParseTuple(args, "s", &str)) return NULL;
00924
00925 return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_NAME, str, 0));
00926 }
00927
00930 static PyObject * rpmdbByProvides(rpmdbObject * s, PyObject * args) {
00931 char * str;
00932
00933 if (!PyArg_ParseTuple(args, "s", &str)) return NULL;
00934
00935 return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_PROVIDENAME, str, 0));
00936 }
00937
00940 static rpmdbMIObject *
00941 py_rpmdbInitIterator (rpmdbObject * s, PyObject * args) {
00942 PyObject *index = NULL;
00943 char *key = NULL;
00944 int len = 0, tag = -1;
00945 rpmdbMIObject * mio;
00946
00947 if (!PyArg_ParseTuple(args, "|Ozi", &index, &key, &len))
00948 return NULL;
00949
00950 if (index == NULL)
00951 tag = 0;
00952 else if ((tag = tagNumFromPyObject (index)) == -1) {
00953 PyErr_SetString(PyExc_TypeError, "unknown tag type");
00954 return NULL;
00955 }
00956
00957 mio = (rpmdbMIObject *) PyObject_NEW(rpmdbMIObject, &rpmdbMIType);
00958 if (mio == NULL) {
00959 PyErr_SetString(pyrpmError, "out of memory creating rpmdbMIObject");
00960 return NULL;
00961 }
00962
00963 mio->mi = rpmdbInitIterator(s->db, tag, key, len);
00964 mio->db = s;
00965 Py_INCREF (mio->db);
00966
00967 return mio;
00968 }
00969
00972 static struct PyMethodDef rpmdbMethods[] = {
00973 {"firstkey", (PyCFunction) rpmdbFirst, 1 },
00974 {"nextkey", (PyCFunction) rpmdbNext, 1 },
00975 {"findbyfile", (PyCFunction) rpmdbByFile, 1 },
00976 {"findbyname", (PyCFunction) rpmdbByName, 1 },
00977 {"findbyprovides", (PyCFunction) rpmdbByProvides, 1 },
00978 {"match", (PyCFunction) py_rpmdbInitIterator, 1 },
00979 {NULL, NULL}
00980 };
00981
00984 static PyObject * rpmdbGetAttr(rpmdbObject * s, char * name) {
00985 return Py_FindMethod(rpmdbMethods, (PyObject * ) s, name);
00986 }
00987
00990 static void rpmdbDealloc(rpmdbObject * s) {
00991 if (s->offsets) {
00992 free(s->offsets);
00993 }
00994 if (s->db) {
00995 rpmdbClose(s->db);
00996 }
00997 PyMem_DEL(s);
00998 }
00999
01000 #ifndef DYINGSOON
01001
01003 static int
01004 rpmdbLength(rpmdbObject * s) {
01005 int count = 0;
01006
01007 { rpmdbMatchIterator mi;
01008
01009
01010 mi = rpmdbInitIterator(s->db, RPMDBI_PACKAGES, NULL, 0);
01011
01012 while (rpmdbNextIterator(mi) != NULL)
01013 count++;
01014 rpmdbFreeIterator(mi);
01015 }
01016
01017 return count;
01018 }
01019
01022 static hdrObject *
01023 rpmdbSubscript(rpmdbObject * s, PyObject * key) {
01024 int offset;
01025 hdrObject * h;
01026
01027 if (!PyInt_Check(key)) {
01028 PyErr_SetString(PyExc_TypeError, "integer expected");
01029 return NULL;
01030 }
01031
01032 offset = (int) PyInt_AsLong(key);
01033
01034 h = PyObject_NEW(hdrObject, &hdrType);
01035 h->h = NULL;
01036 h->sigs = NULL;
01037 { rpmdbMatchIterator mi;
01038 mi = rpmdbInitIterator(s->db, RPMDBI_PACKAGES, &offset, sizeof(offset));
01039 if ((h->h = rpmdbNextIterator(mi)) != NULL)
01040 h->h = headerLink(h->h);
01041 rpmdbFreeIterator(mi);
01042 }
01043 h->fileList = h->linkList = h->md5list = NULL;
01044 h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
01045 h->modes = h->rdevs = NULL;
01046 if (!h->h) {
01047 Py_DECREF(h);
01048 PyErr_SetString(pyrpmError, "cannot read rpmdb entry");
01049 return NULL;
01050 }
01051
01052 return h;
01053 }
01054
01057 static PyMappingMethods rpmdbAsMapping = {
01058 (inquiry) rpmdbLength,
01059 (binaryfunc) rpmdbSubscript,
01060 (objobjargproc)0,
01061 };
01062 #endif
01063
01066 static PyTypeObject rpmdbType = {
01067 PyObject_HEAD_INIT(&PyType_Type)
01068 0,
01069 "rpmdb",
01070 sizeof(rpmdbObject),
01071 0,
01072 (destructor) rpmdbDealloc,
01073 0,
01074 (getattrfunc) rpmdbGetAttr,
01075 0,
01076 0,
01077 0,
01078 0,
01079 0,
01080 #ifndef DYINGSOON
01081 &rpmdbAsMapping,
01082 #else
01083 0,
01084 #endif
01085 };
01086
01191
01194 struct rpmtransObject_s {
01195 PyObject_HEAD;
01196 rpmdbObject * dbo;
01197 rpmTransactionSet ts;
01198 PyObject * keyList;
01199 FD_t scriptFd;
01200 } ;
01201
01204 static PyObject * rpmtransAdd(rpmtransObject * s, PyObject * args) {
01205 hdrObject * h;
01206 PyObject * key;
01207 char * how = NULL;
01208 int isUpgrade = 0;
01209
01210 if (!PyArg_ParseTuple(args, "OO|s", &h, &key, &how)) return NULL;
01211 if (h->ob_type != &hdrType) {
01212 PyErr_SetString(PyExc_TypeError, "bad type for header argument");
01213 return NULL;
01214 }
01215
01216 if (how && strcmp(how, "a") && strcmp(how, "u") && strcmp(how, "i")) {
01217 PyErr_SetString(PyExc_TypeError, "how argument must be \"u\", \"a\", or \"i\"");
01218 return NULL;
01219 } else if (how && !strcmp(how, "u"))
01220 isUpgrade = 1;
01221
01222 if (how && !strcmp(how, "a"))
01223 rpmtransAvailablePackage(s->ts, h->h, key);
01224 else
01225 rpmtransAddPackage(s->ts, h->h, NULL, key, isUpgrade, NULL);
01226
01227
01228 if (key) {
01229 PyList_Append(s->keyList, key);
01230 }
01231
01232 Py_INCREF(Py_None);
01233 return Py_None;
01234 }
01235
01238 static PyObject * rpmtransRemove(rpmtransObject * s, PyObject * args) {
01239 char * name;
01240 int count;
01241 rpmdbMatchIterator mi;
01242
01243 if (!PyArg_ParseTuple(args, "s", &name))
01244 return NULL;
01245
01246
01247 mi = rpmdbInitIterator(s->dbo->db, RPMDBI_LABEL, name, 0);
01248 count = rpmdbGetIteratorCount(mi);
01249 if (count <= 0) {
01250 PyErr_SetString(pyrpmError, "package not installed");
01251 return NULL;
01252 } else {
01253 Header h;
01254 while ((h = rpmdbNextIterator(mi)) != NULL) {
01255 unsigned int recOffset = rpmdbGetIteratorOffset(mi);
01256 if (recOffset) {
01257 rpmtransRemovePackage(s->ts, recOffset);
01258 }
01259 }
01260 }
01261 rpmdbFreeIterator(mi);
01262
01263 Py_INCREF(Py_None);
01264 return Py_None;
01265 }
01266
01269 static PyObject * rpmtransDepCheck(rpmtransObject * s, PyObject * args) {
01270 struct rpmDependencyConflict * conflicts;
01271 int numConflicts;
01272 PyObject * list, * cf;
01273 int i;
01274
01275 if (!PyArg_ParseTuple(args, "")) return NULL;
01276
01277 rpmdepCheck(s->ts, &conflicts, &numConflicts);
01278 if (numConflicts) {
01279 list = PyList_New(0);
01280
01281 for (i = 0; i < numConflicts; i++) {
01282 cf = Py_BuildValue("((sss)(ss)iOi)", conflicts[i].byName,
01283 conflicts[i].byVersion, conflicts[i].byRelease,
01284
01285 conflicts[i].needsName,
01286 conflicts[i].needsVersion,
01287
01288 conflicts[i].needsFlags,
01289 conflicts[i].suggestedPackage ?
01290 conflicts[i].suggestedPackage : Py_None,
01291 conflicts[i].sense);
01292 PyList_Append(list, (PyObject *) cf);
01293 Py_DECREF(cf);
01294 }
01295
01296 rpmdepFreeConflicts(conflicts, numConflicts);
01297
01298 return list;
01299 }
01300
01301 Py_INCREF(Py_None);
01302 return Py_None;
01303 }
01304
01307 static PyObject * rpmtransOrder(rpmtransObject * s, PyObject * args) {
01308 if (!PyArg_ParseTuple(args, "")) return NULL;
01309
01310 rpmdepOrder(s->ts);
01311
01312 Py_INCREF(Py_None);
01313 return Py_None;
01314 }
01315
01318 static PyObject * py_rpmtransGetKeys(rpmtransObject * s, PyObject * args) {
01319 const void **data = NULL;
01320 int num, i;
01321 PyObject *tuple;
01322
01323 rpmtransGetKeys(s->ts, &data, &num);
01324 if (data == NULL) {
01325 Py_INCREF(Py_None);
01326 return Py_None;
01327 }
01328
01329 tuple = PyTuple_New(num);
01330
01331 for (i = 0; i < num; i++) {
01332 PyObject *obj = (PyObject *) data[i];
01333 Py_INCREF(obj);
01334 PyTuple_SetItem(tuple, i, obj);
01335 }
01336
01337 free (data);
01338
01339 return tuple;
01340 }
01341
01344 struct tsCallbackType {
01345 PyObject * cb;
01346 PyObject * data;
01347 int pythonError;
01348 };
01349
01352 static Header transactionSetHeader = NULL;
01353
01356 static void * tsCallback(const void * hd, const rpmCallbackType what,
01357 const unsigned long amount, const unsigned long total,
01358 const void * pkgKey, rpmCallbackData data) {
01359 struct tsCallbackType * cbInfo = data;
01360 PyObject * args, * result;
01361 int fd;
01362 static FD_t fdt;
01363 const Header h = (Header) hd;
01364
01365 if (cbInfo->pythonError) return NULL;
01366
01367 if (!pkgKey) pkgKey = Py_None;
01368 transactionSetHeader = h;
01369
01370 args = Py_BuildValue("(illOO)", what, amount, total, pkgKey, cbInfo->data);
01371 result = PyEval_CallObject(cbInfo->cb, args);
01372 Py_DECREF(args);
01373
01374 if (!result) {
01375 cbInfo->pythonError = 1;
01376 return NULL;
01377 }
01378
01379 if (what == RPMCALLBACK_INST_OPEN_FILE) {
01380 if (!PyArg_Parse(result, "i", &fd)) {
01381 cbInfo->pythonError = 1;
01382 return NULL;
01383 }
01384 fdt = fdDup(fd);
01385
01386 Py_DECREF(result);
01387 return fdt;
01388 }
01389
01390 if (what == RPMCALLBACK_INST_CLOSE_FILE) {
01391 Fclose (fdt);
01392 }
01393
01394 Py_DECREF(result);
01395
01396 return NULL;
01397 }
01398
01401 static PyObject * rpmtransRun(rpmtransObject * s, PyObject * args) {
01402 int flags, ignoreSet;
01403 int rc, i;
01404 PyObject * list, * prob;
01405 rpmProblemSet probs;
01406 struct tsCallbackType cbInfo;
01407
01408 if (!PyArg_ParseTuple(args, "iiOO", &flags, &ignoreSet, &cbInfo.cb,
01409 &cbInfo.data))
01410 return NULL;
01411
01412 cbInfo.pythonError = 0;
01413
01414 rc = rpmRunTransactions(s->ts, tsCallback, &cbInfo, NULL, &probs, flags,
01415 ignoreSet);
01416
01417 if (cbInfo.pythonError) {
01418 if (rc > 0)
01419 rpmProblemSetFree(probs);
01420 return NULL;
01421 }
01422
01423 if (rc < 0) {
01424 list = PyList_New(0);
01425 return list;
01426 } else if (!rc) {
01427 Py_INCREF(Py_None);
01428 return Py_None;
01429 }
01430
01431 list = PyList_New(0);
01432 for (i = 0; i < probs->numProblems; i++) {
01433 rpmProblem myprob = probs->probs + i;
01434 prob = Py_BuildValue("s(isi)", rpmProblemString(myprob),
01435 myprob->type,
01436 myprob->str1,
01437 myprob->ulong1);
01438 PyList_Append(list, prob);
01439 Py_DECREF(prob);
01440 }
01441
01442 rpmProblemSetFree(probs);
01443
01444 return list;
01445 }
01446
01449 static struct PyMethodDef rpmtransMethods[] = {
01450 {"add", (PyCFunction) rpmtransAdd, 1 },
01451 {"remove", (PyCFunction) rpmtransRemove, 1 },
01452 {"depcheck", (PyCFunction) rpmtransDepCheck, 1 },
01453 {"order", (PyCFunction) rpmtransOrder, 1 },
01454 {"getKeys", (PyCFunction) py_rpmtransGetKeys, 1 },
01455 {"run", (PyCFunction) rpmtransRun, 1 },
01456 {NULL, NULL}
01457 };
01458
01461 static PyObject * rpmtransGetAttr(rpmtransObject * o, char * name) {
01462 return Py_FindMethod(rpmtransMethods, (PyObject *) o, name);
01463 }
01464
01467 static void rpmtransDealloc(PyObject * o) {
01468 rpmtransObject * trans = (void *) o;
01469
01470 rpmtransFree(trans->ts);
01471 if (trans->dbo) {
01472 Py_DECREF(trans->dbo);
01473 }
01474 if (trans->scriptFd) Fclose(trans->scriptFd);
01475
01476
01477 Py_DECREF(trans->keyList);
01478 PyMem_DEL(o);
01479 }
01480
01483 static int rpmtransSetAttr(rpmtransObject * o, char * name,
01484 PyObject * val) {
01485 int i;
01486
01487 if (!strcmp(name, "scriptFd")) {
01488 if (!PyArg_Parse(val, "i", &i)) return 0;
01489 if (i < 0) {
01490 PyErr_SetString(PyExc_TypeError, "bad file descriptor");
01491 return -1;
01492 } else {
01493 o->scriptFd = fdDup(i);
01494 rpmtransSetScriptFd(o->ts, o->scriptFd);
01495 }
01496 } else {
01497 PyErr_SetString(PyExc_AttributeError, name);
01498 return -1;
01499 }
01500
01501 return 0;
01502 }
01503
01506 static PyTypeObject rpmtransType = {
01507 PyObject_HEAD_INIT(&PyType_Type)
01508 0,
01509 "rpmtrans",
01510 sizeof(rpmtransObject),
01511 0,
01512 (destructor) rpmtransDealloc,
01513 0,
01514 (getattrfunc) rpmtransGetAttr,
01515 (setattrfunc) rpmtransSetAttr,
01516 0,
01517 0,
01518 0,
01519 0,
01520 0,
01521 };
01522
01529
01532 static PyObject * rpmtransCreate(PyObject * self, PyObject * args) {
01533 rpmtransObject * o;
01534 rpmdbObject * db = NULL;
01535 char * rootPath = "/";
01536
01537 if (!PyArg_ParseTuple(args, "|sO", &rootPath, &db)) return NULL;
01538 if (db && db->ob_type != &rpmdbType) {
01539 PyErr_SetString(PyExc_TypeError, "bad type for database argument");
01540 return NULL;
01541 }
01542
01543 o = (void *) PyObject_NEW(rpmtransObject, &rpmtransType);
01544
01545 Py_XINCREF(db);
01546 o->dbo = db;
01547 o->scriptFd = NULL;
01548 o->ts = rpmtransCreateSet(db ? db->db : NULL, rootPath);
01549 o->keyList = PyList_New(0);
01550
01551 return (void *) o;
01552 }
01553
01556 static PyObject * doAddMacro(PyObject * self, PyObject * args) {
01557 char * name, * val;
01558
01559 if (!PyArg_ParseTuple(args, "ss", &name, &val))
01560 return NULL;
01561
01562 addMacro(NULL, name, NULL, val, RMIL_DEFAULT);
01563
01564 Py_INCREF(Py_None);
01565 return Py_None;
01566 }
01567
01570 static PyObject * doDelMacro(PyObject * self, PyObject * args) {
01571 char * name;
01572
01573 if (!PyArg_ParseTuple(args, "s", &name))
01574 return NULL;
01575
01576 delMacro(NULL, name);
01577
01578 Py_INCREF(Py_None);
01579 return Py_None;
01580 }
01581
01584 static PyObject * archScore(PyObject * self, PyObject * args) {
01585 char * arch;
01586 int score;
01587
01588 if (!PyArg_ParseTuple(args, "s", &arch))
01589 return NULL;
01590
01591 score = rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch);
01592
01593 return Py_BuildValue("i", score);
01594 }
01595
01598 static int psGetArchScore(Header h) {
01599 void * pkgArch;
01600 int type, count;
01601
01602 if (!headerGetEntry(h, RPMTAG_ARCH, &type, (void **) &pkgArch, &count) ||
01603 type == RPM_INT8_TYPE)
01604 return 150;
01605 else
01606 return rpmMachineScore(RPM_MACHTABLE_INSTARCH, pkgArch);
01607 }
01608
01611 static int pkgCompareVer(void * first, void * second) {
01612 struct packageInfo ** a = first;
01613 struct packageInfo ** b = second;
01614 int ret, score1, score2;
01615
01616
01617 if (!(*a)->name) return 1;
01618 if (!(*b)->name) return -1;
01619
01620 ret = xstrcasecmp((*a)->name, (*b)->name);
01621 if (ret) return ret;
01622 score1 = psGetArchScore((*a)->h);
01623 if (!score1) return 1;
01624 score2 = psGetArchScore((*b)->h);
01625 if (!score2) return -1;
01626 if (score1 < score2) return -1;
01627 if (score1 > score2) return 1;
01628 return rpmVersionCompare((*b)->h, (*a)->h);
01629 }
01630
01633 static void pkgSort(struct pkgSet * psp) {
01634 int i;
01635 char *name;
01636
01637 qsort(psp->packages, psp->numPackages, sizeof(*psp->packages),
01638 (void *) pkgCompareVer);
01639
01640 name = psp->packages[0]->name;
01641 if (!name) {
01642 psp->numPackages = 0;
01643 return;
01644 }
01645 for (i = 1; i < psp->numPackages; i++) {
01646 if (!psp->packages[i]->name) break;
01647 if (!strcmp(psp->packages[i]->name, name))
01648 psp->packages[i]->name = NULL;
01649 else
01650 name = psp->packages[i]->name;
01651 }
01652
01653 qsort(psp->packages, psp->numPackages, sizeof(*psp->packages),
01654 (void *) pkgCompareVer);
01655
01656 for (i = 0; i < psp->numPackages; i++)
01657 if (!psp->packages[i]->name) break;
01658 psp->numPackages = i;
01659 }
01660
01663 static PyObject * findUpgradeSet(PyObject * self, PyObject * args) {
01664 PyObject * hdrList, * result;
01665 char * root = "/";
01666 int i;
01667 struct pkgSet list;
01668 hdrObject * hdr;
01669
01670 if (!PyArg_ParseTuple(args, "O|s", &hdrList, &root)) return NULL;
01671
01672 if (!PyList_Check(hdrList)) {
01673 PyErr_SetString(PyExc_TypeError, "list of headers expected");
01674 return NULL;
01675 }
01676
01677 list.numPackages = PyList_Size(hdrList);
01678 list.packages = alloca(sizeof(list.packages) * list.numPackages);
01679 for (i = 0; i < list.numPackages; i++) {
01680 hdr = (hdrObject *) PyList_GetItem(hdrList, i);
01681 if (hdr->ob_type != &hdrType) {
01682 PyErr_SetString(PyExc_TypeError, "list of headers expected");
01683 return NULL;
01684 }
01685 list.packages[i] = alloca(sizeof(struct packageInfo));
01686 list.packages[i]->h = hdr->h;
01687 list.packages[i]->selected = 0;
01688 list.packages[i]->data = hdr;
01689
01690 headerGetEntry(hdr->h, RPMTAG_NAME, NULL,
01691 (void **) &list.packages[i]->name, NULL);
01692 }
01693
01694 pkgSort (&list);
01695
01696 if (ugFindUpgradePackages(&list, root)) {
01697 PyErr_SetString(pyrpmError, "error during upgrade check");
01698 return NULL;
01699 }
01700
01701 result = PyList_New(0);
01702 for (i = 0; i < list.numPackages; i++) {
01703 if (list.packages[i]->selected) {
01704 PyList_Append(result, list.packages[i]->data);
01705
01706 }
01707 }
01708
01709 return result;
01710 }
01711
01714 static PyObject * rpmHeaderFromPackage(PyObject * self, PyObject * args) {
01715 hdrObject * h;
01716 Header header;
01717 Header sigs;
01718 FD_t fd;
01719 int rawFd;
01720 int isSource = 0;
01721 rpmRC rc;
01722
01723 if (!PyArg_ParseTuple(args, "i", &rawFd)) return NULL;
01724 fd = fdDup(rawFd);
01725
01726 rc = rpmReadPackageInfo(fd, &sigs, &header);
01727 Fclose(fd);
01728
01729 switch (rc) {
01730 case RPMRC_BADSIZE:
01731 case RPMRC_OK:
01732 h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
01733 h->h = header;
01734 h->sigs = sigs;
01735 h->fileList = h->linkList = h->md5list = NULL;
01736 h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
01737 h->modes = h->rdevs = NULL;
01738 if (headerIsEntry(header, RPMTAG_SOURCEPACKAGE))
01739 isSource = 1;
01740 break;
01741
01742 case RPMRC_BADMAGIC:
01743 Py_INCREF(Py_None);
01744 h = (hdrObject *) Py_None;
01745 break;
01746
01747 case RPMRC_FAIL:
01748 case RPMRC_SHORTREAD:
01749 default:
01750 PyErr_SetString(pyrpmError, "error reading package");
01751 return NULL;
01752 }
01753
01754 return Py_BuildValue("(Ni)", h, isSource);
01755 }
01756
01759 static PyObject * hdrLoad(PyObject * self, PyObject * args) {
01760 char * obj, * copy=NULL;
01761 Header hdr;
01762 hdrObject * h;
01763 int len;
01764
01765 if (!PyArg_ParseTuple(args, "s#", &obj, &len)) return NULL;
01766
01767 copy = malloc(len);
01768 if (copy == NULL) {
01769 PyErr_SetString(pyrpmError, "out of memory");
01770 return NULL;
01771 }
01772
01773 memcpy (copy, obj, len);
01774
01775 hdr = headerLoad(copy);
01776 if (!hdr) {
01777 PyErr_SetString(pyrpmError, "bad header");
01778 return NULL;
01779 }
01780 compressFilelist (hdr);
01781 providePackageNVR (hdr);
01782
01783 h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
01784 h->h = hdr;
01785 h->sigs = NULL;
01786 h->fileList = h->linkList = h->md5list = NULL;
01787 h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
01788 h->modes = h->rdevs = NULL;
01789
01790 return (PyObject *) h;
01791 }
01792
01795 static PyObject * rpmInitDB(PyObject * self, PyObject * args) {
01796 char *root;
01797 int forWrite = 0;
01798
01799 if (!PyArg_ParseTuple(args, "i|s", &forWrite, &root)) return NULL;
01800
01801 if (rpmdbInit(root, forWrite ? O_RDWR | O_CREAT: O_RDONLY)) {
01802 char * errmsg = "cannot initialize database in %s";
01803 char * errstr = NULL;
01804 int errsize;
01805
01806 errsize = strlen(errmsg) + strlen(root);
01807 errstr = alloca(errsize);
01808 snprintf(errstr, errsize, errmsg, root);
01809 PyErr_SetString(pyrpmError, errstr);
01810 return NULL;
01811 }
01812
01813 Py_INCREF(Py_None);
01814 return(Py_None);
01815 }
01816
01819 static rpmdbObject * rpmOpenDB(PyObject * self, PyObject * args) {
01820 rpmdbObject * o;
01821 char * root = "";
01822 int forWrite = 0;
01823
01824 if (!PyArg_ParseTuple(args, "|is", &forWrite, &root)) return NULL;
01825
01826 o = PyObject_NEW(rpmdbObject, &rpmdbType);
01827 o->db = NULL;
01828 o->offx = 0;
01829 o->noffs = 0;
01830 o->offsets = NULL;
01831
01832 if (rpmdbOpen(root, &o->db, forWrite ? O_RDWR | O_CREAT: O_RDONLY, 0644)) {
01833 char * errmsg = "cannot open database in %s";
01834 char * errstr = NULL;
01835 int errsize;
01836
01837 Py_DECREF(o);
01838
01839 errsize = strlen(errmsg) + *root == '\0' ? 15 : strlen(root);
01840 errstr = alloca(errsize);
01841 snprintf(errstr, errsize, errmsg, *root == '\0' ? "/var/lib/rpm" : root);
01842 PyErr_SetString(pyrpmError, errstr);
01843 return NULL;
01844 }
01845
01846 return o;
01847 }
01848
01851 static PyObject * rebuildDB (PyObject * self, PyObject * args) {
01852 char * root = "";
01853
01854 if (!PyArg_ParseTuple(args, "s", &root)) return NULL;
01855
01856 return Py_BuildValue("i", rpmdbRebuild(root));
01857 }
01858
01861 static PyObject * rpmReadHeaders (FD_t fd) {
01862 PyObject * list;
01863 Header header;
01864 hdrObject * h;
01865
01866 if (!fd) {
01867 PyErr_SetFromErrno(pyrpmError);
01868 return NULL;
01869 }
01870
01871 list = PyList_New(0);
01872 Py_BEGIN_ALLOW_THREADS
01873 header = headerRead(fd, HEADER_MAGIC_YES);
01874
01875 Py_END_ALLOW_THREADS
01876 while (header) {
01877 compressFilelist (header);
01878 providePackageNVR (header);
01879 h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
01880 h->h = header;
01881 h->sigs = NULL;
01882 h->fileList = h->linkList = h->md5list = NULL;
01883 h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
01884 h->modes = h->rdevs = NULL;
01885 if (PyList_Append(list, (PyObject *) h)) {
01886 Py_DECREF(list);
01887 Py_DECREF(h);
01888 return NULL;
01889 }
01890
01891 Py_DECREF(h);
01892
01893 Py_BEGIN_ALLOW_THREADS
01894 header = headerRead(fd, HEADER_MAGIC_YES);
01895 Py_END_ALLOW_THREADS
01896 }
01897
01898 return list;
01899 }
01900
01903 static PyObject * rpmHeaderFromFD(PyObject * self, PyObject * args) {
01904 FD_t fd;
01905 int fileno;
01906 PyObject * list;
01907
01908 if (!PyArg_ParseTuple(args, "i", &fileno)) return NULL;
01909 fd = fdDup(fileno);
01910
01911 list = rpmReadHeaders (fd);
01912 Fclose(fd);
01913
01914 return list;
01915 }
01916
01919 static PyObject * rpmHeaderFromFile(PyObject * self, PyObject * args) {
01920 char * filespec;
01921 FD_t fd;
01922 PyObject * list;
01923
01924 if (!PyArg_ParseTuple(args, "s", &filespec)) return NULL;
01925 fd = Fopen(filespec, "r.fdio");
01926
01927 if (!fd) {
01928 PyErr_SetFromErrno(pyrpmError);
01929 return NULL;
01930 }
01931
01932 list = rpmReadHeaders (fd);
01933 Fclose(fd);
01934
01935 return list;
01936 }
01937
01942 static int rpmMergeHeaders(PyObject * list, FD_t fd, int matchTag) {
01943 Header newH;
01944 HeaderIterator iter;
01945 int_32 * newMatch, * oldMatch;
01946 hdrObject * ho;
01947 int count = 0;
01948 int type, c, tag;
01949 void * p;
01950
01951 Py_BEGIN_ALLOW_THREADS
01952 newH = headerRead(fd, HEADER_MAGIC_YES);
01953
01954 Py_END_ALLOW_THREADS
01955 while (newH) {
01956 if (!headerGetEntry(newH, matchTag, NULL, (void **) &newMatch, NULL)) {
01957 PyErr_SetString(pyrpmError, "match tag missing in new header");
01958 return 1;
01959 }
01960
01961 ho = (hdrObject *) PyList_GetItem(list, count++);
01962 if (!ho) return 1;
01963
01964 if (!headerGetEntry(ho->h, matchTag, NULL, (void **) &oldMatch, NULL)) {
01965 PyErr_SetString(pyrpmError, "match tag missing in new header");
01966 return 1;
01967 }
01968
01969 if (*newMatch != *oldMatch) {
01970 PyErr_SetString(pyrpmError, "match tag mismatch");
01971 return 1;
01972 }
01973
01974 if (ho->sigs) headerFree(ho->sigs);
01975 if (ho->md5list) free(ho->md5list);
01976 if (ho->fileList) free(ho->fileList);
01977 if (ho->linkList) free(ho->linkList);
01978
01979 ho->sigs = NULL;
01980 ho->md5list = NULL;
01981 ho->fileList = NULL;
01982 ho->linkList = NULL;
01983
01984 iter = headerInitIterator(newH);
01985
01986 while (headerNextIterator(iter, &tag, &type, (void *) &p, &c)) {
01987
01988 headerRemoveEntry(ho->h, tag);
01989 headerAddEntry(ho->h, tag, type, p, c);
01990 headerFreeData(p, type);
01991 }
01992
01993 headerFreeIterator(iter);
01994
01995 Py_BEGIN_ALLOW_THREADS
01996 newH = headerRead(fd, HEADER_MAGIC_YES);
01997 Py_END_ALLOW_THREADS
01998 }
01999
02000 return 0;
02001 }
02002
02003 static PyObject * rpmMergeHeadersFromFD(PyObject * self, PyObject * args) {
02004 FD_t fd;
02005 int fileno;
02006 PyObject * list;
02007 int rc;
02008 int matchTag;
02009
02010 if (!PyArg_ParseTuple(args, "Oii", &list, &fileno, &matchTag)) return NULL;
02011
02012 if (!PyList_Check(list)) {
02013 PyErr_SetString(PyExc_TypeError, "first parameter must be a list");
02014 return NULL;
02015 }
02016
02017 fd = fdDup(fileno);
02018
02019 rc = rpmMergeHeaders (list, fd, matchTag);
02020 Fclose(fd);
02021
02022 if (rc) {
02023 return NULL;
02024 }
02025
02026 Py_INCREF(Py_None);
02027 return Py_None;
02028 }
02029
02032 static PyObject * errorCB = NULL, * errorData = NULL;
02033
02036 static void errorcb (void)
02037 {
02038 PyObject * result, * args = NULL;
02039
02040 if (errorData)
02041 args = Py_BuildValue("(O)", errorData);
02042
02043 result = PyEval_CallObject(errorCB, args);
02044 Py_XDECREF(args);
02045
02046 if (result == NULL) {
02047 PyErr_Print();
02048 PyErr_Clear();
02049 }
02050 Py_DECREF (result);
02051 }
02052
02055 static PyObject * errorSetCallback (PyObject * self, PyObject * args) {
02056 if (errorCB != NULL) {
02057 Py_DECREF (errorCB);
02058 errorCB = NULL;
02059 }
02060
02061 if (errorData != NULL) {
02062 Py_DECREF (errorData);
02063 errorData = NULL;
02064 }
02065
02066 if (!PyArg_ParseTuple(args, "O|O", &errorCB, &errorData)) return NULL;
02067
02068
02069
02070
02071 if (PyCObject_Check (errorCB)) {
02072 rpmErrorSetCallback (PyCObject_AsVoidPtr(errorCB));
02073
02074 Py_XDECREF (errorCB);
02075 Py_XDECREF (errorData);
02076
02077 errorCB = NULL;
02078 errorData = NULL;
02079
02080 Py_INCREF(Py_None);
02081 return Py_None;
02082 }
02083
02084 if (!PyCallable_Check (errorCB)) {
02085 PyErr_SetString(PyExc_TypeError, "parameter must be callable");
02086 return NULL;
02087 }
02088
02089 Py_INCREF (errorCB);
02090 Py_XINCREF (errorData);
02091
02092 return PyCObject_FromVoidPtr(rpmErrorSetCallback (errorcb), NULL);
02093 }
02094
02097 static PyObject * errorString (PyObject * self, PyObject * args) {
02098 return PyString_FromString(rpmErrorString ());
02099 }
02100
02103 static PyObject * versionCompare (PyObject * self, PyObject * args) {
02104 hdrObject * h1, * h2;
02105
02106 if (!PyArg_ParseTuple(args, "O!O!", &hdrType, &h1, &hdrType, &h2)) return NULL;
02107
02108 return Py_BuildValue("i", rpmVersionCompare(h1->h, h2->h));
02109 }
02110
02113 static PyObject * labelCompare (PyObject * self, PyObject * args) {
02114 char *v1, *r1, *e1, *v2, *r2, *e2;
02115 int rc;
02116
02117 if (!PyArg_ParseTuple(args, "(zzz)(zzz)",
02118 &e1, &v1, &r1,
02119 &e2, &v2, &r2)) return NULL;
02120
02121 if (e1 && !e2)
02122 return Py_BuildValue("i", 1);
02123 else if (!e1 && e2)
02124 return Py_BuildValue("i", -1);
02125 else if (e1 && e2) {
02126 int ep1, ep2;
02127 ep1 = atoi (e1);
02128 ep2 = atoi (e2);
02129 if (ep1 < ep2)
02130 return Py_BuildValue("i", -1);
02131 else if (ep1 > ep2)
02132 return Py_BuildValue("i", 1);
02133 }
02134
02135 rc = rpmvercmp(v1, v2);
02136 if (rc)
02137 return Py_BuildValue("i", rc);
02138
02139 return Py_BuildValue("i", rpmvercmp(r1, r2));
02140 }
02141
02144 static PyObject * checkSig (PyObject * self, PyObject * args) {
02145 char * filename;
02146 int flags;
02147 int rc = 255;
02148
02149 if (PyArg_ParseTuple(args, "si", &filename, &flags)) {
02150 const char *av[2];
02151 av[0] = filename;
02152 av[1] = NULL;
02153 rc = rpmCheckSig(flags, av);
02154 }
02155 return Py_BuildValue("i", rc);
02156 }
02157
02158
02161 static PyObject * getTsHeader (PyObject * self, PyObject * args) {
02162 hdrObject * h;
02163
02164 if (transactionSetHeader) {
02165 h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
02166 h->h = headerLink(transactionSetHeader);
02167 h->sigs = NULL;
02168 h->fileList = h->linkList = h->md5list = NULL;
02169 h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
02170 h->modes = h->rdevs = NULL;
02171 return (PyObject *) h;
02172 }
02173 Py_INCREF(Py_None);
02174 return (PyObject *) Py_None;
02175 }
02176
02179 typedef struct FDlist_t FDlist;
02180
02183 struct FDlist_t {
02184 FILE *f;
02185 FD_t fd;
02186 char *note;
02187 FDlist *next;
02188 } ;
02189
02192 static FDlist *fdhead = NULL;
02193
02196 static FDlist *fdtail = NULL;
02197
02200 static int closeCallback(FILE * f) {
02201 FDlist *node, *last;
02202
02203 printf ("close callback on %p\n", f);
02204
02205 node = fdhead;
02206 last = NULL;
02207 while (node) {
02208 if (node->f == f)
02209 break;
02210 last = node;
02211 node = node->next;
02212 }
02213 if (node) {
02214 if (last)
02215 last->next = node->next;
02216 else
02217 fdhead = node->next;
02218 printf ("closing %s %p\n", node->note, node->fd);
02219 free (node->note);
02220 node->fd = fdLink(node->fd, "closeCallback");
02221 Fclose (node->fd);
02222 while (node->fd)
02223 node->fd = fdFree(node->fd, "closeCallback");
02224 free (node);
02225 }
02226 return 0;
02227 }
02228
02229 #if 0
02230
02232 static PyObject * doFopen(PyObject * self, PyObject * args) {
02233 char * path, * mode;
02234 FDlist *node;
02235
02236 if (!PyArg_ParseTuple(args, "ss", &path, &mode))
02237 return NULL;
02238
02239 node = malloc (sizeof(FDlist));
02240
02241 node->fd = Fopen(path, mode);
02242 node->fd = fdLink(node->fd, "doFopen");
02243 node->note = strdup (path);
02244
02245 if (!node->fd) {
02246 PyErr_SetFromErrno(pyrpmError);
02247 free (node);
02248 return NULL;
02249 }
02250
02251 if (Ferror(node->fd)) {
02252 const char *err = Fstrerror(node->fd);
02253 free(node);
02254 if (err) {
02255 PyErr_SetString(pyrpmError, err);
02256 return NULL;
02257 }
02258 }
02259 node->f = fdGetFp(node->fd);
02260 printf ("opening %s fd = %p f = %p\n", node->note, node->fd, node->f);
02261 if (!node->f) {
02262 PyErr_SetString(pyrpmError, "FD_t has no FILE*");
02263 free(node);
02264 return NULL;
02265 }
02266
02267 node->next = NULL;
02268 if (!fdhead) {
02269 fdhead = fdtail = node;
02270 } else if (fdtail) {
02271 fdtail->next = node;
02272 } else {
02273 fdhead = node;
02274 }
02275 fdtail = node;
02276
02277 return PyFile_FromFile (node->f, path, mode, closeCallback);
02278 }
02279 #endif
02280
02283 static PyMethodDef rpmModuleMethods[] = {
02284 { "TransactionSet", (PyCFunction) rpmtransCreate, METH_VARARGS, NULL },
02285 { "addMacro", (PyCFunction) doAddMacro, METH_VARARGS, NULL },
02286 { "delMacro", (PyCFunction) doDelMacro, METH_VARARGS, NULL },
02287 { "archscore", (PyCFunction) archScore, METH_VARARGS, NULL },
02288 { "findUpgradeSet", (PyCFunction) findUpgradeSet, METH_VARARGS, NULL },
02289 { "headerFromPackage", (PyCFunction) rpmHeaderFromPackage, METH_VARARGS, NULL },
02290 { "headerLoad", (PyCFunction) hdrLoad, METH_VARARGS, NULL },
02291 { "initdb", (PyCFunction) rpmInitDB, METH_VARARGS, NULL },
02292 { "opendb", (PyCFunction) rpmOpenDB, METH_VARARGS, NULL },
02293 { "rebuilddb", (PyCFunction) rebuildDB, METH_VARARGS, NULL },
02294 { "readHeaderListFromFD", (PyCFunction) rpmHeaderFromFD, METH_VARARGS, NULL },
02295 { "readHeaderListFromFile", (PyCFunction) rpmHeaderFromFile, METH_VARARGS, NULL },
02296 { "errorSetCallback", (PyCFunction) errorSetCallback, METH_VARARGS, NULL },
02297 { "errorString", (PyCFunction) errorString, METH_VARARGS, NULL },
02298 { "versionCompare", (PyCFunction) versionCompare, METH_VARARGS, NULL },
02299 { "labelCompare", (PyCFunction) labelCompare, METH_VARARGS, NULL },
02300 { "checksig", (PyCFunction) checkSig, METH_VARARGS, NULL },
02301 { "getTransactionCallbackHeader", (PyCFunction) getTsHeader, METH_VARARGS, NULL },
02302
02303 { NULL }
02304 } ;
02305
02308 void initrpm(void) {
02309 PyObject * m, * d, *o, * tag = NULL, * dict;
02310 int i;
02311 const struct headerSprintfExtension * extensions = rpmHeaderFormats;
02312 struct headerSprintfExtension * ext;
02313
02314
02315 rpmReadConfigFiles(NULL, NULL);
02316
02317 m = Py_InitModule("rpm", rpmModuleMethods);
02318 d = PyModule_GetDict(m);
02319
02320 pyrpmError = PyString_FromString("rpm.error");
02321 PyDict_SetItemString(d, "error", pyrpmError);
02322 Py_DECREF(pyrpmError);
02323
02324 dict = PyDict_New();
02325
02326 for (i = 0; i < rpmTagTableSize; i++) {
02327 tag = PyInt_FromLong(rpmTagTable[i].val);
02328 PyDict_SetItemString(d, (char *) rpmTagTable[i].name, tag);
02329 Py_DECREF(tag);
02330 PyDict_SetItem(dict, tag, o=PyString_FromString(rpmTagTable[i].name + 7));
02331 Py_DECREF(o);
02332 }
02333
02334 while (extensions->name) {
02335 if (extensions->type == HEADER_EXT_TAG) {
02336 (const struct headerSprintfExtension *) ext = extensions;
02337 PyDict_SetItemString(d, extensions->name, o=PyCObject_FromVoidPtr(ext, NULL));
02338 Py_DECREF(o);
02339 PyDict_SetItem(dict, tag, o=PyString_FromString(ext->name + 7));
02340 Py_DECREF(o);
02341 }
02342 extensions++;
02343 }
02344
02345 PyDict_SetItemString(d, "tagnames",