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