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