rpm
4.5
|
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 /*@abstract@*/ struct availablePackage_s * availablePackage; 00017 00018 /*@unchecked@*/ 00019 int _rpmal_debug = 0; 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 uint_32 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 int baseNameLen; 00086 alNum pkgNum; 00087 uint_32 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 int 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 uint_32 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 #ifdef DYING 00136 00141 static int alGetSize(/*@null@*/ const rpmal al) 00142 /*@*/ 00143 { 00144 return (al != NULL ? al->size : 0); 00145 } 00146 #endif 00147 00148 static inline alNum alKey2Num(/*@unused@*/ /*@null@*/ const rpmal al, 00149 /*@null@*/ alKey pkgKey) 00150 /*@*/ 00151 { 00152 /*@-nullret -temptrans -retalias @*/ 00153 return ((alNum)pkgKey); 00154 /*@=nullret =temptrans =retalias @*/ 00155 } 00156 00157 static inline alKey alNum2Key(/*@unused@*/ /*@null@*/ const rpmal al, 00158 /*@null@*/ alNum pkgNum) 00159 /*@*/ 00160 { 00161 /*@-nullret -temptrans -retalias @*/ 00162 return ((alKey)pkgNum); 00163 /*@=nullret =temptrans =retalias @*/ 00164 } 00165 00166 #ifdef DYING 00167 00173 /*@dependent@*/ /*@null@*/ 00174 static availablePackage alGetPkg(/*@null@*/ const rpmal al, 00175 /*@null@*/ 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 /*@-castexpose@*/ 00247 const dirInfo a = (const dirInfo) one; 00248 const dirInfo b = (const dirInfo) two; 00249 /*@=castexpose@*/ 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 /* XXX FIXME: this might do "backward" strcmp for speed */ 00259 return strcmp(a->dirName, b->dirName); 00260 } 00261 00268 static int fieCompare(const void * one, const void * two) 00269 /*@*/ 00270 { 00271 /*@-castexpose@*/ 00272 const fileIndexEntry a = (const fileIndexEntry) one; 00273 const fileIndexEntry b = (const fileIndexEntry) two; 00274 /*@=castexpose@*/ 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 /*@-modfilesys@*/ 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 /*@=modfilesys@*/ 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; /* XXX can't happen */ 00307 00308 alp = al->list + pkgNum; 00309 00310 /*@-modfilesys@*/ 00311 if (_rpmal_debug) 00312 fprintf(stderr, "*** del %p[%d]\n", al->list, pkgNum); 00313 /*@=modfilesys@*/ 00314 00315 /* Delete directory/file info entries from added package list. */ 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 /* XXX FIXME: We ought to relocate the directory list here */ 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 /*@-assignexpose -dependenttrans -observertrans@*/ 00336 dieNeedle->dirName = (char *) rpmfiDN(fi); 00337 /*@=assignexpose =dependenttrans =observertrans@*/ 00338 dieNeedle->dirNameLen = (dieNeedle->dirName != NULL 00339 ? strlen(dieNeedle->dirName) : 0); 00340 /*@-boundswrite@*/ 00341 die = bsearch(dieNeedle, al->dirs, al->numDirs, 00342 sizeof(*dieNeedle), dieCompare); 00343 /*@=boundswrite@*/ 00344 if (die == NULL) 00345 continue; 00346 00347 /*@-modfilesys@*/ 00348 if (_rpmal_debug) 00349 fprintf(stderr, "--- die[%5d] %p [%3d] %s\n", (int)(die - al->dirs), die, die->dirNameLen, die->dirName); 00350 /*@=modfilesys@*/ 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 /*@innercontinue@*/ continue; 00357 die->numFiles--; 00358 00359 if (i < die->numFiles) { 00360 /*@-modfilesys@*/ 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 /*@=modfilesys@*/ 00364 00365 /*@-bounds@*/ 00366 memmove(fie, fie+1, (die->numFiles - i) * sizeof(*fie)); 00367 /*@=bounds@*/ 00368 } 00369 /*@-modfilesys@*/ 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 /*@=modfilesys@*/ 00373 memset(die->files + die->numFiles, 0, sizeof(*fie)); /* overkill */ 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 /*@-modfilesys@*/ 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 /*@=modfilesys@*/ 00390 00391 /*@-bounds@*/ 00392 memmove(die, die+1, (al->numDirs - (die - al->dirs)) * sizeof(*die)); 00393 /*@=bounds@*/ 00394 } 00395 00396 /*@-modfilesys@*/ 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 /*@=modfilesys@*/ 00400 memset(al->dirs + al->numDirs, 0, sizeof(*al->dirs)); /* overkill */ 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 /*@-boundswrite@*/ 00415 memset(alp, 0, sizeof(*alp)); /* XXX trash and burn */ 00416 /*@=boundswrite@*/ 00417 return; 00418 } 00419 00420 /*@-bounds@*/ 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 /* If list doesn't exist yet, create. */ 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; /* XXX can't happen */ 00446 00447 alp = al->list + pkgNum; 00448 00449 alp->key = key; 00450 alp->tscolor = tscolor; 00451 00452 /*@-modfilesys@*/ 00453 if (_rpmal_debug) 00454 fprintf(stderr, "*** add %p[%d] 0x%x\n", al->list, pkgNum, tscolor); 00455 /*@=modfilesys@*/ 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 /* XXX FIXME: We ought to relocate the directory list here */ 00475 00476 /* XXX enough space for all directories, late realloc to truncate. */ 00477 al->dirs = xrealloc(al->dirs, (al->numDirs + dc) * sizeof(*al->dirs)); 00478 00479 /* Only previously allocated dirInfo is sorted and bsearch'able. */ 00480 origNumDirs = al->numDirs; 00481 00482 /* Package dirnames are not currently unique. Create unique mapping. */ 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 /*@innerbreak@*/ break; 00494 } 00495 dirUnique[dx] = i; 00496 } 00497 00498 /* Map package dirs into transaction dirInfo index. */ 00499 for (dx = 0; dx < dc; dx++) { 00500 00501 /* Non-unique package dirs use the 1st entry mapping. */ 00502 if (dirUnique[dx] < dx) { 00503 dirMapping[dx] = dirMapping[dirUnique[dx]]; 00504 continue; 00505 } 00506 00507 /* Find global dirInfo mapping for first encounter. */ 00508 (void) rpmfiSetDX(fi, dx); 00509 00510 /*@-assignexpose -dependenttrans -observertrans@*/ 00511 { DN = rpmfiDN(fi); 00512 00513 #if defined(__ia64__) 00514 /* XXX Make sure that autorelocated file dependencies are satisfied. */ 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 /*@=assignexpose =dependenttrans =observertrans@*/ 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 /*@-modfilesys@*/ 00538 if (_rpmal_debug) 00539 fprintf(stderr, "+++ die[%5d] %p [%3d] %s\n", al->numDirs, die, die->dirNameLen, die->dirName); 00540 /*@=modfilesys@*/ 00541 00542 al->numDirs++; 00543 } 00544 } 00545 00546 for (first = rpmfiNext(fi); first >= 0;) { 00547 fileIndexEntry fie; 00548 int next; 00549 00550 /* Find the first file of the next directory. */ 00551 dx = rpmfiDX(fi); 00552 while ((next = rpmfiNext(fi)) >= 0) { 00553 if (dx != rpmfiDX(fi)) 00554 /*@innerbreak@*/ break; 00555 } 00556 if (next < 0) next = rpmfiFC(fi); /* XXX reset end-of-list */ 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 /*@-modfilesys@*/ 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 /*@=modfilesys@*/ 00570 00571 /* Rewind to first file, generate file index entry for each file. */ 00572 fi = rpmfiInit(fi, first); 00573 while ((first = rpmfiNext(fi)) >= 0 && first < next) { 00574 /*@-assignexpose -dependenttrans -observertrans @*/ 00575 fie->baseName = rpmfiBN(fi); 00576 /*@=assignexpose =dependenttrans =observertrans @*/ 00577 fie->baseNameLen = (fie->baseName ? strlen(fie->baseName) : 0); 00578 fie->pkgNum = pkgNum; 00579 fie->ficolor = rpmfiFColor(fi); 00580 /*@-modfilesys@*/ 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 /*@=modfilesys@*/ 00584 00585 die->numFiles++; 00586 fie++; 00587 } 00588 qsort(die->files, die->numFiles, sizeof(*die->files), fieCompare); 00589 } 00590 00591 /* Resize the directory list. If any directories were added, resort. */ 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 /*@=bounds@*/ 00604 00611 static int indexcmp(const void * one, const void * two) 00612 /*@*/ 00613 { 00614 /*@-castexpose@*/ 00615 const availableIndexEntry a = (const availableIndexEntry) one; 00616 const availableIndexEntry b = (const availableIndexEntry) two; 00617 /*@=castexpose@*/ 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; /* XXX can't happen */ 00646 00647 /* Ignore colored provides not in our rainbow. */ 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 /*@-assignexpose@*/ 00657 aie->entry = Name; 00658 /*@=assignexpose@*/ 00659 aie->entryLen = strlen(Name); 00660 ix = rpmdsIx(provides); 00661 00662 /* XXX make sure that element index fits in unsigned short */ 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 /* Reset size to the no. of provides added. */ 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 /* Solaris 2.6 bsearch sucks down on this. */ 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++; /* leave the trailing '/' */ 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 /* rewind to the first match */ 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 /*@-branchstate@*/ /* FIX: ret is a problem */ 00750 for (found = 0, ret = NULL; 00751 die < al->dirs + al->numDirs && dieCompare(die, dieNeedle) == 0; 00752 die++) 00753 { 00754 00755 /*@-modfilesys@*/ 00756 if (_rpmal_debug) 00757 fprintf(stderr, "==> die %p %s\n", die, (die->dirName ? die->dirName : "(nil)")); 00758 /*@=modfilesys@*/ 00759 00760 /*@-observertrans@*/ 00761 fieNeedle->baseName = baseName; 00762 /*@=observertrans@*/ 00763 fieNeedle->baseNameLen = strlen(fieNeedle->baseName); 00764 fie = bsearch(fieNeedle, die->files, die->numFiles, 00765 sizeof(*fieNeedle), fieCompare); 00766 if (fie == NULL) 00767 continue; /* XXX shouldn't happen */ 00768 00769 /*@-modfilesys@*/ 00770 if (_rpmal_debug) 00771 fprintf(stderr, "==> fie %p %s\n", fie, (fie->baseName ? fie->baseName : "(nil)")); 00772 /*@=modfilesys@*/ 00773 00774 alp = al->list + fie->pkgNum; 00775 00776 /* Ignore colored files not in our rainbow. */ 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) /* can't happen */ 00786 ret[found] = alp->key; 00787 if (keyp) 00788 *keyp = alNum2Key(al, fie->pkgNum); 00789 found++; 00790 } 00791 /*@=branchstate@*/ 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 /* First, look for files "contained" in package ... */ 00819 ret = rpmalAllFileSatisfiesDepend(al, ds, keyp); 00820 if (ret != NULL && *ret != NULL) 00821 return ret; 00822 ret = _free(ret); 00823 /* ... then, look for files "provided" by package. */ 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 /*@-assignexpose -temptrans@*/ 00832 needle->entry = KName; 00833 /*@=assignexpose =temptrans@*/ 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 /* rewind to the first match */ 00841 while (match > ai->index && indexcmp(match-1, needle) == 0) 00842 match--; 00843 00844 if (al->list != NULL) /* XXX always true */ 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) /* XXX can't happen */ 00853 switch (match->type) { 00854 case IET_PROVIDES: 00855 /* XXX single step on rpmdsNext to regenerate DNEVR string */ 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 /*@switchbreak@*/ break; 00864 } 00865 00866 /*@-branchstate@*/ 00867 if (rc) { 00868 ret = xrealloc(ret, (found + 2) * sizeof(*ret)); 00869 if (ret) /* can't happen */ 00870 ret[found] = alp->key; 00871 /*@-dependenttrans@*/ 00872 if (keyp) 00873 *keyp = match->pkgKey; 00874 /*@=dependenttrans@*/ 00875 found++; 00876 } 00877 /*@=branchstate@*/ 00878 } 00879 00880 if (ret) 00881 ret[found] = NULL; 00882 00883 /*@-nullstate@*/ /* FIX: *keyp may be NULL */ 00884 return ret; 00885 /*@=nullstate@*/ 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 }