rpm  4.5
lib/rpmal.c
Go to the documentation of this file.
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 }