00001
00005 #include "system.h"
00006
00007 #define _USE_COPY_LOAD
00008
00009 #include <sys/file.h>
00010
00011 #include <rpmio.h>
00012 #include <rpmpgp.h>
00013 #include <rpmurl.h>
00014 #include <rpmmacro.h>
00015 #include <rpmsq.h>
00016
00017 #define _RPMEVR_INTERNAL
00018 #include <rpmevr.h>
00019
00020 #define _RPMDB_INTERNAL
00021 #define _MIRE_INTERNAL
00022 #include "rpmdb.h"
00023 #include "fprint.h"
00024 #include "legacy.h"
00025 #include "header_internal.h"
00026 #include "debug.h"
00027
00028
00029
00030
00031
00032
00033
00034
00035 int _rpmdb_debug = 0;
00036
00037
00038 int _rsegfault = 0;
00039
00040
00041 int _wsegfault = 0;
00042
00043
00044 static int _rebuildinprogress = 0;
00045
00046 static int _db_filter_dups = 0;
00047
00048
00049
00050
00051 #define _DB_TAGGED_FILE_INDICES 1
00052
00053 static int _db_tagged_file_indices = _DB_TAGGED_FILE_INDICES;
00054
00055 #define _DBI_FLAGS 0
00056 #define _DBI_PERMS 0644
00057 #define _DBI_MAJOR -1
00058
00059
00060
00061 typedef unsigned int __pbm_bits;
00062
00063 #define __PBM_NBITS (8 * sizeof (__pbm_bits))
00064 #define __PBM_IX(d) ((d) / __PBM_NBITS)
00065 #define __PBM_MASK(d) ((__pbm_bits) 1 << (((unsigned)(d)) % __PBM_NBITS))
00066
00067 typedef struct {
00068 __pbm_bits bits[1];
00069 } pbm_set;
00070
00071 #define __PBM_BITS(set) ((set)->bits)
00072
00073 #define PBM_FREE(s) _free(s);
00074 #define PBM_SET(d, s) (__PBM_BITS (s)[__PBM_IX (d)] |= __PBM_MASK (d))
00075 #define PBM_CLR(d, s) (__PBM_BITS (s)[__PBM_IX (d)] &= ~__PBM_MASK (d))
00076 #define PBM_ISSET(d, s) ((__PBM_BITS (s)[__PBM_IX (d)] & __PBM_MASK (d)) != 0)
00077
00078 #define PBM_ALLOC(d) xcalloc(__PBM_IX (d) + 1, sizeof(__pbm_bits))
00079
00086
00087 static inline pbm_set * PBM_REALLOC(pbm_set ** sp, int * odp, int nd)
00088
00089 {
00090 int i, nb;
00091
00092
00093 if (nd > (*odp)) {
00094 nd *= 2;
00095 nb = __PBM_IX(nd) + 1;
00096
00097 *sp = xrealloc(*sp, nb * sizeof(__pbm_bits));
00098
00099 for (i = __PBM_IX(*odp) + 1; i < nb; i++)
00100 __PBM_BITS(*sp)[i] = 0;
00101 *odp = nd;
00102 }
00103
00104
00105 return *sp;
00106
00107 }
00108
00114 static inline unsigned char nibble(char c)
00115
00116 {
00117 if (c >= '0' && c <= '9')
00118 return (c - '0');
00119 if (c >= 'A' && c <= 'F')
00120 return (c - 'A') + 10;
00121 if (c >= 'a' && c <= 'f')
00122 return (c - 'a') + 10;
00123 return 0;
00124 }
00125
00126 #ifdef DYING
00127
00133 static int printable(const void * ptr, size_t len)
00134 {
00135 const char * s = ptr;
00136 int i;
00137 for (i = 0; i < len; i++, s++)
00138 if (!(*s >= ' ' && *s <= '~')) return 0;
00139 return 1;
00140 }
00141 #endif
00142
00149 static int dbiTagToDbix(rpmdb db, int rpmtag)
00150
00151 {
00152 int dbix;
00153
00154 if (db->db_tagn != NULL)
00155 for (dbix = 0; dbix < db->db_ndbi; dbix++) {
00156
00157 if (rpmtag != db->db_tagn[dbix])
00158 continue;
00159 return dbix;
00160
00161 }
00162 return -1;
00163 }
00164
00168
00169 static void dbiTagsInit(int ** dbiTagsP, int * dbiTagsMaxP)
00170
00171
00172 {
00173
00174 static const char * const _dbiTagStr_default =
00175 "Packages:Name:Basenames:Group:Requirename:Providename:Conflictname:Triggername:Dirnames:Requireversion:Provideversion:Installtid:Sigmd5:Sha1header:Filemd5s:Depends:Pubkeys";
00176 int * dbiTags = NULL;
00177 int dbiTagsMax = 0;
00178 char * dbiTagStr = NULL;
00179 char * o, * oe;
00180 int dbix, rpmtag, bingo;
00181
00182 dbiTagStr = rpmExpand("%{?_dbi_tags}", NULL);
00183 if (!(dbiTagStr && *dbiTagStr)) {
00184 dbiTagStr = _free(dbiTagStr);
00185 dbiTagStr = xstrdup(_dbiTagStr_default);
00186 }
00187
00188
00189 dbiTags = xcalloc(1, sizeof(*dbiTags));
00190 dbiTags[dbiTagsMax++] = RPMDBI_PACKAGES;
00191
00192 for (o = dbiTagStr; o && *o; o = oe) {
00193 while (*o && xisspace(*o))
00194 o++;
00195 if (*o == '\0')
00196 break;
00197 for (oe = o; oe && *oe; oe++) {
00198 if (xisspace(*oe))
00199 break;
00200 if (oe[0] == ':' && !(oe[1] == '/' && oe[2] == '/'))
00201 break;
00202 }
00203 if (oe && *oe)
00204 *oe++ = '\0';
00205 rpmtag = tagValue(o);
00206 if (rpmtag < 0) {
00207 rpmMessage(RPMMESS_WARNING,
00208 _("dbiTagsInit: unrecognized tag name: \"%s\" ignored\n"), o);
00209 continue;
00210 }
00211
00212 bingo = 0;
00213 if (dbiTags != NULL)
00214 for (dbix = 0; dbix < dbiTagsMax; dbix++) {
00215
00216 if (rpmtag == dbiTags[dbix]) {
00217 bingo = 1;
00218 break;
00219 }
00220
00221 }
00222 if (bingo)
00223 continue;
00224
00225 dbiTags = xrealloc(dbiTags, (dbiTagsMax + 1) * sizeof(*dbiTags));
00226 dbiTags[dbiTagsMax++] = rpmtag;
00227 }
00228
00229 if (dbiTagsMaxP != NULL)
00230 *dbiTagsMaxP = dbiTagsMax;
00231
00232 if (dbiTagsP != NULL)
00233 *dbiTagsP = dbiTags;
00234 else
00235 dbiTags = _free(dbiTags);
00236
00237 dbiTagStr = _free(dbiTagStr);
00238 }
00239
00240
00241
00242 #define DB1vec NULL
00243 #define DB2vec NULL
00244
00245 #ifdef HAVE_DB3_DB_H
00246
00247
00248 extern struct _dbiVec db3vec;
00249
00250 #define DB3vec &db3vec
00251
00252 #else
00253 #define DB3vec NULL
00254 #endif
00255
00256 #ifdef HAVE_SQLITE3_H
00257 #define SQLITE_HACK
00258
00259
00260 extern struct _dbiVec sqlitevec;
00261
00262 #define SQLITEvec &sqlitevec
00263
00264 #else
00265 #define SQLITEvec NULL
00266 #endif
00267
00268
00269
00270 static struct _dbiVec *mydbvecs[] = {
00271 DB1vec, DB1vec, DB2vec, DB3vec, SQLITEvec, NULL
00272 };
00273
00274
00275 dbiIndex dbiOpen(rpmdb db, rpmTag rpmtag, unsigned int flags)
00276 {
00277 int dbix;
00278 dbiIndex dbi = NULL;
00279 int _dbapi, _dbapi_rebuild, _dbapi_wanted;
00280 int rc = 0;
00281
00282
00283 if (_rpmdb_debug)
00284 fprintf(stderr, "==> %s(%p, %s, 0x%x)\n", __FUNCTION__, db, tagName(rpmtag), flags);
00285
00286
00287 if (db == NULL)
00288 return NULL;
00289
00290 dbix = dbiTagToDbix(db, rpmtag);
00291 if (dbix < 0 || dbix >= db->db_ndbi)
00292 return NULL;
00293
00294
00295
00296 if (db->_dbi != NULL && (dbi = db->_dbi[dbix]) != NULL)
00297 return dbi;
00298
00299
00300 _dbapi_rebuild = rpmExpandNumeric("%{_dbapi_rebuild}");
00301 if (_dbapi_rebuild < 1 || _dbapi_rebuild > 4)
00302 _dbapi_rebuild = 4;
00303
00304 _dbapi_wanted = (_rebuildinprogress ? _dbapi_rebuild : db->db_api);
00305
00306 switch (_dbapi_wanted) {
00307 default:
00308 _dbapi = _dbapi_wanted;
00309 if (_dbapi < 0 || _dbapi >= 5 || mydbvecs[_dbapi] == NULL) {
00310 rpmMessage(RPMMESS_DEBUG, D_("dbiOpen: _dbiapi failed\n"));
00311 return NULL;
00312 }
00313 errno = 0;
00314 dbi = NULL;
00315 rc = (*mydbvecs[_dbapi]->open) (db, rpmtag, &dbi);
00316 if (rc) {
00317 static int _printed[32];
00318 if (!_printed[dbix & 0x1f]++)
00319 rpmError(RPMERR_DBOPEN,
00320 _("cannot open %s index using db%d - %s (%d)\n"),
00321 tagName(rpmtag), _dbapi,
00322 (rc > 0 ? strerror(rc) : ""), rc);
00323 _dbapi = -1;
00324 }
00325 break;
00326 case -1:
00327 _dbapi = 5;
00328 while (_dbapi-- > 1) {
00329 if (mydbvecs[_dbapi] == NULL)
00330 continue;
00331 errno = 0;
00332 dbi = NULL;
00333 rc = (*mydbvecs[_dbapi]->open) (db, rpmtag, &dbi);
00334 if (rc == 0 && dbi)
00335 break;
00336 }
00337 if (_dbapi <= 0) {
00338 static int _printed[32];
00339 if (!_printed[dbix & 0x1f]++)
00340 rpmError(RPMERR_DBOPEN, _("cannot open %s index\n"),
00341 tagName(rpmtag));
00342 rc = 1;
00343 goto exit;
00344 }
00345 if (db->db_api == -1 && _dbapi > 0)
00346 db->db_api = _dbapi;
00347 break;
00348 }
00349
00350 exit:
00351 if (dbi != NULL && rc == 0) {
00352 if (db->_dbi != NULL)
00353 db->_dbi[dbix] = dbi;
00354
00355 if (rpmtag == RPMDBI_PACKAGES && db->db_bits == NULL) {
00356 db->db_nbits = 1024;
00357 if (!dbiStat(dbi, DB_FAST_STAT)) {
00358 DB_HASH_STAT * hash = (DB_HASH_STAT *)dbi->dbi_stats;
00359 if (hash)
00360 db->db_nbits += hash->hash_nkeys;
00361 }
00362 db->db_bits = PBM_ALLOC(db->db_nbits);
00363 }
00364
00365 }
00366 #ifdef HAVE_DB3_DB_H
00367 else
00368 dbi = db3Free(dbi);
00369 #endif
00370
00371
00372 return dbi;
00373
00374 }
00375
00382 static dbiIndexItem dbiIndexNewItem(unsigned int hdrNum, unsigned int tagNum)
00383
00384 {
00385 dbiIndexItem rec = xcalloc(1, sizeof(*rec));
00386 rec->hdrNum = hdrNum;
00387 rec->tagNum = tagNum;
00388 return rec;
00389 }
00390
00391 union _dbswap {
00392 uint32_t ui;
00393 unsigned char uc[4];
00394 };
00395
00396 #define _DBSWAP(_a) \
00397 \
00398 { unsigned char _b, *_c = (_a).uc; \
00399 _b = _c[3]; _c[3] = _c[0]; _c[0] = _b; \
00400 _b = _c[2]; _c[2] = _c[1]; _c[1] = _b; \
00401 \
00402 }
00403
00411 static int dbt2set(dbiIndex dbi, DBT * data, dbiIndexSet * setp)
00412
00413 {
00414 int _dbbyteswapped;
00415 const char * sdbir;
00416 dbiIndexSet set;
00417 int i;
00418
00419 if (dbi == NULL || data == NULL || setp == NULL)
00420 return -1;
00421 _dbbyteswapped = dbiByteSwapped(dbi);
00422
00423 if ((sdbir = data->data) == NULL) {
00424 *setp = NULL;
00425 return 0;
00426 }
00427
00428 set = xmalloc(sizeof(*set));
00429 set->count = data->size / dbi->dbi_jlen;
00430 set->recs = xmalloc(set->count * sizeof(*(set->recs)));
00431
00432
00433 switch (dbi->dbi_jlen) {
00434 default:
00435 case 2*sizeof(int_32):
00436 for (i = 0; i < set->count; i++) {
00437 union _dbswap hdrNum, tagNum;
00438
00439 memcpy(&hdrNum.ui, sdbir, sizeof(hdrNum.ui));
00440 sdbir += sizeof(hdrNum.ui);
00441 memcpy(&tagNum.ui, sdbir, sizeof(tagNum.ui));
00442 sdbir += sizeof(tagNum.ui);
00443 if (_dbbyteswapped) {
00444 _DBSWAP(hdrNum);
00445 _DBSWAP(tagNum);
00446 }
00447 set->recs[i].hdrNum = hdrNum.ui;
00448 set->recs[i].tagNum = tagNum.ui;
00449 set->recs[i].fpNum = 0;
00450 }
00451 break;
00452 case 1*sizeof(int_32):
00453 for (i = 0; i < set->count; i++) {
00454 union _dbswap hdrNum;
00455
00456 memcpy(&hdrNum.ui, sdbir, sizeof(hdrNum.ui));
00457 sdbir += sizeof(hdrNum.ui);
00458 if (_dbbyteswapped) {
00459 _DBSWAP(hdrNum);
00460 }
00461 set->recs[i].hdrNum = hdrNum.ui;
00462 set->recs[i].tagNum = 0;
00463 set->recs[i].fpNum = 0;
00464 }
00465 break;
00466 }
00467 *setp = set;
00468
00469
00470 return 0;
00471
00472 }
00473
00481 static int set2dbt(dbiIndex dbi, DBT * data, dbiIndexSet set)
00482
00483 {
00484 int _dbbyteswapped;
00485 char * tdbir;
00486 int i;
00487
00488 if (dbi == NULL || data == NULL || set == NULL)
00489 return -1;
00490 _dbbyteswapped = dbiByteSwapped(dbi);
00491
00492 data->size = set->count * (dbi->dbi_jlen);
00493 if (data->size == 0) {
00494 data->data = NULL;
00495 return 0;
00496 }
00497 tdbir = data->data = xmalloc(data->size);
00498
00499
00500 switch (dbi->dbi_jlen) {
00501 default:
00502 case 2*sizeof(int_32):
00503 for (i = 0; i < set->count; i++) {
00504 union _dbswap hdrNum, tagNum;
00505
00506 memset(&hdrNum, 0, sizeof(hdrNum));
00507 memset(&tagNum, 0, sizeof(tagNum));
00508 hdrNum.ui = set->recs[i].hdrNum;
00509 tagNum.ui = set->recs[i].tagNum;
00510 if (_dbbyteswapped) {
00511 _DBSWAP(hdrNum);
00512 _DBSWAP(tagNum);
00513 }
00514 memcpy(tdbir, &hdrNum.ui, sizeof(hdrNum.ui));
00515 tdbir += sizeof(hdrNum.ui);
00516 memcpy(tdbir, &tagNum.ui, sizeof(tagNum.ui));
00517 tdbir += sizeof(tagNum.ui);
00518 }
00519 break;
00520 case 1*sizeof(int_32):
00521 for (i = 0; i < set->count; i++) {
00522 union _dbswap hdrNum;
00523
00524 memset(&hdrNum, 0, sizeof(hdrNum));
00525 hdrNum.ui = set->recs[i].hdrNum;
00526 if (_dbbyteswapped) {
00527 _DBSWAP(hdrNum);
00528 }
00529 memcpy(tdbir, &hdrNum.ui, sizeof(hdrNum.ui));
00530 tdbir += sizeof(hdrNum.ui);
00531 }
00532 break;
00533 }
00534
00535
00536
00537 return 0;
00538
00539 }
00540
00541
00542 static int hdrNumCmp(const void * one, const void * two)
00543
00544 {
00545 const int * a = one, * b = two;
00546 return (*a - *b);
00547 }
00548
00558 static int dbiAppendSet(dbiIndexSet set, const void * recs,
00559 int nrecs, size_t recsize, int sortset)
00560
00561 {
00562 const char * rptr = recs;
00563 size_t rlen = (recsize < sizeof(*(set->recs)))
00564 ? recsize : sizeof(*(set->recs));
00565
00566 if (set == NULL || recs == NULL || nrecs <= 0 || recsize == 0)
00567 return 1;
00568
00569 set->recs = xrealloc(set->recs,
00570 (set->count + nrecs) * sizeof(*(set->recs)));
00571
00572 memset(set->recs + set->count, 0, nrecs * sizeof(*(set->recs)));
00573
00574 while (nrecs-- > 0) {
00575
00576 memcpy(set->recs + set->count, rptr, rlen);
00577
00578 rptr += recsize;
00579 set->count++;
00580 }
00581
00582 if (sortset && set->count > 1)
00583 qsort(set->recs, set->count, sizeof(*(set->recs)), hdrNumCmp);
00584
00585 return 0;
00586 }
00587
00597 static int dbiPruneSet(dbiIndexSet set, void * recs, int nrecs,
00598 size_t recsize, int sorted)
00599
00600 {
00601 int from;
00602 int to = 0;
00603 int num = set->count;
00604 int numCopied = 0;
00605
00606 assert(set->count > 0);
00607 if (nrecs > 1 && !sorted)
00608 qsort(recs, nrecs, recsize, hdrNumCmp);
00609
00610 for (from = 0; from < num; from++) {
00611 if (bsearch(&set->recs[from], recs, nrecs, recsize, hdrNumCmp)) {
00612 set->count--;
00613 continue;
00614 }
00615 if (from != to)
00616 set->recs[to] = set->recs[from];
00617 to++;
00618 numCopied++;
00619 }
00620 return (numCopied == num);
00621 }
00622
00623
00624 unsigned int dbiIndexSetCount(dbiIndexSet set) {
00625 return set->count;
00626 }
00627
00628
00629 unsigned int dbiIndexRecordOffset(dbiIndexSet set, int recno) {
00630 return set->recs[recno].hdrNum;
00631 }
00632
00633
00634 unsigned int dbiIndexRecordFileNumber(dbiIndexSet set, int recno) {
00635 return set->recs[recno].tagNum;
00636 }
00637
00638
00639 dbiIndexSet dbiFreeIndexSet(dbiIndexSet set) {
00640 if (set) {
00641 set->recs = _free(set->recs);
00642 set = _free(set);
00643 }
00644 return set;
00645 }
00646
00647 struct _rpmdbMatchIterator {
00648
00649 rpmdbMatchIterator mi_next;
00650
00651 const void * mi_keyp;
00652 size_t mi_keylen;
00653
00654 rpmdb mi_db;
00655 rpmTag mi_rpmtag;
00656 dbiIndexSet mi_set;
00657 DBC * mi_dbc;
00658 DBT mi_key;
00659 DBT mi_data;
00660 int mi_setx;
00661
00662 Header mi_h;
00663 int mi_sorted;
00664 int mi_cflags;
00665 int mi_modified;
00666 unsigned int mi_prevoffset;
00667 unsigned int mi_offset;
00668 unsigned int mi_filenum;
00669 int mi_nre;
00670
00671 miRE mi_re;
00672
00673 rpmts mi_ts;
00674
00675 rpmRC (*mi_hdrchk) (rpmts ts, const void * uh, size_t uc, const char ** msg)
00676 ;
00677
00678 };
00679
00680
00681 static rpmdb rpmdbRock;
00682
00683
00684 static rpmdbMatchIterator rpmmiRock;
00685
00686 int rpmdbCheckSignals(void)
00687
00688
00689 {
00690 sigset_t newMask, oldMask;
00691 static int terminate = 0;
00692
00693 if (terminate) return 0;
00694
00695 (void) sigfillset(&newMask);
00696 (void) sigprocmask(SIG_BLOCK, &newMask, &oldMask);
00697
00698 if (sigismember(&rpmsqCaught, SIGINT)
00699 || sigismember(&rpmsqCaught, SIGQUIT)
00700 || sigismember(&rpmsqCaught, SIGHUP)
00701 || sigismember(&rpmsqCaught, SIGTERM)
00702 || sigismember(&rpmsqCaught, SIGPIPE))
00703 terminate = 1;
00704
00705 if (terminate) {
00706 rpmdb db;
00707 rpmdbMatchIterator mi;
00708
00709
00710 rpmMessage(RPMMESS_DEBUG, D_("Exiting on signal(0x%lx) ...\n"), *((unsigned long *)&rpmsqCaught));
00711
00712
00713
00714 while ((mi = rpmmiRock) != NULL) {
00715 rpmmiRock = mi->mi_next;
00716 mi->mi_next = NULL;
00717 mi = rpmdbFreeIterator(mi);
00718 }
00719
00720
00721
00722 while ((db = rpmdbRock) != NULL) {
00723 rpmdbRock = db->db_next;
00724 db->db_next = NULL;
00725 (void) rpmdbClose(db);
00726 }
00727
00728 exit(EXIT_FAILURE);
00729 }
00730 return sigprocmask(SIG_SETMASK, &oldMask, NULL);
00731 }
00732
00739 static int blockSignals( rpmdb db, sigset_t * oldMask)
00740
00741
00742 {
00743 sigset_t newMask;
00744
00745 (void) sigfillset(&newMask);
00746 (void) sigprocmask(SIG_BLOCK, &newMask, oldMask);
00747 (void) sigdelset(&newMask, SIGINT);
00748 (void) sigdelset(&newMask, SIGQUIT);
00749 (void) sigdelset(&newMask, SIGHUP);
00750 (void) sigdelset(&newMask, SIGTERM);
00751 (void) sigdelset(&newMask, SIGPIPE);
00752 return sigprocmask(SIG_BLOCK, &newMask, NULL);
00753 }
00754
00761
00762 static int unblockSignals( rpmdb db, sigset_t * oldMask)
00763
00764
00765 {
00766 (void) rpmdbCheckSignals();
00767 return sigprocmask(SIG_SETMASK, oldMask, NULL);
00768 }
00769
00777 static inline const char * queryHeader(Header h, const char * qfmt)
00778
00779 {
00780 static const struct headerSprintfExtension_s * hdrfmts = headerDefaultFormats;
00781 const char * errstr = "(unkown error)";
00782 const char * str;
00783
00784
00785 str = headerSprintf(h, qfmt, rpmTagTable, hdrfmts, &errstr);
00786
00787 if (str == NULL)
00788 rpmError(RPMERR_QFMT, _("incorrect format: \"%s\": %s\n"), qfmt, errstr);
00789 return str;
00790 }
00791
00799 static int rpmdbExportInfo( rpmdb db, Header h, int adding)
00800
00801
00802
00803
00804 {
00805 const char * fn = NULL;
00806 int xx;
00807
00808
00809 { const char * fnfmt = rpmGetPath("%{?_hrmib_path}", NULL);
00810 if (fnfmt && *fnfmt)
00811 fn = queryHeader(h, fnfmt);
00812 fnfmt = _free(fnfmt);
00813 }
00814
00815
00816 if (fn == NULL)
00817 goto exit;
00818
00819 if (adding) {
00820 FD_t fd = Fopen(fn, "w");
00821 int_32 *iidp;
00822
00823 if (fd != NULL) {
00824 xx = Fclose(fd);
00825 fd = NULL;
00826 if (headerGetEntry(h, RPMTAG_INSTALLTID, NULL, &iidp, NULL)) {
00827 struct utimbuf stamp;
00828 stamp.actime = *iidp;
00829 stamp.modtime = *iidp;
00830 if (!Utime(fn, &stamp))
00831 rpmMessage(RPMMESS_DEBUG, " +++ %s\n", fn);
00832 }
00833 }
00834 } else {
00835 if (!Unlink(fn))
00836 rpmMessage(RPMMESS_DEBUG, " --- %s\n", fn);
00837 }
00838
00839 exit:
00840 fn = _free(fn);
00841 return 0;
00842 }
00843
00844 #define _DB_ROOT "/"
00845 #define _DB_HOME "%{?_dbpath}"
00846 #define _DB_FLAGS 0
00847 #define _DB_MODE 0
00848 #define _DB_PERMS 0644
00849
00850 #define _DB_MAJOR -1
00851 #define _DB_ERRPFX "rpmdb"
00852
00853
00854
00855 static struct rpmdb_s dbTemplate = {
00856 _DB_ROOT, _DB_HOME, _DB_FLAGS, _DB_MODE, _DB_PERMS,
00857 _DB_MAJOR, _DB_ERRPFX
00858 };
00859
00860
00861 int rpmdbOpenAll(rpmdb db)
00862 {
00863 int dbix;
00864 int rc = 0;
00865
00866 if (db == NULL) return -2;
00867
00868 if (db->db_tagn != NULL && db->_dbi != NULL)
00869 for (dbix = 0; dbix < db->db_ndbi; dbix++) {
00870 if (db->db_tagn[dbix] < 0)
00871 continue;
00872 if (db->_dbi[dbix] != NULL)
00873 continue;
00874 switch ((db->db_tagn[dbix])) {
00875 case RPMDBI_AVAILABLE:
00876 case RPMDBI_ADDED:
00877 case RPMDBI_REMOVED:
00878 case RPMDBI_DEPENDS:
00879 continue;
00880 break;
00881 default:
00882 break;
00883 }
00884 (void) dbiOpen(db, db->db_tagn[dbix], db->db_flags);
00885 }
00886 return rc;
00887 }
00888
00889 int rpmdbBlockDBI(rpmdb db, int rpmtag)
00890 {
00891 int tagn = (rpmtag >= 0 ? rpmtag : -rpmtag);
00892 int dbix;
00893
00894 if (db == NULL || db->_dbi == NULL)
00895 return 0;
00896
00897 if (db->db_tagn != NULL)
00898 for (dbix = 0; dbix < db->db_ndbi; dbix++) {
00899 if (db->db_tagn[dbix] != tagn)
00900 continue;
00901 db->db_tagn[dbix] = rpmtag;
00902 return 0;
00903 }
00904 return 0;
00905 }
00906
00907 int rpmdbCloseDBI(rpmdb db, int rpmtag)
00908 {
00909 int dbix;
00910 int rc = 0;
00911
00912 if (db == NULL || db->_dbi == NULL)
00913 return 0;
00914
00915 if (db->db_tagn != NULL)
00916 for (dbix = 0; dbix < db->db_ndbi; dbix++) {
00917 if (db->db_tagn[dbix] != rpmtag)
00918 continue;
00919
00920 if (db->_dbi[dbix] != NULL) {
00921 int xx;
00922
00923 xx = dbiClose(db->_dbi[dbix], 0);
00924 if (xx && rc == 0) rc = xx;
00925 db->_dbi[dbix] = NULL;
00926
00927 }
00928
00929 break;
00930 }
00931 return rc;
00932 }
00933
00934
00935
00936 int rpmdbClose(rpmdb db)
00937
00938
00939 {
00940 rpmdb * prev, next;
00941 int dbix;
00942 int rc = 0;
00943
00944 if (db == NULL)
00945 goto exit;
00946
00947 (void) rpmdbUnlink(db, "rpmdbClose");
00948
00949
00950 if (db->nrefs > 0)
00951 goto exit;
00952
00953 if (db->_dbi)
00954 for (dbix = db->db_ndbi; --dbix >= 0; ) {
00955 int xx;
00956 if (db->_dbi[dbix] == NULL)
00957 continue;
00958
00959 xx = dbiClose(db->_dbi[dbix], 0);
00960 if (xx && rc == 0) rc = xx;
00961 db->_dbi[dbix] = NULL;
00962
00963 }
00964 db->db_errpfx = _free(db->db_errpfx);
00965 db->db_root = _free(db->db_root);
00966 db->db_home = _free(db->db_home);
00967 db->db_bits = PBM_FREE(db->db_bits);
00968 db->db_tagn = _free(db->db_tagn);
00969 db->_dbi = _free(db->_dbi);
00970 db->db_ndbi = 0;
00971
00972
00973 prev = &rpmdbRock;
00974 while ((next = *prev) != NULL && next != db)
00975 prev = &next->db_next;
00976 if (next) {
00977 *prev = next->db_next;
00978 next->db_next = NULL;
00979 }
00980
00981
00982 db = _free(db);
00983
00984
00985 exit:
00986 (void) rpmsqEnable(-SIGHUP, NULL);
00987 (void) rpmsqEnable(-SIGINT, NULL);
00988 (void) rpmsqEnable(-SIGTERM,NULL);
00989 (void) rpmsqEnable(-SIGQUIT,NULL);
00990 (void) rpmsqEnable(-SIGPIPE,NULL);
00991 return rc;
00992 }
00993
00994
00995 int rpmdbSync(rpmdb db)
00996 {
00997 int dbix;
00998 int rc = 0;
00999
01000 if (db == NULL) return 0;
01001 if (db->_dbi != NULL)
01002 for (dbix = 0; dbix < db->db_ndbi; dbix++) {
01003 int xx;
01004 if (db->_dbi[dbix] == NULL)
01005 continue;
01006 if (db->_dbi[dbix]->dbi_no_dbsync)
01007 continue;
01008 xx = dbiSync(db->_dbi[dbix], 0);
01009 if (xx && rc == 0) rc = xx;
01010 }
01011 return rc;
01012 }
01013
01019 static const char * rpmdbURIPath(const char *uri)
01020
01021
01022 {
01023 const char * s = rpmGetPath(uri, NULL);
01024 const char * fn = NULL;
01025 urltype ut = urlPath(s, &fn);
01026
01027
01028 switch (ut) {
01029 case URL_IS_PATH:
01030 case URL_IS_UNKNOWN:
01031 fn = s;
01032 s = NULL;
01033 break;
01034 case URL_IS_HTTPS:
01035 case URL_IS_HTTP:
01036 case URL_IS_FTP:
01037 case URL_IS_HKP:
01038 case URL_IS_DASH:
01039 default:
01040
01041 fn = rpmGetPath(fn, NULL);
01042 break;
01043 }
01044
01045
01046
01047 if (ut != URL_IS_PATH)
01048 if (fn && *fn && *fn != '/') {
01049 char dn[PATH_MAX];
01050 char *t;
01051 dn[0] = '\0';
01052 if ((t = realpath(".", dn)) != NULL) {
01053 t += strlen(dn);
01054 if (t > dn && t[-1] != '/')
01055 *t++ = '/';
01056 t = stpncpy(t, fn, (sizeof(dn) - (t - dn)));
01057 *t = '\0';
01058 fn = _free(fn);
01059 fn = rpmGetPath(dn, NULL);
01060 }
01061 }
01062
01063 s = _free(s);
01064 assert(fn != NULL);
01065 return fn;
01066 }
01067
01068
01069
01070
01071 rpmdb rpmdbNew( const char * root,
01072 const char * home,
01073 int mode, int perms, int flags)
01074
01075
01076 {
01077 rpmdb db = xcalloc(sizeof(*db), 1);
01078 const char * epfx = _DB_ERRPFX;
01079 static int oneshot = 0;
01080
01081
01082 if (_rpmdb_debug)
01083 fprintf(stderr, "==> %s(%s, %s, 0x%x, 0%o, 0x%x) db %p\n", __FUNCTION__, root, home, mode, perms, flags, db);
01084
01085
01086 if (!oneshot) {
01087 _db_filter_dups = rpmExpandNumeric("%{_filterdbdups}");
01088 oneshot = 1;
01089 }
01090
01091
01092
01093 *db = dbTemplate;
01094
01095
01096
01097 db->_dbi = NULL;
01098
01099 if (!(perms & 0600)) perms = 0644;
01100
01101 if (mode >= 0) db->db_mode = mode;
01102 if (perms >= 0) db->db_perms = perms;
01103 if (flags >= 0) db->db_flags = flags;
01104
01105 db->db_root = rpmdbURIPath( (root && *root ? root : _DB_ROOT) );
01106 db->db_home = rpmdbURIPath( (home && *home ? home : _DB_HOME) );
01107
01108 if (!(db->db_home && db->db_home[0])) {
01109 rpmError(RPMERR_DBOPEN, _("no dbpath has been set\n"));
01110 db->db_root = _free(db->db_root);
01111 db->db_home = _free(db->db_home);
01112 db = _free(db);
01113 return NULL;
01114 }
01115
01116
01117 { const char * dbpath = rpmGetPath("%{?_dbpath}", NULL);
01118 const char * rootpath = NULL;
01119 const char * homepath = NULL;
01120
01121 (void) urlPath(db->db_root, &rootpath);
01122 (void) urlPath(db->db_home, &homepath);
01123 #define _VARLIBRPM "/var/lib/rpm"
01124 if (!strcmp(rootpath, "/")
01125 && !strncmp(homepath, _VARLIBRPM, sizeof(_VARLIBRPM)-1))
01126 db->db_export = rpmdbExportInfo;
01127 dbpath = _free(dbpath);
01128 #undef _VARLIBRPM
01129 }
01130
01131 db->db_errpfx = rpmExpand( (epfx && *epfx ? epfx : _DB_ERRPFX), NULL);
01132 db->db_remove_env = 0;
01133 db->db_filter_dups = _db_filter_dups;
01134 dbiTagsInit(&db->db_tagn, &db->db_ndbi);
01135 db->_dbi = xcalloc(db->db_ndbi, sizeof(*db->_dbi));
01136 db->nrefs = 0;
01137
01138 return rpmdbLink(db, "rpmdbCreate");
01139
01140 }
01141
01142
01143
01144
01145 int rpmdbOpenDatabase( const char * prefix,
01146 const char * dbpath,
01147 int _dbapi, rpmdb *dbp,
01148 int mode, int perms, int flags)
01149
01150
01151
01152
01153
01154 {
01155 rpmdb db;
01156 int rc, xx;
01157 int justCheck = flags & RPMDB_FLAG_JUSTCHECK;
01158 int minimal = flags & RPMDB_FLAG_MINIMAL;
01159
01160
01161 if (_dbapi < -1 || _dbapi > 4)
01162 _dbapi = -1;
01163 if (_dbapi == 0)
01164 _dbapi = 1;
01165
01166 if (dbp)
01167 *dbp = NULL;
01168 if (mode & O_WRONLY)
01169 return 1;
01170
01171 db = rpmdbNew(prefix, dbpath, mode, perms, flags);
01172 if (db == NULL)
01173 return 1;
01174
01175 (void) rpmsqEnable(SIGHUP, NULL);
01176 (void) rpmsqEnable(SIGINT, NULL);
01177 (void) rpmsqEnable(SIGTERM, NULL);
01178 (void) rpmsqEnable(SIGQUIT, NULL);
01179 (void) rpmsqEnable(SIGPIPE, NULL);
01180
01181 db->db_api = _dbapi;
01182
01183 { int dbix;
01184
01185 rc = 0;
01186 if (db->db_tagn != NULL)
01187 for (dbix = 0; rc == 0 && dbix < db->db_ndbi; dbix++) {
01188 dbiIndex dbi;
01189 int rpmtag;
01190
01191
01192 switch ((rpmtag = db->db_tagn[dbix])) {
01193 case RPMDBI_AVAILABLE:
01194 case RPMDBI_ADDED:
01195 case RPMDBI_REMOVED:
01196 case RPMDBI_DEPENDS:
01197 continue;
01198 break;
01199 default:
01200 break;
01201 }
01202
01203 dbi = dbiOpen(db, rpmtag, 0);
01204 if (dbi == NULL) {
01205 rc = -2;
01206 break;
01207 }
01208
01209 switch (rpmtag) {
01210 case RPMDBI_PACKAGES:
01211 if (dbi == NULL) rc |= 1;
01212 #if 0
01213
01214 if (db->db_api == 3)
01215 #endif
01216 goto exit;
01217 break;
01218 case RPMTAG_NAME:
01219 if (dbi == NULL) rc |= 1;
01220 if (minimal)
01221 goto exit;
01222 break;
01223 default:
01224 break;
01225 }
01226 }
01227 }
01228
01229 exit:
01230 if (rc || justCheck || dbp == NULL)
01231 xx = rpmdbClose(db);
01232 else {
01233
01234 db->db_next = rpmdbRock;
01235 rpmdbRock = db;
01236 *dbp = db;
01237
01238 }
01239
01240 return rc;
01241 }
01242
01243
01244 rpmdb XrpmdbUnlink(rpmdb db, const char * msg, const char * fn, unsigned ln)
01245 {
01246
01247 if (_rpmdb_debug)
01248 fprintf(stderr, "--> db %p -- %d %s at %s:%u\n", db, db->nrefs, msg, fn, ln);
01249
01250 db->nrefs--;
01251 return NULL;
01252 }
01253
01254 rpmdb XrpmdbLink(rpmdb db, const char * msg, const char * fn, unsigned ln)
01255 {
01256 db->nrefs++;
01257
01258 if (_rpmdb_debug)
01259 fprintf(stderr, "--> db %p ++ %d %s at %s:%u\n", db, db->nrefs, msg, fn, ln);
01260
01261 return db;
01262 }
01263
01264
01265 int rpmdbOpen (const char * prefix, rpmdb *dbp, int mode, int perms)
01266 {
01267 int _dbapi = rpmExpandNumeric("%{_dbapi}");
01268
01269 return rpmdbOpenDatabase(prefix, NULL, _dbapi, dbp, mode, perms, 0);
01270
01271 }
01272
01273 int rpmdbInit (const char * prefix, int perms)
01274 {
01275 rpmdb db = NULL;
01276 int _dbapi = rpmExpandNumeric("%{_dbapi}");
01277 int rc;
01278
01279
01280 rc = rpmdbOpenDatabase(prefix, NULL, _dbapi, &db, (O_CREAT | O_RDWR),
01281 perms, RPMDB_FLAG_JUSTCHECK);
01282
01283 if (db != NULL) {
01284 int xx;
01285 xx = rpmdbOpenAll(db);
01286 if (xx && rc == 0) rc = xx;
01287 xx = rpmdbClose(db);
01288 if (xx && rc == 0) rc = xx;
01289 db = NULL;
01290 }
01291 return rc;
01292 }
01293
01294 int rpmdbVerifyAllDBI(rpmdb db)
01295 {
01296 int rc = 0;
01297
01298 if (db != NULL) {
01299 int dbix;
01300 int xx;
01301 rc = rpmdbOpenAll(db);
01302
01303 if (db->_dbi != NULL)
01304 for (dbix = db->db_ndbi; --dbix >= 0; ) {
01305 if (db->_dbi[dbix] == NULL)
01306 continue;
01307
01308 xx = dbiVerify(db->_dbi[dbix], 0);
01309 if (xx && rc == 0) rc = xx;
01310 db->_dbi[dbix] = NULL;
01311
01312 }
01313
01314
01315 xx = rpmdbClose(db);
01316
01317 if (xx && rc == 0) rc = xx;
01318 db = NULL;
01319 }
01320 return rc;
01321 }
01322
01323 int rpmdbVerify(const char * prefix)
01324 {
01325 rpmdb db = NULL;
01326 int _dbapi = rpmExpandNumeric("%{_dbapi}");
01327 int rc = rpmdbOpenDatabase(prefix, NULL, _dbapi, &db, O_RDONLY, 0644, 0);
01328
01329 if (!rc && db != NULL)
01330 rc = rpmdbVerifyAllDBI(db);
01331 return rc;
01332 }
01333
01339 static inline unsigned taghash(const char *s)
01340 {
01341 unsigned int r = 0;
01342 int c;
01343 while ((c = *(const unsigned char *)s++) != 0) {
01344
01345 if (c != '/')
01346 r += (r << 3) + c;
01347 }
01348 return ((r & 0x7fff) | 0x8000) << 16;
01349 }
01350
01360 static int rpmdbFindByFile(rpmdb db, const char * filespec,
01361 DBT * key, DBT * data, dbiIndexSet * matches)
01362
01363
01364
01365
01366 {
01367 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
01368 HFD_t hfd = headerFreeData;
01369 const char * dirName;
01370 const char * baseName;
01371 rpmTagType bnt, dnt;
01372 fingerPrintCache fpc;
01373 fingerPrint fp1;
01374 dbiIndex dbi = NULL;
01375 DBC * dbcursor;
01376 dbiIndexSet allMatches = NULL;
01377 dbiIndexItem rec = NULL;
01378 int i;
01379 int rc;
01380 int xx;
01381
01382 *matches = NULL;
01383 if (filespec == NULL) return -2;
01384
01385
01386 if ((baseName = strrchr(filespec, '/')) != NULL) {
01387 char * t;
01388 size_t len;
01389
01390 len = baseName - filespec + 1;
01391
01392 t = strncpy(alloca(len + 1), filespec, len);
01393 t[len] = '\0';
01394
01395 dirName = t;
01396 baseName++;
01397 } else {
01398 dirName = "";
01399 baseName = filespec;
01400 }
01401
01402 if (baseName == NULL)
01403 return -2;
01404
01405 fpc = fpCacheCreate(20);
01406 fp1 = fpLookup(fpc, dirName, baseName, 1);
01407
01408 dbi = dbiOpen(db, RPMTAG_BASENAMES, 0);
01409
01410 if (dbi != NULL) {
01411 dbcursor = NULL;
01412 xx = dbiCopen(dbi, dbi->dbi_txnid, &dbcursor, 0);
01413
01414
01415 key->data = (void *) baseName;
01416
01417 key->size = strlen(baseName);
01418 if (key->size == 0) key->size++;
01419
01420 rc = dbiGet(dbi, dbcursor, key, data, DB_SET);
01421 if (rc > 0) {
01422 rpmError(RPMERR_DBGETINDEX,
01423 _("error(%d) getting \"%s\" records from %s index\n"),
01424 rc, key->data, tagName(dbi->dbi_rpmtag));
01425 }
01426
01427 if (rc == 0)
01428 (void) dbt2set(dbi, data, &allMatches);
01429
01430
01431 if (_db_tagged_file_indices && allMatches != NULL)
01432 for (i = 0; i < allMatches->count; i++) {
01433 if (allMatches->recs[i].tagNum & 0x80000000)
01434 allMatches->recs[i].tagNum &= 0x0000ffff;
01435 }
01436
01437 xx = dbiCclose(dbi, dbcursor, 0);
01438 dbcursor = NULL;
01439 } else
01440 rc = -2;
01441
01442
01443 if (rc) {
01444 allMatches = dbiFreeIndexSet(allMatches);
01445 fpc = fpCacheFree(fpc);
01446 return rc;
01447 }
01448
01449 *matches = xcalloc(1, sizeof(**matches));
01450 rec = dbiIndexNewItem(0, 0);
01451 i = 0;
01452 if (allMatches != NULL)
01453 while (i < allMatches->count) {
01454 const char ** baseNames, ** dirNames;
01455 int_32 * dirIndexes;
01456 unsigned int offset = dbiIndexRecordOffset(allMatches, i);
01457 unsigned int prevoff;
01458 Header h;
01459
01460 { rpmdbMatchIterator mi;
01461 mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, &offset, sizeof(offset));
01462 h = rpmdbNextIterator(mi);
01463 if (h)
01464 h = headerLink(h);
01465 mi = rpmdbFreeIterator(mi);
01466 }
01467
01468 if (h == NULL) {
01469 i++;
01470 continue;
01471 }
01472
01473 xx = hge(h, RPMTAG_BASENAMES, &bnt, &baseNames, NULL);
01474 xx = hge(h, RPMTAG_DIRNAMES, &dnt, &dirNames, NULL);
01475 xx = hge(h, RPMTAG_DIRINDEXES, NULL, &dirIndexes, NULL);
01476
01477 do {
01478 fingerPrint fp2;
01479 int num = dbiIndexRecordFileNumber(allMatches, i);
01480
01481 fp2 = fpLookup(fpc, dirNames[dirIndexes[num]], baseNames[num], 1);
01482
01483 if (FP_EQUAL(fp1, fp2)) {
01484
01485 rec->hdrNum = dbiIndexRecordOffset(allMatches, i);
01486 rec->tagNum = dbiIndexRecordFileNumber(allMatches, i);
01487 xx = dbiAppendSet(*matches, rec, 1, sizeof(*rec), 0);
01488 }
01489
01490 prevoff = offset;
01491 i++;
01492 if (i < allMatches->count)
01493 offset = dbiIndexRecordOffset(allMatches, i);
01494 } while (i < allMatches->count && offset == prevoff);
01495
01496 baseNames = hfd(baseNames, bnt);
01497 dirNames = hfd(dirNames, dnt);
01498 h = headerFree(h);
01499 }
01500
01501 rec = _free(rec);
01502 allMatches = dbiFreeIndexSet(allMatches);
01503
01504 fpc = fpCacheFree(fpc);
01505
01506 if ((*matches)->count == 0) {
01507 *matches = dbiFreeIndexSet(*matches);
01508 return 1;
01509 }
01510
01511 return 0;
01512 }
01513
01514
01515 int rpmdbCountPackages(rpmdb db, const char * name)
01516 {
01517 DBC * dbcursor = NULL;
01518 DBT * key = alloca(sizeof(*key));
01519 DBT * data = alloca(sizeof(*data));
01520 dbiIndex dbi;
01521 int rc;
01522 int xx;
01523
01524 if (db == NULL)
01525 return 0;
01526
01527 memset(key, 0, sizeof(*key));
01528 memset(data, 0, sizeof(*data));
01529
01530 dbi = dbiOpen(db, RPMTAG_NAME, 0);
01531 if (dbi == NULL)
01532 return 0;
01533
01534
01535 key->data = (void *) name;
01536
01537 key->size = strlen(name);
01538
01539 xx = dbiCopen(dbi, dbi->dbi_txnid, &dbcursor, 0);
01540 rc = dbiGet(dbi, dbcursor, key, data, DB_SET);
01541 #ifndef SQLITE_HACK
01542 xx = dbiCclose(dbi, dbcursor, 0);
01543 dbcursor = NULL;
01544 #endif
01545
01546 if (rc == 0) {
01547 dbiIndexSet matches;
01548
01549 matches = NULL;
01550 (void) dbt2set(dbi, data, &matches);
01551 if (matches) {
01552 rc = dbiIndexSetCount(matches);
01553 matches = dbiFreeIndexSet(matches);
01554 }
01555
01556 } else
01557 if (rc == DB_NOTFOUND) {
01558 rc = 0;
01559 } else {
01560 rpmError(RPMERR_DBGETINDEX,
01561 _("error(%d) getting \"%s\" records from %s index\n"),
01562 rc, key->data, tagName(dbi->dbi_rpmtag));
01563 rc = -1;
01564 }
01565
01566 #ifdef SQLITE_HACK
01567 xx = dbiCclose(dbi, dbcursor, 0);
01568 dbcursor = NULL;
01569 #endif
01570
01571 return rc;
01572 }
01573
01586 static rpmRC dbiFindMatches(dbiIndex dbi, DBC * dbcursor,
01587 DBT * key, DBT * data,
01588 const char * name,
01589 const char * version,
01590 const char * release,
01591 dbiIndexSet * matches)
01592
01593
01594
01595
01596 {
01597 int gotMatches = 0;
01598 int rc;
01599 int i;
01600
01601
01602 key->data = (void *) name;
01603
01604 key->size = strlen(name);
01605
01606 rc = dbiGet(dbi, dbcursor, key, data, DB_SET);
01607
01608 if (rc == 0) {
01609 (void) dbt2set(dbi, data, matches);
01610 if (version == NULL && release == NULL)
01611 return RPMRC_OK;
01612 } else
01613 if (rc == DB_NOTFOUND) {
01614 return RPMRC_NOTFOUND;
01615 } else {
01616 rpmError(RPMERR_DBGETINDEX,
01617 _("error(%d) getting \"%s\" records from %s index\n"),
01618 rc, key->data, tagName(dbi->dbi_rpmtag));
01619 return RPMRC_FAIL;
01620 }
01621
01622
01623
01624 for (i = 0; i < dbiIndexSetCount(*matches); i++) {
01625 unsigned int recoff = dbiIndexRecordOffset(*matches, i);
01626 rpmdbMatchIterator mi;
01627 Header h;
01628
01629 if (recoff == 0)
01630 continue;
01631
01632 mi = rpmdbInitIterator(dbi->dbi_rpmdb,
01633 RPMDBI_PACKAGES, &recoff, sizeof(recoff));
01634
01635
01636 if (version &&
01637 rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_DEFAULT, version))
01638 {
01639 rc = RPMRC_FAIL;
01640 goto exit;
01641 }
01642 if (release &&
01643 rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_DEFAULT, release))
01644 {
01645 rc = RPMRC_FAIL;
01646 goto exit;
01647 }
01648
01649 h = rpmdbNextIterator(mi);
01650
01651 if (h)
01652 (*matches)->recs[gotMatches++] = (*matches)->recs[i];
01653 else
01654 (*matches)->recs[i].hdrNum = 0;
01655
01656 mi = rpmdbFreeIterator(mi);
01657 }
01658
01659
01660 if (gotMatches) {
01661 (*matches)->count = gotMatches;
01662 rc = RPMRC_OK;
01663 } else
01664 rc = RPMRC_NOTFOUND;
01665
01666 exit:
01667
01668 if (rc && matches && *matches)
01669 *matches = dbiFreeIndexSet(*matches);
01670
01671 return rc;
01672 }
01673
01686 static rpmRC dbiFindByLabel(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
01687 const char * arg, dbiIndexSet * matches)
01688
01689
01690
01691
01692 {
01693 const char * release;
01694 char * localarg;
01695 char * s;
01696 char c;
01697 int brackets;
01698 rpmRC rc;
01699
01700 if (arg == NULL || strlen(arg) == 0) return RPMRC_NOTFOUND;
01701
01702
01703 rc = dbiFindMatches(dbi, dbcursor, key, data, arg, NULL, NULL, matches);
01704 if (rc != RPMRC_NOTFOUND) return rc;
01705
01706
01707 *matches = dbiFreeIndexSet(*matches);
01708
01709
01710
01711 localarg = alloca(strlen(arg) + 1);
01712 s = stpcpy(localarg, arg);
01713
01714 c = '\0';
01715 brackets = 0;
01716 for (s -= 1; s > localarg; s--) {
01717 switch (*s) {
01718 case '[':
01719 brackets = 1;
01720 break;
01721 case ']':
01722 if (c != '[') brackets = 0;
01723 break;
01724 }
01725 c = *s;
01726 if (!brackets && *s == '-')
01727 break;
01728 }
01729
01730
01731 if (s == localarg) return RPMRC_NOTFOUND;
01732
01733
01734 *s = '\0';
01735
01736 rc = dbiFindMatches(dbi, dbcursor, key, data, localarg, s + 1, NULL, matches);
01737
01738 if (rc != RPMRC_NOTFOUND) return rc;
01739
01740
01741 *matches = dbiFreeIndexSet(*matches);
01742
01743
01744
01745
01746 release = s + 1;
01747
01748 c = '\0';
01749 brackets = 0;
01750 for (; s > localarg; s--) {
01751 switch (*s) {
01752 case '[':
01753 brackets = 1;
01754 break;
01755 case ']':
01756 if (c != '[') brackets = 0;
01757 break;
01758 }
01759 c = *s;
01760 if (!brackets && *s == '-')
01761 break;
01762 }
01763
01764 if (s == localarg) return RPMRC_NOTFOUND;
01765
01766
01767 *s = '\0';
01768
01769
01770 return dbiFindMatches(dbi, dbcursor, key, data, localarg, s + 1, release, matches);
01771
01772 }
01773
01774 void * dbiStatsAccumulator(dbiIndex dbi, int opx)
01775 {
01776 void * sw = NULL;
01777 switch (opx) {
01778 case 14:
01779 sw = &dbi->dbi_rpmdb->db_getops;
01780 break;
01781 case 15:
01782 sw = &dbi->dbi_rpmdb->db_putops;
01783 break;
01784 default:
01785 case 16:
01786 sw = &dbi->dbi_rpmdb->db_delops;
01787 break;
01788 }
01789 return sw;
01790 }
01791
01800 static int miFreeHeader(rpmdbMatchIterator mi, dbiIndex dbi)
01801
01802
01803 {
01804 int rc = 0;
01805
01806 if (mi == NULL || mi->mi_h == NULL)
01807 return 0;
01808
01809 if (dbi && mi->mi_dbc && mi->mi_modified && mi->mi_prevoffset) {
01810 DBT * key = &mi->mi_key;
01811 DBT * data = &mi->mi_data;
01812 sigset_t signalMask;
01813 rpmRC rpmrc = RPMRC_NOTFOUND;
01814 int xx;
01815
01816 key->data = (void *) &mi->mi_prevoffset;
01817 key->size = sizeof(mi->mi_prevoffset);
01818 data->data = headerUnload(mi->mi_h);
01819 data->size = headerSizeof(mi->mi_h, HEADER_MAGIC_NO);
01820
01821
01822 if (mi->mi_hdrchk && mi->mi_ts) {
01823 const char * msg = NULL;
01824 int lvl;
01825
01826 rpmrc = (*mi->mi_hdrchk) (mi->mi_ts, data->data, data->size, &msg);
01827 lvl = (rpmrc == RPMRC_FAIL ? RPMMESS_ERROR : RPMMESS_DEBUG);
01828 rpmMessage(lvl, "%s h#%8u %s",
01829 (rpmrc == RPMRC_FAIL ? _("miFreeHeader: skipping") : "write"),
01830 mi->mi_prevoffset, (msg ? msg : "\n"));
01831 msg = _free(msg);
01832 }
01833
01834 if (data->data != NULL && rpmrc != RPMRC_FAIL) {
01835 (void) blockSignals(dbi->dbi_rpmdb, &signalMask);
01836 rc = dbiPut(dbi, mi->mi_dbc, key, data, DB_KEYLAST);
01837 if (rc) {
01838 rpmError(RPMERR_DBPUTINDEX,
01839 _("error(%d) storing record #%d into %s\n"),
01840 rc, mi->mi_prevoffset, tagName(dbi->dbi_rpmtag));
01841 }
01842 xx = dbiSync(dbi, 0);
01843 (void) unblockSignals(dbi->dbi_rpmdb, &signalMask);
01844 }
01845 data->data = _free(data->data);
01846 data->size = 0;
01847 }
01848
01849 mi->mi_h = headerFree(mi->mi_h);
01850
01851
01852 return rc;
01853
01854 }
01855
01856 rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi)
01857
01858
01859 {
01860 rpmdbMatchIterator * prev, next;
01861 dbiIndex dbi;
01862 int xx;
01863 int i;
01864
01865 if (mi == NULL)
01866 return NULL;
01867
01868 prev = &rpmmiRock;
01869 while ((next = *prev) != NULL && next != mi)
01870 prev = &next->mi_next;
01871 if (next) {
01872 *prev = next->mi_next;
01873 next->mi_next = NULL;
01874 }
01875
01876 dbi = dbiOpen(mi->mi_db, RPMDBI_PACKAGES, 0);
01877 if (dbi == NULL)
01878 return NULL;
01879
01880 xx = miFreeHeader(mi, dbi);
01881
01882 if (mi->mi_dbc)
01883 xx = dbiCclose(dbi, mi->mi_dbc, 0);
01884 mi->mi_dbc = NULL;
01885
01886 if (mi->mi_re != NULL)
01887 for (i = 0; i < mi->mi_nre; i++)
01888 xx = mireClean(mi->mi_re + i);
01889 mi->mi_re = _free(mi->mi_re);
01890
01891 mi->mi_set = dbiFreeIndexSet(mi->mi_set);
01892 mi->mi_keyp = _free(mi->mi_keyp);
01893 mi->mi_db = rpmdbUnlink(mi->mi_db, "matchIterator");
01894
01895 mi = _free(mi);
01896
01897 (void) rpmdbCheckSignals();
01898
01899 return mi;
01900 }
01901
01902 unsigned int rpmdbGetIteratorOffset(rpmdbMatchIterator mi) {
01903 return (mi ? mi->mi_offset : 0);
01904 }
01905
01906 unsigned int rpmdbGetIteratorFileNum(rpmdbMatchIterator mi) {
01907 return (mi ? mi->mi_filenum : 0);
01908 }
01909
01910 int rpmdbGetIteratorCount(rpmdbMatchIterator mi) {
01911 return (mi && mi->mi_set ? mi->mi_set->count : 0);
01912 }
01913
01920 static int mireCmp(const void * a, const void * b)
01921 {
01922 const miRE mireA = (const miRE) a;
01923 const miRE mireB = (const miRE) b;
01924 return (mireA->tag - mireB->tag);
01925 }
01926
01934 static char * mireDup(rpmTag tag, rpmMireMode *modep,
01935 const char * pattern)
01936
01937
01938 {
01939 const char * s;
01940 char * pat;
01941 char * t;
01942 int brackets;
01943 size_t nb;
01944 int c;
01945
01946
01947 switch (*modep) {
01948 default:
01949 case RPMMIRE_DEFAULT:
01950 if (tag == RPMTAG_DIRNAMES || tag == RPMTAG_BASENAMES) {
01951 *modep = RPMMIRE_GLOB;
01952 pat = xstrdup(pattern);
01953 break;
01954 }
01955
01956 nb = strlen(pattern) + sizeof("^$");
01957
01958
01959
01960 c = '\0';
01961 brackets = 0;
01962 for (s = pattern; *s != '\0'; s++) {
01963 switch (*s) {
01964 case '.':
01965 case '+':
01966 case '*':
01967 if (!brackets) nb++;
01968 break;
01969 case '\\':
01970 s++;
01971 break;
01972 case '[':
01973 brackets = 1;
01974 break;
01975 case ']':
01976 if (c != '[') brackets = 0;
01977 break;
01978 }
01979 c = *s;
01980 }
01981
01982 pat = t = xmalloc(nb);
01983
01984 if (pattern[0] != '^') *t++ = '^';
01985
01986
01987 c = '\0';
01988 brackets = 0;
01989 for (s = pattern; *s != '\0'; s++, t++) {
01990 switch (*s) {
01991 case '.':
01992 case '+':
01993 if (!brackets) *t++ = '\\';
01994 break;
01995 case '*':
01996 if (!brackets) *t++ = '.';
01997 break;
01998 case '\\':
01999 *t++ = *s++;
02000 break;
02001 case '[':
02002 brackets = 1;
02003 break;
02004 case ']':
02005 if (c != '[') brackets = 0;
02006 break;
02007 }
02008 c = *t = *s;
02009 }
02010
02011 if (s > pattern && s[-1] != '$') *t++ = '$';
02012 *t = '\0';
02013 *modep = RPMMIRE_REGEX;
02014 break;
02015 case RPMMIRE_STRCMP:
02016 case RPMMIRE_REGEX:
02017 case RPMMIRE_GLOB:
02018 pat = xstrdup(pattern);
02019 break;
02020 }
02021
02022
02023 return pat;
02024 }
02025
02026 int rpmdbSetIteratorRE(rpmdbMatchIterator mi, rpmTag tag,
02027 rpmMireMode mode, const char * pattern)
02028 {
02029 static rpmMireMode defmode = (rpmMireMode)-1;
02030 miRE nmire = NULL;
02031 miRE mire = NULL;
02032 const char * allpat = NULL;
02033 int notmatch = 0;
02034 int rc = 0;
02035
02036
02037 if (defmode == (rpmMireMode)-1) {
02038 const char *t = rpmExpand("%{?_query_selector_match}", NULL);
02039
02040 if (*t == '\0' || !strcmp(t, "default"))
02041 defmode = RPMMIRE_DEFAULT;
02042 else if (!strcmp(t, "strcmp"))
02043 defmode = RPMMIRE_STRCMP;
02044 else if (!strcmp(t, "regex"))
02045 defmode = RPMMIRE_REGEX;
02046 else if (!strcmp(t, "glob"))
02047 defmode = RPMMIRE_GLOB;
02048 else
02049 defmode = RPMMIRE_DEFAULT;
02050 t = _free(t);
02051 }
02052
02053 if (mi == NULL || pattern == NULL)
02054 return rc;
02055
02056
02057 if (*pattern == '!') {
02058 notmatch = 1;
02059 pattern++;
02060 }
02061
02062
02063 nmire = mireNew(mode, tag);
02064
02065 allpat = mireDup(nmire->tag, &nmire->mode, pattern);
02066
02067
02068 if (nmire->mode == RPMMIRE_DEFAULT)
02069 nmire->mode = defmode;
02070
02071 rc = mireRegcomp(nmire, allpat);
02072 if (rc)
02073 goto exit;
02074
02075 mi->mi_re = xrealloc(mi->mi_re, (mi->mi_nre + 1) * sizeof(*mi->mi_re));
02076 mire = mi->mi_re + mi->mi_nre;
02077 mi->mi_nre++;
02078
02079 mire->mode = nmire->mode;
02080 mire->pattern = nmire->pattern; nmire->pattern = NULL;
02081 mire->preg = nmire->preg; nmire->preg = NULL;
02082 mire->cflags = nmire->cflags;
02083 mire->eflags = nmire->eflags;
02084 mire->fnflags = nmire->fnflags;
02085 mire->tag = nmire->tag;
02086 mire->notmatch = notmatch;
02087
02088
02089 if (mi->mi_nre > 1)
02090 qsort(mi->mi_re, mi->mi_nre, sizeof(*mi->mi_re), mireCmp);
02091
02092
02093 exit:
02094 allpat = _free(allpat);
02095 nmire = mireFree(nmire);
02096 return rc;
02097 }
02098
02104 static int mireSkip (const rpmdbMatchIterator mi)
02105
02106 {
02107 HGE_t hge = (HGE_t) headerGetEntryMinMemory;
02108 HFD_t hfd = (HFD_t) headerFreeData;
02109 union {
02110 void * ptr;
02111 const char ** argv;
02112 const char * str;
02113 int_32 * i32p;
02114 int_16 * i16p;
02115 int_8 * i8p;
02116 } u;
02117 char numbuf[32];
02118 rpmTagType t;
02119 int_32 c;
02120 miRE mire;
02121 static int_32 zero = 0;
02122 int ntags = 0;
02123 int nmatches = 0;
02124 int i, j;
02125 int rc;
02126
02127 if (mi->mi_h == NULL)
02128 return 1;
02129
02130
02131
02132
02133
02134
02135 if ((mire = mi->mi_re) == NULL)
02136 return 0;
02137
02138 for (i = 0; i < mi->mi_nre; i++, mire++) {
02139 int anymatch;
02140
02141 if (!hge(mi->mi_h, mire->tag, &t, (void **)&u, &c)) {
02142 if (mire->tag != RPMTAG_EPOCH)
02143 continue;
02144 t = RPM_INT32_TYPE;
02145
02146 u.i32p = &zero;
02147
02148 c = 1;
02149 }
02150
02151 anymatch = 0;
02152 while (1) {
02153 switch (t) {
02154 case RPM_CHAR_TYPE:
02155 case RPM_INT8_TYPE:
02156 sprintf(numbuf, "%d", (int) *u.i8p);
02157 rc = mireRegexec(mire, numbuf);
02158 if ((!rc && !mire->notmatch) || (rc && mire->notmatch))
02159 anymatch++;
02160 break;
02161 case RPM_INT16_TYPE:
02162 sprintf(numbuf, "%d", (int) *u.i16p);
02163 rc = mireRegexec(mire, numbuf);
02164 if ((!rc && !mire->notmatch) || (rc && mire->notmatch))
02165 anymatch++;
02166 break;
02167 case RPM_INT32_TYPE:
02168 sprintf(numbuf, "%d", (int) *u.i32p);
02169 rc = mireRegexec(mire, numbuf);
02170 if ((!rc && !mire->notmatch) || (rc && mire->notmatch))
02171 anymatch++;
02172 break;
02173 case RPM_STRING_TYPE:
02174 rc = mireRegexec(mire, u.str);
02175 if ((!rc && !mire->notmatch) || (rc && mire->notmatch))
02176 anymatch++;
02177 break;
02178 case RPM_I18NSTRING_TYPE:
02179 case RPM_STRING_ARRAY_TYPE:
02180 for (j = 0; j < c; j++) {
02181 rc = mireRegexec(mire, u.argv[j]);
02182 if ((!rc && !mire->notmatch) || (rc && mire->notmatch)) {
02183 anymatch++;
02184 break;
02185 }
02186 }
02187 break;
02188 case RPM_NULL_TYPE:
02189 case RPM_BIN_TYPE:
02190 default:
02191 break;
02192 }
02193 if ((i+1) < mi->mi_nre && mire[0].tag == mire[1].tag) {
02194 i++;
02195 mire++;
02196 continue;
02197 }
02198 break;
02199 }
02200
02201
02202 u.ptr = hfd(u.ptr, t);
02203
02204 ntags++;
02205 if (anymatch)
02206 nmatches++;
02207 }
02208
02209 return (ntags > 0 && ntags == nmatches ? 0 : 1);
02210 }
02211
02212 int rpmdbSetIteratorRewrite(rpmdbMatchIterator mi, int rewrite)
02213 {
02214 int rc;
02215 if (mi == NULL)
02216 return 0;
02217 rc = (mi->mi_cflags & DB_WRITECURSOR) ? 1 : 0;
02218 if (rewrite)
02219 mi->mi_cflags |= DB_WRITECURSOR;
02220 else
02221 mi->mi_cflags &= ~DB_WRITECURSOR;
02222 return rc;
02223 }
02224
02225 int rpmdbSetIteratorModified(rpmdbMatchIterator mi, int modified)
02226 {
02227 int rc;
02228 if (mi == NULL)
02229 return 0;
02230 rc = mi->mi_modified;
02231 mi->mi_modified = modified;
02232 return rc;
02233 }
02234
02235 int rpmdbSetHdrChk(rpmdbMatchIterator mi, rpmts ts,
02236 rpmRC (*hdrchk) (rpmts ts, const void *uh, size_t uc, const char ** msg))
02237 {
02238 int rc = 0;
02239 if (mi == NULL)
02240 return 0;
02241
02242 mi->mi_ts = ts;
02243 mi->mi_hdrchk = hdrchk;
02244
02245 return rc;
02246 }
02247
02248
02249
02250 Header rpmdbNextIterator(rpmdbMatchIterator mi)
02251 {
02252 dbiIndex dbi;
02253 void * uh;
02254 size_t uhlen;
02255 DBT * key;
02256 DBT * data;
02257 void * keyp;
02258 size_t keylen;
02259 int rc;
02260 int xx;
02261
02262 if (mi == NULL)
02263 return NULL;
02264
02265 dbi = dbiOpen(mi->mi_db, RPMDBI_PACKAGES, 0);
02266 if (dbi == NULL)
02267 return NULL;
02268
02269
02270
02271
02272
02273
02274
02275 if (mi->mi_dbc == NULL)
02276 xx = dbiCopen(dbi, dbi->dbi_txnid, &mi->mi_dbc, mi->mi_cflags);
02277
02278
02279 key = &mi->mi_key;
02280 memset(key, 0, sizeof(*key));
02281 data = &mi->mi_data;
02282 memset(data, 0, sizeof(*data));
02283
02284
02285 top:
02286 uh = NULL;
02287 uhlen = 0;
02288
02289 do {
02290 union _dbswap mi_offset;
02291
02292
02293 if (mi->mi_set) {
02294 if (!(mi->mi_setx < mi->mi_set->count))
02295 return NULL;
02296 mi->mi_offset = dbiIndexRecordOffset(mi->mi_set, mi->mi_setx);
02297 mi->mi_filenum = dbiIndexRecordFileNumber(mi->mi_set, mi->mi_setx);
02298 mi_offset.ui = mi->mi_offset;
02299 if (dbiByteSwapped(dbi) == 1)
02300 _DBSWAP(mi_offset);
02301 keyp = &mi_offset;
02302 keylen = sizeof(mi_offset.ui);
02303 } else {
02304
02305 key->data = keyp = (void *)mi->mi_keyp;
02306 key->size = keylen = mi->mi_keylen;
02307 data->data = uh;
02308 data->size = uhlen;
02309 #if !defined(_USE_COPY_LOAD)
02310 data->flags |= DB_DBT_MALLOC;
02311 #endif
02312 rc = dbiGet(dbi, mi->mi_dbc, key, data,
02313 (key->data == NULL ? DB_NEXT : DB_SET));
02314 data->flags = 0;
02315 keyp = key->data;
02316 keylen = key->size;
02317 uh = data->data;
02318 uhlen = data->size;
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328 if (keyp && mi->mi_setx && rc == 0) {
02329 memcpy(&mi_offset, keyp, sizeof(mi_offset.ui));
02330 if (dbiByteSwapped(dbi) == 1)
02331 _DBSWAP(mi_offset);
02332 mi->mi_offset = mi_offset.ui;
02333 }
02334
02335
02336
02337 if (rc || (mi->mi_setx && mi->mi_offset == 0))
02338 return NULL;
02339 }
02340
02341 mi->mi_setx++;
02342 } while (mi->mi_offset == 0);
02343
02344
02345
02346 if (mi->mi_prevoffset && mi->mi_offset == mi->mi_prevoffset)
02347 return mi->mi_h;
02348
02349
02350
02351
02352 if (uh == NULL) {
02353 key->data = keyp;
02354 key->size = keylen;
02355 #if !defined(_USE_COPY_LOAD)
02356 data->flags |= DB_DBT_MALLOC;
02357 #endif
02358 rc = dbiGet(dbi, mi->mi_dbc, key, data, DB_SET);
02359 data->flags = 0;
02360 keyp = key->data;
02361 keylen = key->size;
02362 uh = data->data;
02363 uhlen = data->size;
02364 if (rc)
02365 return NULL;
02366 }
02367
02368
02369
02370 xx = miFreeHeader(mi, dbi);
02371
02372
02373 if (uh == NULL)
02374 return NULL;
02375
02376
02377
02378 if (mi->mi_hdrchk && mi->mi_ts) {
02379 rpmRC rpmrc = RPMRC_NOTFOUND;
02380
02381
02382 if (mi->mi_db->db_bits) {
02383 pbm_set * set;
02384
02385 set = PBM_REALLOC((pbm_set **)&mi->mi_db->db_bits,
02386 &mi->mi_db->db_nbits, mi->mi_offset);
02387 if (PBM_ISSET(mi->mi_offset, set))
02388 rpmrc = RPMRC_OK;
02389 }
02390
02391
02392 if (rpmrc != RPMRC_OK) {
02393 const char * msg = NULL;
02394 int lvl;
02395
02396 rpmrc = (*mi->mi_hdrchk) (mi->mi_ts, uh, uhlen, &msg);
02397 lvl = (rpmrc == RPMRC_FAIL ? RPMMESS_ERROR : RPMMESS_DEBUG);
02398 rpmMessage(lvl, "%s h#%8u %s",
02399 (rpmrc == RPMRC_FAIL ? _("rpmdbNextIterator: skipping") : " read"),
02400 mi->mi_offset, (msg ? msg : "\n"));
02401 msg = _free(msg);
02402
02403
02404 if (mi->mi_db && mi->mi_db->db_bits && rpmrc == RPMRC_OK) {
02405 pbm_set * set;
02406
02407 set = PBM_REALLOC((pbm_set **)&mi->mi_db->db_bits,
02408 &mi->mi_db->db_nbits, mi->mi_offset);
02409 PBM_SET(mi->mi_offset, set);
02410 }
02411
02412
02413 if (rpmrc == RPMRC_FAIL)
02414 goto top;
02415 }
02416 }
02417
02418
02419
02420 #if !defined(_USE_COPY_LOAD)
02421
02422 mi->mi_h = headerLoad(uh);
02423
02424 if (mi->mi_h)
02425 mi->mi_h->flags |= HEADERFLAG_ALLOCATED;
02426 #else
02427 mi->mi_h = headerCopyLoad(uh);
02428 #endif
02429 if (mi->mi_h == NULL || !headerIsEntry(mi->mi_h, RPMTAG_NAME)) {
02430 rpmError(RPMERR_BADHEADER,
02431 _("rpmdb: damaged header #%u retrieved -- skipping.\n"),
02432 mi->mi_offset);
02433 goto top;
02434 }
02435
02436
02437
02438
02439 if (mireSkip(mi)) {
02440
02441 if (mi->mi_set || mi->mi_keyp == NULL)
02442 goto top;
02443 return NULL;
02444 }
02445
02446
02447 { char origin[32];
02448 sprintf(origin, "rpmdb (h#%u)", mi->mi_offset);
02449 (void) headerSetOrigin(mi->mi_h, origin);
02450 (void) headerSetInstance(mi->mi_h, mi->mi_offset);
02451 }
02452
02453 mi->mi_prevoffset = mi->mi_offset;
02454 mi->mi_modified = 0;
02455
02456
02457 return mi->mi_h;
02458
02459 }
02460
02461
02462 static void rpmdbSortIterator( rpmdbMatchIterator mi)
02463
02464 {
02465 if (mi && mi->mi_set && mi->mi_set->recs && mi->mi_set->count > 0) {
02466
02467
02468
02469
02470 #if defined(__GLIBC__)
02471
02472 qsort(mi->mi_set->recs, mi->mi_set->count,
02473 sizeof(*mi->mi_set->recs), hdrNumCmp);
02474
02475 #else
02476 mergesort(mi->mi_set->recs, mi->mi_set->count,
02477 sizeof(*mi->mi_set->recs), hdrNumCmp);
02478 #endif
02479 mi->mi_sorted = 1;
02480 }
02481 }
02482
02483
02484 static int rpmdbGrowIterator( rpmdbMatchIterator mi, int fpNum,
02485 unsigned int exclude, unsigned int tag)
02486
02487
02488 {
02489 DBC * dbcursor;
02490 DBT * key;
02491 DBT * data;
02492 dbiIndex dbi = NULL;
02493 dbiIndexSet set;
02494 int rc;
02495 int xx;
02496 int i, j;
02497
02498 if (mi == NULL)
02499 return 1;
02500
02501 dbcursor = mi->mi_dbc;
02502 key = &mi->mi_key;
02503 data = &mi->mi_data;
02504 if (key->data == NULL)
02505 return 1;
02506
02507 dbi = dbiOpen(mi->mi_db, mi->mi_rpmtag, 0);
02508 if (dbi == NULL)
02509 return 1;
02510
02511 xx = dbiCopen(dbi, dbi->dbi_txnid, &dbcursor, 0);
02512 rc = dbiGet(dbi, dbcursor, key, data, DB_SET);
02513 #ifndef SQLITE_HACK
02514 xx = dbiCclose(dbi, dbcursor, 0);
02515 dbcursor = NULL;
02516 #endif
02517
02518 if (rc) {
02519 if (rc != DB_NOTFOUND)
02520 rpmError(RPMERR_DBGETINDEX,
02521 _("error(%d) getting \"%s\" records from %s index\n"),
02522 rc, key->data, tagName(dbi->dbi_rpmtag));
02523 #ifdef SQLITE_HACK
02524 xx = dbiCclose(dbi, dbcursor, 0);
02525 dbcursor = NULL;
02526 #endif
02527 return rc;
02528 }
02529
02530 set = NULL;
02531 (void) dbt2set(dbi, data, &set);
02532
02533
02534 for (i = j = 0; i < set->count; i++) {
02535 if (exclude && set->recs[i].hdrNum == exclude)
02536 continue;
02537 if (_db_tagged_file_indices && set->recs[i].tagNum & 0x80000000) {
02538
02539 if ((set->recs[i].tagNum & 0xffff0000) != tag)
02540 continue;
02541 set->recs[i].tagNum &= 0x0000ffff;
02542 }
02543 if (i > j)
02544 set->recs[j] = set->recs[i];
02545 j++;
02546 }
02547 if (j == 0) {
02548 #ifdef SQLITE_HACK
02549 xx = dbiCclose(dbi, dbcursor, 0);
02550 dbcursor = NULL;
02551 #endif
02552 set = dbiFreeIndexSet(set);
02553 return DB_NOTFOUND;
02554 }
02555 set->count = j;
02556
02557 for (i = 0; i < set->count; i++)
02558 set->recs[i].fpNum = fpNum;
02559
02560 #ifdef SQLITE_HACK
02561 xx = dbiCclose(dbi, dbcursor, 0);
02562 dbcursor = NULL;
02563 #endif
02564
02565
02566 if (mi->mi_set == NULL) {
02567 mi->mi_set = set;
02568 } else {
02569 #if 0
02570 fprintf(stderr, "+++ %d = %d + %d\t\"%s\"\n", (mi->mi_set->count + set->count), mi->mi_set->count, set->count, ((char *)key->data));
02571 #endif
02572 mi->mi_set->recs = xrealloc(mi->mi_set->recs,
02573 (mi->mi_set->count + set->count) * sizeof(*(mi->mi_set->recs)));
02574 memcpy(mi->mi_set->recs + mi->mi_set->count, set->recs,
02575 set->count * sizeof(*(mi->mi_set->recs)));
02576 mi->mi_set->count += set->count;
02577 set = dbiFreeIndexSet(set);
02578 }
02579
02580
02581 return rc;
02582 }
02583
02584
02585 int rpmdbPruneIterator(rpmdbMatchIterator mi, int * hdrNums,
02586 int nHdrNums, int sorted)
02587 {
02588 if (mi == NULL || hdrNums == NULL || nHdrNums <= 0)
02589 return 1;
02590
02591 if (mi->mi_set)
02592 (void) dbiPruneSet(mi->mi_set, hdrNums, nHdrNums, sizeof(*hdrNums), sorted);
02593 return 0;
02594 }
02595
02596 int rpmdbAppendIterator(rpmdbMatchIterator mi, const int * hdrNums, int nHdrNums)
02597 {
02598 if (mi == NULL || hdrNums == NULL || nHdrNums <= 0)
02599 return 1;
02600
02601 if (mi->mi_set == NULL)
02602 mi->mi_set = xcalloc(1, sizeof(*mi->mi_set));
02603 (void) dbiAppendSet(mi->mi_set, hdrNums, nHdrNums, sizeof(*hdrNums), 0);
02604 return 0;
02605 }
02606
02607 rpmdbMatchIterator rpmdbInitIterator(rpmdb db, rpmTag rpmtag,
02608 const void * keyp, size_t keylen)
02609
02610
02611 {
02612 rpmdbMatchIterator mi;
02613 DBT * key;
02614 DBT * data;
02615 dbiIndexSet set = NULL;
02616 dbiIndex dbi;
02617 const void * mi_keyp = NULL;
02618 int isLabel = 0;
02619
02620 if (db == NULL)
02621 return NULL;
02622
02623 (void) rpmdbCheckSignals();
02624
02625
02626 if (rpmtag == RPMDBI_LABEL) {
02627 rpmtag = RPMTAG_NAME;
02628 isLabel = 1;
02629 }
02630
02631 dbi = dbiOpen(db, rpmtag, 0);
02632 if (dbi == NULL)
02633 return NULL;
02634
02635
02636 mi = xcalloc(1, sizeof(*mi));
02637 mi->mi_next = rpmmiRock;
02638 rpmmiRock = mi;
02639
02640 key = &mi->mi_key;
02641 data = &mi->mi_data;
02642
02643
02644
02645
02646
02647
02648 if (rpmtag != RPMDBI_PACKAGES && keyp) {
02649 DBC * dbcursor = NULL;
02650 int rc;
02651 int xx;
02652
02653 if (isLabel) {
02654 xx = dbiCopen(dbi, dbi->dbi_txnid, &dbcursor, 0);
02655 rc = dbiFindByLabel(dbi, dbcursor, key, data, keyp, &set);
02656 xx = dbiCclose(dbi, dbcursor, 0);
02657 dbcursor = NULL;
02658 } else if (rpmtag == RPMTAG_BASENAMES) {
02659 rc = rpmdbFindByFile(db, keyp, key, data, &set);
02660 } else {
02661 xx = dbiCopen(dbi, dbi->dbi_txnid, &dbcursor, 0);
02662
02663
02664 key->data = (void *) keyp;
02665
02666 key->size = keylen;
02667 if (key->data && key->size == 0) key->size = strlen((char *)key->data);
02668 if (key->data && key->size == 0) key->size++;
02669
02670
02671 rc = dbiGet(dbi, dbcursor, key, data, DB_SET);
02672
02673 if (rc > 0) {
02674 rpmError(RPMERR_DBGETINDEX,
02675 _("error(%d) getting \"%s\" records from %s index\n"),
02676 rc, (key->data ? key->data : "???"), tagName(dbi->dbi_rpmtag));
02677 }
02678
02679
02680 if (rc == 0)
02681 (void) dbt2set(dbi, data, &set);
02682
02683 xx = dbiCclose(dbi, dbcursor, 0);
02684 dbcursor = NULL;
02685 }
02686 if (rc) {
02687 set = dbiFreeIndexSet(set);
02688 rpmmiRock = mi->mi_next;
02689 mi->mi_next = NULL;
02690 mi = _free(mi);
02691 return NULL;
02692 }
02693 }
02694
02695
02696
02697 if (keyp) {
02698 switch (rpmtag) {
02699 case RPMDBI_PACKAGES:
02700 { union _dbswap *k;
02701
02702 assert(keylen == sizeof(k->ui));
02703 k = xmalloc(sizeof(*k));
02704 memcpy(k, keyp, keylen);
02705 if (dbiByteSwapped(dbi) == 1)
02706 _DBSWAP(*k);
02707 mi_keyp = k;
02708 } break;
02709 default:
02710 { char * k;
02711 if (keylen == 0)
02712 keylen = strlen(keyp);
02713 k = xmalloc(keylen + 1);
02714
02715 memcpy(k, keyp, keylen);
02716
02717 k[keylen] = '\0';
02718 mi_keyp = k;
02719 } break;
02720 }
02721 }
02722
02723 mi->mi_keyp = mi_keyp;
02724 mi->mi_keylen = keylen;
02725
02726 mi->mi_db = rpmdbLink(db, "matchIterator");
02727 mi->mi_rpmtag = rpmtag;
02728
02729 mi->mi_dbc = NULL;
02730 mi->mi_set = set;
02731 mi->mi_setx = 0;
02732 mi->mi_h = NULL;
02733 mi->mi_sorted = 0;
02734 mi->mi_cflags = 0;
02735 mi->mi_modified = 0;
02736 mi->mi_prevoffset = 0;
02737 mi->mi_offset = 0;
02738 mi->mi_filenum = 0;
02739 mi->mi_nre = 0;
02740 mi->mi_re = NULL;
02741
02742 mi->mi_ts = NULL;
02743 mi->mi_hdrchk = NULL;
02744
02745 return mi;
02746 }
02747
02748
02749 int rpmdbRemove(rpmdb db, int rid, unsigned int hdrNum,
02750 rpmts ts,
02751 rpmRC (*hdrchk) (rpmts ts, const void *uh, size_t uc, const char ** msg))
02752 {
02753 DBC * dbcursor = NULL;
02754 DBT * key = alloca(sizeof(*key));
02755 DBT * data = alloca(sizeof(*data));
02756 union _dbswap mi_offset;
02757 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
02758 HFD_t hfd = headerFreeData;
02759 Header h;
02760 sigset_t signalMask;
02761 int ret = 0;
02762 int rc = 0;
02763
02764 if (db == NULL)
02765 return 0;
02766
02767 memset(key, 0, sizeof(*key));
02768 memset(data, 0, sizeof(*data));
02769
02770 { rpmdbMatchIterator mi;
02771 mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, &hdrNum, sizeof(hdrNum));
02772 h = rpmdbNextIterator(mi);
02773 if (h)
02774 h = headerLink(h);
02775 mi = rpmdbFreeIterator(mi);
02776 }
02777
02778 if (h == NULL) {
02779 rpmError(RPMERR_DBCORRUPT, _("%s: cannot read header at 0x%x\n"),
02780 "rpmdbRemove", hdrNum);
02781 return 1;
02782 }
02783
02784 #ifdef DYING
02785
02786 if (rid != 0 && rid != -1) {
02787 int_32 tid = rid;
02788 (void) headerAddEntry(h, RPMTAG_REMOVETID, RPM_INT32_TYPE, &tid, 1);
02789 }
02790 #endif
02791
02792 { const char *n, *v, *r;
02793 (void) headerNVR(h, &n, &v, &r);
02794 rpmMessage(RPMMESS_DEBUG, " --- h#%8u %s-%s-%s\n", hdrNum, n, v, r);
02795 }
02796
02797 (void) blockSignals(db, &signalMask);
02798
02799
02800 { int dbix;
02801 dbiIndexItem rec = dbiIndexNewItem(hdrNum, 0);
02802
02803 if (db->db_tagn != NULL)
02804 for (dbix = 0; dbix < db->db_ndbi; dbix++) {
02805 dbiIndex dbi;
02806 const char *av[1];
02807 const char ** rpmvals = NULL;
02808 byte * bin = NULL;
02809 rpmTagType rpmtype = 0;
02810 int rpmcnt = 0;
02811 int rpmtag;
02812 int xx;
02813 int i, j;
02814
02815 dbi = NULL;
02816
02817 rpmtag = db->db_tagn[dbix];
02818
02819
02820
02821 switch (rpmtag) {
02822
02823 case RPMDBI_AVAILABLE:
02824 case RPMDBI_ADDED:
02825 case RPMDBI_REMOVED:
02826 case RPMDBI_DEPENDS:
02827 continue;
02828 break;
02829 case RPMDBI_PACKAGES:
02830 if (db->db_export != NULL)
02831 xx = db->db_export(db, h, 0);
02832 dbi = dbiOpen(db, rpmtag, 0);
02833 if (dbi == NULL)
02834 continue;
02835
02836
02837 mi_offset.ui = hdrNum;
02838 if (dbiByteSwapped(dbi) == 1)
02839 _DBSWAP(mi_offset);
02840 key->data = &mi_offset;
02841
02842 key->size = sizeof(mi_offset.ui);
02843
02844 rc = dbiCopen(dbi, dbi->dbi_txnid, &dbcursor, DB_WRITECURSOR);
02845 rc = dbiGet(dbi, dbcursor, key, data, DB_SET);
02846 if (rc) {
02847 rpmError(RPMERR_DBGETINDEX,
02848 _("error(%d) setting header #%d record for %s removal\n"),
02849 rc, hdrNum, tagName(dbi->dbi_rpmtag));
02850 } else
02851 rc = dbiDel(dbi, dbcursor, key, data, 0);
02852 xx = dbiCclose(dbi, dbcursor, DB_WRITECURSOR);
02853 dbcursor = NULL;
02854 if (!dbi->dbi_no_dbsync)
02855 xx = dbiSync(dbi, 0);
02856 continue;
02857 break;
02858 }
02859
02860
02861 if (!hge(h, rpmtag, &rpmtype, &rpmvals, &rpmcnt))
02862 continue;
02863
02864 dbi = dbiOpen(db, rpmtag, 0);
02865 if (dbi != NULL) {
02866 int printed;
02867
02868 if (rpmtype == RPM_STRING_TYPE) {
02869
02870 av[0] = (const char *) rpmvals;
02871 rpmvals = av;
02872 rpmcnt = 1;
02873 }
02874
02875 printed = 0;
02876 xx = dbiCopen(dbi, dbi->dbi_txnid, &dbcursor, DB_WRITECURSOR);
02877
02878 for (i = 0; i < rpmcnt; i++) {
02879 dbiIndexSet set;
02880 int stringvalued;
02881
02882 bin = _free(bin);
02883 switch (dbi->dbi_rpmtag) {
02884 case RPMTAG_FILEDIGESTS:
02885
02886 if (!(rpmvals[i] && *rpmvals[i] != '\0'))
02887 continue;
02888 break;
02889 default:
02890 break;
02891 }
02892
02893
02894 stringvalued = 0;
02895 switch (rpmtype) {
02896
02897 case RPM_CHAR_TYPE:
02898 case RPM_INT8_TYPE:
02899 key->size = sizeof(RPM_CHAR_TYPE);
02900 key->data = rpmvals + i;
02901 break;
02902 case RPM_INT16_TYPE:
02903 key->size = sizeof(int_16);
02904 key->data = rpmvals + i;
02905 break;
02906 case RPM_INT32_TYPE:
02907 key->size = sizeof(int_32);
02908 key->data = rpmvals + i;
02909 break;
02910
02911 case RPM_BIN_TYPE:
02912 key->size = rpmcnt;
02913 key->data = rpmvals;
02914 rpmcnt = 1;
02915 break;
02916 case RPM_STRING_TYPE:
02917 case RPM_I18NSTRING_TYPE:
02918 rpmcnt = 1;
02919
02920 case RPM_STRING_ARRAY_TYPE:
02921
02922
02923 if (dbi->dbi_rpmtag == RPMTAG_FILEDIGESTS) {
02924 const char * s = rpmvals[i];
02925 size_t dlen = strlen(s);
02926 byte * t;
02927 assert((dlen & 1) == 0);
02928 dlen /= 2;
02929 bin = t = xcalloc(1, dlen);
02930 for (j = 0; j < dlen; j++, t++, s += 2)
02931 *t = (nibble(s[0]) << 4) | nibble(s[1]);
02932 key->data = bin;
02933 key->size = dlen;
02934 break;
02935 }
02936
02937 if (dbi->dbi_rpmtag == RPMTAG_PUBKEYS) {
02938 int nbin;
02939 bin = xcalloc(1, 32);
02940 nbin = pgpExtractPubkeyFingerprint(rpmvals[i], bin);
02941 if (nbin <= 0)
02942 continue;
02943 key->data = bin;
02944 key->size = nbin;
02945 break;
02946 }
02947
02948
02949 default:
02950 key->data = (void *) rpmvals[i];
02951 key->size = strlen(rpmvals[i]);
02952 stringvalued = 1;
02953 break;
02954 }
02955
02956 if (!printed) {
02957 if (rpmcnt == 1 && stringvalued) {
02958 rpmMessage(RPMMESS_DEBUG,
02959 D_("removing \"%s\" from %s index.\n"),
02960 (char *)key->data, tagName(dbi->dbi_rpmtag));
02961 } else {
02962 rpmMessage(RPMMESS_DEBUG,
02963 D_("removing %d entries from %s index.\n"),
02964 rpmcnt, tagName(dbi->dbi_rpmtag));
02965 }
02966 printed++;
02967 }
02968
02969
02970
02971
02972
02973
02974
02975
02976
02977
02978 set = NULL;
02979
02980 if (key->size == 0) key->size = strlen((char *)key->data);
02981 if (key->size == 0) key->size++;
02982
02983
02984 rc = dbiGet(dbi, dbcursor, key, data, DB_SET);
02985 if (rc == 0) {
02986 (void) dbt2set(dbi, data, &set);
02987 } else if (rc == DB_NOTFOUND) {
02988 continue;
02989 } else {
02990 rpmError(RPMERR_DBGETINDEX,
02991 _("error(%d) setting \"%s\" records from %s index\n"),
02992 rc, key->data, tagName(dbi->dbi_rpmtag));
02993 ret += 1;
02994 continue;
02995 }
02996
02997
02998 rc = dbiPruneSet(set, rec, 1, sizeof(*rec), 1);
02999
03000
03001 if (rc) {
03002 set = dbiFreeIndexSet(set);
03003 continue;
03004 }
03005
03006
03007 if (set->count > 0) {
03008 (void) set2dbt(dbi, data, set);
03009 rc = dbiPut(dbi, dbcursor, key, data, DB_KEYLAST);
03010 if (rc) {
03011 rpmError(RPMERR_DBPUTINDEX,
03012 _("error(%d) storing record \"%s\" into %s\n"),
03013 rc, key->data, tagName(dbi->dbi_rpmtag));
03014 ret += 1;
03015 }
03016 data->data = _free(data->data);
03017 data->size = 0;
03018 } else {
03019 rc = dbiDel(dbi, dbcursor, key, data, 0);
03020 if (rc) {
03021 rpmError(RPMERR_DBPUTINDEX,
03022 _("error(%d) removing record \"%s\" from %s\n"),
03023 rc, key->data, tagName(dbi->dbi_rpmtag));
03024 ret += 1;
03025 }
03026 }
03027
03028 set = dbiFreeIndexSet(set);
03029 }
03030
03031
03032 xx = dbiCclose(dbi, dbcursor, DB_WRITECURSOR);
03033 dbcursor = NULL;
03034
03035 if (!dbi->dbi_no_dbsync)
03036 xx = dbiSync(dbi, 0);
03037 }
03038
03039 if (rpmtype != RPM_BIN_TYPE)
03040 rpmvals = hfd(rpmvals, rpmtype);
03041 rpmtype = 0;
03042 rpmcnt = 0;
03043 bin = _free(bin);
03044 }
03045
03046 rec = _free(rec);
03047 }
03048
03049
03050 (void) unblockSignals(db, &signalMask);
03051
03052 h = headerFree(h);
03053
03054
03055 return 0;
03056 }
03057
03058
03059 int rpmdbAdd(rpmdb db, int iid, Header h,
03060 rpmts ts,
03061 rpmRC (*hdrchk) (rpmts ts, const void *uh, size_t uc, const char ** msg))
03062 {
03063 DBC * dbcursor = NULL;
03064 DBT * key = alloca(sizeof(*key));
03065 DBT * data = alloca(sizeof(*data));
03066 HGE_t hge = (HGE_t) headerGetEntryMinMemory;
03067 HAE_t hae = (HAE_t) headerAddEntry;
03068 HFD_t hfd = headerFreeData;
03069 sigset_t signalMask;
03070 uint32_t hcolor = 0;
03071 const char ** baseNames;
03072 rpmTagType bnt;
03073 const char ** dirNames;
03074 int_32 * dirIndexes;
03075 rpmTagType dit, dnt;
03076 int count = 0;
03077 dbiIndex dbi;
03078 int dbix;
03079 union _dbswap mi_offset;
03080 unsigned int hdrNum = 0;
03081 int ret = 0;
03082 int rc;
03083 int xx;
03084
03085
03086 (void) headerSetInstance(h, 0);
03087
03088 if (db == NULL)
03089 return 0;
03090
03091 memset(key, 0, sizeof(*key));
03092 memset(data, 0, sizeof(*data));
03093
03094 #ifdef NOTYET
03095 xx = headerRemoveEntry(h, RPMTAG_REMOVETID);
03096 #endif
03097 if (iid != 0 && iid != -1) {
03098 int_32 tid = iid;
03099 if (!headerIsEntry(h, RPMTAG_INSTALLTID))
03100 xx = hae(h, RPMTAG_INSTALLTID, RPM_INT32_TYPE, &tid, 1);
03101 }
03102
03103
03104 if (!hge(h, RPMTAG_PACKAGECOLOR, &bnt, &hcolor, &count)) {
03105 hcolor = hGetColor(h);
03106 xx = hae(h, RPMTAG_PACKAGECOLOR, RPM_INT32_TYPE, &hcolor, 1);
03107 }
03108
03109
03110
03111
03112
03113
03114
03115 xx = hge(h, RPMTAG_BASENAMES, &bnt, &baseNames, &count);
03116 xx = hge(h, RPMTAG_DIRINDEXES, &dit, &dirIndexes, NULL);
03117 xx = hge(h, RPMTAG_DIRNAMES, &dnt, &dirNames, NULL);
03118
03119 (void) blockSignals(db, &signalMask);
03120
03121 {
03122 unsigned int firstkey = 0;
03123 void * keyp = &firstkey;
03124 size_t keylen = sizeof(firstkey);
03125 void * datap = NULL;
03126 size_t datalen = 0;
03127
03128 dbi = dbiOpen(db, RPMDBI_PACKAGES, 0);
03129
03130 if (dbi != NULL) {
03131
03132
03133 datap = h;
03134 datalen = headerSizeof(h, HEADER_MAGIC_NO);
03135
03136 xx = dbiCopen(dbi, dbi->dbi_txnid, &dbcursor, DB_WRITECURSOR);
03137
03138
03139
03140
03141 key->data = keyp;
03142 key->size = keylen;
03143 data->data = datap;
03144 data->size = datalen;
03145 ret = dbiGet(dbi, dbcursor, key, data, DB_SET);
03146 keyp = key->data;
03147 keylen = key->size;
03148 datap = data->data;
03149 datalen = data->size;
03150
03151
03152
03153 hdrNum = 0;
03154 if (ret == 0 && datap) {
03155 memcpy(&mi_offset, datap, sizeof(mi_offset.ui));
03156 if (dbiByteSwapped(dbi) == 1)
03157 _DBSWAP(mi_offset);
03158 hdrNum = mi_offset.ui;
03159 }
03160 ++hdrNum;
03161 mi_offset.ui = hdrNum;
03162 if (dbiByteSwapped(dbi) == 1)
03163 _DBSWAP(mi_offset);
03164 if (ret == 0 && datap) {
03165 memcpy(datap, &mi_offset, sizeof(mi_offset.ui));
03166 } else {
03167 datap = &mi_offset;
03168 datalen = sizeof(mi_offset.ui);
03169 }
03170
03171
03172 key->data = keyp;
03173 key->size = keylen;
03174
03175 data->data = datap;
03176
03177 data->size = datalen;
03178
03179
03180 ret = dbiPut(dbi, dbcursor, key, data, DB_KEYLAST);
03181
03182 xx = dbiSync(dbi, 0);
03183
03184 xx = dbiCclose(dbi, dbcursor, DB_WRITECURSOR);
03185 dbcursor = NULL;
03186 }
03187
03188
03189 }
03190
03191 if (ret) {
03192 rpmError(RPMERR_DBCORRUPT,
03193 _("error(%d) allocating new package instance\n"), ret);
03194 goto exit;
03195 }
03196
03197
03198
03199 if (hdrNum)
03200 {
03201 dbiIndexItem rec = dbiIndexNewItem(hdrNum, 0);
03202
03203
03204 (void) headerSetInstance(h, hdrNum);
03205
03206 if (db->db_tagn != NULL)
03207 for (dbix = 0; dbix < db->db_ndbi; dbix++) {
03208 const char *av[1];
03209 const char **rpmvals = NULL;
03210 byte * bin = NULL;
03211 rpmTagType rpmtype = 0;
03212 int rpmcnt = 0;
03213 int rpmtag;
03214 int_32 * requireFlags;
03215 rpmRC rpmrc;
03216 int i, j;
03217
03218 rpmrc = RPMRC_NOTFOUND;
03219 dbi = NULL;
03220 requireFlags = NULL;
03221
03222 rpmtag = db->db_tagn[dbix];
03223
03224
03225 switch (rpmtag) {
03226
03227 case RPMDBI_AVAILABLE:
03228 case RPMDBI_ADDED:
03229 case RPMDBI_REMOVED:
03230 case RPMDBI_DEPENDS:
03231 continue;
03232 break;
03233 case RPMDBI_PACKAGES:
03234 if (db->db_export != NULL)
03235 xx = db->db_export(db, h, 1);
03236 dbi = dbiOpen(db, rpmtag, 0);
03237 if (dbi == NULL)
03238 continue;
03239 xx = dbiCopen(dbi, dbi->dbi_txnid, &dbcursor, DB_WRITECURSOR);
03240
03241 mi_offset.ui = hdrNum;
03242 if (dbiByteSwapped(dbi) == 1)
03243 _DBSWAP(mi_offset);
03244
03245 key->data = (void *) &mi_offset;
03246
03247 key->size = sizeof(mi_offset.ui);
03248 data->data = headerUnload(h);
03249 data->size = headerSizeof(h, HEADER_MAGIC_NO);
03250
03251
03252 if (hdrchk && ts) {
03253 const char * msg = NULL;
03254 int lvl;
03255
03256 rpmrc = (*hdrchk) (ts, data->data, data->size, &msg);
03257 lvl = (rpmrc == RPMRC_FAIL ? RPMMESS_ERROR : RPMMESS_DEBUG);
03258 rpmMessage(lvl, "%s h#%8u %s",
03259 (rpmrc == RPMRC_FAIL ? _("rpmdbAdd: skipping") : " +++"),
03260 hdrNum, (msg ? msg : "\n"));
03261 msg = _free(msg);
03262 }
03263
03264 if (data->data != NULL && rpmrc != RPMRC_FAIL) {
03265
03266 xx = dbiPut(dbi, dbcursor, key, data, DB_KEYLAST);
03267
03268 xx = dbiSync(dbi, 0);
03269 }
03270 data->data = _free(data->data);
03271 data->size = 0;
03272 xx = dbiCclose(dbi, dbcursor, DB_WRITECURSOR);
03273 dbcursor = NULL;
03274 if (!dbi->dbi_no_dbsync)
03275 xx = dbiSync(dbi, 0);
03276 continue;
03277 break;
03278 case RPMTAG_BASENAMES:
03279 rpmtype = bnt;
03280 rpmvals = baseNames;
03281 rpmcnt = count;
03282 break;
03283 case RPMTAG_REQUIRENAME:
03284 xx = hge(h, rpmtag, &rpmtype, &rpmvals, &rpmcnt);
03285 xx = hge(h, RPMTAG_REQUIREFLAGS, NULL, &requireFlags, NULL);
03286 break;
03287 default:
03288 xx = hge(h, rpmtag, &rpmtype, &rpmvals, &rpmcnt);
03289 break;
03290 }
03291
03292
03293 if (rpmcnt <= 0) {
03294 if (rpmtag != RPMTAG_GROUP)
03295 continue;
03296
03297
03298 rpmtype = RPM_STRING_TYPE;
03299 rpmvals = (const char **) "Unknown";
03300 rpmcnt = 1;
03301 }
03302
03303
03304 dbi = dbiOpen(db, rpmtag, 0);
03305 if (dbi != NULL) {
03306 int printed;
03307
03308 if (rpmtype == RPM_STRING_TYPE) {
03309
03310
03311 av[0] = (const char *) rpmvals;
03312
03313 rpmvals = av;
03314 rpmcnt = 1;
03315 }
03316
03317 printed = 0;
03318 xx = dbiCopen(dbi, dbi->dbi_txnid, &dbcursor, DB_WRITECURSOR);
03319
03320
03321 for (i = 0; i < rpmcnt; i++) {
03322 dbiIndexSet set;
03323 int stringvalued;
03324
03325 bin = _free(bin);
03326
03327
03328
03329
03330 rec->tagNum = i;
03331 switch (dbi->dbi_rpmtag) {
03332 case RPMTAG_BASENAMES:
03333
03334 if (_db_tagged_file_indices && i < 0x010000)
03335 rec->tagNum |= taghash(dirNames[dirIndexes[i]]);
03336 break;
03337 case RPMTAG_PUBKEYS:
03338 break;
03339 case RPMTAG_FILEMD5S:
03340
03341 if (!(rpmvals[i] && *rpmvals[i] != '\0'))
03342 continue;
03343 break;
03344 case RPMTAG_REQUIRENAME:
03345
03346 if (requireFlags && isInstallPreReq(requireFlags[i]))
03347 continue;
03348 break;
03349 case RPMTAG_TRIGGERNAME:
03350 if (i) {
03351
03352 for (j = 0; j < i; j++) {
03353 if (!strcmp(rpmvals[i], rpmvals[j]))
03354 break;
03355 }
03356
03357 if (j < i)
03358 continue;
03359 }
03360 break;
03361 default:
03362 break;
03363 }
03364
03365
03366 stringvalued = 0;
03367 switch (rpmtype) {
03368
03369 case RPM_CHAR_TYPE:
03370 case RPM_INT8_TYPE:
03371 key->size = sizeof(int_8);
03372 key->data = rpmvals + i;
03373 break;
03374 case RPM_INT16_TYPE:
03375 key->size = sizeof(int_16);
03376 key->data = rpmvals + i;
03377 break;
03378 case RPM_INT32_TYPE:
03379 key->size = sizeof(int_32);
03380 key->data = rpmvals + i;
03381 break;
03382
03383 case RPM_BIN_TYPE:
03384 key->size = rpmcnt;
03385 key->data = rpmvals;
03386 rpmcnt = 1;
03387 break;
03388 case RPM_STRING_TYPE:
03389 case RPM_I18NSTRING_TYPE:
03390 rpmcnt = 1;
03391
03392 case RPM_STRING_ARRAY_TYPE:
03393
03394
03395 if (dbi->dbi_rpmtag == RPMTAG_FILEDIGESTS) {
03396 const char * s = rpmvals[i];
03397 size_t dlen = strlen(s);
03398 byte * t;
03399 assert((dlen & 1) == 0);
03400 dlen /= 2;
03401 bin = t = xcalloc(1, dlen);
03402 for (j = 0; j < dlen; j++, t++, s += 2)
03403 *t = (nibble(s[0]) << 4) | nibble(s[1]);
03404 key->data = bin;
03405 key->size = dlen;
03406 break;
03407 }
03408
03409 if (dbi->dbi_rpmtag == RPMTAG_PUBKEYS) {
03410 int nbin;
03411 bin = xcalloc(1, 32);
03412 nbin = pgpExtractPubkeyFingerprint(rpmvals[i], bin);
03413 if (nbin <= 0)
03414 continue;
03415 key->data = bin;
03416 key->size = nbin;
03417 break;
03418 }
03419
03420
03421 default:
03422 key->data = (void *) rpmvals[i];
03423 key->size = strlen(rpmvals[i]);
03424 stringvalued = 1;
03425 break;
03426 }
03427
03428 if (!printed) {
03429 if (rpmcnt == 1 && stringvalued) {
03430 rpmMessage(RPMMESS_DEBUG,
03431 D_("adding \"%s\" to %s index.\n"),
03432 (char *)key->data, tagName(dbi->dbi_rpmtag));
03433 } else {
03434 rpmMessage(RPMMESS_DEBUG,
03435 D_("adding %d entries to %s index.\n"),
03436 rpmcnt, tagName(dbi->dbi_rpmtag));
03437 }
03438 printed++;
03439 }
03440
03441
03442
03443 set = NULL;
03444
03445 if (key->size == 0) key->size = strlen((char *)key->data);
03446 if (key->size == 0) key->size++;
03447
03448
03449 rc = dbiGet(dbi, dbcursor, key, data, DB_SET);
03450 if (rc == 0) {
03451
03452 if (!dbi->dbi_permit_dups)
03453 (void) dbt2set(dbi, data, &set);
03454 } else if (rc != DB_NOTFOUND) {
03455 rpmError(RPMERR_DBGETINDEX,
03456 _("error(%d) getting \"%s\" records from %s index\n"),
03457 rc, key->data, tagName(dbi->dbi_rpmtag));
03458 ret += 1;
03459 continue;
03460 }
03461
03462
03463 if (set == NULL)
03464 set = xcalloc(1, sizeof(*set));
03465
03466 (void) dbiAppendSet(set, rec, 1, sizeof(*rec), 0);
03467
03468
03469 (void) set2dbt(dbi, data, set);
03470 rc = dbiPut(dbi, dbcursor, key, data, DB_KEYLAST);
03471
03472
03473 if (rc) {
03474 rpmError(RPMERR_DBPUTINDEX,
03475 _("error(%d) storing record %s into %s\n"),
03476 rc, key->data, tagName(dbi->dbi_rpmtag));
03477 ret += 1;
03478 }
03479
03480 data->data = _free(data->data);
03481
03482 data->size = 0;
03483 set = dbiFreeIndexSet(set);
03484 }
03485
03486
03487 xx = dbiCclose(dbi, dbcursor, DB_WRITECURSOR);
03488 dbcursor = NULL;
03489
03490 if (!dbi->dbi_no_dbsync)
03491 xx = dbiSync(dbi, 0);
03492 }
03493
03494
03495 if (rpmtype != RPM_BIN_TYPE)
03496 rpmvals = hfd(rpmvals, rpmtype);
03497
03498 rpmtype = 0;
03499 rpmcnt = 0;
03500 bin = _free(bin);
03501 }
03502
03503
03504 rec = _free(rec);
03505 }
03506
03507 exit:
03508 (void) unblockSignals(db, &signalMask);
03509 dirIndexes = hfd(dirIndexes, dit);
03510 dirNames = hfd(dirNames, dnt);
03511
03512 return ret;
03513 }
03514
03515
03516
03517 int rpmdbFindFpList(rpmdb db, fingerPrint * fpList, dbiIndexSet * matchList,
03518 int numItems, unsigned int exclude)
03519 {
03520 DBT * key;
03521 DBT * data;
03522 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
03523 HFD_t hfd = headerFreeData;
03524 rpmdbMatchIterator mi;
03525 fingerPrintCache fpc;
03526 Header h;
03527 int i, xx;
03528
03529 if (db == NULL) return 0;
03530
03531 mi = rpmdbInitIterator(db, RPMTAG_BASENAMES, NULL, 0);
03532 if (mi == NULL)
03533 return 0;
03534
03535 key = &mi->mi_key;
03536 data = &mi->mi_data;
03537
03538
03539 for (i = 0; i < numItems; i++) {
03540 unsigned int tag;
03541
03542
03543 matchList[i] = xcalloc(1, sizeof(*(matchList[i])));
03544
03545
03546
03547 key->data = (void *) fpList[i].baseName;
03548
03549 key->size = strlen((char *)key->data);
03550 if (key->size == 0) key->size++;
03551
03552 tag = (_db_tagged_file_indices ? taghash(fpList[i].entry->dirName) : 0);
03553 xx = rpmdbGrowIterator(mi, i, exclude, tag);
03554
03555 }
03556
03557 if ((i = rpmdbGetIteratorCount(mi)) == 0) {
03558 mi = rpmdbFreeIterator(mi);
03559 return 0;
03560 }
03561 fpc = fpCacheCreate(i);
03562
03563 rpmdbSortIterator(mi);
03564
03565
03566
03567 if (mi != NULL)
03568 while ((h = rpmdbNextIterator(mi)) != NULL) {
03569 const char ** dirNames;
03570 const char ** baseNames;
03571 const char ** fullBaseNames;
03572 rpmTagType bnt, dnt;
03573 uint_32 * dirIndexes;
03574 uint_32 * fullDirIndexes;
03575 fingerPrint * fps;
03576 dbiIndexItem im;
03577 int start;
03578 int num;
03579 int end;
03580
03581 start = mi->mi_setx - 1;
03582 im = mi->mi_set->recs + start;
03583
03584
03585
03586 for (end = start + 1; end < mi->mi_set->count; end++) {
03587 if (im->hdrNum != mi->mi_set->recs[end].hdrNum)
03588 break;
03589 }
03590
03591 num = end - start;
03592
03593
03594 xx = hge(h, RPMTAG_BASENAMES, &bnt, &fullBaseNames, NULL);
03595 xx = hge(h, RPMTAG_DIRNAMES, &dnt, &dirNames, NULL);
03596 xx = hge(h, RPMTAG_DIRINDEXES, NULL, &fullDirIndexes, NULL);
03597
03598 baseNames = xcalloc(num, sizeof(*baseNames));
03599 dirIndexes = xcalloc(num, sizeof(*dirIndexes));
03600
03601 for (i = 0; i < num; i++) {
03602 baseNames[i] = fullBaseNames[im[i].tagNum];
03603 dirIndexes[i] = fullDirIndexes[im[i].tagNum];
03604 }
03605
03606
03607 fps = xcalloc(num, sizeof(*fps));
03608 fpLookupList(fpc, dirNames, baseNames, dirIndexes, num, fps);
03609
03610
03611
03612 for (i = 0; i < num; i++, im++) {
03613
03614 if (!FP_EQUAL(fps[i], fpList[im->fpNum]))
03615 continue;
03616
03617 xx = dbiAppendSet(matchList[im->fpNum], im, 1, sizeof(*im), 0);
03618 }
03619
03620
03621 fps = _free(fps);
03622 dirNames = hfd(dirNames, dnt);
03623 fullBaseNames = hfd(fullBaseNames, bnt);
03624 baseNames = _free(baseNames);
03625 dirIndexes = _free(dirIndexes);
03626
03627 mi->mi_setx = end;
03628 }
03629
03630 mi = rpmdbFreeIterator(mi);
03631
03632 fpc = fpCacheFree(fpc);
03633
03634 return 0;
03635
03636 }
03637
03638
03644 static int rpmioFileExists(const char * urlfn)
03645
03646
03647 {
03648 const char *fn;
03649 int urltype = urlPath(urlfn, &fn);
03650 struct stat buf;
03651
03652
03653 if (*fn == '\0') fn = "/";
03654
03655 switch (urltype) {
03656 case URL_IS_HTTPS:
03657 case URL_IS_HTTP:
03658 case URL_IS_FTP:
03659 case URL_IS_HKP:
03660 case URL_IS_PATH:
03661 case URL_IS_UNKNOWN:
03662 if (Stat(fn, &buf)) {
03663 switch(errno) {
03664 case ENOENT:
03665 case EINVAL:
03666 return 0;
03667 }
03668 }
03669 break;
03670 case URL_IS_DASH:
03671 default:
03672 return 0;
03673 break;
03674 }
03675
03676 return 1;
03677 }
03678
03679 static int rpmdbRemoveDatabase(const char * prefix,
03680 const char * dbpath, int _dbapi,
03681 const int * dbiTags, int dbiTagsMax)
03682
03683
03684 {
03685 int i;
03686 char * filename;
03687 int xx;
03688
03689 i = strlen(dbpath);
03690
03691 if (dbpath[i - 1] != '/') {
03692 filename = alloca(i);
03693 strcpy(filename, dbpath);
03694 filename[i] = '/';
03695 filename[i + 1] = '\0';
03696 dbpath = filename;
03697 }
03698
03699
03700 filename = alloca(strlen(prefix) + strlen(dbpath) + 40);
03701
03702 switch (_dbapi) {
03703 case 4:
03704
03705 case 3:
03706 if (dbiTags != NULL)
03707 for (i = 0; i < dbiTagsMax; i++) {
03708
03709 const char * base = tagName(dbiTags[i]);
03710
03711 sprintf(filename, "%s/%s/%s", prefix, dbpath, base);
03712 (void)rpmCleanPath(filename);
03713 if (!rpmioFileExists(filename))
03714 continue;
03715 xx = unlink(filename);
03716 }
03717 for (i = 0; i < 16; i++) {
03718 sprintf(filename, "%s/%s/__db.%03d", prefix, dbpath, i);
03719 (void)rpmCleanPath(filename);
03720 if (!rpmioFileExists(filename))
03721 continue;
03722 xx = unlink(filename);
03723 }
03724 break;
03725 case 2:
03726 case 1:
03727 case 0:
03728 break;
03729 }
03730
03731 sprintf(filename, "%s/%s", prefix, dbpath);
03732 (void)rpmCleanPath(filename);
03733 xx = rmdir(filename);
03734
03735 return 0;
03736 }
03737
03738 static int rpmdbMoveDatabase(const char * prefix,
03739 const char * olddbpath, int _olddbapi,
03740 const char * newdbpath, int _newdbapi,
03741 const int * dbiTags, int dbiTagsMax)
03742
03743
03744 {
03745 int i;
03746 char * ofilename, * nfilename;
03747 struct stat * nst = alloca(sizeof(*nst));
03748 int rc = 0;
03749 int xx;
03750
03751 i = strlen(olddbpath);
03752
03753 if (olddbpath[i - 1] != '/') {
03754 ofilename = alloca(i + 2);
03755 strcpy(ofilename, olddbpath);
03756 ofilename[i] = '/';
03757 ofilename[i + 1] = '\0';
03758 olddbpath = ofilename;
03759 }
03760
03761
03762 i = strlen(newdbpath);
03763
03764 if (newdbpath[i - 1] != '/') {
03765 nfilename = alloca(i + 2);
03766 strcpy(nfilename, newdbpath);
03767 nfilename[i] = '/';
03768 nfilename[i + 1] = '\0';
03769 newdbpath = nfilename;
03770 }
03771
03772
03773 ofilename = alloca(strlen(prefix) + strlen(olddbpath) + 40);
03774 nfilename = alloca(strlen(prefix) + strlen(newdbpath) + 40);
03775
03776 switch (_olddbapi) {
03777 case 4:
03778
03779 case 3:
03780 if (dbiTags != NULL)
03781 for (i = 0; i < dbiTagsMax; i++) {
03782 const char * base;
03783 int rpmtag;
03784
03785
03786 switch ((rpmtag = dbiTags[i])) {
03787 case RPMDBI_AVAILABLE:
03788 case RPMDBI_ADDED:
03789 case RPMDBI_REMOVED:
03790 case RPMDBI_DEPENDS:
03791 continue;
03792 break;
03793 default:
03794 break;
03795 }
03796
03797 base = tagName(rpmtag);
03798 sprintf(ofilename, "%s/%s/%s", prefix, olddbpath, base);
03799 (void)rpmCleanPath(ofilename);
03800 if (!rpmioFileExists(ofilename))
03801 continue;
03802 sprintf(nfilename, "%s/%s/%s", prefix, newdbpath, base);
03803 (void)rpmCleanPath(nfilename);
03804
03805
03806
03807
03808
03809 if (stat(nfilename, nst) < 0)
03810 if (stat(ofilename, nst) < 0)
03811 continue;
03812
03813 if ((xx = rename(ofilename, nfilename)) != 0) {
03814 rc = 1;
03815 continue;
03816 }
03817 xx = chown(nfilename, nst->st_uid, nst->st_gid);
03818 xx = chmod(nfilename, (nst->st_mode & 07777));
03819 { struct utimbuf stamp;
03820 stamp.actime = nst->st_atime;
03821 stamp.modtime = nst->st_mtime;
03822 xx = utime(nfilename, &stamp);
03823 }
03824 }
03825 for (i = 0; i < 16; i++) {
03826 sprintf(ofilename, "%s/%s/__db.%03d", prefix, olddbpath, i);
03827 (void)rpmCleanPath(ofilename);
03828 if (rpmioFileExists(ofilename))
03829 xx = unlink(ofilename);
03830 sprintf(nfilename, "%s/%s/__db.%03d", prefix, newdbpath, i);
03831 (void)rpmCleanPath(nfilename);
03832 if (rpmioFileExists(nfilename))
03833 xx = unlink(nfilename);
03834 }
03835 break;
03836 case 2:
03837 case 1:
03838 case 0:
03839 break;
03840 }
03841
03842 return rc;
03843 }
03844
03845 int rpmdbRebuild(const char * prefix, rpmts ts,
03846 rpmRC (*hdrchk) (rpmts ts, const void *uh, size_t uc, const char ** msg))
03847
03848
03849 {
03850 rpmdb olddb;
03851 const char * dbpath = NULL;
03852 const char * rootdbpath = NULL;
03853 rpmdb newdb;
03854 const char * newdbpath = NULL;
03855 const char * newrootdbpath = NULL;
03856 const char * tfn;
03857 int nocleanup = 1;
03858 int failed = 0;
03859 int removedir = 0;
03860 int rc = 0, xx;
03861 int _dbapi;
03862 int _dbapi_rebuild;
03863 int * dbiTags = NULL;
03864 int dbiTagsMax = 0;
03865
03866
03867 if (prefix == NULL) prefix = "/";
03868
03869 prefix = rpmGetPath(prefix, NULL);
03870
03871 _dbapi = rpmExpandNumeric("%{_dbapi}");
03872 _dbapi_rebuild = rpmExpandNumeric("%{_dbapi_rebuild}");
03873
03874 dbiTagsInit(&dbiTags, &dbiTagsMax);
03875
03876
03877 tfn = rpmGetPath("%{?_dbpath}", NULL);
03878
03879
03880 if (!(tfn && tfn[0] != '\0'))
03881
03882 {
03883 rpmMessage(RPMMESS_DEBUG, D_("no dbpath has been set"));
03884 rc = 1;
03885 goto exit;
03886 }
03887 dbpath = rootdbpath = rpmGetPath(prefix, tfn, NULL);
03888 if (!(prefix[0] == '/' && prefix[1] == '\0'))
03889 dbpath += strlen(prefix) - 1;
03890 tfn = _free(tfn);
03891
03892
03893 tfn = rpmGetPath("%{?_dbpath_rebuild}", NULL);
03894
03895
03896 if (!(tfn && tfn[0] != '\0' && strcmp(tfn, dbpath)))
03897
03898 {
03899 char pidbuf[20];
03900 char *t;
03901 sprintf(pidbuf, "rebuilddb.%d", (int) getpid());
03902 t = xmalloc(strlen(dbpath) + strlen(pidbuf) + 1);
03903
03904 (void)stpcpy(stpcpy(t, dbpath), pidbuf);
03905
03906 tfn = _free(tfn);
03907 tfn = t;
03908 nocleanup = 0;
03909 }
03910 newdbpath = newrootdbpath = rpmGetPath(prefix, tfn, NULL);
03911 if (!(prefix[0] == '/' && prefix[1] == '\0'))
03912 newdbpath += strlen(prefix) - 1;
03913 tfn = _free(tfn);
03914
03915 rpmMessage(RPMMESS_DEBUG, D_("rebuilding database %s into %s\n"),
03916 rootdbpath, newrootdbpath);
03917
03918 if (!Access(newrootdbpath, F_OK)) {
03919 rpmError(RPMERR_MKDIR, _("temporary database %s already exists\n"),
03920 newrootdbpath);
03921 rc = 1;
03922 goto exit;
03923 }
03924
03925 rpmMessage(RPMMESS_DEBUG, D_("creating directory %s\n"), newrootdbpath);
03926 if (Mkdir(newrootdbpath, 0755)) {
03927 rpmError(RPMERR_MKDIR, _("creating directory %s: %s\n"),
03928 newrootdbpath, strerror(errno));
03929 rc = 1;
03930 goto exit;
03931 }
03932 removedir = 1;
03933
03934 _rebuildinprogress = 0;
03935
03936 rpmMessage(RPMMESS_DEBUG, D_("opening old database with dbapi %d\n"),
03937 _dbapi);
03938
03939 if (rpmdbOpenDatabase(prefix, dbpath, _dbapi, &olddb, O_RDONLY, 0644,
03940 RPMDB_FLAG_MINIMAL)) {
03941 rc = 1;
03942 goto exit;
03943 }
03944
03945 _dbapi = olddb->db_api;
03946 _rebuildinprogress = 1;
03947 rpmMessage(RPMMESS_DEBUG, D_("opening new database with dbapi %d\n"),
03948 _dbapi_rebuild);
03949 (void) rpmDefineMacro(NULL, "_rpmdb_rebuild %{nil}", -1);
03950
03951 if (rpmdbOpenDatabase(prefix, newdbpath, _dbapi_rebuild, &newdb, O_RDWR | O_CREAT, 0644, 0)) {
03952 rc = 1;
03953 goto exit;
03954 }
03955
03956
03957 _rebuildinprogress = 0;
03958
03959 _dbapi_rebuild = newdb->db_api;
03960
03961 { Header h = NULL;
03962 rpmdbMatchIterator mi;
03963 #define _RECNUM rpmdbGetIteratorOffset(mi)
03964
03965 mi = rpmdbInitIterator(olddb, RPMDBI_PACKAGES, NULL, 0);
03966 if (ts && hdrchk)
03967 (void) rpmdbSetHdrChk(mi, ts, hdrchk);
03968
03969 while ((h = rpmdbNextIterator(mi)) != NULL) {
03970
03971
03972 if (!(headerIsEntry(h, RPMTAG_NAME) &&
03973 headerIsEntry(h, RPMTAG_VERSION) &&
03974 headerIsEntry(h, RPMTAG_RELEASE) &&
03975 headerIsEntry(h, RPMTAG_BUILDTIME)))
03976 {
03977 rpmError(RPMERR_INTERNAL,
03978 _("header #%u in the database is bad -- skipping.\n"),
03979 _RECNUM);
03980 continue;
03981 }
03982
03983
03984 if (_db_filter_dups || newdb->db_filter_dups) {
03985 const char * name, * version, * release;
03986 int skip = 0;
03987
03988 (void) headerNVR(h, &name, &version, &release);
03989
03990
03991 { rpmdbMatchIterator mi;
03992 mi = rpmdbInitIterator(newdb, RPMTAG_NAME, name, 0);
03993 (void) rpmdbSetIteratorRE(mi, RPMTAG_VERSION,
03994 RPMMIRE_DEFAULT, version);
03995 (void) rpmdbSetIteratorRE(mi, RPMTAG_RELEASE,
03996 RPMMIRE_DEFAULT, release);
03997 while (rpmdbNextIterator(mi)) {
03998 skip = 1;
03999 break;
04000 }
04001 mi = rpmdbFreeIterator(mi);
04002 }
04003
04004
04005 if (skip)
04006 continue;
04007 }
04008
04009
04010 { Header nh = (headerIsEntry(h, RPMTAG_HEADERIMAGE)
04011 ? headerCopy(h) : NULL);
04012 rc = rpmdbAdd(newdb, -1, (nh ? nh : h), ts, hdrchk);
04013 nh = headerFree(nh);
04014 }
04015
04016 if (rc) {
04017 rpmError(RPMERR_INTERNAL,
04018 _("cannot add record originally at %u\n"), _RECNUM);
04019 failed = 1;
04020 break;
04021 }
04022 }
04023
04024 mi = rpmdbFreeIterator(mi);
04025
04026 }
04027
04028 xx = rpmdbClose(olddb);
04029 xx = rpmdbClose(newdb);
04030
04031 if (failed) {
04032 rpmMessage(RPMMESS_NORMAL, _("failed to rebuild database: original database "
04033 "remains in place\n"));
04034
04035 xx = rpmdbRemoveDatabase(prefix, newdbpath, _dbapi_rebuild,
04036 dbiTags, dbiTagsMax);
04037 rc = 1;
04038 goto exit;
04039 } else if (!nocleanup) {
04040 xx = rpmdbMoveDatabase(prefix, newdbpath, _dbapi_rebuild, dbpath, _dbapi,
04041 dbiTags, dbiTagsMax);
04042
04043 if (xx) {
04044 rpmMessage(RPMMESS_ERROR, _("failed to replace old database with new "
04045 "database!\n"));
04046 rpmMessage(RPMMESS_ERROR, _("replace files in %s with files from %s "
04047 "to recover"), dbpath, newdbpath);
04048 rc = 1;
04049 goto exit;
04050 }
04051 }
04052 rc = 0;
04053
04054 exit:
04055 if (removedir && !(rc == 0 && nocleanup)) {
04056 rpmMessage(RPMMESS_DEBUG, D_("removing directory %s\n"), newrootdbpath);
04057 if (Rmdir(newrootdbpath))
04058 rpmMessage(RPMMESS_ERROR, D_("failed to remove directory %s: %s\n"),
04059 newrootdbpath, strerror(errno));
04060 }
04061 newrootdbpath = _free(newrootdbpath);
04062 rootdbpath = _free(rootdbpath);
04063 dbiTags = _free(dbiTags);
04064 prefix = _free(prefix);
04065
04066 return rc;
04067 }