rpm
5.2.1
|
00001 00005 #include "system.h" 00006 00007 #include <rpmio.h> 00008 #include <rpmiotypes.h> /* XXX fnpyKey */ 00009 00010 #include <rpmtag.h> 00011 #include <rpmtypes.h> 00012 00013 #define _RPMDS_INTERNAL 00014 #include <rpmds.h> 00015 #include <rpmal.h> 00016 00017 #include "debug.h" 00018 00019 typedef /*@abstract@*/ struct availablePackage_s * availablePackage; 00020 00021 /*@access alKey @*/ 00022 /*@access alNum @*/ 00023 /*@access rpmal @*/ 00024 /*@access rpmds @*/ 00025 /*@access availablePackage @*/ 00026 00027 /*@access fnpyKey @*/ /* XXX suggestedKeys array */ 00028 00032 struct availablePackage_s { 00033 /*@refcounted@*/ /*@null@*/ 00034 rpmds provides; 00035 /*@refcounted@*/ /*@null@*/ 00036 rpmfi fi; 00038 rpmuint32_t tscolor; 00040 /*@exposed@*/ /*@dependent@*/ /*@null@*/ 00041 fnpyKey key; 00043 }; 00044 00045 typedef /*@abstract@*/ struct availableIndexEntry_s * availableIndexEntry; 00046 /*@access availableIndexEntry@*/ 00047 00051 struct availableIndexEntry_s { 00052 /*@exposed@*/ /*@dependent@*/ /*@null@*/ 00053 alKey pkgKey; 00054 /*@observer@*/ 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 /*@abstract@*/ struct availableIndex_s * availableIndex; 00064 /*@access availableIndex@*/ 00065 00069 struct availableIndex_s { 00070 /*@null@*/ 00071 availableIndexEntry index; 00072 int size; 00073 int k; 00074 }; 00075 00076 typedef /*@abstract@*/ struct fileIndexEntry_s * fileIndexEntry; 00077 /*@access fileIndexEntry@*/ 00078 00082 struct fileIndexEntry_s { 00083 /*@dependent@*/ /*@relnull@*/ 00084 const char * baseName; 00085 size_t baseNameLen; 00086 alNum pkgNum; 00087 rpmuint32_t ficolor; 00088 }; 00089 00090 typedef /*@abstract@*/ struct dirInfo_s * dirInfo; 00091 /*@access dirInfo@*/ 00092 00096 struct dirInfo_s { 00097 /*@owned@*/ /*@relnull@*/ 00098 const char * dirName; 00099 size_t dirNameLen; 00100 /*@owned@*/ 00101 fileIndexEntry files; 00102 int numFiles; 00103 }; 00104 00108 struct rpmal_s { 00109 /*@owned@*/ /*@null@*/ 00110 availablePackage list; 00111 struct availableIndex_s index; 00112 int delta; 00113 int size; 00114 int alloced; 00115 rpmuint32_t tscolor; 00116 int numDirs; 00117 /*@owned@*/ /*@null@*/ 00118 dirInfo dirs; 00119 }; 00120 00125 static void rpmalFreeIndex(rpmal al) 00126 /*@modifies al @*/ 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 static inline alNum alKey2Num(/*@unused@*/ /*@null@*/ const rpmal al, 00136 /*@null@*/ alKey pkgKey) 00137 /*@*/ 00138 { 00139 /*@-nullret -temptrans -retalias @*/ 00140 union { alKey key; alNum num; } u; 00141 u.num = 0; 00142 u.key = pkgKey; 00143 return u.num; 00144 /*@=nullret =temptrans =retalias @*/ 00145 } 00146 00147 static inline alKey alNum2Key(/*@unused@*/ /*@null@*/ const rpmal al, 00148 /*@null@*/ alNum pkgNum) 00149 /*@*/ 00150 { 00151 /*@-nullret -temptrans -retalias @*/ 00152 union { alKey key; alNum num; } u; 00153 u.key = 0; 00154 u.num = pkgNum; 00155 return u.key; 00156 /*@=nullret =temptrans =retalias @*/ 00157 } 00158 00159 rpmal rpmalCreate(int delta) 00160 { 00161 rpmal al = xcalloc(1, sizeof(*al)); 00162 availableIndex ai = &al->index; 00163 00164 al->delta = delta; 00165 al->size = 0; 00166 al->list = xcalloc(al->delta, sizeof(*al->list)); 00167 al->alloced = al->delta; 00168 00169 ai->index = NULL; 00170 ai->size = 0; 00171 00172 al->numDirs = 0; 00173 al->dirs = NULL; 00174 return al; 00175 } 00176 00177 rpmal rpmalFree(rpmal al) 00178 { 00179 availablePackage alp; 00180 dirInfo die; 00181 int i; 00182 00183 if (al == NULL) 00184 return NULL; 00185 00186 if ((alp = al->list) != NULL) 00187 for (i = 0; i < al->size; i++, alp++) { 00188 (void)rpmdsFree(alp->provides); 00189 alp->provides = NULL; 00190 alp->fi = rpmfiFree(alp->fi); 00191 } 00192 00193 if ((die = al->dirs) != NULL) 00194 for (i = 0; i < al->numDirs; i++, die++) { 00195 die->dirName = _free(die->dirName); 00196 die->files = _free(die->files); 00197 } 00198 al->dirs = _free(al->dirs); 00199 al->numDirs = 0; 00200 00201 al->list = _free(al->list); 00202 al->alloced = 0; 00203 rpmalFreeIndex(al); 00204 al = _free(al); 00205 return NULL; 00206 } 00207 00214 static int dieCompare(const void * one, const void * two) 00215 /*@*/ 00216 { 00217 /*@-castexpose@*/ 00218 const dirInfo a = (const dirInfo) one; 00219 const dirInfo b = (const dirInfo) two; 00220 /*@=castexpose@*/ 00221 int lenchk = (int)a->dirNameLen - (int)b->dirNameLen; 00222 00223 if (lenchk || a->dirNameLen == 0) 00224 return lenchk; 00225 00226 if (a->dirName == NULL || b->dirName == NULL) 00227 return lenchk; 00228 00229 /* XXX FIXME: this might do "backward" strcmp for speed */ 00230 return strcmp(a->dirName, b->dirName); 00231 } 00232 00239 static int fieCompare(const void * one, const void * two) 00240 /*@*/ 00241 { 00242 /*@-castexpose@*/ 00243 const fileIndexEntry a = (const fileIndexEntry) one; 00244 const fileIndexEntry b = (const fileIndexEntry) two; 00245 /*@=castexpose@*/ 00246 int lenchk = (int)a->baseNameLen - (int)b->baseNameLen; 00247 00248 if (lenchk) 00249 return lenchk; 00250 00251 if (a->baseName == NULL || b->baseName == NULL) 00252 return lenchk; 00253 00254 return strcmp(a->baseName, b->baseName); 00255 } 00256 00257 void rpmalDel(rpmal al, alKey pkgKey) 00258 { 00259 alNum pkgNum = alKey2Num(al, pkgKey); 00260 availablePackage alp; 00261 rpmfi fi; 00262 00263 if (al == NULL || al->list == NULL) 00264 return; /* XXX can't happen */ 00265 00266 alp = al->list + pkgNum; 00267 00268 /* Delete directory/file info entries from added package list. */ 00269 if ((fi = alp->fi) != NULL) 00270 if (rpmfiFC(fi) > 0) { 00271 int origNumDirs = al->numDirs; 00272 int dx; 00273 dirInfo dieNeedle = 00274 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle)); 00275 dirInfo die; 00276 int last; 00277 int i; 00278 00279 /* XXX FIXME: We ought to relocate the directory list here */ 00280 00281 if (al->dirs != NULL) 00282 for (dx = rpmfiDC(fi) - 1; dx >= 0; dx--) 00283 { 00284 fileIndexEntry fie; 00285 00286 (void) rpmfiSetDX(fi, dx); 00287 00288 /*@-assignexpose -dependenttrans -observertrans@*/ 00289 dieNeedle->dirName = (char *) rpmfiDN(fi); 00290 /*@=assignexpose =dependenttrans =observertrans@*/ 00291 dieNeedle->dirNameLen = (dieNeedle->dirName != NULL 00292 ? strlen(dieNeedle->dirName) : 0); 00293 die = bsearch(dieNeedle, al->dirs, al->numDirs, 00294 sizeof(*dieNeedle), dieCompare); 00295 if (die == NULL) 00296 continue; 00297 00298 last = die->numFiles; 00299 fie = die->files + last - 1; 00300 for (i = last - 1; i >= 0; i--, fie--) { 00301 if (fie->pkgNum != pkgNum) 00302 /*@innercontinue@*/ continue; 00303 die->numFiles--; 00304 00305 if (i < die->numFiles) 00306 memmove(fie, fie+1, (die->numFiles - i) * sizeof(*fie)); 00307 memset(die->files + die->numFiles, 0, sizeof(*fie)); /* overkill */ 00308 00309 } 00310 if (die->numFiles > 0) { 00311 if (last > i) 00312 die->files = xrealloc(die->files, 00313 die->numFiles * sizeof(*die->files)); 00314 continue; 00315 } 00316 die->files = _free(die->files); 00317 die->dirName = _free(die->dirName); 00318 al->numDirs--; 00319 if ((die - al->dirs) < al->numDirs) 00320 memmove(die, die+1, (al->numDirs - (die - al->dirs)) * sizeof(*die)); 00321 00322 memset(al->dirs + al->numDirs, 0, sizeof(*al->dirs)); /* overkill */ 00323 } 00324 00325 if (origNumDirs > al->numDirs) { 00326 if (al->numDirs > 0) 00327 al->dirs = xrealloc(al->dirs, al->numDirs * sizeof(*al->dirs)); 00328 else 00329 al->dirs = _free(al->dirs); 00330 } 00331 } 00332 00333 (void)rpmdsFree(alp->provides); 00334 alp->provides = NULL; 00335 alp->fi = rpmfiFree(alp->fi); 00336 00337 memset(alp, 0, sizeof(*alp)); /* XXX trash and burn */ 00338 return; 00339 } 00340 00341 alKey rpmalAdd(rpmal * alistp, alKey pkgKey, fnpyKey key, 00342 rpmds provides, rpmfi fi, rpmuint32_t tscolor) 00343 { 00344 alNum pkgNum; 00345 rpmal al; 00346 availablePackage alp; 00347 00348 /* If list doesn't exist yet, create. */ 00349 if (*alistp == NULL) 00350 *alistp = rpmalCreate(5); 00351 al = *alistp; 00352 pkgNum = alKey2Num(al, pkgKey); 00353 00354 if (pkgNum >= 0 && pkgNum < al->size) { 00355 rpmalDel(al, pkgKey); 00356 } else { 00357 if (al->size == al->alloced) { 00358 al->alloced += al->delta; 00359 al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced); 00360 } 00361 pkgNum = al->size++; 00362 } 00363 00364 if (al->list == NULL) 00365 return RPMAL_NOMATCH; /* XXX can't happen */ 00366 00367 alp = al->list + pkgNum; 00368 00369 alp->key = key; 00370 alp->tscolor = tscolor; 00371 00372 /*@-assignexpose -castexpose @*/ 00373 alp->provides = rpmdsLink(provides, "Provides (rpmalAdd)"); 00374 alp->fi = rpmfiLink(fi, "Files (rpmalAdd)"); 00375 /*@=assignexpose =castexpose @*/ 00376 00377 /*@-castexpose@*/ 00378 fi = rpmfiLink(alp->fi, "Files index (rpmalAdd)"); 00379 /*@=castexpose@*/ 00380 fi = rpmfiInit(fi, 0); 00381 if (rpmfiFC(fi) > 0) { 00382 dirInfo dieNeedle = 00383 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle)); 00384 dirInfo die; 00385 int dc = rpmfiDC(fi); 00386 int dx; 00387 int * dirMapping = alloca(sizeof(*dirMapping) * dc); 00388 int * dirUnique = alloca(sizeof(*dirUnique) * dc); 00389 const char * DN; 00390 int origNumDirs; 00391 int first; 00392 00393 /* XXX FIXME: We ought to relocate the directory list here */ 00394 00395 /* XXX enough space for all directories, late realloc to truncate. */ 00396 al->dirs = xrealloc(al->dirs, (al->numDirs + dc) * sizeof(*al->dirs)); 00397 00398 /* Only previously allocated dirInfo is sorted and bsearch'able. */ 00399 origNumDirs = al->numDirs; 00400 00401 /* Package dirnames are not currently unique. Create unique mapping. */ 00402 for (dx = 0; dx < dc; dx++) { 00403 int i = 0; 00404 (void) rpmfiSetDX(fi, dx); 00405 DN = rpmfiDN(fi); 00406 if (DN != NULL) 00407 for (i = 0; i < dx; i++) { 00408 const char * iDN; 00409 (void) rpmfiSetDX(fi, i); 00410 iDN = rpmfiDN(fi); 00411 if (iDN != NULL && !strcmp(DN, iDN)) 00412 /*@innerbreak@*/ break; 00413 } 00414 dirUnique[dx] = i; 00415 } 00416 00417 /* Map package dirs into transaction dirInfo index. */ 00418 for (dx = 0; dx < dc; dx++) { 00419 00420 /* Non-unique package dirs use the 1st entry mapping. */ 00421 if (dirUnique[dx] < dx) { 00422 dirMapping[dx] = dirMapping[dirUnique[dx]]; 00423 continue; 00424 } 00425 00426 /* Find global dirInfo mapping for first encounter. */ 00427 (void) rpmfiSetDX(fi, dx); 00428 00429 /*@-assignexpose -dependenttrans -observertrans@*/ 00430 dieNeedle->dirName = rpmfiDN(fi); 00431 /*@=assignexpose =dependenttrans =observertrans@*/ 00432 00433 dieNeedle->dirNameLen = (dieNeedle->dirName != NULL 00434 ? strlen(dieNeedle->dirName) : 0); 00435 die = bsearch(dieNeedle, al->dirs, origNumDirs, 00436 sizeof(*dieNeedle), dieCompare); 00437 if (die) { 00438 dirMapping[dx] = die - al->dirs; 00439 } else { 00440 dirMapping[dx] = al->numDirs; 00441 die = al->dirs + al->numDirs; 00442 if (dieNeedle->dirName != NULL) 00443 die->dirName = xstrdup(dieNeedle->dirName); 00444 die->dirNameLen = dieNeedle->dirNameLen; 00445 die->files = NULL; 00446 die->numFiles = 0; 00447 00448 al->numDirs++; 00449 } 00450 } 00451 00452 for (first = rpmfiNext(fi); first >= 0;) { 00453 fileIndexEntry fie; 00454 int next; 00455 00456 /* Find the first file of the next directory. */ 00457 dx = rpmfiDX(fi); 00458 while ((next = rpmfiNext(fi)) >= 0) { 00459 if (dx != rpmfiDX(fi)) 00460 /*@innerbreak@*/ break; 00461 } 00462 if (next < 0) next = rpmfiFC(fi); /* XXX reset end-of-list */ 00463 00464 die = al->dirs + dirMapping[dx]; 00465 die->files = xrealloc(die->files, 00466 (die->numFiles + next - first) * sizeof(*die->files)); 00467 00468 fie = die->files + die->numFiles; 00469 00470 /* Rewind to first file, generate file index entry for each file. */ 00471 fi = rpmfiInit(fi, first); 00472 while ((first = rpmfiNext(fi)) >= 0 && first < next) { 00473 /*@-assignexpose -dependenttrans -observertrans @*/ 00474 fie->baseName = rpmfiBN(fi); 00475 /*@=assignexpose =dependenttrans =observertrans @*/ 00476 fie->baseNameLen = (fie->baseName ? strlen(fie->baseName) : 0); 00477 fie->pkgNum = pkgNum; 00478 fie->ficolor = rpmfiFColor(fi); 00479 00480 die->numFiles++; 00481 fie++; 00482 } 00483 qsort(die->files, die->numFiles, sizeof(*die->files), fieCompare); 00484 } 00485 00486 /* Resize the directory list. If any directories were added, resort. */ 00487 al->dirs = xrealloc(al->dirs, al->numDirs * sizeof(*al->dirs)); 00488 if (origNumDirs != al->numDirs) 00489 qsort(al->dirs, al->numDirs, sizeof(*al->dirs), dieCompare); 00490 } 00491 fi = rpmfiUnlink(fi, "Files index (rpmalAdd)"); 00492 00493 rpmalFreeIndex(al); 00494 00495 assert(((alNum)(alp - al->list)) == pkgNum); 00496 return ((alKey)(alp - al->list)); 00497 } 00498 00505 static int indexcmp(const void * one, const void * two) 00506 /*@*/ 00507 { 00508 /*@-castexpose@*/ 00509 const availableIndexEntry a = (const availableIndexEntry) one; 00510 const availableIndexEntry b = (const availableIndexEntry) two; 00511 /*@=castexpose@*/ 00512 int lenchk; 00513 00514 lenchk = a->entryLen - b->entryLen; 00515 if (lenchk) 00516 return lenchk; 00517 00518 return strcmp(a->entry, b->entry); 00519 } 00520 00521 void rpmalAddProvides(rpmal al, alKey pkgKey, rpmds provides, rpmuint32_t tscolor) 00522 { 00523 rpmuint32_t dscolor; 00524 const char * Name; 00525 alNum pkgNum = alKey2Num(al, pkgKey); 00526 availableIndex ai = &al->index; 00527 availableIndexEntry aie; 00528 int ix; 00529 00530 if (provides == NULL || pkgNum < 0 || pkgNum >= al->size) 00531 return; 00532 if (ai->index == NULL || ai->k < 0 || ai->k >= ai->size) 00533 return; 00534 00535 if (rpmdsInit(provides) != NULL) 00536 while (rpmdsNext(provides) >= 0) { 00537 00538 if ((Name = provides->N[provides->i]) == NULL) 00539 continue; /* XXX can't happen */ 00540 00541 /* Ignore colored provides not in our rainbow. */ 00542 dscolor = rpmdsColor(provides); 00543 if (tscolor && dscolor && !(tscolor & dscolor)) 00544 continue; 00545 00546 aie = ai->index + ai->k; 00547 ai->k++; 00548 00549 aie->pkgKey = pkgKey; 00550 /*@-assignexpose@*/ 00551 aie->entry = Name; 00552 /*@=assignexpose@*/ 00553 aie->entryLen = (unsigned short)strlen(Name); 00554 ix = rpmdsIx(provides); 00555 00556 /* XXX make sure that element index fits in unsigned short */ 00557 assert(ix < 0x10000); 00558 00559 aie->entryIx = ix; 00560 aie->type = IET_PROVIDES; 00561 } 00562 } 00563 00564 void rpmalMakeIndex(rpmal al) 00565 { 00566 availableIndex ai; 00567 availablePackage alp; 00568 int i; 00569 00570 if (al == NULL || al->list == NULL) return; 00571 ai = &al->index; 00572 00573 ai->size = 0; 00574 for (i = 0; i < al->size; i++) { 00575 alp = al->list + i; 00576 if (alp->provides != NULL) 00577 ai->size += rpmdsCount(alp->provides); 00578 } 00579 if (ai->size == 0) return; 00580 00581 ai->index = xrealloc(ai->index, ai->size * sizeof(*ai->index)); 00582 ai->k = 0; 00583 for (i = 0; i < al->size; i++) { 00584 alp = al->list + i; 00585 rpmalAddProvides(al, alNum2Key(NULL, (alNum)i), alp->provides, alp->tscolor); 00586 } 00587 00588 /* Reset size to the no. of provides added. */ 00589 ai->size = ai->k; 00590 qsort(ai->index, ai->size, sizeof(*ai->index), indexcmp); 00591 } 00592 00593 fnpyKey * 00594 rpmalAllFileSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp) 00595 { 00596 rpmuint32_t tscolor; 00597 rpmuint32_t ficolor; 00598 int found = 0; 00599 const char * dirName; 00600 const char * baseName; 00601 dirInfo dieNeedle = 00602 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle)); 00603 dirInfo die; 00604 fileIndexEntry fieNeedle = 00605 memset(alloca(sizeof(*fieNeedle)), 0, sizeof(*fieNeedle)); 00606 fileIndexEntry fie; 00607 availablePackage alp; 00608 fnpyKey * ret = NULL; 00609 const char * fileName; 00610 00611 if (keyp) *keyp = RPMAL_NOMATCH; 00612 00613 if (al == NULL || (fileName = rpmdsN(ds)) == NULL || *fileName != '/') 00614 return NULL; 00615 00616 /* Solaris 2.6 bsearch sucks down on this. */ 00617 if (al->numDirs == 0 || al->dirs == NULL || al->list == NULL) 00618 return NULL; 00619 00620 { char * t; 00621 dirName = t = xstrdup(fileName); 00622 if ((t = strrchr(t, '/')) != NULL) { 00623 t++; /* leave the trailing '/' */ 00624 *t = '\0'; 00625 } 00626 } 00627 00628 dieNeedle->dirName = (char *) dirName; 00629 dieNeedle->dirNameLen = strlen(dirName); 00630 die = bsearch(dieNeedle, al->dirs, al->numDirs, 00631 sizeof(*dieNeedle), dieCompare); 00632 if (die == NULL) 00633 goto exit; 00634 00635 /* rewind to the first match */ 00636 while (die > al->dirs && dieCompare(die-1, dieNeedle) == 0) 00637 die--; 00638 00639 if ((baseName = strrchr(fileName, '/')) == NULL) 00640 goto exit; 00641 baseName++; 00642 00643 for (found = 0, ret = NULL; 00644 die < al->dirs + al->numDirs && dieCompare(die, dieNeedle) == 0; 00645 die++) 00646 { 00647 00648 /*@-observertrans@*/ 00649 fieNeedle->baseName = baseName; 00650 /*@=observertrans@*/ 00651 fieNeedle->baseNameLen = strlen(fieNeedle->baseName); 00652 fie = bsearch(fieNeedle, die->files, die->numFiles, 00653 sizeof(*fieNeedle), fieCompare); 00654 if (fie == NULL) 00655 continue; /* XXX shouldn't happen */ 00656 00657 alp = al->list + fie->pkgNum; 00658 00659 /* Ignore colored files not in our rainbow. */ 00660 tscolor = alp->tscolor; 00661 ficolor = fie->ficolor; 00662 if (tscolor && ficolor && !(tscolor & ficolor)) 00663 continue; 00664 00665 rpmdsNotify(ds, _("(added files)"), 0); 00666 00667 ret = xrealloc(ret, (found+2) * sizeof(*ret)); 00668 if (ret) /* can't happen */ 00669 ret[found] = alp->key; 00670 if (keyp) 00671 *keyp = alNum2Key(al, fie->pkgNum); 00672 found++; 00673 } 00674 00675 exit: 00676 dirName = _free(dirName); 00677 if (ret) 00678 ret[found] = NULL; 00679 return ret; 00680 } 00681 00682 fnpyKey * 00683 rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp) 00684 { 00685 availableIndex ai; 00686 availableIndexEntry needle; 00687 availableIndexEntry match; 00688 fnpyKey * ret = NULL; 00689 int found = 0; 00690 const char * KName; 00691 availablePackage alp; 00692 int rc; 00693 00694 if (keyp) *keyp = RPMAL_NOMATCH; 00695 00696 if (al == NULL || ds == NULL || (KName = rpmdsN(ds)) == NULL) 00697 return ret; 00698 00699 if (*KName == '/') { 00700 /* First, look for files "contained" in package ... */ 00701 ret = rpmalAllFileSatisfiesDepend(al, ds, keyp); 00702 if (ret != NULL && *ret != NULL) 00703 return ret; 00704 ret = _free(ret); 00705 /* ... then, look for files "provided" by package. */ 00706 } 00707 00708 ai = &al->index; 00709 if (ai->index == NULL || ai->size <= 0) 00710 return NULL; 00711 00712 needle = memset(alloca(sizeof(*needle)), 0, sizeof(*needle)); 00713 /*@-assignexpose -temptrans@*/ 00714 needle->entry = KName; 00715 /*@=assignexpose =temptrans@*/ 00716 needle->entryLen = (unsigned short)strlen(needle->entry); 00717 00718 match = bsearch(needle, ai->index, ai->size, sizeof(*ai->index), indexcmp); 00719 if (match == NULL) 00720 return NULL; 00721 00722 /* rewind to the first match */ 00723 while (match > ai->index && indexcmp(match-1, needle) == 0) 00724 match--; 00725 00726 if (al->list != NULL) /* XXX always true */ 00727 for (ret = NULL, found = 0; 00728 match < ai->index + ai->size && indexcmp(match, needle) == 0; 00729 match++) 00730 { 00731 alp = al->list + alKey2Num(al, match->pkgKey); 00732 00733 rc = 0; 00734 if (alp->provides != NULL) /* XXX can't happen */ 00735 switch (match->type) { 00736 case IET_PROVIDES: 00737 /* XXX single step on rpmdsNext to regenerate DNEVR string */ 00738 (void) rpmdsSetIx(alp->provides, match->entryIx - 1); 00739 if (rpmdsNext(alp->provides) >= 0) 00740 rc = rpmdsCompare(alp->provides, ds); 00741 00742 if (rc) 00743 rpmdsNotify(ds, _("(added provide)"), 0); 00744 00745 /*@switchbreak@*/ break; 00746 } 00747 00748 if (rc) { 00749 ret = xrealloc(ret, (found + 2) * sizeof(*ret)); 00750 if (ret) /* can't happen */ 00751 ret[found] = alp->key; 00752 /*@-dependenttrans@*/ 00753 if (keyp) 00754 *keyp = match->pkgKey; 00755 /*@=dependenttrans@*/ 00756 found++; 00757 } 00758 } 00759 00760 if (ret) 00761 ret[found] = NULL; 00762 00763 /*@-nullstate@*/ /* FIX: *keyp may be NULL */ 00764 return ret; 00765 /*@=nullstate@*/ 00766 } 00767 00768 fnpyKey 00769 rpmalSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp) 00770 { 00771 fnpyKey * tmp = rpmalAllSatisfiesDepend(al, ds, keyp); 00772 00773 if (tmp) { 00774 fnpyKey ret = tmp[0]; 00775 free(tmp); 00776 return ret; 00777 } 00778 return NULL; 00779 }