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

lib/rpmds.c

Go to the documentation of this file.
00001 
00004 #include "system.h"
00005 
00006 #include <rpmlib.h>
00007 
00008 #define _RPMDS_INTERNAL
00009 #include "rpmds.h"
00010 
00011 #include "debug.h"
00012 
00016 /*@unchecked@*/
00017 static int _noisy_range_comparison_debug_message = 0;
00018 
00019 /*@unchecked@*/
00020 int _rpmds_debug = 0;
00021 
00022 /*@unchecked@*/
00023 int _rpmds_nopromote = 1;
00024 
00025 /*@unchecked@*/
00026 /*@-exportheadervar@*/
00027 int _rpmds_unspecified_epoch_noise = 0;
00028 /*@=exportheadervar@*/
00029 
00030 rpmds XrpmdsUnlink(rpmds ds, const char * msg, const char * fn, unsigned ln)
00031 {
00032     if (ds == NULL) return NULL;
00033 /*@-modfilesys@*/
00034 if (_rpmds_debug && msg != NULL)
00035 fprintf(stderr, "--> ds %p -- %d %s at %s:%u\n", ds, ds->nrefs, msg, fn, ln);
00036 /*@=modfilesys@*/
00037     ds->nrefs--;
00038     return NULL;
00039 }
00040 
00041 rpmds XrpmdsLink(rpmds ds, const char * msg, const char * fn, unsigned ln)
00042 {
00043     if (ds == NULL) return NULL;
00044     ds->nrefs++;
00045 
00046 /*@-modfilesys@*/
00047 if (_rpmds_debug && msg != NULL)
00048 fprintf(stderr, "--> ds %p ++ %d %s at %s:%u\n", ds, ds->nrefs, msg, fn, ln);
00049 /*@=modfilesys@*/
00050 
00051     /*@-refcounttrans@*/ return ds; /*@=refcounttrans@*/
00052 }
00053 
00054 rpmds rpmdsFree(rpmds ds)
00055 {
00056     HFD_t hfd = headerFreeData;
00057     rpmTag tagEVR, tagF;
00058 
00059     if (ds == NULL)
00060         return NULL;
00061 
00062     if (ds->nrefs > 1)
00063         return rpmdsUnlink(ds, ds->Type);
00064 
00065 /*@-modfilesys@*/
00066 if (_rpmds_debug < 0)
00067 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
00068 /*@=modfilesys@*/
00069 
00070     if (ds->tagN == RPMTAG_PROVIDENAME) {
00071         tagEVR = RPMTAG_PROVIDEVERSION;
00072         tagF = RPMTAG_PROVIDEFLAGS;
00073     } else
00074     if (ds->tagN == RPMTAG_REQUIRENAME) {
00075         tagEVR = RPMTAG_REQUIREVERSION;
00076         tagF = RPMTAG_REQUIREFLAGS;
00077     } else
00078     if (ds->tagN == RPMTAG_CONFLICTNAME) {
00079         tagEVR = RPMTAG_CONFLICTVERSION;
00080         tagF = RPMTAG_CONFLICTFLAGS;
00081     } else
00082     if (ds->tagN == RPMTAG_OBSOLETENAME) {
00083         tagEVR = RPMTAG_OBSOLETEVERSION;
00084         tagF = RPMTAG_OBSOLETEFLAGS;
00085     } else
00086     if (ds->tagN == RPMTAG_TRIGGERNAME) {
00087         tagEVR = RPMTAG_TRIGGERVERSION;
00088         tagF = RPMTAG_TRIGGERFLAGS;
00089     } else
00090         return NULL;
00091 
00092     /*@-branchstate@*/
00093     if (ds->Count > 0) {
00094         ds->N = hfd(ds->N, ds->Nt);
00095         ds->EVR = hfd(ds->EVR, ds->EVRt);
00096         /*@-evalorder@*/
00097         ds->Flags = (ds->h != NULL ? hfd(ds->Flags, ds->Ft) : _free(ds->Flags));
00098         /*@=evalorder@*/
00099         ds->h = headerFree(ds->h);
00100     }
00101     /*@=branchstate@*/
00102 
00103     ds->DNEVR = _free(ds->DNEVR);
00104     ds->Color = _free(ds->Color);
00105     ds->Refs = _free(ds->Refs);
00106 
00107     (void) rpmdsUnlink(ds, ds->Type);
00108     /*@-refcounttrans -usereleased@*/
00109 /*@-boundswrite@*/
00110     memset(ds, 0, sizeof(*ds));         /* XXX trash and burn */
00111 /*@=boundswrite@*/
00112     ds = _free(ds);
00113     /*@=refcounttrans =usereleased@*/
00114     return NULL;
00115 }
00116 
00117 rpmds rpmdsNew(Header h, rpmTag tagN, int scareMem)
00118 {
00119     HGE_t hge =
00120         (scareMem ? (HGE_t) headerGetEntryMinMemory : (HGE_t) headerGetEntry);
00121     rpmTag tagEVR, tagF;
00122     rpmds ds = NULL;
00123     const char * Type;
00124     const char ** N;
00125     rpmTagType Nt;
00126     int_32 Count;
00127 
00128     if (tagN == RPMTAG_PROVIDENAME) {
00129         Type = "Provides";
00130         tagEVR = RPMTAG_PROVIDEVERSION;
00131         tagF = RPMTAG_PROVIDEFLAGS;
00132     } else
00133     if (tagN == RPMTAG_REQUIRENAME) {
00134         Type = "Requires";
00135         tagEVR = RPMTAG_REQUIREVERSION;
00136         tagF = RPMTAG_REQUIREFLAGS;
00137     } else
00138     if (tagN == RPMTAG_CONFLICTNAME) {
00139         Type = "Conflicts";
00140         tagEVR = RPMTAG_CONFLICTVERSION;
00141         tagF = RPMTAG_CONFLICTFLAGS;
00142     } else
00143     if (tagN == RPMTAG_OBSOLETENAME) {
00144         Type = "Obsoletes";
00145         tagEVR = RPMTAG_OBSOLETEVERSION;
00146         tagF = RPMTAG_OBSOLETEFLAGS;
00147     } else
00148     if (tagN == RPMTAG_TRIGGERNAME) {
00149         Type = "Trigger";
00150         tagEVR = RPMTAG_TRIGGERVERSION;
00151         tagF = RPMTAG_TRIGGERFLAGS;
00152     } else
00153         goto exit;
00154 
00155     /*@-branchstate@*/
00156     if (hge(h, tagN, &Nt, (void **) &N, &Count)
00157      && N != NULL && Count > 0)
00158     {
00159         int xx;
00160 
00161         ds = xcalloc(1, sizeof(*ds));
00162         ds->Type = Type;
00163         ds->h = (scareMem ? headerLink(h) : NULL);
00164         ds->i = -1;
00165         ds->DNEVR = NULL;
00166         ds->tagN = tagN;
00167         ds->N = N;
00168         ds->Nt = Nt;
00169         ds->Count = Count;
00170         ds->nopromote = _rpmds_nopromote;
00171 
00172         xx = hge(h, tagEVR, &ds->EVRt, (void **) &ds->EVR, NULL);
00173         xx = hge(h, tagF, &ds->Ft, (void **) &ds->Flags, NULL);
00174 /*@-boundsread@*/
00175         if (!scareMem && ds->Flags != NULL)
00176             ds->Flags = memcpy(xmalloc(ds->Count * sizeof(*ds->Flags)),
00177                                 ds->Flags, ds->Count * sizeof(*ds->Flags));
00178 /*@=boundsread@*/
00179         ds->Color = xcalloc(Count, sizeof(*ds->Color));
00180         ds->Refs = xcalloc(Count, sizeof(*ds->Refs));
00181 
00182 /*@-modfilesys@*/
00183 if (_rpmds_debug < 0)
00184 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
00185 /*@=modfilesys@*/
00186 
00187     }
00188     /*@=branchstate@*/
00189 
00190 exit:
00191     /*@-nullstate@*/ /* FIX: ds->Flags may be NULL */
00192     return rpmdsLink(ds, (ds ? ds->Type : NULL));
00193     /*@=nullstate@*/
00194 }
00195 
00196 char * rpmdsNewDNEVR(const char * dspfx, const rpmds ds)
00197 {
00198     char * tbuf, * t;
00199     size_t nb;
00200 
00201     nb = 0;
00202     if (dspfx)  nb += strlen(dspfx) + 1;
00203 /*@-boundsread@*/
00204     if (ds->N[ds->i])   nb += strlen(ds->N[ds->i]);
00205     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00206     if (ds->Flags != NULL && (ds->Flags[ds->i] & RPMSENSE_SENSEMASK)) {
00207         if (nb) nb++;
00208         if (ds->Flags[ds->i] & RPMSENSE_LESS)   nb++;
00209         if (ds->Flags[ds->i] & RPMSENSE_GREATER) nb++;
00210         if (ds->Flags[ds->i] & RPMSENSE_EQUAL)  nb++;
00211     }
00212     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00213     if (ds->EVR != NULL && ds->EVR[ds->i] && *ds->EVR[ds->i]) {
00214         if (nb) nb++;
00215         nb += strlen(ds->EVR[ds->i]);
00216     }
00217 /*@=boundsread@*/
00218 
00219 /*@-boundswrite@*/
00220     t = tbuf = xmalloc(nb + 1);
00221     if (dspfx) {
00222         t = stpcpy(t, dspfx);
00223         *t++ = ' ';
00224     }
00225     if (ds->N[ds->i])
00226         t = stpcpy(t, ds->N[ds->i]);
00227     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00228     if (ds->Flags != NULL && (ds->Flags[ds->i] & RPMSENSE_SENSEMASK)) {
00229         if (t != tbuf)  *t++ = ' ';
00230         if (ds->Flags[ds->i] & RPMSENSE_LESS)   *t++ = '<';
00231         if (ds->Flags[ds->i] & RPMSENSE_GREATER) *t++ = '>';
00232         if (ds->Flags[ds->i] & RPMSENSE_EQUAL)  *t++ = '=';
00233     }
00234     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00235     if (ds->EVR != NULL && ds->EVR[ds->i] && *ds->EVR[ds->i]) {
00236         if (t != tbuf)  *t++ = ' ';
00237         t = stpcpy(t, ds->EVR[ds->i]);
00238     }
00239     *t = '\0';
00240 /*@=boundswrite@*/
00241     return tbuf;
00242 }
00243 
00244 rpmds rpmdsThis(Header h, rpmTag tagN, int_32 Flags)
00245 {
00246     HGE_t hge = (HGE_t) headerGetEntryMinMemory;
00247     rpmds ds = NULL;
00248     const char * Type;
00249     const char * n, * v, * r;
00250     int_32 * ep;
00251     const char ** N, ** EVR;
00252     char * t;
00253     int xx;
00254 
00255     if (tagN == RPMTAG_PROVIDENAME) {
00256         Type = "Provides";
00257     } else
00258     if (tagN == RPMTAG_REQUIRENAME) {
00259         Type = "Requires";
00260     } else
00261     if (tagN == RPMTAG_CONFLICTNAME) {
00262         Type = "Conflicts";
00263     } else
00264     if (tagN == RPMTAG_OBSOLETENAME) {
00265         Type = "Obsoletes";
00266     } else
00267     if (tagN == RPMTAG_TRIGGERNAME) {
00268         Type = "Trigger";
00269     } else
00270         goto exit;
00271 
00272     xx = headerNVR(h, &n, &v, &r);
00273     ep = NULL;
00274     xx = hge(h, RPMTAG_EPOCH, NULL, (void **)&ep, NULL);
00275 
00276     t = xmalloc(sizeof(*N) + strlen(n) + 1);
00277 /*@-boundswrite@*/
00278     N = (const char **) t;
00279     t += sizeof(*N);
00280     *t = '\0';
00281     N[0] = t;
00282     t = stpcpy(t, n);
00283 
00284     t = xmalloc(sizeof(*EVR) +
00285                 (ep ? 20 : 0) + strlen(v) + strlen(r) + sizeof("-"));
00286     EVR = (const char **) t;
00287     t += sizeof(*EVR);
00288     *t = '\0';
00289     EVR[0] = t;
00290     if (ep) {
00291         sprintf(t, "%d:", *ep);
00292         t += strlen(t);
00293     }
00294     t = stpcpy( stpcpy( stpcpy( t, v), "-"), r);
00295 /*@=boundswrite@*/
00296 
00297     ds = xcalloc(1, sizeof(*ds));
00298     ds->h = NULL;
00299     ds->Type = Type;
00300     ds->tagN = tagN;
00301     ds->Count = 1;
00302     ds->N = N;
00303     ds->Nt = -1;        /* XXX to insure that hfd will free */
00304     ds->EVR = EVR;
00305     ds->EVRt = -1;      /* XXX to insure that hfd will free */
00306 /*@-boundswrite@*/
00307     ds->Flags = xmalloc(sizeof(*ds->Flags));    ds->Flags[0] = Flags;
00308 /*@=boundswrite@*/
00309     ds->i = 0;
00310     {   char pre[2];
00311 /*@-boundsread@*/
00312         pre[0] = ds->Type[0];
00313 /*@=boundsread@*/
00314         pre[1] = '\0';
00315         /*@-nullstate@*/ /* LCL: ds->Type may be NULL ??? */
00316         ds->DNEVR = rpmdsNewDNEVR(pre, ds);
00317         /*@=nullstate@*/
00318     }
00319 
00320 exit:
00321     return rpmdsLink(ds, (ds ? ds->Type : NULL));
00322 }
00323 
00324 rpmds rpmdsSingle(rpmTag tagN, const char * N, const char * EVR, int_32 Flags)
00325 {
00326     rpmds ds = NULL;
00327     const char * Type;
00328 
00329     if (tagN == RPMTAG_PROVIDENAME) {
00330         Type = "Provides";
00331     } else
00332     if (tagN == RPMTAG_REQUIRENAME) {
00333         Type = "Requires";
00334     } else
00335     if (tagN == RPMTAG_CONFLICTNAME) {
00336         Type = "Conflicts";
00337     } else
00338     if (tagN == RPMTAG_OBSOLETENAME) {
00339         Type = "Obsoletes";
00340     } else
00341     if (tagN == RPMTAG_TRIGGERNAME) {
00342         Type = "Trigger";
00343     } else
00344         goto exit;
00345 
00346     ds = xcalloc(1, sizeof(*ds));
00347     ds->h = NULL;
00348     ds->Type = Type;
00349     ds->tagN = tagN;
00350     ds->Count = 1;
00351     /*@-assignexpose@*/
00352 /*@-boundswrite@*/
00353     ds->N = xmalloc(sizeof(*ds->N));            ds->N[0] = N;
00354     ds->Nt = -1;        /* XXX to insure that hfd will free */
00355     ds->EVR = xmalloc(sizeof(*ds->EVR));        ds->EVR[0] = EVR;
00356     ds->EVRt = -1;      /* XXX to insure that hfd will free */
00357     /*@=assignexpose@*/
00358     ds->Flags = xmalloc(sizeof(*ds->Flags));    ds->Flags[0] = Flags;
00359 /*@=boundswrite@*/
00360     ds->i = 0;
00361     {   char t[2];
00362 /*@-boundsread@*/
00363         t[0] = ds->Type[0];
00364 /*@=boundsread@*/
00365         t[1] = '\0';
00366         ds->DNEVR = rpmdsNewDNEVR(t, ds);
00367     }
00368 
00369 exit:
00370     return rpmdsLink(ds, (ds ? ds->Type : NULL));
00371 }
00372 
00373 int rpmdsCount(const rpmds ds)
00374 {
00375     return (ds != NULL ? ds->Count : 0);
00376 }
00377 
00378 int rpmdsIx(const rpmds ds)
00379 {
00380     return (ds != NULL ? ds->i : -1);
00381 }
00382 
00383 int rpmdsSetIx(rpmds ds, int ix)
00384 {
00385     int i = -1;
00386 
00387     if (ds != NULL) {
00388         i = ds->i;
00389         ds->i = ix;
00390     }
00391     return i;
00392 }
00393 
00394 const char * rpmdsDNEVR(const rpmds ds)
00395 {
00396     const char * DNEVR = NULL;
00397 
00398     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00399 /*@-boundsread@*/
00400         if (ds->DNEVR != NULL)
00401             DNEVR = ds->DNEVR;
00402 /*@=boundsread@*/
00403     }
00404     return DNEVR;
00405 }
00406 
00407 const char * rpmdsN(const rpmds ds)
00408 {
00409     const char * N = NULL;
00410 
00411     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00412 /*@-boundsread@*/
00413         if (ds->N != NULL)
00414             N = ds->N[ds->i];
00415 /*@=boundsread@*/
00416     }
00417     return N;
00418 }
00419 
00420 const char * rpmdsEVR(const rpmds ds)
00421 {
00422     const char * EVR = NULL;
00423 
00424     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00425 /*@-boundsread@*/
00426         if (ds->EVR != NULL)
00427             EVR = ds->EVR[ds->i];
00428 /*@=boundsread@*/
00429     }
00430     return EVR;
00431 }
00432 
00433 int_32 rpmdsFlags(const rpmds ds)
00434 {
00435     int_32 Flags = 0;
00436 
00437     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00438 /*@-boundsread@*/
00439         if (ds->Flags != NULL)
00440             Flags = ds->Flags[ds->i];
00441 /*@=boundsread@*/
00442     }
00443     return Flags;
00444 }
00445 
00446 rpmTag rpmdsTagN(const rpmds ds)
00447 {
00448     rpmTag tagN = 0;
00449 
00450     if (ds != NULL)
00451         tagN = ds->tagN;
00452     return tagN;
00453 }
00454 
00455 int rpmdsNoPromote(const rpmds ds)
00456 {
00457     int nopromote = 0;
00458 
00459     if (ds != NULL)
00460         nopromote = ds->nopromote;
00461     return nopromote;
00462 }
00463 
00464 int rpmdsSetNoPromote(rpmds ds, int nopromote)
00465 {
00466     int onopromote = 0;
00467 
00468     if (ds != NULL) {
00469         onopromote = ds->nopromote;
00470         ds->nopromote = nopromote;
00471     }
00472     return onopromote;
00473 }
00474 
00475 uint_32 rpmdsColor(const rpmds ds)
00476 {
00477     uint_32 Color = 0;
00478 
00479     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00480 /*@-boundsread@*/
00481         if (ds->Color != NULL)
00482             Color = ds->Color[ds->i];
00483 /*@=boundsread@*/
00484     }
00485     return Color;
00486 }
00487 
00488 uint_32 rpmdsSetColor(const rpmds ds, uint_32 color)
00489 {
00490     uint_32 ocolor = 0;
00491 
00492     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00493 /*@-bounds@*/
00494         if (ds->Color != NULL) {
00495             ocolor = ds->Color[ds->i];
00496             ds->Color[ds->i] = color;
00497         }
00498 /*@=bounds@*/
00499     }
00500     return ocolor;
00501 }
00502 
00503 int_32 rpmdsRefs(const rpmds ds)
00504 {
00505     int_32 Refs = 0;
00506 
00507     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00508 /*@-boundsread@*/
00509         if (ds->Refs != NULL)
00510             Refs = ds->Refs[ds->i];
00511 /*@=boundsread@*/
00512     }
00513     return Refs;
00514 }
00515 
00516 int_32 rpmdsSetRefs(const rpmds ds, int_32 refs)
00517 {
00518     int_32 orefs = 0;
00519 
00520     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00521 /*@-bounds@*/
00522         if (ds->Refs != NULL) {
00523             orefs = ds->Refs[ds->i];
00524             ds->Refs[ds->i] = refs;
00525         }
00526 /*@=bounds@*/
00527     }
00528     return orefs;
00529 }
00530 
00531 void rpmdsNotify(rpmds ds, const char * where, int rc)
00532 {
00533     if (!(ds != NULL && ds->i >= 0 && ds->i < ds->Count))
00534         return;
00535     if (!(ds->Type != NULL && ds->DNEVR != NULL))
00536         return;
00537 
00538     rpmMessage(RPMMESS_DEBUG, "%9s: %-45s %-s %s\n", ds->Type,
00539                 (!strcmp(ds->DNEVR, "cached") ? ds->DNEVR : ds->DNEVR+2),
00540                 (rc ? _("NO ") : _("YES")),
00541                 (where != NULL ? where : ""));
00542 }
00543 
00544 int rpmdsNext(/*@null@*/ rpmds ds)
00545         /*@modifies ds @*/
00546 {
00547     int i = -1;
00548 
00549     if (ds != NULL && ++ds->i >= 0) {
00550         if (ds->i < ds->Count) {
00551             char t[2];
00552             i = ds->i;
00553             ds->DNEVR = _free(ds->DNEVR);
00554             t[0] = ((ds->Type != NULL) ? ds->Type[0] : '\0');
00555             t[1] = '\0';
00556             /*@-nullstate@*/
00557             ds->DNEVR = rpmdsNewDNEVR(t, ds);
00558             /*@=nullstate@*/
00559 
00560         } else
00561             ds->i = -1;
00562 
00563 /*@-modfilesys @*/
00564 if (_rpmds_debug  < 0 && i != -1)
00565 fprintf(stderr, "*** ds %p\t%s[%d]: %s\n", ds, (ds->Type ? ds->Type : "?Type?"), i, (ds->DNEVR ? ds->DNEVR : "?DNEVR?"));
00566 /*@=modfilesys @*/
00567 
00568     }
00569 
00570     return i;
00571 }
00572 
00573 rpmds rpmdsInit(/*@null@*/ rpmds ds)
00574         /*@modifies ds @*/
00575 {
00576     if (ds != NULL)
00577         ds->i = -1;
00578     /*@-refcounttrans@*/
00579     return ds;
00580     /*@=refcounttrans@*/
00581 }
00582 
00583 /*@-bounds@*/
00584 static /*@null@*/
00585 const char ** rpmdsDupArgv(/*@null@*/ const char ** argv, int argc)
00586         /*@*/
00587 {
00588     const char ** av;
00589     size_t nb = 0;
00590     int ac = 0;
00591     char * t;
00592 
00593     if (argv == NULL)
00594         return NULL;
00595     for (ac = 0; ac < argc; ac++) {
00596 assert(argv[ac] != NULL);
00597         nb += strlen(argv[ac]) + 1;
00598     }
00599     nb += (ac + 1) * sizeof(*av);
00600 
00601     av = xmalloc(nb);
00602     t = (char *) (av + ac + 1);
00603     for (ac = 0; ac < argc; ac++) {
00604         av[ac] = t;
00605         t = stpcpy(t, argv[ac]) + 1;
00606     }
00607     av[ac] = NULL;
00608 /*@-nullret@*/
00609     return av;
00610 /*@=nullret@*/
00611 }
00612 /*@=bounds@*/
00613 
00614 /*@null@*/
00615 static rpmds rpmdsDup(const rpmds ods)
00616         /*@modifies ods @*/
00617 {
00618     rpmds ds = xcalloc(1, sizeof(*ds));
00619     size_t nb;
00620 
00621     ds->h = (ods->h != NULL ? headerLink(ods->h) : NULL);
00622 /*@-assignexpose@*/
00623     ds->Type = ods->Type;
00624 /*@=assignexpose@*/
00625     ds->tagN = ods->tagN;
00626     ds->Count = ods->Count;
00627     ds->i = ods->i;
00628     ds->l = ods->l;
00629     ds->u = ods->u;
00630 
00631     nb = (ds->Count+1) * sizeof(*ds->N);
00632     ds->N = (ds->h != NULL
00633         ? memcpy(xmalloc(nb), ods->N, nb)
00634         : rpmdsDupArgv(ods->N, ods->Count) );
00635     ds->Nt = ods->Nt;
00636 
00637     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00638 assert(ods->EVR != NULL);
00639 assert(ods->Flags != NULL);
00640 
00641     nb = (ds->Count+1) * sizeof(*ds->EVR);
00642     ds->EVR = (ds->h != NULL
00643         ? memcpy(xmalloc(nb), ods->EVR, nb)
00644         : rpmdsDupArgv(ods->EVR, ods->Count) );
00645     ds->EVRt = ods->EVRt;
00646 
00647     nb = (ds->Count * sizeof(*ds->Flags));
00648     ds->Flags = (ds->h != NULL
00649         ? ods->Flags
00650         : memcpy(xmalloc(nb), ods->Flags, nb) );
00651     ds->Ft = ods->Ft;
00652 
00653 /*@-compmempass@*/ /* FIX: ds->Flags is kept, not only */
00654     return rpmdsLink(ds, (ds ? ds->Type : NULL));
00655 /*@=compmempass@*/
00656 
00657 }
00658 
00659 int rpmdsFind(rpmds ds, rpmds ods)
00660 {
00661     int comparison;
00662 
00663     if (ds == NULL || ods == NULL)
00664         return -1;
00665 
00666     ds->l = 0;
00667     ds->u = ds->Count;
00668     while (ds->l < ds->u) {
00669         ds->i = (ds->l + ds->u) / 2;
00670 
00671         comparison = strcmp(ods->N[ods->i], ds->N[ds->i]);
00672 
00673         /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00674 /*@-nullderef@*/
00675         if (comparison == 0 && ods->EVR && ds->EVR)
00676             comparison = strcmp(ods->EVR[ods->i], ds->EVR[ds->i]);
00677         if (comparison == 0 && ods->Flags && ds->Flags)
00678             comparison = (ods->Flags[ods->i] - ds->Flags[ds->i]);
00679 /*@=nullderef@*/
00680 
00681         if (comparison < 0)
00682             ds->u = ds->i;
00683         else if (comparison > 0)
00684             ds->l = ds->i + 1;
00685         else
00686             return ds->i;
00687     }
00688     return -1;
00689 }
00690 
00691 int rpmdsMerge(rpmds * dsp, rpmds ods)
00692 {
00693     rpmds ds;
00694     const char ** N;
00695     const char ** EVR;
00696     int_32 * Flags;
00697     int j;
00698 int save;
00699 
00700     if (dsp == NULL || ods == NULL)
00701         return -1;
00702 
00703     /* If not initialized yet, dup the 1st entry. */
00704 /*@-branchstate@*/
00705     if (*dsp == NULL) {
00706         save = ods->Count;
00707         ods->Count = 1;
00708         *dsp = rpmdsDup(ods);
00709         ods->Count = save;
00710     }
00711 /*@=branchstate@*/
00712     ds = *dsp;
00713     if (ds == NULL)
00714         return -1;
00715 
00716     /*
00717      * Add new entries.
00718      */
00719 save = ods->i;
00720     ods = rpmdsInit(ods);
00721     if (ods != NULL)
00722     while (rpmdsNext(ods) >= 0) {
00723         /*
00724          * If this entry is already present, don't bother.
00725          */
00726         if (rpmdsFind(ds, ods) >= 0)
00727             continue;
00728 
00729         /*
00730          * Insert new entry.
00731          */
00732         for (j = ds->Count; j > ds->u; j--)
00733             ds->N[j] = ds->N[j-1];
00734         ds->N[ds->u] = ods->N[ods->i];
00735         N = rpmdsDupArgv(ds->N, ds->Count+1);
00736         ds->N = _free(ds->N);
00737         ds->N = N;
00738         
00739         /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00740 /*@-nullderef -nullpass -nullptrarith @*/
00741 assert(ods->EVR != NULL);
00742 assert(ods->Flags != NULL);
00743 
00744         for (j = ds->Count; j > ds->u; j--)
00745             ds->EVR[j] = ds->EVR[j-1];
00746         ds->EVR[ds->u] = ods->EVR[ods->i];
00747         EVR = rpmdsDupArgv(ds->EVR, ds->Count+1);
00748         ds->EVR = _free(ds->EVR);
00749         ds->EVR = EVR;
00750 
00751         Flags = xmalloc((ds->Count+1) * sizeof(*Flags));
00752         if (ds->u > 0)
00753             memcpy(Flags, ds->Flags, ds->u * sizeof(*Flags));
00754         if (ds->u < ds->Count)
00755             memcpy(Flags + ds->u + 1, ds->Flags + ds->u, (ds->Count - ds->u) * sizeof(*Flags));
00756         Flags[ds->u] = ods->Flags[ods->i];
00757         ds->Flags = _free(ds->Flags);
00758         ds->Flags = Flags;
00759 /*@=nullderef =nullpass =nullptrarith @*/
00760 
00761         ds->i = ds->Count;
00762         ds->Count++;
00763 
00764     }
00765 /*@-nullderef@*/
00766 ods->i = save;
00767 /*@=nullderef@*/
00768     return 0;
00769 }
00770 
00778 static
00779 void parseEVR(char * evr,
00780                 /*@exposed@*/ /*@out@*/ const char ** ep,
00781                 /*@exposed@*/ /*@out@*/ const char ** vp,
00782                 /*@exposed@*/ /*@out@*/ const char ** rp)
00783         /*@modifies *ep, *vp, *rp @*/
00784         /*@requires maxSet(ep) >= 0 /\ maxSet(vp) >= 0 /\ maxSet(rp) >= 0 @*/
00785 {
00786     const char *epoch;
00787     const char *version;                /* assume only version is present */
00788     const char *release;
00789     char *s, *se;
00790 
00791     s = evr;
00792     while (*s && xisdigit(*s)) s++;     /* s points to epoch terminator */
00793     se = strrchr(s, '-');               /* se points to version terminator */
00794 
00795     if (*s == ':') {
00796         epoch = evr;
00797         *s++ = '\0';
00798         version = s;
00799         /*@-branchstate@*/
00800         if (*epoch == '\0') epoch = "0";
00801         /*@=branchstate@*/
00802     } else {
00803         epoch = NULL;   /* XXX disable epoch compare if missing */
00804         version = evr;
00805     }
00806     if (se) {
00807 /*@-boundswrite@*/
00808         *se++ = '\0';
00809 /*@=boundswrite@*/
00810         release = se;
00811     } else {
00812         release = NULL;
00813     }
00814 
00815     if (ep) *ep = epoch;
00816     if (vp) *vp = version;
00817     if (rp) *rp = release;
00818 }
00819 
00820 int rpmdsCompare(const rpmds A, const rpmds B)
00821 {
00822     const char *aDepend = (A->DNEVR != NULL ? xstrdup(A->DNEVR+2) : "");
00823     const char *bDepend = (B->DNEVR != NULL ? xstrdup(B->DNEVR+2) : "");
00824     char *aEVR, *bEVR;
00825     const char *aE, *aV, *aR, *bE, *bV, *bR;
00826     int result;
00827     int sense;
00828 
00829 /*@-boundsread@*/
00830     /* Different names don't overlap. */
00831     if (strcmp(A->N[A->i], B->N[B->i])) {
00832         result = 0;
00833         goto exit;
00834     }
00835 
00836     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00837 /*@-nullderef@*/
00838     if (!(A->EVR && A->Flags && B->EVR && B->Flags)) {
00839         result = 1;
00840         goto exit;
00841     }
00842 
00843     /* Same name. If either A or B is an existence test, always overlap. */
00844     if (!((A->Flags[A->i] & RPMSENSE_SENSEMASK) && (B->Flags[B->i] & RPMSENSE_SENSEMASK))) {
00845         result = 1;
00846         goto exit;
00847     }
00848 
00849     /* If either EVR is non-existent or empty, always overlap. */
00850     if (!(A->EVR[A->i] && *A->EVR[A->i] && B->EVR[B->i] && *B->EVR[B->i])) {
00851         result = 1;
00852         goto exit;
00853     }
00854 
00855     /* Both AEVR and BEVR exist. */
00856 /*@-boundswrite@*/
00857     aEVR = xstrdup(A->EVR[A->i]);
00858     parseEVR(aEVR, &aE, &aV, &aR);
00859     bEVR = xstrdup(B->EVR[B->i]);
00860     parseEVR(bEVR, &bE, &bV, &bR);
00861 /*@=boundswrite@*/
00862 
00863     /* Compare {A,B} [epoch:]version[-release] */
00864     sense = 0;
00865     if (aE && *aE && bE && *bE)
00866         sense = rpmvercmp(aE, bE);
00867     else if (aE && *aE && atol(aE) > 0) {
00868         if (!B->nopromote) {
00869             int lvl = (_rpmds_unspecified_epoch_noise  ? RPMMESS_WARNING : RPMMESS_DEBUG);
00870             rpmMessage(lvl, _("The \"B\" dependency needs an epoch (assuming same epoch as \"A\")\n\tA = \"%s\"\tB = \"%s\"\n"),
00871                 aDepend, bDepend);
00872             sense = 0;
00873         } else
00874             sense = 1;
00875     } else if (bE && *bE && atol(bE) > 0)
00876         sense = -1;
00877 
00878     if (sense == 0) {
00879         sense = rpmvercmp(aV, bV);
00880         if (sense == 0 && aR && *aR && bR && *bR) {
00881             sense = rpmvercmp(aR, bR);
00882         }
00883     }
00884 /*@=boundsread@*/
00885     aEVR = _free(aEVR);
00886     bEVR = _free(bEVR);
00887 
00888     /* Detect overlap of {A,B} range. */
00889     result = 0;
00890     if (sense < 0 && ((A->Flags[A->i] & RPMSENSE_GREATER) || (B->Flags[B->i] & RPMSENSE_LESS))) {
00891         result = 1;
00892     } else if (sense > 0 && ((A->Flags[A->i] & RPMSENSE_LESS) || (B->Flags[B->i] & RPMSENSE_GREATER))) {
00893         result = 1;
00894     } else if (sense == 0 &&
00895         (((A->Flags[A->i] & RPMSENSE_EQUAL) && (B->Flags[B->i] & RPMSENSE_EQUAL)) ||
00896          ((A->Flags[A->i] & RPMSENSE_LESS) && (B->Flags[B->i] & RPMSENSE_LESS)) ||
00897          ((A->Flags[A->i] & RPMSENSE_GREATER) && (B->Flags[B->i] & RPMSENSE_GREATER)))) {
00898         result = 1;
00899     }
00900 /*@=nullderef@*/
00901 
00902 exit:
00903     if (_noisy_range_comparison_debug_message)
00904     rpmMessage(RPMMESS_DEBUG, _("  %s    A %s\tB %s\n"),
00905         (result ? _("YES") : _("NO ")), aDepend, bDepend);
00906     aDepend = _free(aDepend);
00907     bDepend = _free(bDepend);
00908     return result;
00909 }
00910 
00911 void rpmdsProblem(rpmps ps, const char * pkgNEVR, const rpmds ds,
00912         const fnpyKey * suggestedKeys, int adding)
00913 {
00914     const char * Name =  rpmdsN(ds);
00915     const char * DNEVR = rpmdsDNEVR(ds);
00916     const char * EVR = rpmdsEVR(ds);
00917     rpmProblemType type;
00918     fnpyKey key;
00919 
00920     if (ps == NULL) return;
00921 
00922     /*@-branchstate@*/
00923     if (Name == NULL) Name = "?N?";
00924     if (EVR == NULL) EVR = "?EVR?";
00925     if (DNEVR == NULL) DNEVR = "? ?N? ?OP? ?EVR?";
00926     /*@=branchstate@*/
00927 
00928     rpmMessage(RPMMESS_DEBUG, _("package %s has unsatisfied %s: %s\n"),
00929             pkgNEVR, ds->Type, DNEVR+2);
00930 
00931     switch ((unsigned)DNEVR[0]) {
00932     case 'C':   type = RPMPROB_CONFLICT;        break;
00933     default:
00934     case 'R':   type = RPMPROB_REQUIRES;        break;
00935     }
00936 
00937     key = (suggestedKeys ? suggestedKeys[0] : NULL);
00938     rpmpsAppend(ps, type, pkgNEVR, key, NULL, NULL, DNEVR, adding);
00939 }
00940 
00941 int rpmdsAnyMatchesDep (const Header h, const rpmds req, int nopromote)
00942 {
00943     int scareMem = 1;
00944     rpmds provides = NULL;
00945     int result = 0;
00946 
00947     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00948     if (req->EVR == NULL || req->Flags == NULL)
00949         return 1;
00950 
00951 /*@-boundsread@*/
00952     if (!(req->Flags[req->i] & RPMSENSE_SENSEMASK) || !req->EVR[req->i] || *req->EVR[req->i] == '\0')
00953         return 1;
00954 /*@=boundsread@*/
00955 
00956     /* Get provides information from header */
00957     provides = rpmdsInit(rpmdsNew(h, RPMTAG_PROVIDENAME, scareMem));
00958     if (provides == NULL)
00959         goto exit;      /* XXX should never happen */
00960     if (nopromote)
00961         (void) rpmdsSetNoPromote(provides, nopromote);
00962 
00963     /*
00964      * Rpm prior to 3.0.3 did not have versioned provides.
00965      * If no provides version info is available, match any/all requires
00966      * with same name.
00967      */
00968     if (provides->EVR == NULL) {
00969         result = 1;
00970         goto exit;
00971     }
00972 
00973     result = 0;
00974     if (provides != NULL)
00975     while (rpmdsNext(provides) >= 0) {
00976 
00977         /* Filter out provides that came along for the ride. */
00978 /*@-boundsread@*/
00979         if (strcmp(provides->N[provides->i], req->N[req->i]))
00980             continue;
00981 /*@=boundsread@*/
00982 
00983         result = rpmdsCompare(provides, req);
00984 
00985         /* If this provide matches the require, we're done. */
00986         if (result)
00987             break;
00988     }
00989 
00990 exit:
00991     provides = rpmdsFree(provides);
00992 
00993     return result;
00994 }
00995 
00996 int rpmdsNVRMatchesDep(const Header h, const rpmds req, int nopromote)
00997 {
00998     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00999     const char * pkgN, * v, * r;
01000     int_32 * epoch;
01001     const char * pkgEVR;
01002     char * t;
01003     int_32 pkgFlags = RPMSENSE_EQUAL;
01004     rpmds pkg;
01005     int rc = 1; /* XXX assume match, names already match here */
01006 
01007     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
01008     if (req->EVR == NULL || req->Flags == NULL)
01009         return rc;
01010 
01011 /*@-boundsread@*/
01012     if (!((req->Flags[req->i] & RPMSENSE_SENSEMASK) && req->EVR[req->i] && *req->EVR[req->i]))
01013         return rc;
01014 /*@=boundsread@*/
01015 
01016     /* Get package information from header */
01017     (void) headerNVR(h, &pkgN, &v, &r);
01018 
01019 /*@-boundswrite@*/
01020     t = alloca(21 + strlen(v) + 1 + strlen(r) + 1);
01021     pkgEVR = t;
01022     *t = '\0';
01023     if (hge(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
01024         sprintf(t, "%d:", *epoch);
01025         while (*t != '\0')
01026             t++;
01027     }
01028     (void) stpcpy( stpcpy( stpcpy(t, v) , "-") , r);
01029 /*@=boundswrite@*/
01030 
01031     if ((pkg = rpmdsSingle(RPMTAG_PROVIDENAME, pkgN, pkgEVR, pkgFlags)) != NULL) {
01032         if (nopromote)
01033             (void) rpmdsSetNoPromote(pkg, nopromote);
01034         rc = rpmdsCompare(pkg, req);
01035         pkg = rpmdsFree(pkg);
01036     }
01037 
01038     return rc;
01039 }

Generated on Sun Oct 26 13:02:00 2003 for rpm by doxygen1.2.18