00001
00005 #include "system.h"
00006
00007 static int _debug = 0;
00008 #define INLINE
00009
00010 #include <sys/file.h>
00011 #include <signal.h>
00012 #include <sys/signal.h>
00013
00014 #include <rpmlib.h>
00015 #include <rpmmacro.h>
00016
00017 #include "rpmdb.h"
00018 #include "fprint.h"
00019 #include "misc.h"
00020 #include "debug.h"
00021
00022
00023
00024
00025
00026
00027 extern int _noDirTokens;
00028 static int _rebuildinprogress = 0;
00029 static int _db_filter_dups = 0;
00030
00031 int _filterDbDups = 0;
00032
00033 #define _DBI_FLAGS 0
00034 #define _DBI_PERMS 0644
00035 #define _DBI_MAJOR -1
00036
00037 static int dbiTagsMax = 0;
00038 static int *dbiTags = NULL;
00039
00045 static int dbiTagToDbix(int rpmtag)
00046 {
00047 int dbix;
00048
00049 if (!(dbiTagsMax > 0 && dbiTags))
00050 return -1;
00051 for (dbix = 0; dbix < dbiTagsMax; dbix++) {
00052 if (rpmtag == dbiTags[dbix])
00053 return dbix;
00054 }
00055 return -1;
00056 }
00057
00061 static void dbiTagsInit(void)
00062 {
00063 static const char * const _dbiTagStr_default =
00064 "Packages:Name:Basenames:Group:Requirename:Providename:Conflictname:Triggername:Dirnames:Requireversion:Provideversion:Installtid:Removetid";
00065 char * dbiTagStr = NULL;
00066 char * o, * oe;
00067 int rpmtag;
00068
00069 dbiTagStr = rpmExpand("%{_dbi_tags}", NULL);
00070 if (!(dbiTagStr && *dbiTagStr && *dbiTagStr != '%')) {
00071 free((void *)dbiTagStr);
00072 dbiTagStr = xstrdup(_dbiTagStr_default);
00073 }
00074
00075 if (dbiTagsMax || dbiTags) {
00076 free(dbiTags);
00077 dbiTags = NULL;
00078 dbiTagsMax = 0;
00079 }
00080
00081
00082 dbiTagsMax = 1;
00083 dbiTags = xcalloc(1, dbiTagsMax * sizeof(*dbiTags));
00084
00085 for (o = dbiTagStr; o && *o; o = oe) {
00086 while (*o && isspace(*o))
00087 o++;
00088 if (*o == '\0')
00089 break;
00090 for (oe = o; oe && *oe; oe++) {
00091 if (isspace(*oe))
00092 break;
00093 if (oe[0] == ':' && !(oe[1] == '/' && oe[2] == '/'))
00094 break;
00095 }
00096 if (oe && *oe)
00097 *oe++ = '\0';
00098 rpmtag = tagValue(o);
00099 if (rpmtag < 0) {
00100
00101 fprintf(stderr, _("dbiTagsInit: unrecognized tag name: \"%s\" ignored\n"), o);
00102 continue;
00103 }
00104 if (dbiTagToDbix(rpmtag) >= 0)
00105 continue;
00106
00107 dbiTags = xrealloc(dbiTags, (dbiTagsMax + 1) * sizeof(*dbiTags));
00108 dbiTags[dbiTagsMax++] = rpmtag;
00109 }
00110
00111 if (dbiTagStr)
00112 free(dbiTagStr);
00113 }
00114
00115 #if USE_DB1
00116 extern struct _dbiVec db1vec;
00117 #define DB1vec &db1vec
00118 #else
00119 #define DB1vec NULL
00120 #endif
00121
00122 #if USE_DB2
00123 extern struct _dbiVec db2vec;
00124 #define DB2vec &db2vec
00125 #else
00126 #define DB2vec NULL
00127 #endif
00128
00129 #if USE_DB3
00130 extern struct _dbiVec db3vec;
00131 #define DB3vec &db3vec
00132 #else
00133 #define DB3vec NULL
00134 #endif
00135
00136 static struct _dbiVec *mydbvecs[] = {
00137 DB1vec, DB1vec, DB2vec, DB3vec, NULL
00138 };
00139
00140 INLINE int dbiSync(dbiIndex dbi, unsigned int flags) {
00141 if (_debug < 0 || dbi->dbi_debug)
00142 fprintf(stderr, " Sync %s\n", tagName(dbi->dbi_rpmtag));
00143 return (*dbi->dbi_vec->sync) (dbi, flags);
00144 }
00145
00146 INLINE int dbiByteSwapped(dbiIndex dbi) {
00147 return (*dbi->dbi_vec->byteswapped) (dbi);
00148 }
00149
00150 INLINE int XdbiCopen(dbiIndex dbi, DBC ** dbcp, unsigned int flags,
00151 const char * f, unsigned int l)
00152 {
00153 if (_debug < 0 || dbi->dbi_debug)
00154 fprintf(stderr, "+++ RMW %s (%s:%u)\n", tagName(dbi->dbi_rpmtag), f, l);
00155 return (*dbi->dbi_vec->copen) (dbi, dbcp, flags);
00156 }
00157
00158 INLINE int XdbiCclose(dbiIndex dbi, DBC * dbcursor, unsigned int flags,
00159 const char * f, unsigned int l)
00160 {
00161 if (_debug < 0 || dbi->dbi_debug)
00162 fprintf(stderr, "--- RMW %s (%s:%u)\n", tagName(dbi->dbi_rpmtag), f, l);
00163 return (*dbi->dbi_vec->cclose) (dbi, dbcursor, flags);
00164 }
00165
00166 INLINE int dbiDel(dbiIndex dbi, DBC * dbcursor, const void * keyp, size_t keylen, unsigned int flags)
00167 {
00168 int NULkey;
00169 int rc;
00170
00171
00172 NULkey = (keyp && *((char *)keyp) == '\0' && keylen == 0);
00173 if (NULkey) keylen++;
00174 rc = (*dbi->dbi_vec->cdel) (dbi, dbcursor, keyp, keylen, flags);
00175 if (NULkey) keylen--;
00176
00177 if (_debug < 0 || dbi->dbi_debug)
00178 fprintf(stderr, " Del %s key (%p,%ld) %s rc %d\n", tagName(dbi->dbi_rpmtag), keyp, (long)keylen, (dbi->dbi_rpmtag != RPMDBI_PACKAGES ? (char *)keyp : ""), rc);
00179
00180 return rc;
00181 }
00182
00183 INLINE int dbiGet(dbiIndex dbi, DBC * dbcursor, void ** keypp, size_t * keylenp,
00184 void ** datapp, size_t * datalenp, unsigned int flags)
00185 {
00186 int NULkey;
00187 int rc;
00188
00189
00190 NULkey = (keypp && *keypp && *((char *)(*keypp)) == '\0' && keylenp && *keylenp == 0);
00191 if (NULkey) (*keylenp)++;
00192 rc = (*dbi->dbi_vec->cget) (dbi, dbcursor, keypp, keylenp, datapp, datalenp, flags);
00193 if (NULkey) (*keylenp)--;
00194
00195 if (_debug < 0 || dbi->dbi_debug) {
00196 char keyval[32];
00197 int dataval = 0xdeadbeef;
00198 if (dbi->dbi_rpmtag == RPMDBI_PACKAGES && keypp && *keypp && keylenp && *keylenp >= sizeof(keyval)) {
00199 int keyint;
00200 memcpy(&keyint, *keypp, sizeof(keyint));
00201 sprintf(keyval, "%d", keyint);
00202 } else keyval[0] = '\0';
00203 if (rc == 0 && datapp && *datapp && datalenp && *datalenp >= sizeof(dataval))
00204 memcpy(&dataval, *datapp, sizeof(dataval));
00205 fprintf(stderr, " Get %s key (%p,%ld) data (%p,%ld) \"%s\" %x rc %d\n",
00206 tagName(dbi->dbi_rpmtag), *keypp, (long)*keylenp, *datapp, (long)*datalenp,
00207 (dbi->dbi_rpmtag != RPMDBI_PACKAGES ? (char *)*keypp : keyval), (unsigned)dataval, rc);
00208 }
00209 return rc;
00210 }
00211
00212 INLINE int dbiPut(dbiIndex dbi, DBC * dbcursor, const void * keyp, size_t keylen,
00213 const void * datap, size_t datalen, unsigned int flags)
00214 {
00215 int NULkey;
00216 int rc;
00217
00218
00219 NULkey = (keyp && *((char *)keyp) == '\0' && keylen == 0);
00220 if (NULkey) keylen++;
00221 rc = (*dbi->dbi_vec->cput) (dbi, dbcursor, keyp, keylen, datap, datalen, flags);
00222 if (NULkey) keylen--;
00223
00224 if (_debug < 0 || dbi->dbi_debug) {
00225 int dataval = 0xdeadbeef;
00226 if (datap) memcpy(&dataval, datap, sizeof(dataval));
00227 fprintf(stderr, " Put %s key (%p,%ld) data (%p,%ld) \"%s\" %x rc %d\n", tagName(dbi->dbi_rpmtag), keyp, (long)keylen, datap, (long)datalen, (dbi->dbi_rpmtag != RPMDBI_PACKAGES ? (char *)keyp : ""), (unsigned)dataval, rc);
00228 }
00229
00230 return rc;
00231 }
00232
00233 INLINE int dbiClose(dbiIndex dbi, unsigned int flags) {
00234 if (_debug < 0 || dbi->dbi_debug)
00235 fprintf(stderr, " %s Close\n", tagName(dbi->dbi_rpmtag));
00236 return (*dbi->dbi_vec->close) (dbi, flags);
00237 }
00238
00239 dbiIndex dbiOpen(rpmdb rpmdb, int rpmtag, unsigned int flags)
00240 {
00241 int dbix;
00242 dbiIndex dbi = NULL;
00243 int _dbapi, _dbapi_rebuild, _dbapi_wanted;
00244 int rc = 0;
00245
00246 dbix = dbiTagToDbix(rpmtag);
00247 if (dbix < 0 || dbix >= dbiTagsMax)
00248 return NULL;
00249
00250
00251 if ((dbi = rpmdb->_dbi[dbix]) != NULL)
00252 return dbi;
00253
00254 _dbapi_rebuild = rpmExpandNumeric("%{_dbapi_rebuild}");
00255 if (_dbapi_rebuild < 1 || _dbapi_rebuild > 3)
00256 _dbapi_rebuild = 3;
00257 _dbapi_wanted = (_rebuildinprogress ? -1 : rpmdb->db_api);
00258
00259 switch (_dbapi_wanted) {
00260 default:
00261 _dbapi = _dbapi_wanted;
00262 if (_dbapi < 0 || _dbapi >= 4 || mydbvecs[_dbapi] == NULL) {
00263 return NULL;
00264 }
00265 errno = 0;
00266 dbi = NULL;
00267 rc = (*mydbvecs[_dbapi]->open) (rpmdb, rpmtag, &dbi);
00268 if (rc) {
00269 static int _printed[32];
00270 if (!_printed[dbix & 0x1f]++)
00271 rpmError(RPMERR_DBOPEN,
00272 _("cannot open %s index using db%d - %s (%d)\n"),
00273 tagName(rpmtag), _dbapi,
00274 (rc > 0 ? strerror(rc) : ""), rc);
00275 _dbapi = -1;
00276 }
00277 break;
00278 case -1:
00279 _dbapi = 4;
00280 while (_dbapi-- > 1) {
00281 if (mydbvecs[_dbapi] == NULL)
00282 continue;
00283 errno = 0;
00284 dbi = NULL;
00285 rc = (*mydbvecs[_dbapi]->open) (rpmdb, rpmtag, &dbi);
00286 if (rc == 0 && dbi)
00287 break;
00288 }
00289 if (_dbapi <= 0) {
00290 static int _printed[32];
00291 if (!_printed[dbix & 0x1f]++)
00292 rpmError(RPMERR_DBOPEN, _("cannot open %s index\n"),
00293 tagName(rpmtag));
00294 rc = 1;
00295 goto exit;
00296 }
00297 if (rpmdb->db_api == -1 && _dbapi > 0)
00298 rpmdb->db_api = _dbapi;
00299 break;
00300 }
00301
00302
00303 if (rc && _dbapi_wanted >= 0 && _dbapi != _dbapi_wanted && _dbapi_wanted == _dbapi_rebuild) {
00304 rc = (_rebuildinprogress ? 0 : 1);
00305 goto exit;
00306 }
00307
00308
00309 if (_dbapi_wanted >= 0 && _dbapi != _dbapi_wanted) {
00310 rc = 1;
00311 goto exit;
00312 }
00313
00314
00315 if (_dbapi_wanted < 0 && _dbapi != _dbapi_rebuild) {
00316 rc = (_rebuildinprogress ? 0 : 1);
00317 goto exit;
00318 }
00319
00320 exit:
00321 if (rc == 0 && dbi) {
00322 rpmdb->_dbi[dbix] = dbi;
00323 } else if (dbi) {
00324 db3Free(dbi);
00325 dbi = NULL;
00326 }
00327
00328 return dbi;
00329 }
00330
00337 static INLINE dbiIndexItem dbiIndexNewItem(unsigned int hdrNum, unsigned int tagNum) {
00338 dbiIndexItem rec = xcalloc(1, sizeof(*rec));
00339 rec->hdrNum = hdrNum;
00340 rec->tagNum = tagNum;
00341 return rec;
00342 }
00343
00344 union _dbswap {
00345 unsigned int ui;
00346 unsigned char uc[4];
00347 };
00348
00349 #define _DBSWAP(_a) \
00350 { unsigned char _b, *_c = (_a).uc; \
00351 _b = _c[3]; _c[3] = _c[0]; _c[0] = _b; \
00352 _b = _c[2]; _c[2] = _c[1]; _c[1] = _b; \
00353 }
00354
00364 static int dbiSearch(dbiIndex dbi, DBC * dbcursor,
00365 const char * keyp, size_t keylen, dbiIndexSet * setp)
00366 {
00367 void * datap = NULL;
00368 size_t datalen = 0;
00369 int rc;
00370
00371 if (setp) *setp = NULL;
00372 if (keylen == 0) keylen = strlen(keyp);
00373
00374 rc = dbiGet(dbi, dbcursor, (void **)&keyp, &keylen, &datap, &datalen, 0);
00375
00376 if (rc > 0) {
00377 rpmError(RPMERR_DBGETINDEX,
00378 _("error(%d) getting \"%s\" records from %s index\n"),
00379 rc, keyp, tagName(dbi->dbi_rpmtag));
00380 } else
00381 if (rc == 0 && setp) {
00382 int _dbbyteswapped = dbiByteSwapped(dbi);
00383 const char * sdbir = datap;
00384 dbiIndexSet set;
00385 int i;
00386
00387 set = xmalloc(sizeof(*set));
00388
00389
00390 switch (dbi->dbi_jlen) {
00391 default:
00392 case 2*sizeof(int_32):
00393 set->count = datalen / (2*sizeof(int_32));
00394 set->recs = xmalloc(set->count * sizeof(*(set->recs)));
00395 for (i = 0; i < set->count; i++) {
00396 union _dbswap hdrNum, tagNum;
00397
00398 memcpy(&hdrNum.ui, sdbir, sizeof(hdrNum.ui));
00399 sdbir += sizeof(hdrNum.ui);
00400 memcpy(&tagNum.ui, sdbir, sizeof(tagNum.ui));
00401 sdbir += sizeof(tagNum.ui);
00402 if (_dbbyteswapped) {
00403 _DBSWAP(hdrNum);
00404 _DBSWAP(tagNum);
00405 }
00406 set->recs[i].hdrNum = hdrNum.ui;
00407 set->recs[i].tagNum = tagNum.ui;
00408 set->recs[i].fpNum = 0;
00409 set->recs[i].dbNum = 0;
00410 }
00411 break;
00412 case 1*sizeof(int_32):
00413 set->count = datalen / (1*sizeof(int_32));
00414 set->recs = xmalloc(set->count * sizeof(*(set->recs)));
00415 for (i = 0; i < set->count; i++) {
00416 union _dbswap hdrNum;
00417
00418 memcpy(&hdrNum.ui, sdbir, sizeof(hdrNum.ui));
00419 sdbir += sizeof(hdrNum.ui);
00420 if (_dbbyteswapped) {
00421 _DBSWAP(hdrNum);
00422 }
00423 set->recs[i].hdrNum = hdrNum.ui;
00424 set->recs[i].tagNum = 0;
00425 set->recs[i].fpNum = 0;
00426 set->recs[i].dbNum = 0;
00427 }
00428 break;
00429 }
00430 *setp = set;
00431 }
00432 return rc;
00433 }
00434
00444
00445 static int dbiUpdateIndex(dbiIndex dbi, DBC * dbcursor,
00446 const void * keyp, size_t keylen, dbiIndexSet set)
00447 {
00448 void * datap;
00449 size_t datalen;
00450 int rc;
00451
00452 if (set->count) {
00453 char * tdbir;
00454 int i;
00455 int _dbbyteswapped = dbiByteSwapped(dbi);
00456
00457
00458
00459 switch (dbi->dbi_jlen) {
00460 default:
00461 case 2*sizeof(int_32):
00462 datalen = set->count * (2 * sizeof(int_32));
00463 datap = tdbir = alloca(datalen);
00464 for (i = 0; i < set->count; i++) {
00465 union _dbswap hdrNum, tagNum;
00466
00467 hdrNum.ui = set->recs[i].hdrNum;
00468 tagNum.ui = set->recs[i].tagNum;
00469 if (_dbbyteswapped) {
00470 _DBSWAP(hdrNum);
00471 _DBSWAP(tagNum);
00472 }
00473 memcpy(tdbir, &hdrNum.ui, sizeof(hdrNum.ui));
00474 tdbir += sizeof(hdrNum.ui);
00475 memcpy(tdbir, &tagNum.ui, sizeof(tagNum.ui));
00476 tdbir += sizeof(tagNum.ui);
00477 }
00478 break;
00479 case 1*sizeof(int_32):
00480 datalen = set->count * (1 * sizeof(int_32));
00481 datap = tdbir = alloca(datalen);
00482 for (i = 0; i < set->count; i++) {
00483 union _dbswap hdrNum;
00484
00485 hdrNum.ui = set->recs[i].hdrNum;
00486 if (_dbbyteswapped) {
00487 _DBSWAP(hdrNum);
00488 }
00489 memcpy(tdbir, &hdrNum.ui, sizeof(hdrNum.ui));
00490 tdbir += sizeof(hdrNum.ui);
00491 }
00492 break;
00493 }
00494
00495 rc = dbiPut(dbi, dbcursor, keyp, keylen, datap, datalen, 0);
00496
00497 if (rc) {
00498 rpmError(RPMERR_DBPUTINDEX,
00499 _("error(%d) storing record %s into %s\n"),
00500 rc, keyp, tagName(dbi->dbi_rpmtag));
00501 }
00502
00503 } else {
00504
00505 rc = dbiDel(dbi, dbcursor, keyp, keylen, 0);
00506
00507 if (rc) {
00508 rpmError(RPMERR_DBPUTINDEX,
00509 _("error(%d) removing record %s from %s\n"),
00510 rc, keyp, tagName(dbi->dbi_rpmtag));
00511 }
00512
00513 }
00514
00515 return rc;
00516 }
00517
00518
00519
00520 static int hdrNumCmp(const void * one, const void * two) {
00521 const int * a = one, * b = two;
00522 return (*a - *b);
00523 }
00524
00534 static INLINE int dbiAppendSet(dbiIndexSet set, const void * recs,
00535 int nrecs, size_t recsize, int sortset)
00536 {
00537 const char * rptr = recs;
00538 size_t rlen = (recsize < sizeof(*(set->recs)))
00539 ? recsize : sizeof(*(set->recs));
00540
00541 if (set == NULL || recs == NULL || nrecs <= 0 || recsize <= 0)
00542 return 1;
00543
00544 set->recs = (set->count == 0)
00545 ? xmalloc(nrecs * sizeof(*(set->recs)))
00546 : xrealloc(set->recs, (set->count + nrecs) * sizeof(*(set->recs)));
00547
00548 memset(set->recs + set->count, 0, nrecs * sizeof(*(set->recs)));
00549
00550 while (nrecs-- > 0) {
00551 memcpy(set->recs + set->count, rptr, rlen);
00552 rptr += recsize;
00553 set->count++;
00554 }
00555
00556 if (set->count > 1 && sortset)
00557 qsort(set->recs, set->count, sizeof(*(set->recs)), hdrNumCmp);
00558
00559 return 0;
00560 }
00561
00571 static INLINE int dbiPruneSet(dbiIndexSet set, void * recs, int nrecs,
00572 size_t recsize, int sorted)
00573 {
00574 int from;
00575 int to = 0;
00576 int num = set->count;
00577 int numCopied = 0;
00578
00579 if (nrecs > 1 && !sorted)
00580 qsort(recs, nrecs, recsize, hdrNumCmp);
00581
00582 for (from = 0; from < num; from++) {
00583 if (bsearch(&set->recs[from], recs, nrecs, recsize, hdrNumCmp)) {
00584 set->count--;
00585 continue;
00586 }
00587 if (from != to)
00588 set->recs[to] = set->recs[from];
00589 to++;
00590 numCopied++;
00591 }
00592
00593 return (numCopied == num);
00594 }
00595
00596
00597 unsigned int dbiIndexSetCount(dbiIndexSet set) {
00598 return set->count;
00599 }
00600
00601
00602 unsigned int dbiIndexRecordOffset(dbiIndexSet set, int recno) {
00603 return set->recs[recno].hdrNum;
00604 }
00605
00606
00607 unsigned int dbiIndexRecordFileNumber(dbiIndexSet set, int recno) {
00608 return set->recs[recno].tagNum;
00609 }
00610
00611
00612 void dbiFreeIndexSet(dbiIndexSet set) {
00613 if (set) {
00614 if (set->recs) free(set->recs);
00615 free(set);
00616 }
00617 }
00618
00622 static void blockSignals(rpmdb rpmdb, sigset_t * oldMask)
00623 {
00624 sigset_t newMask;
00625
00626
00627 if (!(rpmdb && rpmdb->db_api == 4)) {
00628 sigfillset(&newMask);
00629 sigprocmask(SIG_BLOCK, &newMask, oldMask);
00630 }
00631 }
00632
00636 static void unblockSignals(rpmdb rpmdb, sigset_t * oldMask)
00637 {
00638
00639 if (!(rpmdb && rpmdb->db_api == 4)) {
00640 sigprocmask(SIG_SETMASK, oldMask, NULL);
00641 }
00642 }
00643
00644 #define _DB_ROOT "/"
00645 #define _DB_HOME "%{_dbpath}"
00646 #define _DB_FLAGS 0
00647 #define _DB_MODE 0
00648 #define _DB_PERMS 0644
00649
00650 #define _DB_MAJOR -1
00651 #define _DB_REMOVE_ENV 0
00652 #define _DB_FILTER_DUPS 0
00653 #define _DB_ERRPFX "rpmdb"
00654
00655
00656 static struct rpmdb_s dbTemplate = {
00657 _DB_ROOT, _DB_HOME, _DB_FLAGS, _DB_MODE, _DB_PERMS,
00658 _DB_MAJOR, _DB_REMOVE_ENV, _DB_FILTER_DUPS, _DB_ERRPFX
00659 };
00660
00661
00662 int rpmdbOpenAll (rpmdb rpmdb)
00663 {
00664 int dbix;
00665
00666 for (dbix = 0; dbix < dbiTagsMax; dbix++) {
00667 if (rpmdb->_dbi[dbix] != NULL)
00668 continue;
00669 (void) dbiOpen(rpmdb, dbiTags[dbix], rpmdb->db_flags);
00670 }
00671 return 0;
00672 }
00673
00674
00675 int rpmdbClose (rpmdb rpmdb)
00676 {
00677 int dbix;
00678
00679 for (dbix = rpmdb->db_ndbi; --dbix >= 0; ) {
00680 if (rpmdb->_dbi[dbix] == NULL)
00681 continue;
00682 dbiClose(rpmdb->_dbi[dbix], 0);
00683 rpmdb->_dbi[dbix] = NULL;
00684 }
00685 if (rpmdb->db_errpfx) {
00686 free((void *)rpmdb->db_errpfx);
00687 rpmdb->db_errpfx = NULL;
00688 }
00689 if (rpmdb->db_root) {
00690 free((void *)rpmdb->db_root);
00691 rpmdb->db_root = NULL;
00692 }
00693 if (rpmdb->db_home) {
00694 free((void *)rpmdb->db_home);
00695 rpmdb->db_home = NULL;
00696 }
00697 if (rpmdb->_dbi) {
00698 free((void *)rpmdb->_dbi);
00699 rpmdb->_dbi = NULL;
00700 }
00701 free(rpmdb);
00702 return 0;
00703 }
00704
00705 int rpmdbSync(rpmdb rpmdb)
00706 {
00707 int dbix;
00708
00709 for (dbix = 0; dbix < rpmdb->db_ndbi; dbix++) {
00710 int xx;
00711 if (rpmdb->_dbi[dbix] == NULL)
00712 continue;
00713 xx = dbiSync(rpmdb->_dbi[dbix], 0);
00714 }
00715 return 0;
00716 }
00717
00718 static rpmdb newRpmdb( const char * root,
00719 const char * home,
00720 int mode, int perms, int flags)
00721 {
00722 rpmdb rpmdb = xcalloc(sizeof(*rpmdb), 1);
00723 const char * epfx = _DB_ERRPFX;
00724 static int _initialized = 0;
00725
00726 if (!_initialized) {
00727 _filterDbDups = rpmExpandNumeric("%{_filterdbdups}");
00728 _initialized = 1;
00729 }
00730
00731 *rpmdb = dbTemplate;
00732
00733 if (!(perms & 0600)) perms = 0644;
00734
00735 if (mode >= 0) rpmdb->db_mode = mode;
00736 if (perms >= 0) rpmdb->db_perms = perms;
00737 if (flags >= 0) rpmdb->db_flags = flags;
00738
00739 rpmdb->db_root = rpmGetPath( (root && *root ? root : _DB_ROOT), NULL);
00740 rpmdb->db_home = rpmGetPath( (home && *home ? home : _DB_HOME), NULL);
00741 if (!(rpmdb->db_home && rpmdb->db_home[0] != '%')) {
00742 rpmError(RPMERR_DBOPEN, _("no dbpath has been set\n"));
00743 rpmdbClose(rpmdb);
00744 return NULL;
00745 }
00746 rpmdb->db_errpfx = rpmExpand( (epfx && *epfx ? epfx : _DB_ERRPFX), NULL);
00747 rpmdb->db_remove_env = 0;
00748 rpmdb->db_filter_dups = _filterDbDups;
00749 rpmdb->db_ndbi = dbiTagsMax;
00750 rpmdb->_dbi = xcalloc(rpmdb->db_ndbi, sizeof(*rpmdb->_dbi));
00751 return rpmdb;
00752 }
00753
00754 static int openDatabase(const char * prefix, const char * dbpath, int _dbapi,
00755 rpmdb *dbp, int mode, int perms, int flags)
00756 {
00757 rpmdb rpmdb;
00758 int rc;
00759 static int _initialized = 0;
00760 int justCheck = flags & RPMDB_FLAG_JUSTCHECK;
00761 int minimal = flags & RPMDB_FLAG_MINIMAL;
00762
00763 if (!_initialized || dbiTagsMax == 0) {
00764 dbiTagsInit();
00765 _initialized++;
00766 }
00767
00768
00769 if (_dbapi < -1 || _dbapi > 3)
00770 _dbapi = -1;
00771 if (_dbapi == 0)
00772 _dbapi = 1;
00773
00774 if (dbp)
00775 *dbp = NULL;
00776 if (mode & O_WRONLY)
00777 return 1;
00778
00779 rpmdb = newRpmdb(prefix, dbpath, mode, perms, flags);
00780 rpmdb->db_api = _dbapi;
00781
00782 { int dbix;
00783
00784 rc = 0;
00785 for (dbix = 0; rc == 0 && dbix < dbiTagsMax; dbix++) {
00786 dbiIndex dbi;
00787 int rpmtag;
00788
00789
00790 switch ((rpmtag = dbiTags[dbix])) {
00791 case RPMDBI_AVAILABLE:
00792 case RPMDBI_ADDED:
00793 case RPMDBI_REMOVED:
00794 case RPMDBI_DEPENDS:
00795 continue;
00796 break;
00797 default:
00798 break;
00799 }
00800
00801 dbi = dbiOpen(rpmdb, rpmtag, 0);
00802
00803 switch (rpmtag) {
00804 case RPMDBI_PACKAGES:
00805 if (dbi == NULL) rc |= 1;
00806
00807 #if 0
00808 if (rpmdb->db_api == 3)
00809 #endif
00810 goto exit;
00811 break;
00812 case RPMTAG_NAME:
00813 if (dbi == NULL) rc |= 1;
00814 if (minimal)
00815 goto exit;
00816 break;
00817 case RPMTAG_BASENAMES:
00818 { void * keyp = NULL;
00819 DBC * dbcursor;
00820 int xx;
00821
00822
00823
00824
00825
00826
00827
00828 if (justCheck)
00829 break;
00830 dbcursor = NULL;
00831 xx = dbiCopen(dbi, &dbcursor, 0);
00832 xx = dbiGet(dbi, dbcursor, &keyp, NULL, NULL, NULL, 0);
00833 if (xx == 0) {
00834 const char * akey = keyp;
00835 if (strchr(akey, '/')) {
00836 rpmError(RPMERR_OLDDB, _("old format database is present; "
00837 "use --rebuilddb to generate a new format database\n"));
00838 rc |= 1;
00839 }
00840 }
00841 xx = dbiCclose(dbi, dbcursor, 0);
00842 dbcursor = NULL;
00843 } break;
00844 default:
00845 break;
00846 }
00847 }
00848 }
00849
00850 exit:
00851 if (rc || justCheck || dbp == NULL)
00852 rpmdbClose(rpmdb);
00853 else
00854 *dbp = rpmdb;
00855
00856 return rc;
00857 }
00858
00859
00860 int rpmdbOpen (const char * prefix, rpmdb *dbp, int mode, int perms)
00861 {
00862 int _dbapi = rpmExpandNumeric("%{_dbapi}");
00863 return openDatabase(prefix, NULL, _dbapi, dbp, mode, perms, 0);
00864 }
00865
00866 int rpmdbInit (const char * prefix, int perms)
00867 {
00868 rpmdb rpmdb = NULL;
00869 int _dbapi = rpmExpandNumeric("%{_dbapi}");
00870 int rc;
00871
00872 rc = openDatabase(prefix, NULL, _dbapi, &rpmdb, (O_CREAT | O_RDWR),
00873 perms, RPMDB_FLAG_JUSTCHECK);
00874 if (rpmdb) {
00875 rpmdbOpenAll(rpmdb);
00876 rpmdbClose(rpmdb);
00877 rpmdb = NULL;
00878 }
00879 return rc;
00880 }
00881
00882 static int rpmdbFindByFile(rpmdb rpmdb, const char * filespec,
00883 dbiIndexSet * matches)
00884 {
00885 const char * dirName;
00886 const char * baseName;
00887 fingerPrintCache fpc;
00888 fingerPrint fp1;
00889 dbiIndex dbi = NULL;
00890 DBC * dbcursor;
00891 dbiIndexSet allMatches = NULL;
00892 dbiIndexItem rec = NULL;
00893 int i;
00894 int rc;
00895 int xx;
00896
00897 *matches = NULL;
00898 if ((baseName = strrchr(filespec, '/')) != NULL) {
00899 char * t;
00900 size_t len;
00901
00902 len = baseName - filespec + 1;
00903 t = strncpy(alloca(len + 1), filespec, len);
00904 t[len] = '\0';
00905 dirName = t;
00906 baseName++;
00907 } else {
00908 dirName = "";
00909 baseName = filespec;
00910 }
00911
00912 fpc = fpCacheCreate(20);
00913 fp1 = fpLookup(fpc, dirName, baseName, 1);
00914
00915 dbi = dbiOpen(rpmdb, RPMTAG_BASENAMES, 0);
00916 dbcursor = NULL;
00917 xx = dbiCopen(dbi, &dbcursor, 0);
00918 rc = dbiSearch(dbi, dbcursor, baseName, strlen(baseName), &allMatches);
00919 xx = dbiCclose(dbi, dbcursor, 0);
00920 dbcursor = NULL;
00921 if (rc) {
00922 dbiFreeIndexSet(allMatches);
00923 allMatches = NULL;
00924 fpCacheFree(fpc);
00925 return rc;
00926 }
00927
00928 *matches = xcalloc(1, sizeof(**matches));
00929 rec = dbiIndexNewItem(0, 0);
00930 i = 0;
00931 while (i < allMatches->count) {
00932 const char ** baseNames, ** dirNames;
00933 int_32 * dirIndexes;
00934 unsigned int offset = dbiIndexRecordOffset(allMatches, i);
00935 unsigned int prevoff;
00936 Header h;
00937
00938 { rpmdbMatchIterator mi;
00939 mi = rpmdbInitIterator(rpmdb, RPMDBI_PACKAGES, &offset, sizeof(offset));
00940 h = rpmdbNextIterator(mi);
00941 if (h)
00942 h = headerLink(h);
00943 rpmdbFreeIterator(mi);
00944 }
00945
00946 if (h == NULL) {
00947 i++;
00948 continue;
00949 }
00950
00951 headerGetEntryMinMemory(h, RPMTAG_BASENAMES, NULL,
00952 (const void **) &baseNames, NULL);
00953 headerGetEntryMinMemory(h, RPMTAG_DIRNAMES, NULL,
00954 (const void **) &dirNames, NULL);
00955 headerGetEntryMinMemory(h, RPMTAG_DIRINDEXES, NULL,
00956 (const void **) &dirIndexes, NULL);
00957
00958 do {
00959 fingerPrint fp2;
00960 int num = dbiIndexRecordFileNumber(allMatches, i);
00961
00962 fp2 = fpLookup(fpc, dirNames[dirIndexes[num]], baseNames[num], 1);
00963 if (FP_EQUAL(fp1, fp2)) {
00964 rec->hdrNum = dbiIndexRecordOffset(allMatches, i);
00965 rec->tagNum = dbiIndexRecordFileNumber(allMatches, i);
00966 dbiAppendSet(*matches, rec, 1, sizeof(*rec), 0);
00967 }
00968
00969 prevoff = offset;
00970 i++;
00971 offset = dbiIndexRecordOffset(allMatches, i);
00972 } while (i < allMatches->count &&
00973 (i == 0 || offset == prevoff));
00974
00975 free(baseNames);
00976 free(dirNames);
00977 headerFree(h);
00978 }
00979
00980 if (rec) {
00981 free(rec);
00982 rec = NULL;
00983 }
00984 if (allMatches) {
00985 dbiFreeIndexSet(allMatches);
00986 allMatches = NULL;
00987 }
00988
00989 fpCacheFree(fpc);
00990
00991 if ((*matches)->count == 0) {
00992 dbiFreeIndexSet(*matches);
00993 *matches = NULL;
00994 return 1;
00995 }
00996
00997 return 0;
00998 }
00999
01000
01001 int rpmdbCountPackages(rpmdb rpmdb, const char * name)
01002 {
01003 dbiIndex dbi;
01004 dbiIndexSet matches = NULL;
01005 int rc = -1;
01006 int xx;
01007
01008 dbi = dbiOpen(rpmdb, RPMTAG_NAME, 0);
01009 if (dbi) {
01010 DBC * dbcursor = NULL;
01011 xx = dbiCopen(dbi, &dbcursor, 0);
01012 rc = dbiSearch(dbi, dbcursor, name, strlen(name), &matches);
01013 xx = dbiCclose(dbi, dbcursor, 0);
01014 dbcursor = NULL;
01015 }
01016
01017 if (rc == 0)
01018 rc = dbiIndexSetCount(matches);
01019 else if (rc > 0)
01020 rpmError(RPMERR_DBCORRUPT, _("error(%d) counting packages\n"), rc);
01021 else
01022 rc = 0;
01023
01024 if (matches)
01025 dbiFreeIndexSet(matches);
01026
01027 return rc;
01028 }
01029
01030
01031
01032
01033
01034 static int dbiFindMatches(dbiIndex dbi, DBC * dbcursor,
01035 const char * name, const char * version, const char * release,
01036 dbiIndexSet * matches)
01037 {
01038 int gotMatches;
01039 int rc;
01040 int i;
01041
01042 rc = dbiSearch(dbi, dbcursor, name, strlen(name), matches);
01043
01044 if (rc != 0) {
01045 rc = ((rc == -1) ? 2 : 1);
01046 goto exit;
01047 }
01048
01049 if (!version && !release) {
01050 rc = 0;
01051 goto exit;
01052 }
01053
01054 gotMatches = 0;
01055
01056
01057 for (i = 0; i < dbiIndexSetCount(*matches); i++) {
01058 unsigned int recoff = dbiIndexRecordOffset(*matches, i);
01059 int goodRelease, goodVersion;
01060 const char * pkgVersion;
01061 const char * pkgRelease;
01062 Header h;
01063
01064 if (recoff == 0)
01065 continue;
01066
01067 { rpmdbMatchIterator mi;
01068 mi = rpmdbInitIterator(dbi->dbi_rpmdb, RPMDBI_PACKAGES, &recoff, sizeof(recoff));
01069 h = rpmdbNextIterator(mi);
01070 if (h)
01071 h = headerLink(h);
01072 rpmdbFreeIterator(mi);
01073 }
01074
01075 if (h == NULL) {
01076 rpmError(RPMERR_DBCORRUPT, _("%s: cannot read header at 0x%x\n"),
01077 "findMatches", recoff);
01078 rc = 2;
01079 goto exit;
01080 }
01081
01082 headerNVR(h, NULL, &pkgVersion, &pkgRelease);
01083
01084 goodRelease = goodVersion = 1;
01085
01086 if (release && strcmp(release, pkgRelease)) goodRelease = 0;
01087 if (version && strcmp(version, pkgVersion)) goodVersion = 0;
01088
01089 if (goodRelease && goodVersion) {
01090
01091 (*matches)->recs[gotMatches++] = (*matches)->recs[i];
01092 } else
01093 (*matches)->recs[i].hdrNum = 0;
01094
01095 headerFree(h);
01096 }
01097
01098 if (gotMatches) {
01099 (*matches)->count = gotMatches;
01100 rc = 0;
01101 } else {
01102 rc = 1;
01103 }
01104
01105 exit:
01106 if (rc && matches && *matches) {
01107 dbiFreeIndexSet(*matches);
01108 *matches = NULL;
01109 }
01110 return rc;
01111 }
01112
01121 static int dbiFindByLabel(dbiIndex dbi, DBC * dbcursor, const char * arg, dbiIndexSet * matches)
01122 {
01123 char * localarg, * chptr;
01124 char * release;
01125 int rc;
01126
01127 if (!strlen(arg)) return 1;
01128
01129
01130 rc = dbiFindMatches(dbi, dbcursor, arg, NULL, NULL, matches);
01131 if (rc != 1) return rc;
01132 if (*matches) {
01133 dbiFreeIndexSet(*matches);
01134 *matches = NULL;
01135 }
01136
01137
01138 localarg = alloca(strlen(arg) + 1);
01139 strcpy(localarg, arg);
01140
01141 chptr = (localarg + strlen(localarg)) - 1;
01142 while (chptr > localarg && *chptr != '-') chptr--;
01143 if (chptr == localarg) return 1;
01144
01145 *chptr = '\0';
01146 rc = dbiFindMatches(dbi, dbcursor, localarg, chptr + 1, NULL, matches);
01147 if (rc != 1) return rc;
01148 if (*matches) dbiFreeIndexSet(*matches);
01149
01150
01151
01152 release = chptr + 1;
01153 while (chptr > localarg && *chptr != '-') chptr--;
01154 if (chptr == localarg) return 1;
01155
01156 *chptr = '\0';
01157 return dbiFindMatches(dbi, dbcursor, localarg, chptr + 1, release, matches);
01158 }
01159
01170 static int dbiUpdateRecord(dbiIndex dbi, DBC * dbcursor, int offset, Header h)
01171 {
01172 sigset_t signalMask;
01173 void * uh;
01174 size_t uhlen;
01175 int rc;
01176 int xx;
01177
01178 if (_noDirTokens)
01179 expandFilelist(h);
01180
01181 uhlen = headerSizeof(h, HEADER_MAGIC_NO);
01182 uh = headerUnload(h);
01183 blockSignals(dbi->dbi_rpmdb, &signalMask);
01184 rc = dbiPut(dbi, dbcursor, &offset, sizeof(offset), uh, uhlen, 0);
01185 xx = dbiSync(dbi, 0);
01186 unblockSignals(dbi->dbi_rpmdb, &signalMask);
01187 free(uh);
01188
01189 return rc;
01190 }
01191
01192 struct _rpmdbMatchIterator {
01193 const void * mi_keyp;
01194 size_t mi_keylen;
01195 rpmdb mi_rpmdb;
01196 int mi_rpmtag;
01197 dbiIndexSet mi_set;
01198 DBC * mi_dbc;
01199 int mi_setx;
01200 Header mi_h;
01201 int mi_sorted;
01202 int mi_modified;
01203 unsigned int mi_prevoffset;
01204 unsigned int mi_offset;
01205 unsigned int mi_filenum;
01206 unsigned int mi_fpnum;
01207 unsigned int mi_dbnum;
01208 const char *mi_version;
01209 const char *mi_release;
01210 };
01211
01212 void rpmdbFreeIterator(rpmdbMatchIterator mi)
01213 {
01214 dbiIndex dbi = NULL;
01215 int xx;
01216
01217 if (mi == NULL)
01218 return;
01219
01220 dbi = dbiOpen(mi->mi_rpmdb, RPMDBI_PACKAGES, 0);
01221 if (mi->mi_h) {
01222 if (mi->mi_modified && mi->mi_prevoffset) {
01223 DBC * dbcursor = NULL;
01224 xx = dbiCopen(dbi, &dbcursor, 0);
01225 dbiUpdateRecord(dbi, dbcursor, mi->mi_prevoffset, mi->mi_h);
01226 xx = dbiCclose(dbi, dbcursor, 0);
01227 dbcursor = NULL;
01228 }
01229 headerFree(mi->mi_h);
01230 mi->mi_h = NULL;
01231 }
01232 if (dbi->dbi_rmw) {
01233 xx = dbiCclose(dbi, dbi->dbi_rmw, 0);
01234 dbi->dbi_rmw = NULL;
01235 }
01236
01237 if (mi->mi_release) {
01238 free((void *)mi->mi_release);
01239 mi->mi_release = NULL;
01240 }
01241 if (mi->mi_version) {
01242 free((void *)mi->mi_version);
01243 mi->mi_version = NULL;
01244 }
01245 if (mi->mi_dbc) {
01246 xx = dbiCclose(dbi, mi->mi_dbc, 1);
01247 mi->mi_dbc = NULL;
01248 }
01249 if (mi->mi_set) {
01250 dbiFreeIndexSet(mi->mi_set);
01251 mi->mi_set = NULL;
01252 }
01253 if (mi->mi_keyp) {
01254 free((void *)mi->mi_keyp);
01255 mi->mi_keyp = NULL;
01256 }
01257 free(mi);
01258 }
01259
01260 rpmdb rpmdbGetIteratorRpmDB(rpmdbMatchIterator mi) {
01261 if (mi == NULL)
01262 return 0;
01263 return mi->mi_rpmdb;
01264 }
01265
01266 unsigned int rpmdbGetIteratorOffset(rpmdbMatchIterator mi) {
01267 if (mi == NULL)
01268 return 0;
01269 return mi->mi_offset;
01270 }
01271
01272 unsigned int rpmdbGetIteratorFileNum(rpmdbMatchIterator mi) {
01273 if (mi == NULL)
01274 return 0;
01275 return mi->mi_filenum;
01276 }
01277
01278 int rpmdbGetIteratorCount(rpmdbMatchIterator mi) {
01279 if (!(mi && mi->mi_set))
01280 return 0;
01281 return mi->mi_set->count;
01282 }
01283
01284 void rpmdbSetIteratorRelease(rpmdbMatchIterator mi, const char * release) {
01285 if (mi == NULL)
01286 return;
01287 if (mi->mi_release) {
01288 free((void *)mi->mi_release);
01289 mi->mi_release = NULL;
01290 }
01291 mi->mi_release = (release ? xstrdup(release) : NULL);
01292 }
01293
01294 void rpmdbSetIteratorVersion(rpmdbMatchIterator mi, const char * version) {
01295 if (mi == NULL)
01296 return;
01297 if (mi->mi_version) {
01298 free((void *)mi->mi_version);
01299 mi->mi_version = NULL;
01300 }
01301 mi->mi_version = (version ? xstrdup(version) : NULL);
01302 }
01303
01304 int rpmdbSetIteratorModified(rpmdbMatchIterator mi, int modified) {
01305 int rc;
01306 if (mi == NULL)
01307 return 0;
01308 rc = mi->mi_modified;
01309 mi->mi_modified = modified;
01310 return rc;
01311 }
01312
01313 Header XrpmdbNextIterator(rpmdbMatchIterator mi, const char * f, unsigned l)
01314 {
01315 dbiIndex dbi;
01316 void * uh = NULL;
01317 size_t uhlen = 0;
01318 void * keyp;
01319 size_t keylen;
01320 int rc;
01321 int xx;
01322
01323 if (mi == NULL)
01324 return NULL;
01325
01326 dbi = dbiOpen(mi->mi_rpmdb, RPMDBI_PACKAGES, 0);
01327 if (dbi == NULL)
01328 return NULL;
01329
01330 if (mi->mi_dbc == NULL) {
01331 xx = XdbiCopen(dbi, &mi->mi_dbc, 1, f, l);
01332 }
01333 dbi->dbi_lastoffset = mi->mi_prevoffset;
01334
01335 top:
01336
01337 do {
01338 if (mi->mi_set) {
01339 if (!(mi->mi_setx < mi->mi_set->count))
01340 return NULL;
01341 mi->mi_offset = dbiIndexRecordOffset(mi->mi_set, mi->mi_setx);
01342 mi->mi_filenum = dbiIndexRecordFileNumber(mi->mi_set, mi->mi_setx);
01343 keyp = &mi->mi_offset;
01344 keylen = sizeof(mi->mi_offset);
01345 } else {
01346 keyp = (void *)mi->mi_keyp;
01347 keylen = mi->mi_keylen;
01348
01349 rc = dbiGet(dbi, mi->mi_dbc, &keyp, &keylen, &uh, &uhlen, 0);
01350
01351
01352
01353
01354
01355
01356
01357
01358 if (rc == 0 && keyp && (dbi->dbi_lastoffset || mi->mi_setx))
01359 memcpy(&mi->mi_offset, keyp, sizeof(mi->mi_offset));
01360
01361
01362 if (rc || (mi->mi_setx && mi->mi_offset == 0))
01363 return NULL;
01364 }
01365 mi->mi_setx++;
01366 } while (mi->mi_offset == 0);
01367
01368 if (mi->mi_prevoffset && mi->mi_offset == mi->mi_prevoffset)
01369 goto exit;
01370
01371
01372 if (uh == NULL) {
01373 rc = dbiGet(dbi, mi->mi_dbc, &keyp, &keylen, &uh, &uhlen, 0);
01374 if (rc)
01375 return NULL;
01376 }
01377
01378
01379 if (mi->mi_h) {
01380 if (mi->mi_modified && mi->mi_prevoffset)
01381 dbiUpdateRecord(dbi, mi->mi_dbc, mi->mi_prevoffset, mi->mi_h);
01382 headerFree(mi->mi_h);
01383 mi->mi_h = NULL;
01384 }
01385
01386 mi->mi_h = headerCopyLoad(uh);
01387
01388 if (mi->mi_release) {
01389 const char *release;
01390 headerNVR(mi->mi_h, NULL, NULL, &release);
01391 if (strcmp(mi->mi_release, release))
01392 goto top;
01393 }
01394
01395 if (mi->mi_version) {
01396 const char *version;
01397 headerNVR(mi->mi_h, NULL, &version, NULL);
01398 if (strcmp(mi->mi_version, version))
01399 goto top;
01400 }
01401
01402 mi->mi_prevoffset = mi->mi_offset;
01403 mi->mi_modified = 0;
01404
01405 exit:
01406 #ifdef NOTNOW
01407 if (mi->mi_h) {
01408 const char *n, *v, *r;
01409 headerNVR(mi->mi_h, &n, &v, &r);
01410 rpmMessage(RPMMESS_DEBUG, "%s-%s-%s at 0x%x, h %p\n", n, v, r,
01411 mi->mi_offset, mi->mi_h);
01412 }
01413 #endif
01414 return mi->mi_h;
01415 }
01416
01417 static void rpmdbSortIterator(rpmdbMatchIterator mi) {
01418 if (mi && mi->mi_set && mi->mi_set->recs && mi->mi_set->count > 0) {
01419 qsort(mi->mi_set->recs, mi->mi_set->count, sizeof(*mi->mi_set->recs),
01420 hdrNumCmp);
01421 mi->mi_sorted = 1;
01422 }
01423 }
01424
01425 static int rpmdbGrowIterator(rpmdbMatchIterator mi,
01426 const void * keyp, size_t keylen, int fpNum)
01427 {
01428 dbiIndex dbi = NULL;
01429 DBC * dbcursor = NULL;
01430 dbiIndexSet set = NULL;
01431 int rc;
01432 int xx;
01433
01434 if (!(mi && keyp))
01435 return 1;
01436
01437 dbi = dbiOpen(mi->mi_rpmdb, mi->mi_rpmtag, 0);
01438 if (dbi == NULL)
01439 return 1;
01440
01441 if (keylen == 0)
01442 keylen = strlen(keyp);
01443
01444 xx = dbiCopen(dbi, &dbcursor, 0);
01445 rc = dbiSearch(dbi, dbcursor, keyp, keylen, &set);
01446 xx = dbiCclose(dbi, dbcursor, 0);
01447 dbcursor = NULL;
01448
01449 if (rc == 0) {
01450 int i;
01451 for (i = 0; i < set->count; i++)
01452 set->recs[i].fpNum = fpNum;
01453
01454 if (mi->mi_set == NULL) {
01455 mi->mi_set = set;
01456 set = NULL;
01457 } else {
01458 mi->mi_set->recs = xrealloc(mi->mi_set->recs,
01459 (mi->mi_set->count + set->count) * sizeof(*(mi->mi_set->recs)));
01460 memcpy(mi->mi_set->recs + mi->mi_set->count, set->recs,
01461 set->count * sizeof(*(mi->mi_set->recs)));
01462 mi->mi_set->count += set->count;
01463 }
01464 }
01465
01466 if (set)
01467 dbiFreeIndexSet(set);
01468 return rc;
01469 }
01470
01471 int rpmdbPruneIterator(rpmdbMatchIterator mi, int * hdrNums,
01472 int nHdrNums, int sorted)
01473 {
01474 if (mi == NULL || hdrNums == NULL || nHdrNums <= 0)
01475 return 1;
01476
01477 if (mi->mi_set)
01478 dbiPruneSet(mi->mi_set, hdrNums, nHdrNums, sizeof(*hdrNums), sorted);
01479 return 0;
01480 }
01481
01482 int rpmdbAppendIterator(rpmdbMatchIterator mi, const int * hdrNums, int nHdrNums)
01483 {
01484 if (mi == NULL || hdrNums == NULL || nHdrNums <= 0)
01485 return 1;
01486
01487 if (mi->mi_set == NULL)
01488 mi->mi_set = xcalloc(1, sizeof(*mi->mi_set));
01489 dbiAppendSet(mi->mi_set, hdrNums, nHdrNums, sizeof(*hdrNums), 0);
01490 return 0;
01491 }
01492
01493 rpmdbMatchIterator rpmdbInitIterator(rpmdb rpmdb, int rpmtag,
01494 const void * keyp, size_t keylen)
01495 {
01496 rpmdbMatchIterator mi = NULL;
01497 dbiIndexSet set = NULL;
01498 dbiIndex dbi;
01499 const void * mi_keyp = NULL;
01500 int isLabel = 0;
01501
01502
01503 switch (rpmtag) {
01504 case RPMDBI_LABEL:
01505 rpmtag = RPMTAG_NAME;
01506 isLabel = 1;
01507 break;
01508 }
01509
01510 dbi = dbiOpen(rpmdb, rpmtag, 0);
01511 if (dbi == NULL)
01512 return NULL;
01513
01514 #if 0
01515 assert(dbi->dbi_rmw == NULL);
01516 assert(dbi->dbi_lastoffset == 0);
01517 #else
01518 if (dbi->dbi_rmw)
01519 fprintf(stderr, "*** RMW %s %p\n", tagName(rpmtag), dbi->dbi_rmw);
01520 #endif
01521
01522 dbi->dbi_lastoffset = 0;
01523
01524 if (rpmtag != RPMDBI_PACKAGES && keyp) {
01525 DBC * dbcursor = NULL;
01526 int rc;
01527 int xx;
01528
01529 if (isLabel) {
01530
01531 xx = dbiCopen(dbi, &dbcursor, 0);
01532 rc = dbiFindByLabel(dbi, dbcursor, keyp, &set);
01533 xx = dbiCclose(dbi, dbcursor, 0);
01534 dbcursor = NULL;
01535 } else if (rpmtag == RPMTAG_BASENAMES) {
01536 rc = rpmdbFindByFile(rpmdb, keyp, &set);
01537 } else {
01538 xx = dbiCopen(dbi, &dbcursor, 0);
01539 rc = dbiSearch(dbi, dbcursor, keyp, keylen, &set);
01540 xx = dbiCclose(dbi, dbcursor, 0);
01541 dbcursor = NULL;
01542 }
01543 if (rc) {
01544 if (set)
01545 dbiFreeIndexSet(set);
01546 return NULL;
01547 }
01548 }
01549
01550 if (keyp) {
01551 char * k;
01552
01553 if (rpmtag != RPMDBI_PACKAGES && keylen == 0)
01554 keylen = strlen(keyp);
01555 k = xmalloc(keylen + 1);
01556 memcpy(k, keyp, keylen);
01557 k[keylen] = '\0';
01558 mi_keyp = k;
01559 }
01560
01561 mi = xcalloc(1, sizeof(*mi));
01562 mi->mi_keyp = mi_keyp;
01563 mi->mi_keylen = keylen;
01564
01565 mi->mi_rpmdb = rpmdb;
01566 mi->mi_rpmtag = rpmtag;
01567
01568 mi->mi_dbc = NULL;
01569 mi->mi_set = set;
01570 mi->mi_setx = 0;
01571 mi->mi_h = NULL;
01572 mi->mi_sorted = 0;
01573 mi->mi_modified = 0;
01574 mi->mi_prevoffset = 0;
01575 mi->mi_offset = 0;
01576 mi->mi_filenum = 0;
01577 mi->mi_fpnum = 0;
01578 mi->mi_dbnum = 0;
01579 mi->mi_version = NULL;
01580 mi->mi_release = NULL;
01581 return mi;
01582 }
01583
01593 static INLINE int removeIndexEntry(dbiIndex dbi, DBC * dbcursor,
01594 const void * keyp, size_t keylen, dbiIndexItem rec)
01595 {
01596 dbiIndexSet set = NULL;
01597 int rc;
01598
01599 rc = dbiSearch(dbi, dbcursor, keyp, keylen, &set);
01600
01601 if (rc < 0)
01602 rc = 0;
01603 else if (rc > 0)
01604 rc = 1;
01605 else {
01606 if (!dbiPruneSet(set, rec, 1, sizeof(*rec), 1) &&
01607 dbiUpdateIndex(dbi, dbcursor, keyp, keylen, set))
01608 rc = 1;
01609 }
01610
01611 if (set) {
01612 dbiFreeIndexSet(set);
01613 set = NULL;
01614 }
01615
01616 return rc;
01617 }
01618
01619
01620 int rpmdbRemove(rpmdb rpmdb, int rid, unsigned int hdrNum)
01621 {
01622 Header h;
01623 sigset_t signalMask;
01624
01625 { rpmdbMatchIterator mi;
01626 mi = rpmdbInitIterator(rpmdb, RPMDBI_PACKAGES, &hdrNum, sizeof(hdrNum));
01627 h = rpmdbNextIterator(mi);
01628 if (h)
01629 h = headerLink(h);
01630 rpmdbFreeIterator(mi);
01631 }
01632
01633 if (h == NULL) {
01634 rpmError(RPMERR_DBCORRUPT, _("%s: cannot read header at 0x%x\n"),
01635 "rpmdbRemove", hdrNum);
01636 return 1;
01637 }
01638
01639
01640 if (rid > 0) {
01641 int_32 tid = rid;
01642 headerAddEntry(h, RPMTAG_REMOVETID, RPM_INT32_TYPE, &tid, 1);
01643 }
01644
01645 { const char *n, *v, *r;
01646 headerNVR(h, &n, &v, &r);
01647 rpmMessage(RPMMESS_DEBUG, " --- %10d %s-%s-%s\n", hdrNum, n, v, r);
01648 }
01649
01650 blockSignals(rpmdb, &signalMask);
01651
01652 { int dbix;
01653 dbiIndexItem rec = dbiIndexNewItem(hdrNum, 0);
01654
01655 for (dbix = 0; dbix < dbiTagsMax; dbix++) {
01656 dbiIndex dbi;
01657 DBC * dbcursor = NULL;
01658 const char *av[1];
01659 const char ** rpmvals = NULL;
01660 int rpmtype = 0;
01661 int rpmcnt = 0;
01662 int rpmtag;
01663 int xx;
01664 int i;
01665
01666 dbi = NULL;
01667 rpmtag = dbiTags[dbix];
01668
01669 switch (rpmtag) {
01670
01671 case RPMDBI_AVAILABLE:
01672 case RPMDBI_ADDED:
01673 case RPMDBI_REMOVED:
01674 case RPMDBI_DEPENDS:
01675 continue;
01676 break;
01677 case RPMDBI_PACKAGES:
01678 dbi = dbiOpen(rpmdb, rpmtag, 0);
01679 xx = dbiCopen(dbi, &dbcursor, 0);
01680 xx = dbiDel(dbi, dbcursor, &hdrNum, sizeof(hdrNum), 0);
01681 xx = dbiCclose(dbi, dbcursor, 0);
01682 dbcursor = NULL;
01683 if (!dbi->dbi_no_dbsync)
01684 xx = dbiSync(dbi, 0);
01685 continue;
01686 break;
01687 }
01688
01689 if (!headerGetEntry(h, rpmtag, &rpmtype,
01690 (void **) &rpmvals, &rpmcnt))
01691 continue;
01692
01693 dbi = dbiOpen(rpmdb, rpmtag, 0);
01694 xx = dbiCopen(dbi, &dbcursor, 0);
01695
01696 if (rpmtype == RPM_STRING_TYPE) {
01697
01698 rpmMessage(RPMMESS_DEBUG, _("removing \"%s\" from %s index.\n"),
01699 (const char *)rpmvals, tagName(dbi->dbi_rpmtag));
01700
01701
01702 av[0] = (const char *) rpmvals;
01703 rpmvals = av;
01704 rpmcnt = 1;
01705 } else {
01706
01707 rpmMessage(RPMMESS_DEBUG, _("removing %d entries from %s index.\n"),
01708 rpmcnt, tagName(dbi->dbi_rpmtag));
01709
01710 }
01711
01712 for (i = 0; i < rpmcnt; i++) {
01713 const void * valp;
01714 size_t vallen;
01715
01716
01717 switch (rpmtype) {
01718 case RPM_CHAR_TYPE:
01719 case RPM_INT8_TYPE:
01720 vallen = sizeof(RPM_CHAR_TYPE);
01721 valp = rpmvals + i;
01722 break;
01723 case RPM_INT16_TYPE:
01724 vallen = sizeof(int_16);
01725 valp = rpmvals + i;
01726 break;
01727 case RPM_INT32_TYPE:
01728 vallen = sizeof(int_32);
01729 valp = rpmvals + i;
01730 break;
01731 case RPM_BIN_TYPE:
01732 vallen = rpmcnt;
01733 valp = rpmvals;
01734 rpmcnt = 1;
01735 break;
01736 case RPM_STRING_TYPE:
01737 case RPM_I18NSTRING_TYPE:
01738 rpmcnt = 1;
01739
01740 case RPM_STRING_ARRAY_TYPE:
01741 default:
01742 vallen = strlen(rpmvals[i]);
01743 valp = rpmvals[i];
01744 break;
01745 }
01746
01747
01748
01749
01750
01751
01752
01753 xx = removeIndexEntry(dbi, dbcursor, valp, vallen, rec);
01754 }
01755
01756 xx = dbiCclose(dbi, dbcursor, 0);
01757 dbcursor = NULL;
01758
01759 if (!dbi->dbi_no_dbsync)
01760 xx = dbiSync(dbi, 0);
01761
01762 rpmvals = headerFreeData(rpmvals, rpmtype);
01763 rpmtype = 0;
01764 rpmcnt = 0;
01765 }
01766
01767 if (rec) {
01768 free(rec);
01769 rec = NULL;
01770 }
01771 }
01772
01773 unblockSignals(rpmdb, &signalMask);
01774
01775 headerFree(h);
01776
01777 return 0;
01778 }
01779
01789 static INLINE int addIndexEntry(dbiIndex dbi, DBC * dbcursor,
01790 const char * keyp, size_t keylen, dbiIndexItem rec)
01791 {
01792 dbiIndexSet set = NULL;
01793 int rc;
01794
01795 rc = dbiSearch(dbi, dbcursor, keyp, keylen, &set);
01796
01797 if (rc > 0) {
01798 rc = 1;
01799 } else {
01800 if (rc < 0) {
01801 rc = 0;
01802 set = xcalloc(1, sizeof(*set));
01803 }
01804 dbiAppendSet(set, rec, 1, sizeof(*rec), 0);
01805 if (dbiUpdateIndex(dbi, dbcursor, keyp, keylen, set))
01806 rc = 1;
01807 }
01808
01809 if (set) {
01810 dbiFreeIndexSet(set);
01811 set = NULL;
01812 }
01813
01814 return 0;
01815 }
01816
01817
01818 int rpmdbAdd(rpmdb rpmdb, int iid, Header h)
01819 {
01820 sigset_t signalMask;
01821 const char ** baseNames;
01822 int count = 0;
01823 int type;
01824 dbiIndex dbi;
01825 int dbix;
01826 unsigned int hdrNum;
01827 int rc = 0;
01828 int xx;
01829
01830 if (iid > 0) {
01831 int_32 tid = iid;
01832 headerRemoveEntry(h, RPMTAG_REMO