Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

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 #include "rpmds.h"
00011 #include "rpmfi.h"
00012 
00013 #include "debug.h"
00014 
00015 typedef /*@abstract@*/ struct availablePackage_s * availablePackage;
00016 
00017 /*@unchecked@*/
00018 int _rpmal_debug = 0;
00019 
00020 /*@access alKey @*/
00021 /*@access alNum @*/
00022 /*@access rpmal @*/
00023 /*@access availablePackage @*/
00024 
00025 /*@access fnpyKey @*/   /* XXX suggestedKeys array */
00026 
00030 struct availablePackage_s {
00031 /*@refcounted@*/ /*@null@*/
00032     rpmds provides;             
00033 /*@refcounted@*/ /*@null@*/
00034     rpmfi fi;                   
00036 #ifdef  DYING
00037     uint_32 multiLib;   /* MULTILIB */
00038 #endif
00039 
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@*/ /*@null@*/
00084     const char * baseName;      
00085     int baseNameLen;
00086     alNum pkgNum;               
00087     int fileFlags;      /* MULTILIB */
00088 };
00089 
00090 typedef /*@abstract@*/ struct dirInfo_s *               dirInfo;
00091 /*@access dirInfo@*/
00092 
00096 struct dirInfo_s {
00097 /*@owned@*/ /*@null@*/
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     int numDirs;                
00116 /*@owned@*/ /*@null@*/
00117     dirInfo dirs;               
00118 };
00119 
00124 static void rpmalFreeIndex(rpmal al)
00125         /*@modifies al @*/
00126 {
00127     availableIndex ai = &al->index;
00128     if (ai->size > 0) {
00129         ai->index = _free(ai->index);
00130         ai->size = 0;
00131     }
00132 }
00133 
00134 #ifdef  DYING
00135 
00140 static int alGetSize(/*@null@*/ const rpmal al)
00141         /*@*/
00142 {
00143     return (al != NULL ? al->size : 0);
00144 }
00145 #endif
00146 
00147 static inline alNum alKey2Num(/*@unused@*/ /*@null@*/ const rpmal al,
00148                 /*@null@*/ alKey pkgKey)
00149         /*@*/
00150 {
00151     /*@-nullret -temptrans -retalias @*/
00152     return ((alNum)pkgKey);
00153     /*@=nullret =temptrans =retalias @*/
00154 }
00155 
00156 static inline alKey alNum2Key(/*@unused@*/ /*@null@*/ const rpmal al,
00157                 /*@null@*/ alNum pkgNum)
00158         /*@*/
00159 {
00160     /*@-nullret -temptrans -retalias @*/
00161     return ((alKey)pkgNum);
00162     /*@=nullret =temptrans =retalias @*/
00163 }
00164 
00165 #ifdef  DYING
00166 
00172 /*@dependent@*/ /*@null@*/
00173 static availablePackage alGetPkg(/*@null@*/ const rpmal al,
00174                 /*@null@*/ alKey pkgKey)
00175         /*@*/
00176 {
00177     alNum pkgNum = alKey2Num(al, pkgKey);
00178     availablePackage alp = NULL;
00179 
00180     if (al != NULL && pkgNum >= 0 && pkgNum < alGetSize(al)) {
00181         if (al->list != NULL)
00182             alp = al->list + pkgNum;
00183     }
00184     return alp;
00185 }
00186 #endif
00187 
00188 rpmal rpmalCreate(int delta)
00189 {
00190     rpmal al = xcalloc(1, sizeof(*al));
00191     availableIndex ai = &al->index;
00192 
00193     al->delta = delta;
00194     al->size = 0;
00195     al->list = xcalloc(al->delta, sizeof(*al->list));
00196     al->alloced = al->delta;
00197 
00198     ai->index = NULL;
00199     ai->size = 0;
00200 
00201     al->numDirs = 0;
00202     al->dirs = NULL;
00203     return al;
00204 }
00205 
00206 rpmal rpmalFree(rpmal al)
00207 {
00208     availablePackage alp;
00209     dirInfo die;
00210     int i;
00211 
00212     if (al == NULL)
00213         return NULL;
00214 
00215     if ((alp = al->list) != NULL)
00216     for (i = 0; i < al->size; i++, alp++) {
00217         alp->provides = rpmdsFree(alp->provides);
00218         alp->fi = rpmfiFree(alp->fi);
00219     }
00220 
00221     if ((die = al->dirs) != NULL)
00222     for (i = 0; i < al->numDirs; i++, die++) {
00223         die->dirName = _free(die->dirName);
00224         die->files = _free(die->files);
00225     }
00226     al->dirs = _free(al->dirs);
00227     al->numDirs = 0;
00228 
00229     al->list = _free(al->list);
00230     al->alloced = 0;
00231     rpmalFreeIndex(al);
00232     al = _free(al);
00233     return NULL;
00234 }
00235 
00242 static int dieCompare(const void * one, const void * two)
00243         /*@*/
00244 {
00245     /*@-castexpose@*/
00246     const dirInfo a = (const dirInfo) one;
00247     const dirInfo b = (const dirInfo) two;
00248     /*@=castexpose@*/
00249     int lenchk = a->dirNameLen - b->dirNameLen;
00250 
00251     if (lenchk || a->dirNameLen == 0)
00252         return lenchk;
00253 
00254     if (a->dirName == NULL || b->dirName == NULL)
00255         return lenchk;
00256 
00257     /* XXX FIXME: this might do "backward" strcmp for speed */
00258     return strcmp(a->dirName, b->dirName);
00259 }
00260 
00267 static int fieCompare(const void * one, const void * two)
00268         /*@*/
00269 {
00270     /*@-castexpose@*/
00271     const fileIndexEntry a = (const fileIndexEntry) one;
00272     const fileIndexEntry b = (const fileIndexEntry) two;
00273     /*@=castexpose@*/
00274     int lenchk = a->baseNameLen - b->baseNameLen;
00275 
00276     if (lenchk)
00277         return lenchk;
00278 
00279     if (a->baseName == NULL || b->baseName == NULL)
00280         return lenchk;
00281 
00282     /* XXX FIXME: this might do "backward" strcmp for speed */
00283     return strcmp(a->baseName, b->baseName);
00284 }
00285 
00286 void rpmalDel(rpmal al, alKey pkgKey)
00287 {
00288     alNum pkgNum = alKey2Num(al, pkgKey);
00289     availablePackage alp;
00290     rpmfi fi;
00291 
00292     if (al == NULL || al->list == NULL)
00293         return;         /* XXX can't happen */
00294 
00295     alp = al->list + pkgNum;
00296 
00297 /*@-modfilesys@*/
00298 if (_rpmal_debug)
00299 fprintf(stderr, "*** del %p[%d]\n", al->list, pkgNum);
00300 /*@=modfilesys@*/
00301 
00302     /* Delete directory/file info entries from added package list. */
00303     if ((fi = alp->fi) != NULL)
00304     if (rpmfiFC(fi) > 0) {
00305         int origNumDirs = al->numDirs;
00306         int dx;
00307         dirInfo dieNeedle =
00308                 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
00309         dirInfo die;
00310         int last;
00311         int i;
00312 
00313         /* XXX FIXME: We ought to relocate the directory list here */
00314 
00315         if (al->dirs != NULL)
00316         for (dx = rpmfiDC(fi) - 1; dx >= 0; dx--)
00317         {
00318             fileIndexEntry fie;
00319 
00320             (void) rpmfiSetDX(fi, dx);
00321 
00322             /*@-assignexpose -dependenttrans -observertrans@*/
00323             dieNeedle->dirName = (char *) rpmfiDN(fi);
00324             /*@=assignexpose =dependenttrans =observertrans@*/
00325             dieNeedle->dirNameLen = (dieNeedle->dirName != NULL
00326                         ? strlen(dieNeedle->dirName) : 0);
00327 /*@-boundswrite@*/
00328             die = bsearch(dieNeedle, al->dirs, al->numDirs,
00329                                sizeof(*dieNeedle), dieCompare);
00330 /*@=boundswrite@*/
00331             if (die == NULL)
00332                 continue;
00333 
00334             last = die->numFiles;
00335             fie = die->files + last - 1;
00336             for (i = last - 1; i >= 0; i--, fie--) {
00337                 if (fie->pkgNum != pkgNum)
00338                     /*@innercontinue@*/ continue;
00339                 die->numFiles--;
00340                 if (i > die->numFiles)
00341                     /*@innercontinue@*/ continue;
00342 /*@-bounds@*/
00343                 memmove(fie, fie+1, (die->numFiles - i) * sizeof(*fie));
00344 /*@=bounds@*/
00345             }
00346             if (die->numFiles > 0) {
00347                 if (last > i)
00348                     die->files = xrealloc(die->files,
00349                                         die->numFiles * sizeof(*die->files));
00350                 continue;
00351             }
00352             die->files = _free(die->files);
00353             die->dirName = _free(die->dirName);
00354             al->numDirs--;
00355             if ((die - al->dirs) > al->numDirs)
00356                 continue;
00357 /*@-bounds@*/
00358             memmove(die, die+1, (al->numDirs - (die - al->dirs)) * sizeof(*die));
00359 /*@=bounds@*/
00360         }
00361 
00362         if (origNumDirs > al->numDirs) {
00363             if (al->numDirs > 0)
00364                 al->dirs = xrealloc(al->dirs, al->numDirs * sizeof(*al->dirs));
00365             else
00366                 al->dirs = _free(al->dirs);
00367         }
00368     }
00369 
00370     alp->provides = rpmdsFree(alp->provides);
00371     alp->fi = rpmfiFree(alp->fi);
00372 
00373 /*@-boundswrite@*/
00374     memset(alp, 0, sizeof(*alp));       /* XXX trash and burn */
00375 /*@=boundswrite@*/
00376     return;
00377 }
00378 
00379 /*@-bounds@*/
00380 alKey rpmalAdd(rpmal * alistp, alKey pkgKey, fnpyKey key,
00381                 rpmds provides, rpmfi fi)
00382 {
00383     alNum pkgNum;
00384     rpmal al;
00385     availablePackage alp;
00386 
00387     /* If list doesn't exist yet, create. */
00388     if (*alistp == NULL)
00389         *alistp = rpmalCreate(5);
00390     al = *alistp;
00391     pkgNum = alKey2Num(al, pkgKey);
00392 
00393     if (pkgNum >= 0 && pkgNum < al->size) {
00394         rpmalDel(al, pkgKey);
00395     } else {
00396         if (al->size == al->alloced) {
00397             al->alloced += al->delta;
00398             al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced);
00399         }
00400         pkgNum = al->size++;
00401     }
00402 
00403     if (al->list == NULL)
00404         return RPMAL_NOMATCH;           /* XXX can't happen */
00405 
00406     alp = al->list + pkgNum;
00407 
00408     alp->key = key;
00409 
00410 /*@-modfilesys@*/
00411 if (_rpmal_debug)
00412 fprintf(stderr, "*** add %p[%d]\n", al->list, pkgNum);
00413 /*@=modfilesys@*/
00414 
00415     alp->provides = rpmdsLink(provides, "Provides (rpmalAdd)");
00416     alp->fi = rpmfiLink(fi, "Files (rpmalAdd)");
00417 
00418     fi = rpmfiLink(alp->fi, "Files index (rpmalAdd)");
00419     fi = rpmfiInit(fi, 0);
00420     if (rpmfiFC(fi) > 0) {
00421         int * dirMapping;
00422         dirInfo dieNeedle =
00423                 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
00424         dirInfo die;
00425         int first;
00426         int origNumDirs;
00427         int dx;
00428         int dc;
00429 
00430         dc = rpmfiDC(fi);
00431 
00432         /* XXX FIXME: We ought to relocate the directory list here */
00433 
00434         dirMapping = alloca(sizeof(*dirMapping) * dc);
00435 
00436         /*
00437          * Allocated enough space for all the directories we could possible
00438          * need to add
00439          */
00440         al->dirs = xrealloc(al->dirs, (al->numDirs + dc) * sizeof(*al->dirs));
00441         origNumDirs = al->numDirs;
00442 
00443         for (dx = 0; dx < dc; dx++) {
00444 
00445             (void) rpmfiSetDX(fi, dx);
00446 
00447             /*@-assignexpose -dependenttrans -observertrans@*/
00448             dieNeedle->dirName = (char *) rpmfiDN(fi);
00449             /*@=assignexpose =dependenttrans =observertrans@*/
00450             dieNeedle->dirNameLen = (dieNeedle->dirName != NULL
00451                         ? strlen(dieNeedle->dirName) : 0);
00452             die = bsearch(dieNeedle, al->dirs, origNumDirs,
00453                                sizeof(*dieNeedle), dieCompare);
00454             if (die) {
00455                 dirMapping[dx] = die - al->dirs;
00456             } else {
00457                 dirMapping[dx] = al->numDirs;
00458                 die = al->dirs + al->numDirs;
00459                 if (dieNeedle->dirName != NULL)
00460                     die->dirName = xstrdup(dieNeedle->dirName);
00461                 die->dirNameLen = dieNeedle->dirNameLen;
00462                 die->files = NULL;
00463                 die->numFiles = 0;
00464 /*@-modfilesys@*/
00465 if (_rpmal_debug)
00466 fprintf(stderr, "+++ die[%3d] %p [%d] %s\n", al->numDirs, die, die->dirNameLen, die->dirName);
00467 /*@=modfilesys@*/
00468 
00469                 al->numDirs++;
00470             }
00471         }
00472 
00473         for (first = rpmfiNext(fi); first >= 0;) {
00474             fileIndexEntry fie;
00475             int next;
00476 
00477             /* Find the first file of the next directory. */
00478             dx = rpmfiDX(fi);
00479             while ((next = rpmfiNext(fi)) >= 0) {
00480                 if (dx != rpmfiDX(fi))
00481                     /*@innerbreak@*/ break;
00482             }
00483             if (next < 0) next = rpmfiFC(fi);   /* XXX reset end-of-list */
00484 
00485             die = al->dirs + dirMapping[dx];
00486             die->files = xrealloc(die->files,
00487                         (die->numFiles + next - first) * sizeof(*die->files));
00488             fie = die->files + die->numFiles;
00489 
00490             /* Rewind to first file, generate file index entry for each file. */
00491             fi = rpmfiInit(fi, first);
00492             while ((first = rpmfiNext(fi)) >= 0 && first < next) {
00493                 /*@-assignexpose -dependenttrans -observertrans @*/
00494                 fie->baseName = rpmfiBN(fi);
00495                 /*@=assignexpose =dependenttrans =observertrans @*/
00496                 fie->baseNameLen = (fie->baseName ? strlen(fie->baseName) : 0);
00497                 fie->pkgNum = pkgNum;
00498                 fie->fileFlags = rpmfiFFlags(fi);
00499                 die->numFiles++;
00500                 fie++;
00501             }
00502             qsort(die->files, die->numFiles, sizeof(*die->files), fieCompare);
00503         }
00504 
00505         /* Resize the directory list. If any directories were added, resort. */
00506         al->dirs = xrealloc(al->dirs, al->numDirs * sizeof(*al->dirs));
00507         if (origNumDirs != al->numDirs)
00508             qsort(al->dirs, al->numDirs, sizeof(*al->dirs), dieCompare);
00509     }
00510     fi = rpmfiUnlink(fi, "Files index (rpmalAdd)");
00511 
00512     rpmalFreeIndex(al);
00513 
00514 assert(((alNum)(alp - al->list)) == pkgNum);
00515     return ((alKey)(alp - al->list));
00516 }
00517 /*@=bounds@*/
00518 
00525 static int indexcmp(const void * one, const void * two)
00526         /*@*/
00527 {
00528     /*@-castexpose@*/
00529     const availableIndexEntry a = (const availableIndexEntry) one;
00530     const availableIndexEntry b = (const availableIndexEntry) two;
00531     /*@=castexpose@*/
00532     int lenchk;
00533 
00534     lenchk = a->entryLen - b->entryLen;
00535     if (lenchk)
00536         return lenchk;
00537 
00538     return strcmp(a->entry, b->entry);
00539 }
00540 
00541 void rpmalAddProvides(rpmal al, alKey pkgKey, rpmds provides)
00542 {
00543     alNum pkgNum = alKey2Num(al, pkgKey);
00544     availableIndex ai = &al->index;
00545     availableIndexEntry aie;
00546     int ix;
00547 
00548     if (provides == NULL || pkgNum < 0 || pkgNum >= al->size)
00549         return;
00550     if (ai->index == NULL || ai->k < 0 || ai->k >= ai->size)
00551         return;
00552 
00553     if (rpmdsInit(provides) != NULL)
00554     while (rpmdsNext(provides) >= 0) {
00555         const char * Name;
00556 
00557 #ifdef  DYING   /* XXX FIXME: multilib colored dependency search */
00558         const int_32 Flags = rpmdsFlags(provides);
00559 
00560         /* If multilib install, skip non-multilib provides. */
00561         if (al->list[i].multiLib && !isDependsMULTILIB(Flags)) {
00562             ai->size--;
00563             /*@innercontinue@*/ continue;
00564         }
00565 #endif
00566 
00567         if ((Name = rpmdsN(provides)) == NULL)
00568             continue;   /* XXX can't happen */
00569 
00570         aie = ai->index + ai->k;
00571         ai->k++;
00572 
00573         aie->pkgKey = pkgKey;
00574         aie->entry = Name;
00575         aie->entryLen = strlen(Name);
00576         ix = rpmdsIx(provides);
00577 
00578 /* XXX make sure that element index fits in unsigned short */
00579 assert(ix < 0x10000);
00580 
00581         aie->entryIx = ix;
00582         aie->type = IET_PROVIDES;
00583     }
00584 }
00585 
00586 void rpmalMakeIndex(rpmal al)
00587 {
00588     availableIndex ai;
00589     availablePackage alp;
00590     int i;
00591 
00592     if (al == NULL || al->list == NULL) return;
00593     ai = &al->index;
00594 
00595     ai->size = 0;
00596     for (i = 0; i < al->size; i++) {
00597         alp = al->list + i;
00598         if (alp->provides != NULL)
00599             ai->size += rpmdsCount(alp->provides);
00600     }
00601 
00602     ai->index = xrealloc(ai->index, ai->size * sizeof(*ai->index));
00603     ai->k = 0;
00604 
00605     for (i = 0; i < al->size; i++) {
00606         alp = al->list + i;
00607         rpmalAddProvides(al, (alKey)i, alp->provides);
00608     }
00609     qsort(ai->index, ai->size, sizeof(*ai->index), indexcmp);
00610 }
00611 
00612 fnpyKey *
00613 rpmalAllFileSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
00614 {
00615     int found = 0;
00616     const char * dirName;
00617     const char * baseName;
00618     dirInfo dieNeedle =
00619                 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
00620     dirInfo die;
00621     fileIndexEntry fieNeedle =
00622                 memset(alloca(sizeof(*fieNeedle)), 0, sizeof(*fieNeedle));
00623     fileIndexEntry fie;
00624     availablePackage alp;
00625     fnpyKey * ret = NULL;
00626     const char * fileName;
00627 
00628     if (keyp) *keyp = RPMAL_NOMATCH;
00629     if (al == NULL || (fileName = rpmdsN(ds)) == NULL || *fileName != '/')
00630         return NULL;
00631 
00632     /* Solaris 2.6 bsearch sucks down on this. */
00633     if (al->numDirs == 0 || al->dirs == NULL || al->list == NULL)
00634         return NULL;
00635 
00636     {   char * t;
00637         dirName = t = xstrdup(fileName);
00638         if ((t = strrchr(t, '/')) != NULL) {
00639             t++;                /* leave the trailing '/' */
00640             *t = '\0';
00641         }
00642     }
00643 
00644     dieNeedle->dirName = (char *) dirName;
00645     dieNeedle->dirNameLen = strlen(dirName);
00646     die = bsearch(dieNeedle, al->dirs, al->numDirs,
00647                        sizeof(*dieNeedle), dieCompare);
00648     if (die == NULL)
00649         goto exit;
00650 
00651     /* rewind to the first match */
00652     while (die > al->dirs && dieCompare(die-1, dieNeedle) == 0)
00653         die--;
00654 
00655     if ((baseName = strrchr(fileName, '/')) == NULL)
00656         goto exit;
00657     baseName++;
00658 
00659     /*@-branchstate@*/ /* FIX: ret is a problem */
00660     for (found = 0, ret = NULL;
00661          die <= al->dirs + al->numDirs && dieCompare(die, dieNeedle) == 0;
00662          die++)
00663     {
00664 
00665 /*@-modfilesys@*/
00666 if (_rpmal_debug)
00667 fprintf(stderr, "==> die %p %s\n", die, (die->dirName ? die->dirName : "(nil)"));
00668 /*@=modfilesys@*/
00669 
00670 /*@-observertrans@*/
00671         fieNeedle->baseName = baseName;
00672 /*@=observertrans@*/
00673         fieNeedle->baseNameLen = strlen(fieNeedle->baseName);
00674         fie = bsearch(fieNeedle, die->files, die->numFiles,
00675                        sizeof(*fieNeedle), fieCompare);
00676         if (fie == NULL)
00677             continue;   /* XXX shouldn't happen */
00678 
00679 /*@-modfilesys@*/
00680 if (_rpmal_debug)
00681 fprintf(stderr, "==> fie %p %s\n", fie, (fie->baseName ? fie->baseName : "(nil)"));
00682 /*@=modfilesys@*/
00683 
00684 #ifdef  DYING   /* XXX FIXME: multilib colored dependency search */
00685         /*
00686          * If a file dependency would be satisfied by a file
00687          * we are not going to install, skip it.
00688          */
00689         if (al->list[fie->pkgNum].multiLib && !isFileMULTILIB(fie->fileFlags))
00690             continue;
00691 #endif
00692 
00693         rpmdsNotify(ds, _("(added files)"), 0);
00694 
00695         alp = al->list + fie->pkgNum;
00696         ret = xrealloc(ret, (found+2) * sizeof(*ret));
00697         if (ret)        /* can't happen */
00698             ret[found++] = alp->key;
00699         if (keyp)
00700             *keyp = alNum2Key(al, fie->pkgNum);
00701     }
00702     /*@=branchstate@*/
00703 
00704 exit:
00705     dirName = _free(dirName);
00706     if (ret)
00707         ret[found] = NULL;
00708     return ret;
00709 }
00710 
00711 fnpyKey *
00712 rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
00713 {
00714     availableIndex ai;
00715     availableIndexEntry needle;
00716     availableIndexEntry match;
00717     fnpyKey * ret = NULL;
00718     int found = 0;
00719     const char * KName;
00720     availablePackage alp;
00721     int rc;
00722 
00723     if (keyp) *keyp = RPMAL_NOMATCH;
00724 
00725     if (al == NULL || ds == NULL || (KName = rpmdsN(ds)) == NULL)
00726         return ret;
00727 
00728     if (*KName == '/') {
00729         ret = rpmalAllFileSatisfiesDepend(al, ds, keyp);
00730         /* XXX Provides: /path was broken with added packages (#52183). */
00731         if (ret != NULL && *ret != NULL)
00732             return ret;
00733     }
00734 
00735     ai = &al->index;
00736     if (ai->index == NULL || ai->size <= 0)
00737         return NULL;
00738 
00739     needle = memset(alloca(sizeof(*needle)), 0, sizeof(*needle));
00740     /*@-assignexpose -temptrans@*/
00741     needle->entry = KName;
00742     /*@=assignexpose =temptrans@*/
00743     needle->entryLen = strlen(needle->entry);
00744 
00745     match = bsearch(needle, ai->index, ai->size, sizeof(*ai->index), indexcmp);
00746     if (match == NULL)
00747         return NULL;
00748 
00749     /* rewind to the first match */
00750     while (match > ai->index && indexcmp(match-1, needle) == 0)
00751         match--;
00752 
00753     if (al->list != NULL)       /* XXX always true */
00754     for (ret = NULL, found = 0;
00755          match <= ai->index + ai->size && indexcmp(match, needle) == 0;
00756          match++)
00757     {
00758         alp = al->list + alKey2Num(al, match->pkgKey);
00759 
00760         rc = 0;
00761         if (alp->provides != NULL)      /* XXX can't happen */
00762         switch (match->type) {
00763         case IET_PROVIDES:
00764             /* XXX single step on rpmdsNext to regenerate DNEVR string */
00765             (void) rpmdsSetIx(alp->provides, match->entryIx - 1);
00766             if (rpmdsNext(alp->provides) >= 0)
00767                 rc = rpmdsCompare(alp->provides, ds);
00768 
00769             if (rc)
00770                 rpmdsNotify(ds, _("(added provide)"), 0);
00771 
00772             /*@switchbreak@*/ break;
00773         }
00774 
00775         /*@-branchstate@*/
00776         if (rc) {
00777             ret = xrealloc(ret, (found + 2) * sizeof(*ret));
00778             if (ret)    /* can't happen */
00779                 ret[found++] = alp->key;
00780             if (keyp)
00781                 *keyp = ((alKey)(alp - al->list));
00782         }
00783         /*@=branchstate@*/
00784     }
00785 
00786     if (ret)
00787         ret[found] = NULL;
00788 
00789     return ret;
00790 }
00791 
00792 fnpyKey
00793 rpmalSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
00794 {
00795     fnpyKey * tmp = rpmalAllSatisfiesDepend(al, ds, keyp);
00796 
00797     if (tmp) {
00798         fnpyKey ret = tmp[0];
00799         free(tmp);
00800         return ret;
00801     }
00802     return NULL;
00803 }

Generated on Wed Sep 4 12:49:51 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002