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 }