lib/rpmal.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 
00007 #include <rpmlib.h>
00008 
00009 #include "rpmal.h"
00010 #include "rpmds.h"
00011 #include "rpmfi.h"
00012 
00013 #include "debug.h"
00014 
00015 typedef /*@abstract@*/ struct availablePackage_s * availablePackage;
00016 
00017 /*@unchecked@*/
00018 int _rpmal_debug = 0;
00019 
00020 /*@access alKey @*/
00021 /*@access alNum @*/
00022 /*@access rpmal @*/
00023 /*@access availablePackage @*/
00024 
00025 /*@access fnpyKey @*/   /* XXX suggestedKeys array */
00026 
00030 struct availablePackage_s {
00031 /*@refcounted@*/ /*@null@*/
00032     rpmds provides;             
00033 /*@refcounted@*/ /*@null@*/
00034     rpmfi fi;                   
00036     uint_32 tscolor;            
00038 /*@exposed@*/ /*@dependent@*/ /*@null@*/
00039     fnpyKey key;                
00041 };
00042 
00043 typedef /*@abstract@*/ struct availableIndexEntry_s *   availableIndexEntry;
00044 /*@access availableIndexEntry@*/
00045 
00049 struct availableIndexEntry_s {
00050 /*@exposed@*/ /*@dependent@*/ /*@null@*/
00051     alKey pkgKey;               
00052 /*@observer@*/
00053     const char * entry;         
00054     unsigned short entryLen;    
00055     unsigned short entryIx;     
00056     enum indexEntryType {
00057         IET_PROVIDES=1                  
00058     } type;                     
00059 };
00060 
00061 typedef /*@abstract@*/ struct availableIndex_s *        availableIndex;
00062 /*@access availableIndex@*/
00063 
00067 struct availableIndex_s {
00068 /*@null@*/
00069     availableIndexEntry index;  
00070     int size;                   
00071     int k;                      
00072 };
00073 
00074 typedef /*@abstract@*/ struct fileIndexEntry_s *        fileIndexEntry;
00075 /*@access fileIndexEntry@*/
00076 
00080 struct fileIndexEntry_s {
00081 /*@dependent@*/ /*@relnull@*/
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@*/ /*@relnull@*/
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 #ifdef  NOISY
00282 /*@-modfilesys@*/
00283 if (_rpmal_debug) {
00284 fprintf(stderr, "\t\tstrcmp(%p:%p, %p:%p)", a, a->baseName, b, b->baseName);
00285 #if 0
00286 fprintf(stderr, " a %s", a->baseName);
00287 #endif
00288 fprintf(stderr, " b %s", a->baseName);
00289 fprintf(stderr, "\n");
00290 }
00291 /*@=modfilesys@*/
00292 #endif
00293 
00294     return strcmp(a->baseName, b->baseName);
00295 }
00296 
00297 void rpmalDel(rpmal al, alKey pkgKey)
00298 {
00299     alNum pkgNum = alKey2Num(al, pkgKey);
00300     availablePackage alp;
00301     rpmfi fi;
00302 
00303     if (al == NULL || al->list == NULL)
00304         return;         /* XXX can't happen */
00305 
00306     alp = al->list + pkgNum;
00307 
00308 /*@-modfilesys@*/
00309 if (_rpmal_debug)
00310 fprintf(stderr, "*** del %p[%d]\n", al->list, pkgNum);
00311 /*@=modfilesys@*/
00312 
00313     /* Delete directory/file info entries from added package list. */
00314     if ((fi = alp->fi) != NULL)
00315     if (rpmfiFC(fi) > 0) {
00316         int origNumDirs = al->numDirs;
00317         int dx;
00318         dirInfo dieNeedle =
00319                 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
00320         dirInfo die;
00321         int last;
00322         int i;
00323 
00324         /* XXX FIXME: We ought to relocate the directory list here */
00325 
00326         if (al->dirs != NULL)
00327         for (dx = rpmfiDC(fi) - 1; dx >= 0; dx--)
00328         {
00329             fileIndexEntry fie;
00330 
00331             (void) rpmfiSetDX(fi, dx);
00332 
00333             /*@-assignexpose -dependenttrans -observertrans@*/
00334             dieNeedle->dirName = (char *) rpmfiDN(fi);
00335             /*@=assignexpose =dependenttrans =observertrans@*/
00336             dieNeedle->dirNameLen = (dieNeedle->dirName != NULL
00337                         ? strlen(dieNeedle->dirName) : 0);
00338 /*@-boundswrite@*/
00339             die = bsearch(dieNeedle, al->dirs, al->numDirs,
00340                                sizeof(*dieNeedle), dieCompare);
00341 /*@=boundswrite@*/
00342             if (die == NULL)
00343                 continue;
00344 
00345 /*@-modfilesys@*/
00346 if (_rpmal_debug)
00347 fprintf(stderr, "--- die[%5d] %p [%3d] %s\n", (die - al->dirs), die, die->dirNameLen, die->dirName);
00348 /*@=modfilesys@*/
00349 
00350             last = die->numFiles;
00351             fie = die->files + last - 1;
00352             for (i = last - 1; i >= 0; i--, fie--) {
00353                 if (fie->pkgNum != pkgNum)
00354                     /*@innercontinue@*/ continue;
00355                 die->numFiles--;
00356 
00357                 if (i < die->numFiles) {
00358 /*@-modfilesys@*/
00359 if (_rpmal_debug)
00360 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, ((die->numFiles - i) * sizeof(*fie)), fie->baseName, (fie+1)->baseName);
00361 /*@=modfilesys@*/
00362 
00363 /*@-bounds@*/
00364                     memmove(fie, fie+1, (die->numFiles - i) * sizeof(*fie));
00365 /*@=bounds@*/
00366                 }
00367 /*@-modfilesys@*/
00368 if (_rpmal_debug)
00369 fprintf(stderr, "\t%p[%3d] memset(%p,0,0x%x) %p [%3d] %s\n", die->files, die->numFiles, die->files + die->numFiles, sizeof(*fie), fie->baseName, fie->baseNameLen, fie->baseName);
00370 /*@=modfilesys@*/
00371                 memset(die->files + die->numFiles, 0, sizeof(*fie)); /* overkill */
00372 
00373             }
00374             if (die->numFiles > 0) {
00375                 if (last > i)
00376                     die->files = xrealloc(die->files,
00377                                         die->numFiles * sizeof(*die->files));
00378                 continue;
00379             }
00380             die->files = _free(die->files);
00381             die->dirName = _free(die->dirName);
00382             al->numDirs--;
00383             if ((die - al->dirs) < al->numDirs) {
00384 /*@-modfilesys@*/
00385 if (_rpmal_debug)
00386 fprintf(stderr, "    die[%5d] memmove(%p,%p,0x%x)\n", (die - al->dirs), die, die+1, ((al->numDirs - (die - al->dirs)) * sizeof(*die)));
00387 /*@=modfilesys@*/
00388 
00389 /*@-bounds@*/
00390                 memmove(die, die+1, (al->numDirs - (die - al->dirs)) * sizeof(*die));
00391 /*@=bounds@*/
00392             }
00393 
00394 /*@-modfilesys@*/
00395 if (_rpmal_debug)
00396 fprintf(stderr, "    die[%5d] memset(%p,0,0x%x)\n", al->numDirs, al->dirs + al->numDirs, sizeof(*die));
00397 /*@=modfilesys@*/
00398             memset(al->dirs + al->numDirs, 0, sizeof(*al->dirs)); /* overkill */
00399         }
00400 
00401         if (origNumDirs > al->numDirs) {
00402             if (al->numDirs > 0)
00403                 al->dirs = xrealloc(al->dirs, al->numDirs * sizeof(*al->dirs));
00404             else
00405                 al->dirs = _free(al->dirs);
00406         }
00407     }
00408 
00409     alp->provides = rpmdsFree(alp->provides);
00410     alp->fi = rpmfiFree(alp->fi);
00411 
00412 /*@-boundswrite@*/
00413     memset(alp, 0, sizeof(*alp));       /* XXX trash and burn */
00414 /*@=boundswrite@*/
00415     return;
00416 }
00417 
00418 /*@-bounds@*/
00419 alKey rpmalAdd(rpmal * alistp, alKey pkgKey, fnpyKey key,
00420                 rpmds provides, rpmfi fi, uint_32 tscolor)
00421 {
00422     alNum pkgNum;
00423     rpmal al;
00424     availablePackage alp;
00425 
00426     /* If list doesn't exist yet, create. */
00427     if (*alistp == NULL)
00428         *alistp = rpmalCreate(5);
00429     al = *alistp;
00430     pkgNum = alKey2Num(al, pkgKey);
00431 
00432     if (pkgNum >= 0 && pkgNum < al->size) {
00433         rpmalDel(al, pkgKey);
00434     } else {
00435         if (al->size == al->alloced) {
00436             al->alloced += al->delta;
00437             al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced);
00438         }
00439         pkgNum = al->size++;
00440     }
00441 
00442     if (al->list == NULL)
00443         return RPMAL_NOMATCH;           /* XXX can't happen */
00444 
00445     alp = al->list + pkgNum;
00446 
00447     alp->key = key;
00448     alp->tscolor = tscolor;
00449 
00450 /*@-modfilesys@*/
00451 if (_rpmal_debug)
00452 fprintf(stderr, "*** add %p[%d] 0x%x\n", al->list, pkgNum, tscolor);
00453 /*@=modfilesys@*/
00454 
00455     alp->provides = rpmdsLink(provides, "Provides (rpmalAdd)");
00456     alp->fi = rpmfiLink(fi, "Files (rpmalAdd)");
00457 
00458     fi = rpmfiLink(alp->fi, "Files index (rpmalAdd)");
00459     fi = rpmfiInit(fi, 0);
00460     if (rpmfiFC(fi) > 0) {
00461         dirInfo dieNeedle =
00462                 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
00463         dirInfo die;
00464         int dc = rpmfiDC(fi);
00465         int dx;
00466         int * dirMapping = alloca(sizeof(*dirMapping) * dc);
00467         int * dirUnique = alloca(sizeof(*dirUnique) * dc);
00468         const char * DN;
00469         int origNumDirs;
00470         int first;
00471         int i;
00472 
00473         /* XXX FIXME: We ought to relocate the directory list here */
00474 
00475         /* XXX enough space for all directories, late realloc to truncate. */
00476         al->dirs = xrealloc(al->dirs, (al->numDirs + dc) * sizeof(*al->dirs));
00477 
00478         /* Only previously allocated dirInfo is sorted and bsearch'able. */
00479         origNumDirs = al->numDirs;
00480 
00481         /* Package dirnames are not currently unique. Create unique mapping. */
00482         for (dx = 0; dx < dc; dx++) {
00483             (void) rpmfiSetDX(fi, dx);
00484             DN = rpmfiDN(fi);
00485             if (DN != NULL)
00486             for (i = 0; i < dx; i++) {
00487                 const char * iDN;
00488                 (void) rpmfiSetDX(fi, i);
00489                 iDN = rpmfiDN(fi);
00490                 if (iDN != NULL && !strcmp(DN, iDN))
00491                     /*@innerbreak@*/ break;
00492             }
00493             dirUnique[dx] = i;
00494         }
00495 
00496         /* Map package dirs into transaction dirInfo index. */
00497         for (dx = 0; dx < dc; dx++) {
00498 
00499             /* Non-unique package dirs use the 1st entry mapping. */
00500             if (dirUnique[dx] < dx) {
00501                 dirMapping[dx] = dirMapping[dirUnique[dx]];
00502                 continue;
00503             }
00504 
00505             /* Find global dirInfo mapping for first encounter. */
00506             (void) rpmfiSetDX(fi, dx);
00507 
00508             /*@-assignexpose -dependenttrans -observertrans@*/
00509             {   DN = rpmfiDN(fi);
00510 
00511 #if defined(__ia64__)
00512 /* XXX Make sure that autorelocated file dependencies are satisfied. */
00513 #define DNPREFIX        "/emul/ia32-linux"
00514                 if (!strncmp(DN, DNPREFIX, sizeof(DNPREFIX)-1))
00515                     DN += sizeof(DNPREFIX)-1;
00516 #endif
00517                 dieNeedle->dirName = DN;
00518             }
00519             /*@=assignexpose =dependenttrans =observertrans@*/
00520 
00521             dieNeedle->dirNameLen = (dieNeedle->dirName != NULL
00522                         ? strlen(dieNeedle->dirName) : 0);
00523             die = bsearch(dieNeedle, al->dirs, origNumDirs,
00524                                sizeof(*dieNeedle), dieCompare);
00525             if (die) {
00526                 dirMapping[dx] = die - al->dirs;
00527             } else {
00528                 dirMapping[dx] = al->numDirs;
00529                 die = al->dirs + al->numDirs;
00530                 if (dieNeedle->dirName != NULL)
00531                     die->dirName = xstrdup(dieNeedle->dirName);
00532                 die->dirNameLen = dieNeedle->dirNameLen;
00533                 die->files = NULL;
00534                 die->numFiles = 0;
00535 /*@-modfilesys@*/
00536 if (_rpmal_debug)
00537 fprintf(stderr, "+++ die[%5d] %p [%3d] %s\n", al->numDirs, die, die->dirNameLen, die->dirName);
00538 /*@=modfilesys@*/
00539 
00540                 al->numDirs++;
00541             }
00542         }
00543 
00544         for (first = rpmfiNext(fi); first >= 0;) {
00545             fileIndexEntry fie;
00546             int next;
00547 
00548             /* Find the first file of the next directory. */
00549             dx = rpmfiDX(fi);
00550             while ((next = rpmfiNext(fi)) >= 0) {
00551                 if (dx != rpmfiDX(fi))
00552                     /*@innerbreak@*/ break;
00553             }
00554             if (next < 0) next = rpmfiFC(fi);   /* XXX reset end-of-list */
00555 
00556             die = al->dirs + dirMapping[dx];
00557             die->files = xrealloc(die->files,
00558                         (die->numFiles + next - first) * sizeof(*die->files));
00559 
00560             fie = die->files + die->numFiles;
00561 
00562 /*@-modfilesys@*/
00563 if (_rpmal_debug)
00564 fprintf(stderr, "    die[%5d] %p->files [%p[%d],%p) -> [%p[%d],%p)\n", dirMapping[dx], die,
00565 die->files, die->numFiles, die->files+die->numFiles,
00566 fie, (next - first), fie + (next - first));
00567 /*@=modfilesys@*/
00568 
00569             /* Rewind to first file, generate file index entry for each file. */
00570             fi = rpmfiInit(fi, first);
00571             while ((first = rpmfiNext(fi)) >= 0 && first < next) {
00572                 /*@-assignexpose -dependenttrans -observertrans @*/
00573                 fie->baseName = rpmfiBN(fi);
00574                 /*@=assignexpose =dependenttrans =observertrans @*/
00575                 fie->baseNameLen = (fie->baseName ? strlen(fie->baseName) : 0);
00576                 fie->pkgNum = pkgNum;
00577                 fie->ficolor = rpmfiFColor(fi);
00578 /*@-modfilesys@*/
00579 if (_rpmal_debug)
00580 fprintf(stderr, "\t%p[%3d] %p:%p[%2d] %s\n", die->files, die->numFiles, fie, fie->baseName, fie->baseNameLen, rpmfiFN(fi));
00581 /*@=modfilesys@*/
00582 
00583                 die->numFiles++;
00584                 fie++;
00585             }
00586             qsort(die->files, die->numFiles, sizeof(*die->files), fieCompare);
00587         }
00588 
00589         /* Resize the directory list. If any directories were added, resort. */
00590         al->dirs = xrealloc(al->dirs, al->numDirs * sizeof(*al->dirs));
00591         if (origNumDirs != al->numDirs)
00592             qsort(al->dirs, al->numDirs, sizeof(*al->dirs), dieCompare);
00593     }
00594     fi = rpmfiUnlink(fi, "Files index (rpmalAdd)");
00595 
00596     rpmalFreeIndex(al);
00597 
00598 assert(((alNum)(alp - al->list)) == pkgNum);
00599     return ((alKey)(alp - al->list));
00600 }
00601 /*@=bounds@*/
00602 
00609 static int indexcmp(const void * one, const void * two)
00610         /*@*/
00611 {
00612     /*@-castexpose@*/
00613     const availableIndexEntry a = (const availableIndexEntry) one;
00614     const availableIndexEntry b = (const availableIndexEntry) two;
00615     /*@=castexpose@*/
00616     int lenchk;
00617 
00618     lenchk = a->entryLen - b->entryLen;
00619     if (lenchk)
00620         return lenchk;
00621 
00622     return strcmp(a->entry, b->entry);
00623 }
00624 
00625 void rpmalAddProvides(rpmal al, alKey pkgKey, rpmds provides, uint_32 tscolor)
00626 {
00627     uint_32 dscolor;
00628     const char * Name;
00629     alNum pkgNum = alKey2Num(al, pkgKey);
00630     availableIndex ai = &al->index;
00631     availableIndexEntry aie;
00632     int ix;
00633 
00634     if (provides == NULL || pkgNum < 0 || pkgNum >= al->size)
00635         return;
00636     if (ai->index == NULL || ai->k < 0 || ai->k >= ai->size)
00637         return;
00638 
00639     if (rpmdsInit(provides) != NULL)
00640     while (rpmdsNext(provides) >= 0) {
00641 
00642         if ((Name = rpmdsN(provides)) == NULL)
00643             continue;   /* XXX can't happen */
00644 
00645         /* Ignore colored provides not in our rainbow. */
00646         dscolor = rpmdsColor(provides);
00647         if (tscolor && dscolor && !(tscolor & dscolor))
00648             continue;
00649 
00650         aie = ai->index + ai->k;
00651         ai->k++;
00652 
00653         aie->pkgKey = pkgKey;
00654         aie->entry = Name;
00655         aie->entryLen = strlen(Name);
00656         ix = rpmdsIx(provides);
00657 
00658 /* XXX make sure that element index fits in unsigned short */
00659 assert(ix < 0x10000);
00660 
00661         aie->entryIx = ix;
00662         aie->type = IET_PROVIDES;
00663     }
00664 }
00665 
00666 void rpmalMakeIndex(rpmal al)
00667 {
00668     availableIndex ai;
00669     availablePackage alp;
00670     int i;
00671 
00672     if (al == NULL || al->list == NULL) return;
00673     ai = &al->index;
00674 
00675     ai->size = 0;
00676     for (i = 0; i < al->size; i++) {
00677         alp = al->list + i;
00678         if (alp->provides != NULL)
00679             ai->size += rpmdsCount(alp->provides);
00680     }
00681     if (ai->size == 0) return;
00682 
00683     ai->index = xrealloc(ai->index, ai->size * sizeof(*ai->index));
00684     ai->k = 0;
00685     for (i = 0; i < al->size; i++) {
00686         alp = al->list + i;
00687         rpmalAddProvides(al, (alKey)i, alp->provides, alp->tscolor);
00688     }
00689 
00690     /* Reset size to the no. of provides added. */
00691     ai->size = ai->k;
00692     qsort(ai->index, ai->size, sizeof(*ai->index), indexcmp);
00693 }
00694 
00695 fnpyKey *
00696 rpmalAllFileSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
00697 {
00698     uint_32 tscolor;
00699     uint_32 ficolor;
00700     int found = 0;
00701     const char * dirName;
00702     const char * baseName;
00703     dirInfo dieNeedle =
00704                 memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
00705     dirInfo die;
00706     fileIndexEntry fieNeedle =
00707                 memset(alloca(sizeof(*fieNeedle)), 0, sizeof(*fieNeedle));
00708     fileIndexEntry fie;
00709     availablePackage alp;
00710     fnpyKey * ret = NULL;
00711     const char * fileName;
00712 
00713     if (keyp) *keyp = RPMAL_NOMATCH;
00714 
00715     if (al == NULL || (fileName = rpmdsN(ds)) == NULL || *fileName != '/')
00716         return NULL;
00717 
00718     /* Solaris 2.6 bsearch sucks down on this. */
00719     if (al->numDirs == 0 || al->dirs == NULL || al->list == NULL)
00720         return NULL;
00721 
00722     {   char * t;
00723         dirName = t = xstrdup(fileName);
00724         if ((t = strrchr(t, '/')) != NULL) {
00725             t++;                /* leave the trailing '/' */
00726             *t = '\0';
00727         }
00728     }
00729 
00730     dieNeedle->dirName = (char *) dirName;
00731     dieNeedle->dirNameLen = strlen(dirName);
00732     die = bsearch(dieNeedle, al->dirs, al->numDirs,
00733                        sizeof(*dieNeedle), dieCompare);
00734     if (die == NULL)
00735         goto exit;
00736 
00737     /* rewind to the first match */
00738     while (die > al->dirs && dieCompare(die-1, dieNeedle) == 0)
00739         die--;
00740 
00741     if ((baseName = strrchr(fileName, '/')) == NULL)
00742         goto exit;
00743     baseName++;
00744 
00745     /*@-branchstate@*/ /* FIX: ret is a problem */
00746     for (found = 0, ret = NULL;
00747          die < al->dirs + al->numDirs && dieCompare(die, dieNeedle) == 0;
00748          die++)
00749     {
00750 
00751 /*@-modfilesys@*/
00752 if (_rpmal_debug)
00753 fprintf(stderr, "==> die %p %s\n", die, (die->dirName ? die->dirName : "(nil)"));
00754 /*@=modfilesys@*/
00755 
00756 /*@-observertrans@*/
00757         fieNeedle->baseName = baseName;
00758 /*@=observertrans@*/
00759         fieNeedle->baseNameLen = strlen(fieNeedle->baseName);
00760         fie = bsearch(fieNeedle, die->files, die->numFiles,
00761                        sizeof(*fieNeedle), fieCompare);
00762         if (fie == NULL)
00763             continue;   /* XXX shouldn't happen */
00764 
00765 /*@-modfilesys@*/
00766 if (_rpmal_debug)
00767 fprintf(stderr, "==> fie %p %s\n", fie, (fie->baseName ? fie->baseName : "(nil)"));
00768 /*@=modfilesys@*/
00769 
00770         alp = al->list + fie->pkgNum;
00771 
00772         /* Ignore colored files not in our rainbow. */
00773         tscolor = alp->tscolor;
00774         ficolor = fie->ficolor;
00775         if (tscolor && ficolor && !(tscolor & ficolor))
00776             continue;
00777 
00778         rpmdsNotify(ds, _("(added files)"), 0);
00779 
00780         ret = xrealloc(ret, (found+2) * sizeof(*ret));
00781         if (ret)        /* can't happen */
00782             ret[found] = alp->key;
00783         if (keyp)
00784             *keyp = alNum2Key(al, fie->pkgNum);
00785         found++;
00786     }
00787     /*@=branchstate@*/
00788 
00789 exit:
00790     dirName = _free(dirName);
00791     if (ret)
00792         ret[found] = NULL;
00793     return ret;
00794 }
00795 
00796 fnpyKey *
00797 rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
00798 {
00799     availableIndex ai;
00800     availableIndexEntry needle;
00801     availableIndexEntry match;
00802     fnpyKey * ret = NULL;
00803     int found = 0;
00804     const char * KName;
00805     availablePackage alp;
00806     int rc;
00807 
00808     if (keyp) *keyp = RPMAL_NOMATCH;
00809 
00810     if (al == NULL || ds == NULL || (KName = rpmdsN(ds)) == NULL)
00811         return ret;
00812 
00813     if (*KName == '/') {
00814         /* First, look for files "contained" in package ... */
00815         ret = rpmalAllFileSatisfiesDepend(al, ds, keyp);
00816         if (ret != NULL && *ret != NULL)
00817             return ret;
00818         /* ... then, look for files "provided" by package. */
00819         ret = _free(ret);
00820     }
00821 
00822     ai = &al->index;
00823     if (ai->index == NULL || ai->size <= 0)
00824         return NULL;
00825 
00826     needle = memset(alloca(sizeof(*needle)), 0, sizeof(*needle));
00827     /*@-assignexpose -temptrans@*/
00828     needle->entry = KName;
00829     /*@=assignexpose =temptrans@*/
00830     needle->entryLen = strlen(needle->entry);
00831 
00832     match = bsearch(needle, ai->index, ai->size, sizeof(*ai->index), indexcmp);
00833     if (match == NULL)
00834         return NULL;
00835 
00836     /* rewind to the first match */
00837     while (match > ai->index && indexcmp(match-1, needle) == 0)
00838         match--;
00839 
00840     if (al->list != NULL)       /* XXX always true */
00841     for (ret = NULL, found = 0;
00842          match < ai->index + ai->size && indexcmp(match, needle) == 0;
00843          match++)
00844     {
00845         alp = al->list + alKey2Num(al, match->pkgKey);
00846 
00847         rc = 0;
00848         if (alp->provides != NULL)      /* XXX can't happen */
00849         switch (match->type) {
00850         case IET_PROVIDES:
00851             /* XXX single step on rpmdsNext to regenerate DNEVR string */
00852             (void) rpmdsSetIx(alp->provides, match->entryIx - 1);
00853             if (rpmdsNext(alp->provides) >= 0)
00854                 rc = rpmdsCompare(alp->provides, ds);
00855 
00856             if (rc)
00857                 rpmdsNotify(ds, _("(added provide)"), 0);
00858 
00859             /*@switchbreak@*/ break;
00860         }
00861 
00862         /*@-branchstate@*/
00863         if (rc) {
00864             ret = xrealloc(ret, (found + 2) * sizeof(*ret));
00865             if (ret)    /* can't happen */
00866                 ret[found] = alp->key;
00867 /*@-dependenttrans@*/
00868             if (keyp)
00869                 *keyp = match->pkgKey;
00870 /*@=dependenttrans@*/
00871             found++;
00872         }
00873         /*@=branchstate@*/
00874     }
00875 
00876     if (ret)
00877         ret[found] = NULL;
00878 
00879 /*@-nullstate@*/ /* FIX: *keyp may be NULL */
00880     return ret;
00881 /*@=nullstate@*/
00882 }
00883 
00884 fnpyKey
00885 rpmalSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
00886 {
00887     fnpyKey * tmp = rpmalAllSatisfiesDepend(al, ds, keyp);
00888 
00889     if (tmp) {
00890         fnpyKey ret = tmp[0];
00891         free(tmp);
00892         return ret;
00893     }
00894     return NULL;
00895 }

Generated on Fri Oct 12 08:44:53 2007 for rpm by  doxygen 1.5.2