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