rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

lib/rpmal.c
Go to the documentation of this file.

    00001
    00005 #include "system.h"
    00006
    00007 #include <rpmio.h>
    00008 #include <rpmiotypes.h>         /* XXX fnpyKey */
    00009
    00010 #include <rpmtag.h>
    00011 #include <rpmtypes.h>
    00012
    00013 #define _RPMDS_INTERNAL
    00014 #include <rpmds.h>
    00015 #include <rpmal.h>
    00016
    00017 #include "debug.h"
    00018
    00019 typedef /*@abstract@*/ struct availablePackage_s * availablePackage;
    00020
    00021 /*@access alKey @*/
    00022 /*@access alNum @*/
    00023 /*@access rpmal @*/
    00024 /*@access rpmds @*/
    00025 /*@access availablePackage @*/
    00026
    00027 /*@access fnpyKey @*/   /* XXX suggestedKeys array */
    00028
    00032 struct availablePackage_s {
    00033 /*@refcounted@*/ /*@null@*/
    00034     rpmds provides;
    00035 /*@refcounted@*/ /*@null@*/
    00036     rpmfi fi;
    00038     rpmuint32_t tscolor;
    00040 /*@exposed@*/ /*@dependent@*/ /*@null@*/
    00041     fnpyKey key;
    00043 };
    00044
    00045 typedef /*@abstract@*/ struct availableIndexEntry_s *   availableIndexEntry;
    00046 /*@access availableIndexEntry@*/
    00047
    00051 struct availableIndexEntry_s {
    00052 /*@exposed@*/ /*@dependent@*/ /*@null@*/
    00053     alKey pkgKey;
    00054 /*@observer@*/
    00055     const char * entry;
    00056     unsigned short entryLen;
    00057     unsigned short entryIx;
    00058     enum indexEntryType {
    00059         IET_PROVIDES=1
    00060     } type;
    00061 };
    00062
    00063 typedef /*@abstract@*/ struct availableIndex_s *        availableIndex;
    00064 /*@access availableIndex@*/
    00065
    00069 struct availableIndex_s {
    00070 /*@null@*/
    00071     availableIndexEntry index;
    00072     int size;
    00073     int k;
    00074 };
    00075
    00076 typedef /*@abstract@*/ struct fileIndexEntry_s *        fileIndexEntry;
    00077 /*@access fileIndexEntry@*/
    00078
    00082 struct fileIndexEntry_s {
    00083 /*@dependent@*/ /*@relnull@*/
    00084     const char * baseName;
    00085     size_t baseNameLen;
    00086     alNum pkgNum;
    00087     rpmuint32_t ficolor;
    00088 };
    00089
    00090 typedef /*@abstract@*/ struct dirInfo_s *               dirInfo;
    00091 /*@access dirInfo@*/
    00092
    00096 struct dirInfo_s {
    00097 /*@owned@*/ /*@relnull@*/
    00098     const char * dirName;
    00099     size_t dirNameLen;
    00100 /*@owned@*/
    00101     fileIndexEntry files;
    00102     int numFiles;
    00103 };
    00104
    00108 struct rpmal_s {
    00109 /*@owned@*/ /*@null@*/
    00110     availablePackage list;
    00111     struct availableIndex_s index;
    00112     int delta;
    00113     int size;
    00114     int alloced;
    00115     rpmuint32_t tscolor;
    00116     int numDirs;
    00117 /*@owned@*/ /*@null@*/
    00118     dirInfo dirs;
    00119 };
    00120
    00125 static void rpmalFreeIndex(rpmal al)
    00126         /*@modifies al @*/
    00127 {
    00128     availableIndex ai = &al->index;
    00129     if (ai->size > 0) {
    00130         ai->index = _free(ai->index);
    00131         ai->size = 0;
    00132     }
    00133 }
    00134
    00135 static inline alNum alKey2Num(/*@unused@*/ /*@null@*/ const rpmal al,
    00136                 /*@null@*/ alKey pkgKey)
    00137         /*@*/
    00138 {
    00139     /*@-nullret -temptrans -retalias @*/
    00140     union { alKey key; alNum num; } u;
    00141     u.num = 0;
    00142     u.key = pkgKey;
    00143     return u.num;
    00144     /*@=nullret =temptrans =retalias @*/
    00145 }
    00146
    00147 static inline alKey alNum2Key(/*@unused@*/ /*@null@*/ const rpmal al,
    00148                 /*@null@*/ alNum pkgNum)
    00149         /*@*/
    00150 {
    00151     /*@-nullret -temptrans -retalias @*/
    00152     union { alKey key; alNum num; } u;
    00153     u.key = 0;
    00154     u.num = pkgNum;
    00155     return u.key;
    00156     /*@=nullret =temptrans =retalias @*/
    00157 }
    00158
    00159 rpmal rpmalCreate(int delta)
    00160 {
    00161     rpmal al = xcalloc(1, sizeof(*al));
    00162     availableIndex ai = &al->index;
    00163
    00164     al->delta = delta;
    00165     al->size = 0;
    00166     al->list = xcalloc(al->delta, sizeof(*al->list));
    00167     al->alloced = al->delta;
    00168
    00169     ai->index = NULL;
    00170     ai->size = 0;
    00171
    00172     al->numDirs = 0;
    00173     al->dirs = NULL;
    00174     return al;
    00175 }
    00176
    00177 rpmal rpmalFree(rpmal al)
    00178 {
    00179     availablePackage alp;
    00180     dirInfo die;
    00181     int i;
    00182
    00183     if (al == NULL)
    00184         return NULL;
    00185
    00186     if ((alp = al->list) != NULL)
    00187     for (i = 0; i < al->size; i++, alp++) {
    00188         (void)rpmdsFree(alp->provides);
    00189         alp->provides = NULL;
    00190         alp->fi = rpmfiFree(alp->fi);
    00191     }
    00192
    00193     if ((die = al->dirs) != NULL)
    00194     for (i = 0; i < al->numDirs; i++, die++) {
    00195         die->dirName = _free(die->dirName);
    00196         die->files = _free(die->files);
    00197     }
    00198     al->dirs = _free(al->dirs);
    00199     al->numDirs = 0;
    00200
    00201     al->list = _free(al->list);
    00202     al->alloced = 0;
    00203     rpmalFreeIndex(al);
    00204     al = _free(al);
    00205     return NULL;
    00206 }
    00207
    00214 static int dieCompare(const void * one, const void * two)
    00215         /*@*/
    00216 {
    00217     /*@-castexpose@*/
    00218     const dirInfo a = (const dirInfo) one;
    00219     const dirInfo b = (const dirInfo) two;
    00220     /*@=castexpose@*/
    00221     int lenchk = (int)a->dirNameLen - (int)b->dirNameLen;
    00222
    00223     if (lenchk || a->dirNameLen == 0)
    00224         return lenchk;
    00225
    00226     if (a->dirName == NULL || b->dirName == NULL)
    00227         return lenchk;
    00228
    00229     /* XXX FIXME: this might do "backward" strcmp for speed */
    00230     return strcmp(a->dirName, b->dirName);
    00231 }
    00232
    00239 static int fieCompare(const void * one, const void * two)
    00240         /*@*/
    00241 {
    00242     /*@-castexpose@*/
    00243     const fileIndexEntry a = (const fileIndexEntry) one;
    00244     const fileIndexEntry b = (const fileIndexEntry) two;
    00245     /*@=castexpose@*/
    00246     int lenchk = (int)a->baseNameLen - (int)b->baseNameLen;
    00247
    00248     if (lenchk)
    00249         return lenchk;
    00250
    00251     if (a->baseName == NULL || b->baseName == NULL)
    00252         return lenchk;
    00253
    00254     return strcmp(a->baseName, b->baseName);
    00255 }
    00256
    00257 void rpmalDel(rpmal al, alKey pkgKey)
    00258 {
    00259     alNum pkgNum = alKey2Num(al, pkgKey);
    00260     availablePackage alp;
    00261     rpmfi fi;
    00262
    00263     if (al == NULL || al->list == NULL)
    00264         return;         /* XXX can't happen */
    00265
    00266     alp = al->list + pkgNum;
    00267
    00268     /* Delete directory/file info entries from added package list. */
    00269     if ((fi = alp->fi) != NULL)
    00270     if (rpmfiFC(fi) > 0) {
    00271         int origNumDirs = al->numDirs;
    00272         int dx;
    00273         dirInfo dieNeedle =
    00274                 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
    00275         dirInfo die;
    00276         int last;
    00277         int i;
    00278
    00279         /* XXX FIXME: We ought to relocate the directory list here */
    00280
    00281         if (al->dirs != NULL)
    00282         for (dx = rpmfiDC(fi) - 1; dx >= 0; dx--)
    00283         {
    00284             fileIndexEntry fie;
    00285
    00286             (void) rpmfiSetDX(fi, dx);
    00287
    00288             /*@-assignexpose -dependenttrans -observertrans@*/
    00289             dieNeedle->dirName = (char *) rpmfiDN(fi);
    00290             /*@=assignexpose =dependenttrans =observertrans@*/
    00291             dieNeedle->dirNameLen = (dieNeedle->dirName != NULL
    00292                         ? strlen(dieNeedle->dirName) : 0);
    00293             die = bsearch(dieNeedle, al->dirs, al->numDirs,
    00294                                sizeof(*dieNeedle), dieCompare);
    00295             if (die == NULL)
    00296                 continue;
    00297
    00298             last = die->numFiles;
    00299             fie = die->files + last - 1;
    00300             for (i = last - 1; i >= 0; i--, fie--) {
    00301                 if (fie->pkgNum != pkgNum)
    00302                     /*@innercontinue@*/ continue;
    00303                 die->numFiles--;
    00304
    00305                 if (i < die->numFiles)
    00306                     memmove(fie, fie+1, (die->numFiles - i) * sizeof(*fie));
    00307                 memset(die->files + die->numFiles, 0, sizeof(*fie)); /* overkill */
    00308
    00309             }
    00310             if (die->numFiles > 0) {
    00311                 if (last > i)
    00312                     die->files = xrealloc(die->files,
    00313                                         die->numFiles * sizeof(*die->files));
    00314                 continue;
    00315             }
    00316             die->files = _free(die->files);
    00317             die->dirName = _free(die->dirName);
    00318             al->numDirs--;
    00319             if ((die - al->dirs) < al->numDirs)
    00320                 memmove(die, die+1, (al->numDirs - (die - al->dirs)) * sizeof(*die));
    00321
    00322             memset(al->dirs + al->numDirs, 0, sizeof(*al->dirs)); /* overkill */
    00323         }
    00324
    00325         if (origNumDirs > al->numDirs) {
    00326             if (al->numDirs > 0)
    00327                 al->dirs = xrealloc(al->dirs, al->numDirs * sizeof(*al->dirs));
    00328             else
    00329                 al->dirs = _free(al->dirs);
    00330         }
    00331     }
    00332
    00333     (void)rpmdsFree(alp->provides);
    00334     alp->provides = NULL;
    00335     alp->fi = rpmfiFree(alp->fi);
    00336
    00337     memset(alp, 0, sizeof(*alp));       /* XXX trash and burn */
    00338     return;
    00339 }
    00340
    00341 alKey rpmalAdd(rpmal * alistp, alKey pkgKey, fnpyKey key,
    00342                 rpmds provides, rpmfi fi, rpmuint32_t tscolor)
    00343 {
    00344     alNum pkgNum;
    00345     rpmal al;
    00346     availablePackage alp;
    00347
    00348     /* If list doesn't exist yet, create. */
    00349     if (*alistp == NULL)
    00350         *alistp = rpmalCreate(5);
    00351     al = *alistp;
    00352     pkgNum = alKey2Num(al, pkgKey);
    00353
    00354     if (pkgNum >= 0 && pkgNum < al->size) {
    00355         rpmalDel(al, pkgKey);
    00356     } else {
    00357         if (al->size == al->alloced) {
    00358             al->alloced += al->delta;
    00359             al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced);
    00360         }
    00361         pkgNum = al->size++;
    00362     }
    00363
    00364     if (al->list == NULL)
    00365         return RPMAL_NOMATCH;           /* XXX can't happen */
    00366
    00367     alp = al->list + pkgNum;
    00368
    00369     alp->key = key;
    00370     alp->tscolor = tscolor;
    00371
    00372 /*@-assignexpose -castexpose @*/
    00373     alp->provides = rpmdsLink(provides, "Provides (rpmalAdd)");
    00374     alp->fi = rpmfiLink(fi, "Files (rpmalAdd)");
    00375 /*@=assignexpose =castexpose @*/
    00376
    00377 /*@-castexpose@*/
    00378     fi = rpmfiLink(alp->fi, "Files index (rpmalAdd)");
    00379 /*@=castexpose@*/
    00380     fi = rpmfiInit(fi, 0);
    00381     if (rpmfiFC(fi) > 0) {
    00382         dirInfo dieNeedle =
    00383                 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
    00384         dirInfo die;
    00385         int dc = rpmfiDC(fi);
    00386         int dx;
    00387         int * dirMapping = alloca(sizeof(*dirMapping) * dc);
    00388         int * dirUnique = alloca(sizeof(*dirUnique) * dc);
    00389         const char * DN;
    00390         int origNumDirs;
    00391         int first;
    00392
    00393         /* XXX FIXME: We ought to relocate the directory list here */
    00394
    00395         /* XXX enough space for all directories, late realloc to truncate. */
    00396         al->dirs = xrealloc(al->dirs, (al->numDirs + dc) * sizeof(*al->dirs));
    00397
    00398         /* Only previously allocated dirInfo is sorted and bsearch'able. */
    00399         origNumDirs = al->numDirs;
    00400
    00401         /* Package dirnames are not currently unique. Create unique mapping. */
    00402         for (dx = 0; dx < dc; dx++) {
    00403             int i = 0;
    00404             (void) rpmfiSetDX(fi, dx);
    00405             DN = rpmfiDN(fi);
    00406             if (DN != NULL)
    00407             for (i = 0; i < dx; i++) {
    00408                 const char * iDN;
    00409                 (void) rpmfiSetDX(fi, i);
    00410                 iDN = rpmfiDN(fi);
    00411                 if (iDN != NULL && !strcmp(DN, iDN))
    00412                     /*@innerbreak@*/ break;
    00413             }
    00414             dirUnique[dx] = i;
    00415         }
    00416
    00417         /* Map package dirs into transaction dirInfo index. */
    00418         for (dx = 0; dx < dc; dx++) {
    00419
    00420             /* Non-unique package dirs use the 1st entry mapping. */
    00421             if (dirUnique[dx] < dx) {
    00422                 dirMapping[dx] = dirMapping[dirUnique[dx]];
    00423                 continue;
    00424             }
    00425
    00426             /* Find global dirInfo mapping for first encounter. */
    00427             (void) rpmfiSetDX(fi, dx);
    00428
    00429             /*@-assignexpose -dependenttrans -observertrans@*/
    00430             dieNeedle->dirName = rpmfiDN(fi);
    00431             /*@=assignexpose =dependenttrans =observertrans@*/
    00432
    00433             dieNeedle->dirNameLen = (dieNeedle->dirName != NULL
    00434                         ? strlen(dieNeedle->dirName) : 0);
    00435             die = bsearch(dieNeedle, al->dirs, origNumDirs,
    00436                                sizeof(*dieNeedle), dieCompare);
    00437             if (die) {
    00438                 dirMapping[dx] = die - al->dirs;
    00439             } else {
    00440                 dirMapping[dx] = al->numDirs;
    00441                 die = al->dirs + al->numDirs;
    00442                 if (dieNeedle->dirName != NULL)
    00443                     die->dirName = xstrdup(dieNeedle->dirName);
    00444                 die->dirNameLen = dieNeedle->dirNameLen;
    00445                 die->files = NULL;
    00446                 die->numFiles = 0;
    00447
    00448                 al->numDirs++;
    00449             }
    00450         }
    00451
    00452         for (first = rpmfiNext(fi); first >= 0;) {
    00453             fileIndexEntry fie;
    00454             int next;
    00455
    00456             /* Find the first file of the next directory. */
    00457             dx = rpmfiDX(fi);
    00458             while ((next = rpmfiNext(fi)) >= 0) {
    00459                 if (dx != rpmfiDX(fi))
    00460                     /*@innerbreak@*/ break;
    00461             }
    00462             if (next < 0) next = rpmfiFC(fi);   /* XXX reset end-of-list */
    00463
    00464             die = al->dirs + dirMapping[dx];
    00465             die->files = xrealloc(die->files,
    00466                         (die->numFiles + next - first) * sizeof(*die->files));
    00467
    00468             fie = die->files + die->numFiles;
    00469
    00470             /* Rewind to first file, generate file index entry for each file. */
    00471             fi = rpmfiInit(fi, first);
    00472             while ((first = rpmfiNext(fi)) >= 0 && first < next) {
    00473                 /*@-assignexpose -dependenttrans -observertrans @*/
    00474                 fie->baseName = rpmfiBN(fi);
    00475                 /*@=assignexpose =dependenttrans =observertrans @*/
    00476                 fie->baseNameLen = (fie->baseName ? strlen(fie->baseName) : 0);
    00477                 fie->pkgNum = pkgNum;
    00478                 fie->ficolor = rpmfiFColor(fi);
    00479
    00480                 die->numFiles++;
    00481                 fie++;
    00482             }
    00483             qsort(die->files, die->numFiles, sizeof(*die->files), fieCompare);
    00484         }
    00485
    00486         /* Resize the directory list. If any directories were added, resort. */
    00487         al->dirs = xrealloc(al->dirs, al->numDirs * sizeof(*al->dirs));
    00488         if (origNumDirs != al->numDirs)
    00489             qsort(al->dirs, al->numDirs, sizeof(*al->dirs), dieCompare);
    00490     }
    00491     fi = rpmfiUnlink(fi, "Files index (rpmalAdd)");
    00492
    00493     rpmalFreeIndex(al);
    00494
    00495 assert(((alNum)(alp - al->list)) == pkgNum);
    00496     return ((alKey)(alp - al->list));
    00497 }
    00498
    00505 static int indexcmp(const void * one, const void * two)
    00506         /*@*/
    00507 {
    00508     /*@-castexpose@*/
    00509     const availableIndexEntry a = (const availableIndexEntry) one;
    00510     const availableIndexEntry b = (const availableIndexEntry) two;
    00511     /*@=castexpose@*/
    00512     int lenchk;
    00513
    00514     lenchk = a->entryLen - b->entryLen;
    00515     if (lenchk)
    00516         return lenchk;
    00517
    00518     return strcmp(a->entry, b->entry);
    00519 }
    00520
    00521 void rpmalAddProvides(rpmal al, alKey pkgKey, rpmds provides, rpmuint32_t tscolor)
    00522 {
    00523     rpmuint32_t dscolor;
    00524     const char * Name;
    00525     alNum pkgNum = alKey2Num(al, pkgKey);
    00526     availableIndex ai = &al->index;
    00527     availableIndexEntry aie;
    00528     int ix;
    00529
    00530     if (provides == NULL || pkgNum < 0 || pkgNum >= al->size)
    00531         return;
    00532     if (ai->index == NULL || ai->k < 0 || ai->k >= ai->size)
    00533         return;
    00534
    00535     if (rpmdsInit(provides) != NULL)
    00536     while (rpmdsNext(provides) >= 0) {
    00537
    00538         if ((Name = provides->N[provides->i]) == NULL)
    00539             continue;   /* XXX can't happen */
    00540
    00541         /* Ignore colored provides not in our rainbow. */
    00542         dscolor = rpmdsColor(provides);
    00543         if (tscolor && dscolor && !(tscolor & dscolor))
    00544             continue;
    00545
    00546         aie = ai->index + ai->k;
    00547         ai->k++;
    00548
    00549         aie->pkgKey = pkgKey;
    00550 /*@-assignexpose@*/
    00551         aie->entry = Name;
    00552 /*@=assignexpose@*/
    00553         aie->entryLen = (unsigned short)strlen(Name);
    00554         ix = rpmdsIx(provides);
    00555
    00556 /* XXX make sure that element index fits in unsigned short */
    00557 assert(ix < 0x10000);
    00558
    00559         aie->entryIx = ix;
    00560         aie->type = IET_PROVIDES;
    00561     }
    00562 }
    00563
    00564 void rpmalMakeIndex(rpmal al)
    00565 {
    00566     availableIndex ai;
    00567     availablePackage alp;
    00568     int i;
    00569
    00570     if (al == NULL || al->list == NULL) return;
    00571     ai = &al->index;
    00572
    00573     ai->size = 0;
    00574     for (i = 0; i < al->size; i++) {
    00575         alp = al->list + i;
    00576         if (alp->provides != NULL)
    00577             ai->size += rpmdsCount(alp->provides);
    00578     }
    00579     if (ai->size == 0) return;
    00580
    00581     ai->index = xrealloc(ai->index, ai->size * sizeof(*ai->index));
    00582     ai->k = 0;
    00583     for (i = 0; i < al->size; i++) {
    00584         alp = al->list + i;
    00585         rpmalAddProvides(al, alNum2Key(NULL, (alNum)i), alp->provides, alp->tscolor);
    00586     }
    00587
    00588     /* Reset size to the no. of provides added. */
    00589     ai->size = ai->k;
    00590     qsort(ai->index, ai->size, sizeof(*ai->index), indexcmp);
    00591 }
    00592
    00593 fnpyKey *
    00594 rpmalAllFileSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
    00595 {
    00596     rpmuint32_t tscolor;
    00597     rpmuint32_t ficolor;
    00598     int found = 0;
    00599     const char * dirName;
    00600     const char * baseName;
    00601     dirInfo dieNeedle =
    00602                 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
    00603     dirInfo die;
    00604     fileIndexEntry fieNeedle =
    00605                 memset(alloca(sizeof(*fieNeedle)), 0, sizeof(*fieNeedle));
    00606     fileIndexEntry fie;
    00607     availablePackage alp;
    00608     fnpyKey * ret = NULL;
    00609     const char * fileName;
    00610
    00611     if (keyp) *keyp = RPMAL_NOMATCH;
    00612
    00613     if (al == NULL || (fileName = rpmdsN(ds)) == NULL || *fileName != '/')
    00614         return NULL;
    00615
    00616     /* Solaris 2.6 bsearch sucks down on this. */
    00617     if (al->numDirs == 0 || al->dirs == NULL || al->list == NULL)
    00618         return NULL;
    00619
    00620     {   char * t;
    00621         dirName = t = xstrdup(fileName);
    00622         if ((t = strrchr(t, '/')) != NULL) {
    00623             t++;                /* leave the trailing '/' */
    00624             *t = '\0';
    00625         }
    00626     }
    00627
    00628     dieNeedle->dirName = (char *) dirName;
    00629     dieNeedle->dirNameLen = strlen(dirName);
    00630     die = bsearch(dieNeedle, al->dirs, al->numDirs,
    00631                        sizeof(*dieNeedle), dieCompare);
    00632     if (die == NULL)
    00633         goto exit;
    00634
    00635     /* rewind to the first match */
    00636     while (die > al->dirs && dieCompare(die-1, dieNeedle) == 0)
    00637         die--;
    00638
    00639     if ((baseName = strrchr(fileName, '/')) == NULL)
    00640         goto exit;
    00641     baseName++;
    00642
    00643     for (found = 0, ret = NULL;
    00644          die < al->dirs + al->numDirs && dieCompare(die, dieNeedle) == 0;
    00645          die++)
    00646     {
    00647
    00648 /*@-observertrans@*/
    00649         fieNeedle->baseName = baseName;
    00650 /*@=observertrans@*/
    00651         fieNeedle->baseNameLen = strlen(fieNeedle->baseName);
    00652         fie = bsearch(fieNeedle, die->files, die->numFiles,
    00653                        sizeof(*fieNeedle), fieCompare);
    00654         if (fie == NULL)
    00655             continue;   /* XXX shouldn't happen */
    00656
    00657         alp = al->list + fie->pkgNum;
    00658
    00659         /* Ignore colored files not in our rainbow. */
    00660         tscolor = alp->tscolor;
    00661         ficolor = fie->ficolor;
    00662         if (tscolor && ficolor && !(tscolor & ficolor))
    00663             continue;
    00664
    00665         rpmdsNotify(ds, _("(added files)"), 0);
    00666
    00667         ret = xrealloc(ret, (found+2) * sizeof(*ret));
    00668         if (ret)        /* can't happen */
    00669             ret[found] = alp->key;
    00670         if (keyp)
    00671             *keyp = alNum2Key(al, fie->pkgNum);
    00672         found++;
    00673     }
    00674
    00675 exit:
    00676     dirName = _free(dirName);
    00677     if (ret)
    00678         ret[found] = NULL;
    00679     return ret;
    00680 }
    00681
    00682 fnpyKey *
    00683 rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
    00684 {
    00685     availableIndex ai;
    00686     availableIndexEntry needle;
    00687     availableIndexEntry match;
    00688     fnpyKey * ret = NULL;
    00689     int found = 0;
    00690     const char * KName;
    00691     availablePackage alp;
    00692     int rc;
    00693
    00694     if (keyp) *keyp = RPMAL_NOMATCH;
    00695
    00696     if (al == NULL || ds == NULL || (KName = rpmdsN(ds)) == NULL)
    00697         return ret;
    00698
    00699     if (*KName == '/') {
    00700         /* First, look for files "contained" in package ... */
    00701         ret = rpmalAllFileSatisfiesDepend(al, ds, keyp);
    00702         if (ret != NULL && *ret != NULL)
    00703             return ret;
    00704         ret = _free(ret);
    00705         /* ... then, look for files "provided" by package. */
    00706     }
    00707
    00708     ai = &al->index;
    00709     if (ai->index == NULL || ai->size <= 0)
    00710         return NULL;
    00711
    00712     needle = memset(alloca(sizeof(*needle)), 0, sizeof(*needle));
    00713     /*@-assignexpose -temptrans@*/
    00714     needle->entry = KName;
    00715     /*@=assignexpose =temptrans@*/
    00716     needle->entryLen = (unsigned short)strlen(needle->entry);
    00717
    00718     match = bsearch(needle, ai->index, ai->size, sizeof(*ai->index), indexcmp);
    00719     if (match == NULL)
    00720         return NULL;
    00721
    00722     /* rewind to the first match */
    00723     while (match > ai->index && indexcmp(match-1, needle) == 0)
    00724         match--;
    00725
    00726     if (al->list != NULL)       /* XXX always true */
    00727     for (ret = NULL, found = 0;
    00728          match < ai->index + ai->size && indexcmp(match, needle) == 0;
    00729          match++)
    00730     {
    00731         alp = al->list + alKey2Num(al, match->pkgKey);
    00732
    00733         rc = 0;
    00734         if (alp->provides != NULL)      /* XXX can't happen */
    00735         switch (match->type) {
    00736         case IET_PROVIDES:
    00737             /* XXX single step on rpmdsNext to regenerate DNEVR string */
    00738             (void) rpmdsSetIx(alp->provides, match->entryIx - 1);
    00739             if (rpmdsNext(alp->provides) >= 0)
    00740                 rc = rpmdsCompare(alp->provides, ds);
    00741
    00742             if (rc)
    00743                 rpmdsNotify(ds, _("(added provide)"), 0);
    00744
    00745             /*@switchbreak@*/ break;
    00746         }
    00747
    00748         if (rc) {
    00749             ret = xrealloc(ret, (found + 2) * sizeof(*ret));
    00750             if (ret)    /* can't happen */
    00751                 ret[found] = alp->key;
    00752 /*@-dependenttrans@*/
    00753             if (keyp)
    00754                 *keyp = match->pkgKey;
    00755 /*@=dependenttrans@*/
    00756             found++;
    00757         }
    00758     }
    00759
    00760     if (ret)
    00761         ret[found] = NULL;
    00762
    00763 /*@-nullstate@*/ /* FIX: *keyp may be NULL */
    00764     return ret;
    00765 /*@=nullstate@*/
    00766 }
    00767
    00768 fnpyKey
    00769 rpmalSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
    00770 {
    00771     fnpyKey * tmp = rpmalAllSatisfiesDepend(al, ds, keyp);
    00772
    00773     if (tmp) {
    00774         fnpyKey ret = tmp[0];
    00775         free(tmp);
    00776         return ret;
    00777     }
    00778     return NULL;
    00779 }