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) {
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
00167
00168
00169
00170
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
00311
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
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}
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
00483
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,
00626 (binaryfunc) hdrSubscript,
00627 (objobjargproc)0,
00628 };
00629
00632 static PyTypeObject hdrType = {
00633 PyObject_HEAD_INIT(&PyType_Type)
00634 0,
00635 "header",
00636 sizeof(hdrObject),
00637 0,
00638 (destructor) hdrDealloc,
00639 0,
00640 (getattrfunc) hdrGetAttr,
00641 0,
00642 0,
00643 0,
00644 0,
00645 0,
00646 &hdrAsMapping,
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
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}
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,
00733 "rpmdbMatchIterator",
00734 sizeof(rpmdbMIObject),
00735 0,
00736 (destructor) rpmdbMIDealloc,
00737 0,
00738 (getattrfunc) rpmdbMIGetAttr,
00739 0,
00740 0,
00741 0,
00742 0,
00743 0,
00744 0,
00745 };
00746
00815
00818 static PyObject * rpmdbFirst(rpmdbObject * s, PyObject * args) {
00819 int first;
00820
00821 if (!PyArg_ParseTuple (args, "")) return NULL;
00822
00823
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
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}
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
00998 mi = rpmdbInitIterator(s->db, RPMDBI_PACKAGES, NULL, 0);
00999
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,
01047 (binaryfunc) rpmdbSubscript,
01048 (objobjargproc)0,
01049 };
01050 #endif
01051
01054 static PyTypeObject rpmdbType = {
01055 PyObject_HEAD_INIT(&PyType_Type)
01056 0,
01057 "rpmdb",
01058 sizeof(rpmdbObject),
01059 0,
01060 (destructor) rpmdbDealloc,
01061 0,
01062 (getattrfunc) rpmdbGetAttr,
01063 0,
01064 0,
01065 0,
01066 0,
01067 0,
01068 #ifndef DYINGSOON
01069 &rpmdbAsMapping,
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;
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
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
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 {
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}
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
01464
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,
01497 "rpmtrans",
01498 sizeof(rpmtransObject),
01499 0,
01500 (destructor) rpmtransDealloc,
01501 0,
01502 (getattrfunc) rpmtransGetAttr,
01503 (setattrfunc) rpmtransSetAttr,
01504 0,
01505 0,
01506 0,
01507 0,
01508 0,
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
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
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
01824 errsize = strlen(errmsg) + *root == '\0' ? 15 : 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
01927
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
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
02055
02056
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
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
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
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