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

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     for (i = 0; i < al->size; i++) {
00602         alp = al->list + i;
00603         rpmalAddProvides(al, (alKey)i, alp->provides, alp->tscolor);
00604     }
00605 
00606     /* Reset size to the no. of provides added. */
00607     ai->size = ai->k;
00608     qsort(ai->index, ai->size, sizeof(*ai->index), indexcmp);
00609 }
00610 
00611 fnpyKey *
00612 rpmalAllFileSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
00613 {
00614     uint_32 tscolor;
00615     uint_32 ficolor;
00616     int found = 0;
00617     const char * dirName;
00618     const char * baseName;
00619     dirInfo dieNeedle =
00620                 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
00621     dirInfo die;
00622     fileIndexEntry fieNeedle =
00623                 memset(alloca(sizeof(*fieNeedle)), 0, sizeof(*fieNeedle));
00624     fileIndexEntry fie;
00625     availablePackage alp;
00626     fnpyKey * ret = NULL;
00627     const char * fileName;
00628 
00629     if (keyp) *keyp = RPMAL_NOMATCH;
00630 
00631     if (al == NULL || (fileName = rpmdsN(ds)) == NULL || *fileName != '/')
00632         return NULL;
00633 
00634     /* Solaris 2.6 bsearch sucks down on this. */
00635     if (al->numDirs == 0 || al->dirs == NULL || al->list == NULL)
00636         return NULL;
00637 
00638     {   char * t;
00639         dirName = t = xstrdup(fileName);
00640         if ((t = strrchr(t, '/')) != NULL) {
00641             t++;                /* leave the trailing '/' */
00642             *t = '\0';
00643         }
00644     }
00645 
00646     dieNeedle->dirName = (char *) dirName;
00647     dieNeedle->dirNameLen = strlen(dirName);
00648     die = bsearch(dieNeedle, al->dirs, al->numDirs,
00649                        sizeof(*dieNeedle), dieCompare);
00650     if (die == NULL)
00651         goto exit;
00652 
00653     /* rewind to the first match */
00654     while (die > al->dirs && dieCompare(die-1, dieNeedle) == 0)
00655         die--;
00656 
00657     if ((baseName = strrchr(fileName, '/')) == NULL)
00658         goto exit;
00659     baseName++;
00660 
00661     /*@-branchstate@*/ /* FIX: ret is a problem */
00662     for (found = 0, ret = NULL;
00663          die <= al->dirs + al->numDirs && dieCompare(die, dieNeedle) == 0;
00664          die++)
00665     {
00666 
00667 /*@-modfilesys@*/
00668 if (_rpmal_debug)
00669 fprintf(stderr, "==> die %p %s\n", die, (die->dirName ? die->dirName : "(nil)"));
00670 /*@=modfilesys@*/
00671 
00672 /*@-observertrans@*/
00673         fieNeedle->baseName = baseName;
00674 /*@=observertrans@*/
00675         fieNeedle->baseNameLen = strlen(fieNeedle->baseName);
00676         fie = bsearch(fieNeedle, die->files, die->numFiles,
00677                        sizeof(*fieNeedle), fieCompare);
00678         if (fie == NULL)
00679             continue;   /* XXX shouldn't happen */
00680 
00681 /*@-modfilesys@*/
00682 if (_rpmal_debug)
00683 fprintf(stderr, "==> fie %p %s\n", fie, (fie->baseName ? fie->baseName : "(nil)"));
00684 /*@=modfilesys@*/
00685 
00686         alp = al->list + fie->pkgNum;
00687 
00688         /* Ignore colored files not in our rainbow. */
00689         tscolor = alp->tscolor;
00690         ficolor = fie->ficolor;
00691         if (tscolor && ficolor && !(tscolor & ficolor))
00692             continue;
00693 
00694         rpmdsNotify(ds, _("(added files)"), 0);
00695 
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         found++;
00702     }
00703     /*@=branchstate@*/
00704 
00705 exit:
00706     dirName = _free(dirName);
00707     if (ret)
00708         ret[found] = NULL;
00709     return ret;
00710 }
00711 
00712 fnpyKey *
00713 rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
00714 {
00715     availableIndex ai;
00716     availableIndexEntry needle;
00717     availableIndexEntry match;
00718     fnpyKey * ret = NULL;
00719     int found = 0;
00720     const char * KName;
00721     availablePackage alp;
00722     int rc;
00723 
00724     if (keyp) *keyp = RPMAL_NOMATCH;
00725 
00726     if (al == NULL || ds == NULL || (KName = rpmdsN(ds)) == NULL)
00727         return ret;
00728 
00729     if (*KName == '/') {
00730         /* First, look for files "contained" in package ... */
00731         ret = rpmalAllFileSatisfiesDepend(al, ds, keyp);
00732         if (ret != NULL && *ret != NULL)
00733             return ret;
00734         /* ... then, look for files "provided" by package. */
00735     }
00736 
00737     ai = &al->index;
00738     if (ai->index == NULL || ai->size <= 0)
00739         return NULL;
00740 
00741     needle = memset(alloca(sizeof(*needle)), 0, sizeof(*needle));
00742     /*@-assignexpose -temptrans@*/
00743     needle->entry = KName;
00744     /*@=assignexpose =temptrans@*/
00745     needle->entryLen = strlen(needle->entry);
00746 
00747     match = bsearch(needle, ai->index, ai->size, sizeof(*ai->index), indexcmp);
00748     if (match == NULL)
00749         return NULL;
00750 
00751     /* rewind to the first match */
00752     while (match > ai->index && indexcmp(match-1, needle) == 0)
00753         match--;
00754 
00755     if (al->list != NULL)       /* XXX always true */
00756     for (ret = NULL, found = 0;
00757          match < ai->index + ai->size && indexcmp(match, needle) == 0;
00758          match++)
00759     {
00760         alp = al->list + alKey2Num(al, match->pkgKey);
00761 
00762         rc = 0;
00763         if (alp->provides != NULL)      /* XXX can't happen */
00764         switch (match->type) {
00765         case IET_PROVIDES:
00766             /* XXX single step on rpmdsNext to regenerate DNEVR string */
00767             (void) rpmdsSetIx(alp->provides, match->entryIx - 1);
00768             if (rpmdsNext(alp->provides) >= 0)
00769                 rc = rpmdsCompare(alp->provides, ds);
00770 
00771             if (rc)
00772                 rpmdsNotify(ds, _("(added provide)"), 0);
00773 
00774             /*@switchbreak@*/ break;
00775         }
00776 
00777         /*@-branchstate@*/
00778         if (rc) {
00779             ret = xrealloc(ret, (found + 2) * sizeof(*ret));
00780             if (ret)    /* can't happen */
00781                 ret[found] = alp->key;
00782 /*@-dependenttrans@*/
00783             if (keyp)
00784                 *keyp = match->pkgKey;
00785 /*@=dependenttrans@*/
00786             found++;
00787         }
00788         /*@=branchstate@*/
00789     }
00790 
00791     if (ret)
00792         ret[found] = NULL;
00793 
00794 /*@-nullstate@*/ /* FIX: *keyp may be NULL */
00795     return ret;
00796 /*@=nullstate@*/
00797 }
00798 
00799 fnpyKey
00800 rpmalSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
00801 {
00802     fnpyKey * tmp = rpmalAllSatisfiesDepend(al, ds, keyp);
00803 
00804     if (tmp) {
00805         fnpyKey ret = tmp[0];
00806         free(tmp);
00807         return ret;
00808     }
00809     return NULL;
00810 }

Generated on Sun Jul 24 03:53:38 2005 for rpm by  doxygen 1.3.9.1