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     uint_32 tscolor;            
00038 /*@exposed@*/ /*@dependent@*/ /*@null@*/
00039     fnpyKey key;                
00041 };
00042 
00043 typedef /*@abstract@*/ struct availableIndexEntry_s *   availableIndexEntry;
00044 /*@access availableIndexEntry@*/
00045 
00049 struct availableIndexEntry_s {
00050 /*@exposed@*/ /*@dependent@*/ /*@null@*/
00051     alKey pkgKey;               
00052 /*@observer@*/
00053     const char * entry;         
00054     unsigned short entryLen;    
00055     unsigned short entryIx;     
00056     enum indexEntryType {
00057         IET_PROVIDES=1                  
00058     } type;                     
00059 };
00060 
00061 typedef /*@abstract@*/ struct availableIndex_s *        availableIndex;
00062 /*@access availableIndex@*/
00063 
00067 struct availableIndex_s {
00068 /*@null@*/
00069     availableIndexEntry index;  
00070     int size;                   
00071     int k;                      
00072 };
00073 
00074 typedef /*@abstract@*/ struct fileIndexEntry_s *        fileIndexEntry;
00075 /*@access fileIndexEntry@*/
00076 
00080 struct fileIndexEntry_s {
00081 /*@dependent@*/ /*@null@*/
00082     const char * baseName;      
00083     int baseNameLen;
00084     alNum pkgNum;               
00085     uint_32 ficolor;
00086 };
00087 
00088 typedef /*@abstract@*/ struct dirInfo_s *               dirInfo;
00089 /*@access dirInfo@*/
00090 
00094 struct dirInfo_s {
00095 /*@owned@*/ /*@null@*/
00096     const char * dirName;       
00097     int dirNameLen;             
00098 /*@owned@*/
00099     fileIndexEntry files;       
00100     int numFiles;               
00101 };
00102 
00106 struct rpmal_s {
00107 /*@owned@*/ /*@null@*/
00108     availablePackage list;      
00109     struct availableIndex_s index;      
00110     int delta;                  
00111     int size;                   
00112     int alloced;                
00113     uint_32 tscolor;            
00114     int numDirs;                
00115 /*@owned@*/ /*@null@*/
00116     dirInfo dirs;               
00117 };
00118 
00123 static void rpmalFreeIndex(rpmal al)
00124         /*@modifies al @*/
00125 {
00126     availableIndex ai = &al->index;
00127     if (ai->size > 0) {
00128         ai->index = _free(ai->index);
00129         ai->size = 0;
00130     }
00131 }
00132 
00133 #ifdef  DYING
00134 
00139 static int alGetSize(/*@null@*/ const rpmal al)
00140         /*@*/
00141 {
00142     return (al != NULL ? al->size : 0);
00143 }
00144 #endif
00145 
00146 static inline alNum alKey2Num(/*@unused@*/ /*@null@*/ const rpmal al,
00147                 /*@null@*/ alKey pkgKey)
00148         /*@*/
00149 {
00150     /*@-nullret -temptrans -retalias @*/
00151     return ((alNum)pkgKey);
00152     /*@=nullret =temptrans =retalias @*/
00153 }
00154 
00155 static inline alKey alNum2Key(/*@unused@*/ /*@null@*/ const rpmal al,
00156                 /*@null@*/ alNum pkgNum)
00157         /*@*/
00158 {
00159     /*@-nullret -temptrans -retalias @*/
00160     return ((alKey)pkgNum);
00161     /*@=nullret =temptrans =retalias @*/
00162 }
00163 
00164 #ifdef  DYING
00165 
00171 /*@dependent@*/ /*@null@*/
00172 static availablePackage alGetPkg(/*@null@*/ const rpmal al,
00173                 /*@null@*/ alKey pkgKey)
00174         /*@*/
00175 {
00176     alNum pkgNum = alKey2Num(al, pkgKey);
00177     availablePackage alp = NULL;
00178 
00179     if (al != NULL && pkgNum >= 0 && pkgNum < alGetSize(al)) {
00180         if (al->list != NULL)
00181             alp = al->list + pkgNum;
00182     }
00183     return alp;
00184 }
00185 #endif
00186 
00187 rpmal rpmalCreate(int delta)
00188 {
00189     rpmal al = xcalloc(1, sizeof(*al));
00190     availableIndex ai = &al->index;
00191 
00192     al->delta = delta;
00193     al->size = 0;
00194     al->list = xcalloc(al->delta, sizeof(*al->list));
00195     al->alloced = al->delta;
00196 
00197     ai->index = NULL;
00198     ai->size = 0;
00199 
00200     al->numDirs = 0;
00201     al->dirs = NULL;
00202     return al;
00203 }
00204 
00205 rpmal rpmalFree(rpmal al)
00206 {
00207     availablePackage alp;
00208     dirInfo die;
00209     int i;
00210 
00211     if (al == NULL)
00212         return NULL;
00213 
00214     if ((alp = al->list) != NULL)
00215     for (i = 0; i < al->size; i++, alp++) {
00216         alp->provides = rpmdsFree(alp->provides);
00217         alp->fi = rpmfiFree(alp->fi);
00218     }
00219 
00220     if ((die = al->dirs) != NULL)
00221     for (i = 0; i < al->numDirs; i++, die++) {
00222         die->dirName = _free(die->dirName);
00223         die->files = _free(die->files);
00224     }
00225     al->dirs = _free(al->dirs);
00226     al->numDirs = 0;
00227 
00228     al->list = _free(al->list);
00229     al->alloced = 0;
00230     rpmalFreeIndex(al);
00231     al = _free(al);
00232     return NULL;
00233 }
00234 
00241 static int dieCompare(const void * one, const void * two)
00242         /*@*/
00243 {
00244     /*@-castexpose@*/
00245     const dirInfo a = (const dirInfo) one;
00246     const dirInfo b = (const dirInfo) two;
00247     /*@=castexpose@*/
00248     int lenchk = a->dirNameLen - b->dirNameLen;
00249 
00250     if (lenchk || a->dirNameLen == 0)
00251         return lenchk;
00252 
00253     if (a->dirName == NULL || b->dirName == NULL)
00254         return lenchk;
00255 
00256     /* XXX FIXME: this might do "backward" strcmp for speed */
00257     return strcmp(a->dirName, b->dirName);
00258 }
00259 
00266 static int fieCompare(const void * one, const void * two)
00267         /*@*/
00268 {
00269     /*@-castexpose@*/
00270     const fileIndexEntry a = (const fileIndexEntry) one;
00271     const fileIndexEntry b = (const fileIndexEntry) two;
00272     /*@=castexpose@*/
00273     int lenchk = a->baseNameLen - b->baseNameLen;
00274 
00275     if (lenchk)
00276         return lenchk;
00277 
00278     if (a->baseName == NULL || b->baseName == NULL)
00279         return lenchk;
00280 
00281     /* XXX FIXME: this might do "backward" strcmp for speed */
00282     return strcmp(a->baseName, b->baseName);
00283 }
00284 
00285 void rpmalDel(rpmal al, alKey pkgKey)
00286 {
00287     alNum pkgNum = alKey2Num(al, pkgKey);
00288     availablePackage alp;
00289     rpmfi fi;
00290 
00291     if (al == NULL || al->list == NULL)
00292         return;         /* XXX can't happen */
00293 
00294     alp = al->list + pkgNum;
00295 
00296 /*@-modfilesys@*/
00297 if (_rpmal_debug)
00298 fprintf(stderr, "*** del %p[%d]\n", al->list, pkgNum);
00299 /*@=modfilesys@*/
00300 
00301     /* Delete directory/file info entries from added package list. */
00302     if ((fi = alp->fi) != NULL)
00303     if (rpmfiFC(fi) > 0) {
00304         int origNumDirs = al->numDirs;
00305         int dx;
00306         dirInfo dieNeedle =
00307                 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
00308         dirInfo die;
00309         int last;
00310         int i;
00311 
00312         /* XXX FIXME: We ought to relocate the directory list here */
00313 
00314         if (al->dirs != NULL)
00315         for (dx = rpmfiDC(fi) - 1; dx >= 0; dx--)
00316         {
00317             fileIndexEntry fie;
00318 
00319             (void) rpmfiSetDX(fi, dx);
00320 
00321             /*@-assignexpose -dependenttrans -observertrans@*/
00322             dieNeedle->dirName = (char *) rpmfiDN(fi);
00323             /*@=assignexpose =dependenttrans =observertrans@*/
00324             dieNeedle->dirNameLen = (dieNeedle->dirName != NULL
00325                         ? strlen(dieNeedle->dirName) : 0);
00326 /*@-boundswrite@*/
00327             die = bsearch(dieNeedle, al->dirs, al->numDirs,
00328                                sizeof(*dieNeedle), dieCompare);
00329 /*@=boundswrite@*/
00330             if (die == NULL)
00331                 continue;
00332 
00333             last = die->numFiles;
00334             fie = die->files + last - 1;
00335             for (i = last - 1; i >= 0; i--, fie--) {
00336                 if (fie->pkgNum != pkgNum)
00337                     /*@innercontinue@*/ continue;
00338                 die->numFiles--;
00339                 if (i > die->numFiles)
00340                     /*@innercontinue@*/ continue;
00341 /*@-bounds@*/
00342                 memmove(fie, fie+1, (die->numFiles - i) * sizeof(*fie));
00343 /*@=bounds@*/
00344             }
00345             if (die->numFiles > 0) {
00346                 if (last > i)
00347                     die->files = xrealloc(die->files,
00348                                         die->numFiles * sizeof(*die->files));
00349                 continue;
00350             }
00351             die->files = _free(die->files);
00352             die->dirName = _free(die->dirName);
00353             al->numDirs--;
00354             if ((die - al->dirs) > al->numDirs)
00355                 continue;
00356 /*@-bounds@*/
00357             memmove(die, die+1, (al->numDirs - (die - al->dirs)) * sizeof(*die));
00358 /*@=bounds@*/
00359         }
00360 
00361         if (origNumDirs > al->numDirs) {
00362             if (al->numDirs > 0)
00363                 al->dirs = xrealloc(al->dirs, al->numDirs * sizeof(*al->dirs));
00364             else
00365                 al->dirs = _free(al->dirs);
00366         }
00367     }
00368 
00369     alp->provides = rpmdsFree(alp->provides);
00370     alp->fi = rpmfiFree(alp->fi);
00371 
00372 /*@-boundswrite@*/
00373     memset(alp, 0, sizeof(*alp));       /* XXX trash and burn */
00374 /*@=boundswrite@*/
00375     return;
00376 }
00377 
00378 /*@-bounds@*/
00379 alKey rpmalAdd(rpmal * alistp, alKey pkgKey, fnpyKey key,
00380                 rpmds provides, rpmfi fi, uint_32 tscolor)
00381 {
00382     alNum pkgNum;
00383     rpmal al;
00384     availablePackage alp;
00385 
00386     /* If list doesn't exist yet, create. */
00387     if (*alistp == NULL)
00388         *alistp = rpmalCreate(5);
00389     al = *alistp;
00390     pkgNum = alKey2Num(al, pkgKey);
00391 
00392     if (pkgNum >= 0 && pkgNum < al->size) {
00393         rpmalDel(al, pkgKey);
00394     } else {
00395         if (al->size == al->alloced) {
00396             al->alloced += al->delta;
00397             al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced);
00398         }
00399         pkgNum = al->size++;
00400     }
00401 
00402     if (al->list == NULL)
00403         return RPMAL_NOMATCH;           /* XXX can't happen */
00404 
00405     alp = al->list + pkgNum;
00406 
00407     alp->key = key;
00408     alp->tscolor = tscolor;
00409 
00410 /*@-modfilesys@*/
00411 if (_rpmal_debug)
00412 fprintf(stderr, "*** add %p[%d] 0x%x\n", al->list, pkgNum, tscolor);
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->ficolor = rpmfiFColor(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, uint_32 tscolor)
00542 {
00543     uint_32 dscolor;
00544     const char * Name;
00545     alNum pkgNum = alKey2Num(al, pkgKey);
00546     availableIndex ai = &al->index;
00547     availableIndexEntry aie;
00548     int ix;
00549 
00550     if (provides == NULL || pkgNum < 0 || pkgNum >= al->size)
00551         return;
00552     if (ai->index == NULL || ai->k < 0 || ai->k >= ai->size)
00553         return;
00554 
00555     if (rpmdsInit(provides) != NULL)
00556     while (rpmdsNext(provides) >= 0) {
00557 
00558         if ((Name = rpmdsN(provides)) == NULL)
00559             continue;   /* XXX can't happen */
00560 
00561         /* Ignore colored provides not in our rainbow. */
00562         dscolor = rpmdsColor(provides);
00563         if (tscolor && dscolor && !(tscolor & dscolor))
00564             continue;
00565 
00566         aie = ai->index + ai->k;
00567         ai->k++;
00568 
00569         aie->pkgKey = pkgKey;
00570         aie->entry = Name;
00571         aie->entryLen = strlen(Name);
00572         ix = rpmdsIx(provides);
00573 
00574 /* XXX make sure that element index fits in unsigned short */
00575 assert(ix < 0x10000);
00576 
00577         aie->entryIx = ix;
00578         aie->type = IET_PROVIDES;
00579     }
00580 }
00581 
00582 void rpmalMakeIndex(rpmal al)
00583 {
00584     availableIndex ai;
00585     availablePackage alp;
00586     int i;
00587 
00588     if (al == NULL || al->list == NULL) return;
00589     ai = &al->index;
00590 
00591     ai->size = 0;
00592     for (i = 0; i < al->size; i++) {
00593         alp = al->list + i;
00594         if (alp->provides != NULL)
00595             ai->size += rpmdsCount(alp->provides);
00596     }
00597     if (ai->size == 0) return;
00598 
00599     ai->index = xrealloc(ai->index, ai->size * sizeof(*ai->index));
00600     ai->k = 0;
00601 
00602     for (i = 0; i < al->size; i++) {
00603         alp = al->list + i;
00604         rpmalAddProvides(al, (alKey)i, alp->provides, alp->tscolor);
00605     }
00606     qsort(ai->index, ai->size, sizeof(*ai->index), indexcmp);
00607 }
00608 
00609 fnpyKey *
00610 rpmalAllFileSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
00611 {
00612     uint_32 tscolor;
00613     uint_32 ficolor;
00614     int found = 0;
00615     const char * dirName;
00616     const char * baseName;
00617     dirInfo dieNeedle =
00618                 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
00619     dirInfo die;
00620     fileIndexEntry fieNeedle =
00621                 memset(alloca(sizeof(*fieNeedle)), 0, sizeof(*fieNeedle));
00622     fileIndexEntry fie;
00623     availablePackage alp;
00624     fnpyKey * ret = NULL;
00625     const char * fileName;
00626 
00627     if (keyp) *keyp = RPMAL_NOMATCH;
00628 
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         alp = al->list + fie->pkgNum;
00685 
00686         /* Ignore colored files not in our rainbow. */
00687         tscolor = alp->tscolor;
00688         ficolor = fie->ficolor;
00689         if (tscolor && ficolor && !(tscolor & ficolor))
00690             continue;
00691 
00692         rpmdsNotify(ds, _("(added files)"), 0);
00693 
00694         ret = xrealloc(ret, (found+2) * sizeof(*ret));
00695         if (ret)        /* can't happen */
00696             ret[found] = alp->key;
00697         if (keyp)
00698             *keyp = alNum2Key(al, fie->pkgNum);
00699         found++;
00700     }
00701     /*@=branchstate@*/
00702 
00703 exit:
00704     dirName = _free(dirName);
00705     if (ret)
00706         ret[found] = NULL;
00707     return ret;
00708 }
00709 
00710 fnpyKey *
00711 rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
00712 {
00713     availableIndex ai;
00714     availableIndexEntry needle;
00715     availableIndexEntry match;
00716     fnpyKey * ret = NULL;
00717     int found = 0;
00718     const char * KName;
00719     availablePackage alp;
00720     int rc;
00721 
00722     if (keyp) *keyp = RPMAL_NOMATCH;
00723 
00724     if (al == NULL || ds == NULL || (KName = rpmdsN(ds)) == NULL)
00725         return ret;
00726 
00727     if (*KName == '/') {
00728         /* First, look for files "contained" in package ... */
00729         ret = rpmalAllFileSatisfiesDepend(al, ds, keyp);
00730         if (ret != NULL && *ret != NULL)
00731             return ret;
00732         /* ... then, look for files "provided" by package. */
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 /*@-dependenttrans@*/
00781             if (keyp)
00782                 *keyp = match->pkgKey;
00783 /*@=dependenttrans@*/
00784             found++;
00785         }
00786         /*@=branchstate@*/
00787     }
00788 
00789     if (ret)
00790         ret[found] = NULL;
00791 
00792 /*@-nullstate@*/ /* FIX: *keyp may be NULL */
00793     return ret;
00794 /*@=nullstate@*/
00795 }
00796 
00797 fnpyKey
00798 rpmalSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
00799 {
00800     fnpyKey * tmp = rpmalAllSatisfiesDepend(al, ds, keyp);
00801 
00802     if (tmp) {
00803         fnpyKey ret = tmp[0];
00804         free(tmp);
00805         return ret;
00806     }
00807     return NULL;
00808 }

Generated on Sun Oct 26 13:02:00 2003 for rpm by doxygen1.2.18