• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

lib/rpmal.c

Go to the documentation of this file.
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 }

Generated on Fri Dec 3 2010 20:53:29 for rpm by  doxygen 1.7.2