00001
00005 #include "system.h"
00006
00007 #include <rpmlib.h>
00008
00009 #include "rpmal.h"
00010 #define _RPMDS_INTERNAL
00011 #include "rpmds.h"
00012 #include "rpmfi.h"
00013
00014 #include "debug.h"
00015
00016 typedef struct availablePackage_s * availablePackage;
00017
00018
00019 int _rpmal_debug = 0;
00020
00021
00022
00023
00024
00025
00026
00027
00028
00032 struct availablePackage_s {
00033
00034 rpmds provides;
00035
00036 rpmfi fi;
00038 uint_32 tscolor;
00040
00041 fnpyKey key;
00043 };
00044
00045 typedef struct availableIndexEntry_s * availableIndexEntry;
00046
00047
00051 struct availableIndexEntry_s {
00052
00053 alKey pkgKey;
00054
00055 const char * entry;
00056 unsigned short entryLen;
00057 unsigned short entryIx;
00058 enum indexEntryType {
00059 IET_PROVIDES=1
00060 } type;
00061 };
00062
00063 typedef struct availableIndex_s * availableIndex;
00064
00065
00069 struct availableIndex_s {
00070
00071 availableIndexEntry index;
00072 int size;
00073 int k;
00074 };
00075
00076 typedef struct fileIndexEntry_s * fileIndexEntry;
00077
00078
00082 struct fileIndexEntry_s {
00083
00084 const char * baseName;
00085 int baseNameLen;
00086 alNum pkgNum;
00087 uint_32 ficolor;
00088 };
00089
00090 typedef struct dirInfo_s * dirInfo;
00091
00092
00096 struct dirInfo_s {
00097
00098 const char * dirName;
00099 int dirNameLen;
00100
00101 fileIndexEntry files;
00102 int numFiles;
00103 };
00104
00108 struct rpmal_s {
00109
00110 availablePackage list;
00111 struct availableIndex_s index;
00112 int delta;
00113 int size;
00114 int alloced;
00115 uint_32 tscolor;
00116 int numDirs;
00117
00118 dirInfo dirs;
00119 };
00120
00125 static void rpmalFreeIndex(rpmal al)
00126
00127 {
00128 availableIndex ai = &al->index;
00129 if (ai->size > 0) {
00130 ai->index = _free(ai->index);
00131 ai->size = 0;
00132 }
00133 }
00134
00135 #ifdef DYING
00136
00141 static int alGetSize( const rpmal al)
00142
00143 {
00144 return (al != NULL ? al->size : 0);
00145 }
00146 #endif
00147
00148 static inline alNum alKey2Num( const rpmal al,
00149 alKey pkgKey)
00150
00151 {
00152
00153 return ((alNum)pkgKey);
00154
00155 }
00156
00157 static inline alKey alNum2Key( const rpmal al,
00158 alNum pkgNum)
00159
00160 {
00161
00162 return ((alKey)pkgNum);
00163
00164 }
00165
00166 #ifdef DYING
00167
00173
00174 static availablePackage alGetPkg( const rpmal al,
00175 alKey pkgKey)
00176
00177 {
00178 alNum pkgNum = alKey2Num(al, pkgKey);
00179 availablePackage alp = NULL;
00180
00181 if (al != NULL && pkgNum >= 0 && pkgNum < alGetSize(al)) {
00182 if (al->list != NULL)
00183 alp = al->list + pkgNum;
00184 }
00185 return alp;
00186 }
00187 #endif
00188
00189 rpmal rpmalCreate(int delta)
00190 {
00191 rpmal al = xcalloc(1, sizeof(*al));
00192 availableIndex ai = &al->index;
00193
00194 al->delta = delta;
00195 al->size = 0;
00196 al->list = xcalloc(al->delta, sizeof(*al->list));
00197 al->alloced = al->delta;
00198
00199 ai->index = NULL;
00200 ai->size = 0;
00201
00202 al->numDirs = 0;
00203 al->dirs = NULL;
00204 return al;
00205 }
00206
00207 rpmal rpmalFree(rpmal al)
00208 {
00209 availablePackage alp;
00210 dirInfo die;
00211 int i;
00212
00213 if (al == NULL)
00214 return NULL;
00215
00216 if ((alp = al->list) != NULL)
00217 for (i = 0; i < al->size; i++, alp++) {
00218 alp->provides = rpmdsFree(alp->provides);
00219 alp->fi = rpmfiFree(alp->fi);
00220 }
00221
00222 if ((die = al->dirs) != NULL)
00223 for (i = 0; i < al->numDirs; i++, die++) {
00224 die->dirName = _free(die->dirName);
00225 die->files = _free(die->files);
00226 }
00227 al->dirs = _free(al->dirs);
00228 al->numDirs = 0;
00229
00230 al->list = _free(al->list);
00231 al->alloced = 0;
00232 rpmalFreeIndex(al);
00233 al = _free(al);
00234 return NULL;
00235 }
00236
00243 static int dieCompare(const void * one, const void * two)
00244
00245 {
00246
00247 const dirInfo a = (const dirInfo) one;
00248 const dirInfo b = (const dirInfo) two;
00249
00250 int lenchk = a->dirNameLen - b->dirNameLen;
00251
00252 if (lenchk || a->dirNameLen == 0)
00253 return lenchk;
00254
00255 if (a->dirName == NULL || b->dirName == NULL)
00256 return lenchk;
00257
00258
00259 return strcmp(a->dirName, b->dirName);
00260 }
00261
00268 static int fieCompare(const void * one, const void * two)
00269
00270 {
00271
00272 const fileIndexEntry a = (const fileIndexEntry) one;
00273 const fileIndexEntry b = (const fileIndexEntry) two;
00274
00275 int lenchk = a->baseNameLen - b->baseNameLen;
00276
00277 if (lenchk)
00278 return lenchk;
00279
00280 if (a->baseName == NULL || b->baseName == NULL)
00281 return lenchk;
00282
00283 #ifdef NOISY
00284
00285 if (_rpmal_debug) {
00286 fprintf(stderr, "\t\tstrcmp(%p:%p, %p:%p)", a, a->baseName, b, b->baseName);
00287 #if 0
00288 fprintf(stderr, " a %s", a->baseName);
00289 #endif
00290 fprintf(stderr, " b %s", a->baseName);
00291 fprintf(stderr, "\n");
00292 }
00293
00294 #endif
00295
00296 return strcmp(a->baseName, b->baseName);
00297 }
00298
00299 void rpmalDel(rpmal al, alKey pkgKey)
00300 {
00301 alNum pkgNum = alKey2Num(al, pkgKey);
00302 availablePackage alp;
00303 rpmfi fi;
00304
00305 if (al == NULL || al->list == NULL)
00306 return;
00307
00308 alp = al->list + pkgNum;
00309
00310
00311 if (_rpmal_debug)
00312 fprintf(stderr, "*** del %p[%d]\n", al->list, pkgNum);
00313
00314
00315
00316 if ((fi = alp->fi) != NULL)
00317 if (rpmfiFC(fi) > 0) {
00318 int origNumDirs = al->numDirs;
00319 int dx;
00320 dirInfo dieNeedle =
00321 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
00322 dirInfo die;
00323 int last;
00324 int i;
00325
00326
00327
00328 if (al->dirs != NULL)
00329 for (dx = rpmfiDC(fi) - 1; dx >= 0; dx--)
00330 {
00331 fileIndexEntry fie;
00332
00333 (void) rpmfiSetDX(fi, dx);
00334
00335
00336 dieNeedle->dirName = (char *) rpmfiDN(fi);
00337
00338 dieNeedle->dirNameLen = (dieNeedle->dirName != NULL
00339 ? strlen(dieNeedle->dirName) : 0);
00340
00341 die = bsearch(dieNeedle, al->dirs, al->numDirs,
00342 sizeof(*dieNeedle), dieCompare);
00343
00344 if (die == NULL)
00345 continue;
00346
00347
00348 if (_rpmal_debug)
00349 fprintf(stderr, "--- die[%5d] %p [%3d] %s\n", (int)(die - al->dirs), die, die->dirNameLen, die->dirName);
00350
00351
00352 last = die->numFiles;
00353 fie = die->files + last - 1;
00354 for (i = last - 1; i >= 0; i--, fie--) {
00355 if (fie->pkgNum != pkgNum)
00356 continue;
00357 die->numFiles--;
00358
00359 if (i < die->numFiles) {
00360
00361 if (_rpmal_debug)
00362 fprintf(stderr, "\t%p[%3d] memmove(%p:%p,%p:%p,0x%x) %s <- %s\n", die->files, die->numFiles, fie, fie->baseName, fie+1, (fie+1)->baseName, (unsigned) ((die->numFiles - i) * sizeof(*fie)), fie->baseName, (fie+1)->baseName);
00363
00364
00365
00366 memmove(fie, fie+1, (die->numFiles - i) * sizeof(*fie));
00367
00368 }
00369
00370 if (_rpmal_debug)
00371 fprintf(stderr, "\t%p[%3d] memset(%p,0,0x%x) %p [%3d] %s\n", die->files, die->numFiles, die->files + die->numFiles, (unsigned)sizeof(*fie), fie->baseName, fie->baseNameLen, fie->baseName);
00372
00373 memset(die->files + die->numFiles, 0, sizeof(*fie));
00374
00375 }
00376 if (die->numFiles > 0) {
00377 if (last > i)
00378 die->files = xrealloc(die->files,
00379 die->numFiles * sizeof(*die->files));
00380 continue;
00381 }
00382 die->files = _free(die->files);
00383 die->dirName = _free(die->dirName);
00384 al->numDirs--;
00385 if ((die - al->dirs) < al->numDirs) {
00386
00387 if (_rpmal_debug)
00388 fprintf(stderr, " die[%5d] memmove(%p,%p,0x%x)\n", (int)(die - al->dirs), die, die+1, (unsigned)((al->numDirs - (die - al->dirs)) * sizeof(*die)));
00389
00390
00391
00392 memmove(die, die+1, (al->numDirs - (die - al->dirs)) * sizeof(*die));
00393
00394 }
00395
00396
00397 if (_rpmal_debug)
00398 fprintf(stderr, " die[%5d] memset(%p,0,0x%x)\n", al->numDirs, al->dirs + al->numDirs, (unsigned)sizeof(*die));
00399
00400 memset(al->dirs + al->numDirs, 0, sizeof(*al->dirs));
00401 }
00402
00403 if (origNumDirs > al->numDirs) {
00404 if (al->numDirs > 0)
00405 al->dirs = xrealloc(al->dirs, al->numDirs * sizeof(*al->dirs));
00406 else
00407 al->dirs = _free(al->dirs);
00408 }
00409 }
00410
00411 alp->provides = rpmdsFree(alp->provides);
00412 alp->fi = rpmfiFree(alp->fi);
00413
00414
00415 memset(alp, 0, sizeof(*alp));
00416
00417 return;
00418 }
00419
00420
00421 alKey rpmalAdd(rpmal * alistp, alKey pkgKey, fnpyKey key,
00422 rpmds provides, rpmfi fi, uint_32 tscolor)
00423 {
00424 alNum pkgNum;
00425 rpmal al;
00426 availablePackage alp;
00427
00428
00429 if (*alistp == NULL)
00430 *alistp = rpmalCreate(5);
00431 al = *alistp;
00432 pkgNum = alKey2Num(al, pkgKey);
00433
00434 if (pkgNum >= 0 && pkgNum < al->size) {
00435 rpmalDel(al, pkgKey);
00436 } else {
00437 if (al->size == al->alloced) {
00438 al->alloced += al->delta;
00439 al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced);
00440 }
00441 pkgNum = al->size++;
00442 }
00443
00444 if (al->list == NULL)
00445 return RPMAL_NOMATCH;
00446
00447 alp = al->list + pkgNum;
00448
00449 alp->key = key;
00450 alp->tscolor = tscolor;
00451
00452
00453 if (_rpmal_debug)
00454 fprintf(stderr, "*** add %p[%d] 0x%x\n", al->list, pkgNum, tscolor);
00455
00456
00457 alp->provides = rpmdsLink(provides, "Provides (rpmalAdd)");
00458 alp->fi = rpmfiLink(fi, "Files (rpmalAdd)");
00459
00460 fi = rpmfiLink(alp->fi, "Files index (rpmalAdd)");
00461 fi = rpmfiInit(fi, 0);
00462 if (rpmfiFC(fi) > 0) {
00463 dirInfo dieNeedle =
00464 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
00465 dirInfo die;
00466 int dc = rpmfiDC(fi);
00467 int dx;
00468 int * dirMapping = alloca(sizeof(*dirMapping) * dc);
00469 int * dirUnique = alloca(sizeof(*dirUnique) * dc);
00470 const char * DN;
00471 int origNumDirs;
00472 int first;
00473
00474
00475
00476
00477 al->dirs = xrealloc(al->dirs, (al->numDirs + dc) * sizeof(*al->dirs));
00478
00479
00480 origNumDirs = al->numDirs;
00481
00482
00483 for (dx = 0; dx < dc; dx++) {
00484 int i = 0;
00485 (void) rpmfiSetDX(fi, dx);
00486 DN = rpmfiDN(fi);
00487 if (DN != NULL)
00488 for (i = 0; i < dx; i++) {
00489 const char * iDN;
00490 (void) rpmfiSetDX(fi, i);
00491 iDN = rpmfiDN(fi);
00492 if (iDN != NULL && !strcmp(DN, iDN))
00493 break;
00494 }
00495 dirUnique[dx] = i;
00496 }
00497
00498
00499 for (dx = 0; dx < dc; dx++) {
00500
00501
00502 if (dirUnique[dx] < dx) {
00503 dirMapping[dx] = dirMapping[dirUnique[dx]];
00504 continue;
00505 }
00506
00507
00508 (void) rpmfiSetDX(fi, dx);
00509
00510
00511 { DN = rpmfiDN(fi);
00512
00513 #if defined(__ia64__)
00514
00515 #define DNPREFIX "/emul/ia32-linux"
00516 if (!strncmp(DN, DNPREFIX, sizeof(DNPREFIX)-1))
00517 DN += sizeof(DNPREFIX)-1;
00518 #endif
00519 dieNeedle->dirName = DN;
00520 }
00521
00522
00523 dieNeedle->dirNameLen = (dieNeedle->dirName != NULL
00524 ? strlen(dieNeedle->dirName) : 0);
00525 die = bsearch(dieNeedle, al->dirs, origNumDirs,
00526 sizeof(*dieNeedle), dieCompare);
00527 if (die) {
00528 dirMapping[dx] = die - al->dirs;
00529 } else {
00530 dirMapping[dx] = al->numDirs;
00531 die = al->dirs + al->numDirs;
00532 if (dieNeedle->dirName != NULL)
00533 die->dirName = xstrdup(dieNeedle->dirName);
00534 die->dirNameLen = dieNeedle->dirNameLen;
00535 die->files = NULL;
00536 die->numFiles = 0;
00537
00538 if (_rpmal_debug)
00539 fprintf(stderr, "+++ die[%5d] %p [%3d] %s\n", al->numDirs, die, die->dirNameLen, die->dirName);
00540
00541
00542 al->numDirs++;
00543 }
00544 }
00545
00546 for (first = rpmfiNext(fi); first >= 0;) {
00547 fileIndexEntry fie;
00548 int next;
00549
00550
00551 dx = rpmfiDX(fi);
00552 while ((next = rpmfiNext(fi)) >= 0) {
00553 if (dx != rpmfiDX(fi))
00554 break;
00555 }
00556 if (next < 0) next = rpmfiFC(fi);
00557
00558 die = al->dirs + dirMapping[dx];
00559 die->files = xrealloc(die->files,
00560 (die->numFiles + next - first) * sizeof(*die->files));
00561
00562 fie = die->files + die->numFiles;
00563
00564
00565 if (_rpmal_debug)
00566 fprintf(stderr, " die[%5d] %p->files [%p[%d],%p) -> [%p[%d],%p)\n", dirMapping[dx], die,
00567 die->files, die->numFiles, die->files+die->numFiles,
00568 fie, (next - first), fie + (next - first));
00569
00570
00571
00572 fi = rpmfiInit(fi, first);
00573 while ((first = rpmfiNext(fi)) >= 0 && first < next) {
00574
00575 fie->baseName = rpmfiBN(fi);
00576
00577 fie->baseNameLen = (fie->baseName ? strlen(fie->baseName) : 0);
00578 fie->pkgNum = pkgNum;
00579 fie->ficolor = rpmfiFColor(fi);
00580
00581 if (_rpmal_debug)
00582 fprintf(stderr, "\t%p[%3d] %p:%p[%2d] %s\n", die->files, die->numFiles, fie, fie->baseName, fie->baseNameLen, rpmfiFN(fi));
00583
00584
00585 die->numFiles++;
00586 fie++;
00587 }
00588 qsort(die->files, die->numFiles, sizeof(*die->files), fieCompare);
00589 }
00590
00591
00592 al->dirs = xrealloc(al->dirs, al->numDirs * sizeof(*al->dirs));
00593 if (origNumDirs != al->numDirs)
00594 qsort(al->dirs, al->numDirs, sizeof(*al->dirs), dieCompare);
00595 }
00596 fi = rpmfiUnlink(fi, "Files index (rpmalAdd)");
00597
00598 rpmalFreeIndex(al);
00599
00600 assert(((alNum)(alp - al->list)) == pkgNum);
00601 return ((alKey)(alp - al->list));
00602 }
00603
00604
00611 static int indexcmp(const void * one, const void * two)
00612
00613 {
00614
00615 const availableIndexEntry a = (const availableIndexEntry) one;
00616 const availableIndexEntry b = (const availableIndexEntry) two;
00617
00618 int lenchk;
00619
00620 lenchk = a->entryLen - b->entryLen;
00621 if (lenchk)
00622 return lenchk;
00623
00624 return strcmp(a->entry, b->entry);
00625 }
00626
00627 void rpmalAddProvides(rpmal al, alKey pkgKey, rpmds provides, uint_32 tscolor)
00628 {
00629 uint_32 dscolor;
00630 const char * Name;
00631 alNum pkgNum = alKey2Num(al, pkgKey);
00632 availableIndex ai = &al->index;
00633 availableIndexEntry aie;
00634 int ix;
00635
00636 if (provides == NULL || pkgNum < 0 || pkgNum >= al->size)
00637 return;
00638 if (ai->index == NULL || ai->k < 0 || ai->k >= ai->size)
00639 return;
00640
00641 if (rpmdsInit(provides) != NULL)
00642 while (rpmdsNext(provides) >= 0) {
00643
00644 if ((Name = provides->N[provides->i]) == NULL)
00645 continue;
00646
00647
00648 dscolor = rpmdsColor(provides);
00649 if (tscolor && dscolor && !(tscolor & dscolor))
00650 continue;
00651
00652 aie = ai->index + ai->k;
00653 ai->k++;
00654
00655 aie->pkgKey = pkgKey;
00656
00657 aie->entry = Name;
00658
00659 aie->entryLen = strlen(Name);
00660 ix = rpmdsIx(provides);
00661
00662
00663 assert(ix < 0x10000);
00664
00665 aie->entryIx = ix;
00666 aie->type = IET_PROVIDES;
00667 }
00668 }
00669
00670 void rpmalMakeIndex(rpmal al)
00671 {
00672 availableIndex ai;
00673 availablePackage alp;
00674 int i;
00675
00676 if (al == NULL || al->list == NULL) return;
00677 ai = &al->index;
00678
00679 ai->size = 0;
00680 for (i = 0; i < al->size; i++) {
00681 alp = al->list + i;
00682 if (alp->provides != NULL)
00683 ai->size += rpmdsCount(alp->provides);
00684 }
00685 if (ai->size == 0) return;
00686
00687 ai->index = xrealloc(ai->index, ai->size * sizeof(*ai->index));
00688 ai->k = 0;
00689 for (i = 0; i < al->size; i++) {
00690 alp = al->list + i;
00691 rpmalAddProvides(al, (alKey)i, alp->provides, alp->tscolor);
00692 }
00693
00694
00695 ai->size = ai->k;
00696 qsort(ai->index, ai->size, sizeof(*ai->index), indexcmp);
00697 }
00698
00699 fnpyKey *
00700 rpmalAllFileSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
00701 {
00702 uint_32 tscolor;
00703 uint_32 ficolor;
00704 int found = 0;
00705 const char * dirName;
00706 const char * baseName;
00707 dirInfo dieNeedle =
00708 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
00709 dirInfo die;
00710 fileIndexEntry fieNeedle =
00711 memset(alloca(sizeof(*fieNeedle)), 0, sizeof(*fieNeedle));
00712 fileIndexEntry fie;
00713 availablePackage alp;
00714 fnpyKey * ret = NULL;
00715 const char * fileName;
00716
00717 if (keyp) *keyp = RPMAL_NOMATCH;
00718
00719 if (al == NULL || (fileName = rpmdsN(ds)) == NULL || *fileName != '/')
00720 return NULL;
00721
00722
00723 if (al->numDirs == 0 || al->dirs == NULL || al->list == NULL)
00724 return NULL;
00725
00726 { char * t;
00727 dirName = t = xstrdup(fileName);
00728 if ((t = strrchr(t, '/')) != NULL) {
00729 t++;
00730 *t = '\0';
00731 }
00732 }
00733
00734 dieNeedle->dirName = (char *) dirName;
00735 dieNeedle->dirNameLen = strlen(dirName);
00736 die = bsearch(dieNeedle, al->dirs, al->numDirs,
00737 sizeof(*dieNeedle), dieCompare);
00738 if (die == NULL)
00739 goto exit;
00740
00741
00742 while (die > al->dirs && dieCompare(die-1, dieNeedle) == 0)
00743 die--;
00744
00745 if ((baseName = strrchr(fileName, '/')) == NULL)
00746 goto exit;
00747 baseName++;
00748
00749
00750 for (found = 0, ret = NULL;
00751 die < al->dirs + al->numDirs && dieCompare(die, dieNeedle) == 0;
00752 die++)
00753 {
00754
00755
00756 if (_rpmal_debug)
00757 fprintf(stderr, "==> die %p %s\n", die, (die->dirName ? die->dirName : "(nil)"));
00758
00759
00760
00761 fieNeedle->baseName = baseName;
00762
00763 fieNeedle->baseNameLen = strlen(fieNeedle->baseName);
00764 fie = bsearch(fieNeedle, die->files, die->numFiles,
00765 sizeof(*fieNeedle), fieCompare);
00766 if (fie == NULL)
00767 continue;
00768
00769
00770 if (_rpmal_debug)
00771 fprintf(stderr, "==> fie %p %s\n", fie, (fie->baseName ? fie->baseName : "(nil)"));
00772
00773
00774 alp = al->list + fie->pkgNum;
00775
00776
00777 tscolor = alp->tscolor;
00778 ficolor = fie->ficolor;
00779 if (tscolor && ficolor && !(tscolor & ficolor))
00780 continue;
00781
00782 rpmdsNotify(ds, _("(added files)"), 0);
00783
00784 ret = xrealloc(ret, (found+2) * sizeof(*ret));
00785 if (ret)
00786 ret[found] = alp->key;
00787 if (keyp)
00788 *keyp = alNum2Key(al, fie->pkgNum);
00789 found++;
00790 }
00791
00792
00793 exit:
00794 dirName = _free(dirName);
00795 if (ret)
00796 ret[found] = NULL;
00797 return ret;
00798 }
00799
00800 fnpyKey *
00801 rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
00802 {
00803 availableIndex ai;
00804 availableIndexEntry needle;
00805 availableIndexEntry match;
00806 fnpyKey * ret = NULL;
00807 int found = 0;
00808 const char * KName;
00809 availablePackage alp;
00810 int rc;
00811
00812 if (keyp) *keyp = RPMAL_NOMATCH;
00813
00814 if (al == NULL || ds == NULL || (KName = rpmdsN(ds)) == NULL)
00815 return ret;
00816
00817 if (*KName == '/') {
00818
00819 ret = rpmalAllFileSatisfiesDepend(al, ds, keyp);
00820 if (ret != NULL && *ret != NULL)
00821 return ret;
00822 ret = _free(ret);
00823
00824 }
00825
00826 ai = &al->index;
00827 if (ai->index == NULL || ai->size <= 0)
00828 return NULL;
00829
00830 needle = memset(alloca(sizeof(*needle)), 0, sizeof(*needle));
00831
00832 needle->entry = KName;
00833
00834 needle->entryLen = strlen(needle->entry);
00835
00836 match = bsearch(needle, ai->index, ai->size, sizeof(*ai->index), indexcmp);
00837 if (match == NULL)
00838 return NULL;
00839
00840
00841 while (match > ai->index && indexcmp(match-1, needle) == 0)
00842 match--;
00843
00844 if (al->list != NULL)
00845 for (ret = NULL, found = 0;
00846 match < ai->index + ai->size && indexcmp(match, needle) == 0;
00847 match++)
00848 {
00849 alp = al->list + alKey2Num(al, match->pkgKey);
00850
00851 rc = 0;
00852 if (alp->provides != NULL)
00853 switch (match->type) {
00854 case IET_PROVIDES:
00855
00856 (void) rpmdsSetIx(alp->provides, match->entryIx - 1);
00857 if (rpmdsNext(alp->provides) >= 0)
00858 rc = rpmdsCompare(alp->provides, ds);
00859
00860 if (rc)
00861 rpmdsNotify(ds, _("(added provide)"), 0);
00862
00863 break;
00864 }
00865
00866
00867 if (rc) {
00868 ret = xrealloc(ret, (found + 2) * sizeof(*ret));
00869 if (ret)
00870 ret[found] = alp->key;
00871
00872 if (keyp)
00873 *keyp = match->pkgKey;
00874
00875 found++;
00876 }
00877
00878 }
00879
00880 if (ret)
00881 ret[found] = NULL;
00882
00883
00884 return ret;
00885
00886 }
00887
00888 fnpyKey
00889 rpmalSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
00890 {
00891 fnpyKey * tmp = rpmalAllSatisfiesDepend(al, ds, keyp);
00892
00893 if (tmp) {
00894 fnpyKey ret = tmp[0];
00895 free(tmp);
00896 return ret;
00897 }
00898 return NULL;
00899 }