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