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

Generated on Mon Nov 29 2010 05:18:43 for rpm by  doxygen 1.7.2