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 /*@unchecked@*/ /*@observer@*/
00118 static const char * beehiveToken = "redhatbuilddependency";
00119 
00125 static int archFilter(const char * arch)
00126         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00127         /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
00128 {
00129     static int oneshot = 0;
00130     int negate = 0;     /* assume no negation. */
00131     int rc = 0;         /* assume arch does not apply */
00132 
00133     if (*arch == '!') {
00134         negate = 1;
00135         arch++;
00136     }
00137     if (*arch == '=') {
00138         const char * myarch = NULL;
00139         arch++;
00140 
00141         if (oneshot <= 0) {
00142             rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
00143             rpmSetMachine(NULL, NULL);
00144             oneshot++;
00145         }
00146         rpmGetMachine(&myarch, NULL);
00147         if (myarch != NULL) {
00148             if (negate)
00149                 rc = (!strcmp(arch, myarch) ? 0 : 1);
00150             else
00151                 rc = (!strcmp(arch, myarch) ? 1 : 0);
00152 /*@-modfilesys@*/
00153 if (_rpmds_debug < 0)
00154 fprintf(stderr, "=== strcmp(\"%s\", \"%s\") negate %d rc %d\n", arch, myarch, negate, rc);
00155 /*@=modfilesys@*/
00156         }
00157     } else {
00158         int archScore = rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch);
00159         if (negate)
00160             rc = (archScore > 0 ? 0 : 1);
00161         else
00162             rc = (archScore > 0 ? 1 : 0);
00163 /*@-modfilesys@*/
00164 if (_rpmds_debug < 0)
00165 fprintf(stderr, "=== archScore(\"%s\") %d negate %d rc %d\n", arch, archScore, negate, rc);
00166 /*@=modfilesys@*/
00167     }
00168     return rc;
00169 }
00170 
00177 /*@null@*/
00178 static rpmds rpmdsFilter(/*@null@*/ /*@returned@*/ rpmds ds,
00179                 /*@null@*/ const char * token)
00180         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00181         /*@modifies ds, rpmGlobalMacroContext, fileSystem, internalState @*/
00182 {
00183     size_t toklen;
00184     rpmds fds;
00185     int i;
00186 
00187     if (ds == NULL || token == NULL || *token == '\0')
00188         goto exit;
00189 
00190     toklen = strlen(token);
00191     fds = rpmdsLink(ds, ds->Type);
00192     fds = rpmdsInit(ds);
00193     if (fds != NULL)
00194     while ((i = rpmdsNext(fds)) >= 0) {
00195         const char * N = rpmdsN(fds);
00196         const char * gN;
00197         const char * f, * fe;
00198         const char * g, * ge;
00199         size_t len;
00200         int ignore;
00201         int state;
00202         char buf[1024+1];
00203         int nb;
00204 
00205         if (N == NULL)
00206             continue;
00207         len = strlen(N);
00208         if (len < (toklen + (sizeof("()")-1)))
00209             continue;
00210         if (strncmp(N, token, toklen))
00211             continue;
00212         if (*(f = N + toklen) != '(')
00213             continue;
00214         if (*(fe = N + len - 1) != ')')
00215             continue;
00216 /*@-modfilesys@*/
00217 if (_rpmds_debug < 0)
00218 fprintf(stderr, "*** f \"%s\"\n", f);
00219 /*@=modfilesys@*/
00220         g = f + 1;
00221         state = 0;
00222         gN = NULL;
00223         ignore = 1;     /* assume depedency will be skipped. */
00224         for (ge = (char *) g; ge < fe; g = ++ge) {
00225             while (ge < fe && *ge != ':')
00226                 ge++;
00227 
00228             nb = (ge - g);
00229             if (nb < 0 || nb > (sizeof(buf)-1))
00230                 nb = sizeof(buf) - 1;
00231             (void) strncpy(buf, g, nb);
00232             buf[nb] = '\0';
00233 /*@-branchstate@*/
00234             switch (state) {
00235             case 0:             /* g is unwrapped N */
00236                 gN = xstrdup(buf);
00237                 /*@switchbreak@*/ break;
00238             default:            /* g is next arch score token. */
00239                 /* arch score tokens are compared assuming || */
00240                 if (archFilter(buf))
00241                     ignore = 0;
00242                 /*@switchbreak@*/ break;
00243             }
00244 /*@=branchstate@*/
00245             state++;
00246         }
00247         if (ignore) {
00248             int Count = rpmdsCount(fds);
00249 /*@-modfilesys@*/
00250 if (_rpmds_debug < 0)
00251 fprintf(stderr, "***   deleting N[%d:%d] = \"%s\"\n", i, Count, N);
00252 /*@=modfilesys@*/
00253             if (i < (Count - 1)) {
00254                 memmove((fds->N + i), (fds->N + i + 1), (Count - (i+1)) * sizeof(*fds->N));
00255                 if (fds->EVR != NULL)
00256                     memmove((fds->EVR + i), (fds->EVR + i + 1), (Count - (i+1)) * sizeof(*fds->EVR));
00257                 if (fds->Flags != NULL)
00258                     memmove((fds->Flags + i), (fds->Flags + i + 1), (Count - (i+1)) * sizeof(*fds->Flags));
00259                 fds->i--;
00260             }
00261             fds->Count--;
00262         } else if (gN != NULL) {
00263 /*@-modobserver -observertrans@*/
00264             char * t = (char *) N;
00265             (void) strcpy(t, gN);
00266 /*@=modobserver =observertrans@*/
00267 /*@-modfilesys@*/
00268 if (_rpmds_debug < 0)
00269 fprintf(stderr, "*** unwrapping N[%d] = \"%s\"\n", i, N);
00270 /*@=modfilesys@*/
00271         }
00272         gN = _free(gN);
00273     }
00274     fds = rpmdsFree(fds);
00275 
00276 exit:
00277     /*@-refcounttrans@*/
00278     return ds;
00279     /*@=refcounttrans@*/
00280 }
00281 
00282 rpmds rpmdsNew(Header h, rpmTag tagN, int flags)
00283 {
00284     int scareMem = (flags & 0x1);
00285     int nofilter = (flags & 0x2);
00286     HGE_t hge =
00287         (scareMem ? (HGE_t) headerGetEntryMinMemory : (HGE_t) headerGetEntry);
00288     rpmTag tagBT = RPMTAG_BUILDTIME;
00289     rpmTagType BTt;
00290     int_32 * BTp;
00291     rpmTag tagEVR, tagF;
00292     rpmds ds = NULL;
00293     const char * Type;
00294     const char ** N;
00295     rpmTagType Nt;
00296     int_32 Count;
00297 
00298     if (tagN == RPMTAG_PROVIDENAME) {
00299         Type = "Provides";
00300         tagEVR = RPMTAG_PROVIDEVERSION;
00301         tagF = RPMTAG_PROVIDEFLAGS;
00302     } else
00303     if (tagN == RPMTAG_REQUIRENAME) {
00304         Type = "Requires";
00305         tagEVR = RPMTAG_REQUIREVERSION;
00306         tagF = RPMTAG_REQUIREFLAGS;
00307     } else
00308     if (tagN == RPMTAG_CONFLICTNAME) {
00309         Type = "Conflicts";
00310         tagEVR = RPMTAG_CONFLICTVERSION;
00311         tagF = RPMTAG_CONFLICTFLAGS;
00312     } else
00313     if (tagN == RPMTAG_OBSOLETENAME) {
00314         Type = "Obsoletes";
00315         tagEVR = RPMTAG_OBSOLETEVERSION;
00316         tagF = RPMTAG_OBSOLETEFLAGS;
00317     } else
00318     if (tagN == RPMTAG_TRIGGERNAME) {
00319         Type = "Trigger";
00320         tagEVR = RPMTAG_TRIGGERVERSION;
00321         tagF = RPMTAG_TRIGGERFLAGS;
00322     } else
00323         goto exit;
00324 
00325     /*@-branchstate@*/
00326     if (hge(h, tagN, &Nt, (void **) &N, &Count)
00327      && N != NULL && Count > 0)
00328     {
00329         int xx;
00330 
00331         ds = xcalloc(1, sizeof(*ds));
00332         ds->Type = Type;
00333         ds->h = (scareMem ? headerLink(h) : NULL);
00334         ds->i = -1;
00335         ds->DNEVR = NULL;
00336         ds->tagN = tagN;
00337         ds->N = N;
00338         ds->Nt = Nt;
00339         ds->Count = Count;
00340         ds->nopromote = _rpmds_nopromote;
00341 
00342         xx = hge(h, tagEVR, &ds->EVRt, (void **) &ds->EVR, NULL);
00343         xx = hge(h, tagF, &ds->Ft, (void **) &ds->Flags, NULL);
00344 /*@-boundsread@*/
00345         if (!scareMem && ds->Flags != NULL)
00346             ds->Flags = memcpy(xmalloc(ds->Count * sizeof(*ds->Flags)),
00347                                 ds->Flags, ds->Count * sizeof(*ds->Flags));
00348         xx = hge(h, tagBT, &BTt, (void **) &BTp, NULL);
00349         ds->BT = (xx && BTp != NULL && BTt == RPM_INT32_TYPE ? *BTp : 0);
00350 /*@=boundsread@*/
00351         ds->Color = xcalloc(Count, sizeof(*ds->Color));
00352         ds->Refs = xcalloc(Count, sizeof(*ds->Refs));
00353 
00354 /*@-modfilesys@*/
00355 if (_rpmds_debug < 0)
00356 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
00357 /*@=modfilesys@*/
00358 
00359     }
00360     /*@=branchstate@*/
00361 
00362 exit:
00363     /*@-nullstate@*/ /* FIX: ds->Flags may be NULL */
00364     ds = rpmdsLink(ds, (ds ? ds->Type : NULL));
00365     /*@=nullstate@*/
00366 
00367     if (!nofilter)
00368         ds = rpmdsFilter(ds, beehiveToken);
00369 
00370     return ds;
00371 }
00372 
00373 char * rpmdsNewDNEVR(const char * dspfx, const rpmds ds)
00374 {
00375     char * tbuf, * t;
00376     size_t nb;
00377 
00378     nb = 0;
00379     if (dspfx)  nb += strlen(dspfx) + 1;
00380 /*@-boundsread@*/
00381     if (ds->N[ds->i])   nb += strlen(ds->N[ds->i]);
00382     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00383     if (ds->Flags != NULL && (ds->Flags[ds->i] & RPMSENSE_SENSEMASK)) {
00384         if (nb) nb++;
00385         if (ds->Flags[ds->i] & RPMSENSE_LESS)   nb++;
00386         if (ds->Flags[ds->i] & RPMSENSE_GREATER) nb++;
00387         if (ds->Flags[ds->i] & RPMSENSE_EQUAL)  nb++;
00388     }
00389     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00390     if (ds->EVR != NULL && ds->EVR[ds->i] && *ds->EVR[ds->i]) {
00391         if (nb) nb++;
00392         nb += strlen(ds->EVR[ds->i]);
00393     }
00394 /*@=boundsread@*/
00395 
00396 /*@-boundswrite@*/
00397     t = tbuf = xmalloc(nb + 1);
00398     if (dspfx) {
00399         t = stpcpy(t, dspfx);
00400         *t++ = ' ';
00401     }
00402     if (ds->N[ds->i])
00403         t = stpcpy(t, ds->N[ds->i]);
00404     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00405     if (ds->Flags != NULL && (ds->Flags[ds->i] & RPMSENSE_SENSEMASK)) {
00406         if (t != tbuf)  *t++ = ' ';
00407         if (ds->Flags[ds->i] & RPMSENSE_LESS)   *t++ = '<';
00408         if (ds->Flags[ds->i] & RPMSENSE_GREATER) *t++ = '>';
00409         if (ds->Flags[ds->i] & RPMSENSE_EQUAL)  *t++ = '=';
00410     }
00411     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00412     if (ds->EVR != NULL && ds->EVR[ds->i] && *ds->EVR[ds->i]) {
00413         if (t != tbuf)  *t++ = ' ';
00414         t = stpcpy(t, ds->EVR[ds->i]);
00415     }
00416     *t = '\0';
00417 /*@=boundswrite@*/
00418     return tbuf;
00419 }
00420 
00421 rpmds rpmdsThis(Header h, rpmTag tagN, int_32 Flags)
00422 {
00423     HGE_t hge = (HGE_t) headerGetEntryMinMemory;
00424     rpmds ds = NULL;
00425     const char * Type;
00426     const char * n, * v, * r;
00427     int_32 * ep;
00428     const char ** N, ** EVR;
00429     char * t;
00430     int xx;
00431 
00432     if (tagN == RPMTAG_PROVIDENAME) {
00433         Type = "Provides";
00434     } else
00435     if (tagN == RPMTAG_REQUIRENAME) {
00436         Type = "Requires";
00437     } else
00438     if (tagN == RPMTAG_CONFLICTNAME) {
00439         Type = "Conflicts";
00440     } else
00441     if (tagN == RPMTAG_OBSOLETENAME) {
00442         Type = "Obsoletes";
00443     } else
00444     if (tagN == RPMTAG_TRIGGERNAME) {
00445         Type = "Trigger";
00446     } else
00447         goto exit;
00448 
00449     xx = headerNVR(h, &n, &v, &r);
00450     ep = NULL;
00451     xx = hge(h, RPMTAG_EPOCH, NULL, (void **)&ep, NULL);
00452 
00453     t = xmalloc(sizeof(*N) + strlen(n) + 1);
00454 /*@-boundswrite@*/
00455     N = (const char **) t;
00456     t += sizeof(*N);
00457     *t = '\0';
00458     N[0] = t;
00459     t = stpcpy(t, n);
00460 
00461     t = xmalloc(sizeof(*EVR) +
00462                 (ep ? 20 : 0) + strlen(v) + strlen(r) + sizeof("-"));
00463     EVR = (const char **) t;
00464     t += sizeof(*EVR);
00465     *t = '\0';
00466     EVR[0] = t;
00467     if (ep) {
00468         sprintf(t, "%d:", *ep);
00469         t += strlen(t);
00470     }
00471     t = stpcpy( stpcpy( stpcpy( t, v), "-"), r);
00472 /*@=boundswrite@*/
00473 
00474     ds = xcalloc(1, sizeof(*ds));
00475     ds->h = NULL;
00476     ds->Type = Type;
00477     ds->tagN = tagN;
00478     ds->Count = 1;
00479     ds->nopromote = _rpmds_nopromote;
00480     ds->N = N;
00481     ds->Nt = -1;        /* XXX to insure that hfd will free */
00482     ds->EVR = EVR;
00483     ds->EVRt = -1;      /* XXX to insure that hfd will free */
00484 /*@-boundswrite@*/
00485     ds->Flags = xmalloc(sizeof(*ds->Flags));    ds->Flags[0] = Flags;
00486 /*@=boundswrite@*/
00487     ds->i = 0;
00488     {   char pre[2];
00489 /*@-boundsread@*/
00490         pre[0] = ds->Type[0];
00491 /*@=boundsread@*/
00492         pre[1] = '\0';
00493         /*@-nullstate@*/ /* LCL: ds->Type may be NULL ??? */
00494         ds->DNEVR = rpmdsNewDNEVR(pre, ds);
00495         /*@=nullstate@*/
00496     }
00497 
00498 exit:
00499     return rpmdsLink(ds, (ds ? ds->Type : NULL));
00500 }
00501 
00502 rpmds rpmdsSingle(rpmTag tagN, const char * N, const char * EVR, int_32 Flags)
00503 {
00504     rpmds ds = NULL;
00505     const char * Type;
00506 
00507     if (tagN == RPMTAG_PROVIDENAME) {
00508         Type = "Provides";
00509     } else
00510     if (tagN == RPMTAG_REQUIRENAME) {
00511         Type = "Requires";
00512     } else
00513     if (tagN == RPMTAG_CONFLICTNAME) {
00514         Type = "Conflicts";
00515     } else
00516     if (tagN == RPMTAG_OBSOLETENAME) {
00517         Type = "Obsoletes";
00518     } else
00519     if (tagN == RPMTAG_TRIGGERNAME) {
00520         Type = "Trigger";
00521     } else
00522         goto exit;
00523 
00524     ds = xcalloc(1, sizeof(*ds));
00525     ds->h = NULL;
00526     ds->Type = Type;
00527     ds->tagN = tagN;
00528     {   time_t now = time(NULL);
00529         ds->BT = now;
00530     }
00531     ds->Count = 1;
00532     ds->nopromote = _rpmds_nopromote;
00533     /*@-assignexpose@*/
00534 /*@-boundswrite@*/
00535     ds->N = xmalloc(sizeof(*ds->N));            ds->N[0] = N;
00536     ds->Nt = -1;        /* XXX to insure that hfd will free */
00537     ds->EVR = xmalloc(sizeof(*ds->EVR));        ds->EVR[0] = EVR;
00538     ds->EVRt = -1;      /* XXX to insure that hfd will free */
00539     /*@=assignexpose@*/
00540     ds->Flags = xmalloc(sizeof(*ds->Flags));    ds->Flags[0] = Flags;
00541 /*@=boundswrite@*/
00542     ds->i = 0;
00543     {   char t[2];
00544 /*@-boundsread@*/
00545         t[0] = ds->Type[0];
00546 /*@=boundsread@*/
00547         t[1] = '\0';
00548         ds->DNEVR = rpmdsNewDNEVR(t, ds);
00549     }
00550 
00551 exit:
00552     return rpmdsLink(ds, (ds ? ds->Type : NULL));
00553 }
00554 
00555 int rpmdsCount(const rpmds ds)
00556 {
00557     return (ds != NULL ? ds->Count : 0);
00558 }
00559 
00560 int rpmdsIx(const rpmds ds)
00561 {
00562     return (ds != NULL ? ds->i : -1);
00563 }
00564 
00565 int rpmdsSetIx(rpmds ds, int ix)
00566 {
00567     int i = -1;
00568 
00569     if (ds != NULL) {
00570         i = ds->i;
00571         ds->i = ix;
00572     }
00573     return i;
00574 }
00575 
00576 const char * rpmdsDNEVR(const rpmds ds)
00577 {
00578     const char * DNEVR = NULL;
00579 
00580     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00581 /*@-boundsread@*/
00582         if (ds->DNEVR != NULL)
00583             DNEVR = ds->DNEVR;
00584 /*@=boundsread@*/
00585     }
00586     return DNEVR;
00587 }
00588 
00589 const char * rpmdsN(const rpmds ds)
00590 {
00591     const char * N = NULL;
00592 
00593     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00594 /*@-boundsread@*/
00595         if (ds->N != NULL)
00596             N = ds->N[ds->i];
00597 /*@=boundsread@*/
00598     }
00599     return N;
00600 }
00601 
00602 const char * rpmdsEVR(const rpmds ds)
00603 {
00604     const char * EVR = NULL;
00605 
00606     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00607 /*@-boundsread@*/
00608         if (ds->EVR != NULL)
00609             EVR = ds->EVR[ds->i];
00610 /*@=boundsread@*/
00611     }
00612     return EVR;
00613 }
00614 
00615 int_32 rpmdsFlags(const rpmds ds)
00616 {
00617     int_32 Flags = 0;
00618 
00619     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00620 /*@-boundsread@*/
00621         if (ds->Flags != NULL)
00622             Flags = ds->Flags[ds->i];
00623 /*@=boundsread@*/
00624     }
00625     return Flags;
00626 }
00627 
00628 rpmTag rpmdsTagN(const rpmds ds)
00629 {
00630     rpmTag tagN = 0;
00631 
00632     if (ds != NULL)
00633         tagN = ds->tagN;
00634     return tagN;
00635 }
00636 
00637 time_t rpmdsBT(const rpmds ds)
00638 {
00639     time_t BT = 0;
00640     if (ds != NULL && ds->BT > 0)
00641         BT = ds->BT;
00642     return BT;
00643 }
00644 
00645 time_t rpmdsSetBT(const rpmds ds, time_t BT)
00646 {
00647     time_t oBT = 0;
00648     if (ds != NULL) {
00649         oBT = ds->BT;
00650         ds->BT = BT;
00651     }
00652     return oBT;
00653 }
00654 
00655 int rpmdsNoPromote(const rpmds ds)
00656 {
00657     int nopromote = 0;
00658 
00659     if (ds != NULL)
00660         nopromote = ds->nopromote;
00661     return nopromote;
00662 }
00663 
00664 int rpmdsSetNoPromote(rpmds ds, int nopromote)
00665 {
00666     int onopromote = 0;
00667 
00668     if (ds != NULL) {
00669         onopromote = ds->nopromote;
00670         ds->nopromote = nopromote;
00671     }
00672     return onopromote;
00673 }
00674 
00675 uint_32 rpmdsColor(const rpmds ds)
00676 {
00677     uint_32 Color = 0;
00678 
00679     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00680 /*@-boundsread@*/
00681         if (ds->Color != NULL)
00682             Color = ds->Color[ds->i];
00683 /*@=boundsread@*/
00684     }
00685     return Color;
00686 }
00687 
00688 uint_32 rpmdsSetColor(const rpmds ds, uint_32 color)
00689 {
00690     uint_32 ocolor = 0;
00691 
00692     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00693 /*@-bounds@*/
00694         if (ds->Color != NULL) {
00695             ocolor = ds->Color[ds->i];
00696             ds->Color[ds->i] = color;
00697         }
00698 /*@=bounds@*/
00699     }
00700     return ocolor;
00701 }
00702 
00703 int_32 rpmdsRefs(const rpmds ds)
00704 {
00705     int_32 Refs = 0;
00706 
00707     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00708 /*@-boundsread@*/
00709         if (ds->Refs != NULL)
00710             Refs = ds->Refs[ds->i];
00711 /*@=boundsread@*/
00712     }
00713     return Refs;
00714 }
00715 
00716 int_32 rpmdsSetRefs(const rpmds ds, int_32 refs)
00717 {
00718     int_32 orefs = 0;
00719 
00720     if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00721 /*@-bounds@*/
00722         if (ds->Refs != NULL) {
00723             orefs = ds->Refs[ds->i];
00724             ds->Refs[ds->i] = refs;
00725         }
00726 /*@=bounds@*/
00727     }
00728     return orefs;
00729 }
00730 
00731 void rpmdsNotify(rpmds ds, const char * where, int rc)
00732 {
00733     if (!(ds != NULL && ds->i >= 0 && ds->i < ds->Count))
00734         return;
00735     if (!(ds->Type != NULL && ds->DNEVR != NULL))
00736         return;
00737 
00738     rpmMessage(RPMMESS_DEBUG, "%9s: %-45s %-s %s\n", ds->Type,
00739                 (!strcmp(ds->DNEVR, "cached") ? ds->DNEVR : ds->DNEVR+2),
00740                 (rc ? _("NO ") : _("YES")),
00741                 (where != NULL ? where : ""));
00742 }
00743 
00744 int rpmdsNext(/*@null@*/ rpmds ds)
00745         /*@modifies ds @*/
00746 {
00747     int i = -1;
00748 
00749     if (ds != NULL && ++ds->i >= 0) {
00750         if (ds->i < ds->Count) {
00751             char t[2];
00752             i = ds->i;
00753             ds->DNEVR = _free(ds->DNEVR);
00754             t[0] = ((ds->Type != NULL) ? ds->Type[0] : '\0');
00755             t[1] = '\0';
00756             /*@-nullstate@*/
00757             ds->DNEVR = rpmdsNewDNEVR(t, ds);
00758             /*@=nullstate@*/
00759 
00760         } else
00761             ds->i = -1;
00762 
00763 /*@-modfilesys @*/
00764 if (_rpmds_debug  < 0 && i != -1)
00765 fprintf(stderr, "*** ds %p\t%s[%d]: %s\n", ds, (ds->Type ? ds->Type : "?Type?"), i, (ds->DNEVR ? ds->DNEVR : "?DNEVR?"));
00766 /*@=modfilesys @*/
00767 
00768     }
00769 
00770     return i;
00771 }
00772 
00773 rpmds rpmdsInit(/*@null@*/ rpmds ds)
00774         /*@modifies ds @*/
00775 {
00776     if (ds != NULL)
00777         ds->i = -1;
00778     /*@-refcounttrans@*/
00779     return ds;
00780     /*@=refcounttrans@*/
00781 }
00782 
00783 /*@-bounds@*/
00784 static /*@null@*/
00785 const char ** rpmdsDupArgv(/*@null@*/ const char ** argv, int argc)
00786         /*@*/
00787 {
00788     const char ** av;
00789     size_t nb = 0;
00790     int ac = 0;
00791     char * t;
00792 
00793     if (argv == NULL)
00794         return NULL;
00795     for (ac = 0; ac < argc; ac++) {
00796 assert(argv[ac] != NULL);
00797         nb += strlen(argv[ac]) + 1;
00798     }
00799     nb += (ac + 1) * sizeof(*av);
00800 
00801     av = xmalloc(nb);
00802     t = (char *) (av + ac + 1);
00803     for (ac = 0; ac < argc; ac++) {
00804         av[ac] = t;
00805         t = stpcpy(t, argv[ac]) + 1;
00806     }
00807     av[ac] = NULL;
00808 /*@-nullret@*/
00809     return av;
00810 /*@=nullret@*/
00811 }
00812 /*@=bounds@*/
00813 
00814 /*@null@*/
00815 static rpmds rpmdsDup(const rpmds ods)
00816         /*@modifies ods @*/
00817 {
00818     rpmds ds = xcalloc(1, sizeof(*ds));
00819     size_t nb;
00820 
00821     ds->h = (ods->h != NULL ? headerLink(ods->h) : NULL);
00822 /*@-assignexpose@*/
00823     ds->Type = ods->Type;
00824 /*@=assignexpose@*/
00825     ds->tagN = ods->tagN;
00826     ds->Count = ods->Count;
00827     ds->i = ods->i;
00828     ds->l = ods->l;
00829     ds->u = ods->u;
00830     ds->nopromote = ods->nopromote;
00831 
00832     nb = (ds->Count+1) * sizeof(*ds->N);
00833     ds->N = (ds->h != NULL
00834         ? memcpy(xmalloc(nb), ods->N, nb)
00835         : rpmdsDupArgv(ods->N, ods->Count) );
00836     ds->Nt = ods->Nt;
00837 
00838     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00839 assert(ods->EVR != NULL);
00840 assert(ods->Flags != NULL);
00841 
00842     nb = (ds->Count+1) * sizeof(*ds->EVR);
00843     ds->EVR = (ds->h != NULL
00844         ? memcpy(xmalloc(nb), ods->EVR, nb)
00845         : rpmdsDupArgv(ods->EVR, ods->Count) );
00846     ds->EVRt = ods->EVRt;
00847 
00848     nb = (ds->Count * sizeof(*ds->Flags));
00849     ds->Flags = (ds->h != NULL
00850         ? ods->Flags
00851         : memcpy(xmalloc(nb), ods->Flags, nb) );
00852     ds->Ft = ods->Ft;
00853 
00854 /*@-compmempass@*/ /* FIX: ds->Flags is kept, not only */
00855     return rpmdsLink(ds, (ds ? ds->Type : NULL));
00856 /*@=compmempass@*/
00857 
00858 }
00859 
00860 int rpmdsFind(rpmds ds, const rpmds ods)
00861 {
00862     int comparison;
00863 
00864     if (ds == NULL || ods == NULL)
00865         return -1;
00866 
00867     ds->l = 0;
00868     ds->u = ds->Count;
00869     while (ds->l < ds->u) {
00870         ds->i = (ds->l + ds->u) / 2;
00871 
00872         comparison = strcmp(ods->N[ods->i], ds->N[ds->i]);
00873 
00874         /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00875 /*@-nullderef@*/
00876         if (comparison == 0 && ods->EVR && ds->EVR)
00877             comparison = strcmp(ods->EVR[ods->i], ds->EVR[ds->i]);
00878         if (comparison == 0 && ods->Flags && ds->Flags)
00879             comparison = (ods->Flags[ods->i] - ds->Flags[ds->i]);
00880 /*@=nullderef@*/
00881 
00882         if (comparison < 0)
00883             ds->u = ds->i;
00884         else if (comparison > 0)
00885             ds->l = ds->i + 1;
00886         else
00887             return ds->i;
00888     }
00889     return -1;
00890 }
00891 
00892 int rpmdsMerge(rpmds * dsp, rpmds ods)
00893 {
00894     rpmds ds;
00895     const char ** N;
00896     const char ** EVR;
00897     int_32 * Flags;
00898     int j;
00899 int save;
00900 
00901     if (dsp == NULL || ods == NULL)
00902         return -1;
00903 
00904     /* If not initialized yet, dup the 1st entry. */
00905 /*@-branchstate@*/
00906     if (*dsp == NULL) {
00907         save = ods->Count;
00908         ods->Count = 1;
00909         *dsp = rpmdsDup(ods);
00910         ods->Count = save;
00911     }
00912 /*@=branchstate@*/
00913     ds = *dsp;
00914     if (ds == NULL)
00915         return -1;
00916 
00917     /*
00918      * Add new entries.
00919      */
00920 save = ods->i;
00921     ods = rpmdsInit(ods);
00922     if (ods != NULL)
00923     while (rpmdsNext(ods) >= 0) {
00924         /*
00925          * If this entry is already present, don't bother.
00926          */
00927         if (rpmdsFind(ds, ods) >= 0)
00928             continue;
00929 
00930         /*
00931          * Insert new entry.
00932          */
00933         for (j = ds->Count; j > ds->u; j--)
00934             ds->N[j] = ds->N[j-1];
00935         ds->N[ds->u] = ods->N[ods->i];
00936         N = rpmdsDupArgv(ds->N, ds->Count+1);
00937         ds->N = _free(ds->N);
00938         ds->N = N;
00939         
00940         /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
00941 /*@-nullderef -nullpass -nullptrarith @*/
00942 assert(ods->EVR != NULL);
00943 assert(ods->Flags != NULL);
00944 
00945         for (j = ds->Count; j > ds->u; j--)
00946             ds->EVR[j] = ds->EVR[j-1];
00947         ds->EVR[ds->u] = ods->EVR[ods->i];
00948         EVR = rpmdsDupArgv(ds->EVR, ds->Count+1);
00949         ds->EVR = _free(ds->EVR);
00950         ds->EVR = EVR;
00951 
00952         Flags = xmalloc((ds->Count+1) * sizeof(*Flags));
00953         if (ds->u > 0)
00954             memcpy(Flags, ds->Flags, ds->u * sizeof(*Flags));
00955         if (ds->u < ds->Count)
00956             memcpy(Flags + ds->u + 1, ds->Flags + ds->u, (ds->Count - ds->u) * sizeof(*Flags));
00957         Flags[ds->u] = ods->Flags[ods->i];
00958         ds->Flags = _free(ds->Flags);
00959         ds->Flags = Flags;
00960 /*@=nullderef =nullpass =nullptrarith @*/
00961 
00962         ds->i = ds->Count;
00963         ds->Count++;
00964 
00965     }
00966 /*@-nullderef@*/
00967 ods->i = save;
00968 /*@=nullderef@*/
00969     return 0;
00970 }
00971 
00979 static
00980 void parseEVR(char * evr,
00981                 /*@exposed@*/ /*@out@*/ const char ** ep,
00982                 /*@exposed@*/ /*@out@*/ const char ** vp,
00983                 /*@exposed@*/ /*@out@*/ const char ** rp)
00984         /*@modifies *ep, *vp, *rp @*/
00985         /*@requires maxSet(ep) >= 0 /\ maxSet(vp) >= 0 /\ maxSet(rp) >= 0 @*/
00986 {
00987     const char *epoch;
00988     const char *version;                /* assume only version is present */
00989     const char *release;
00990     char *s, *se;
00991 
00992     s = evr;
00993     while (*s && xisdigit(*s)) s++;     /* s points to epoch terminator */
00994     se = strrchr(s, '-');               /* se points to version terminator */
00995 
00996     if (*s == ':') {
00997         epoch = evr;
00998         *s++ = '\0';
00999         version = s;
01000         /*@-branchstate@*/
01001         if (*epoch == '\0') epoch = "0";
01002         /*@=branchstate@*/
01003     } else {
01004         epoch = NULL;   /* XXX disable epoch compare if missing */
01005         version = evr;
01006     }
01007     if (se) {
01008 /*@-boundswrite@*/
01009         *se++ = '\0';
01010 /*@=boundswrite@*/
01011         release = se;
01012     } else {
01013         release = NULL;
01014     }
01015 
01016     if (ep) *ep = epoch;
01017     if (vp) *vp = version;
01018     if (rp) *rp = release;
01019 }
01020 
01021 int rpmdsCompare(const rpmds A, const rpmds B)
01022 {
01023     const char *aDepend = (A->DNEVR != NULL ? A->DNEVR+2 : "");
01024     const char *bDepend = (B->DNEVR != NULL ? B->DNEVR+2 : "");
01025     char *aEVR, *bEVR;
01026     const char *aE, *aV, *aR, *bE, *bV, *bR;
01027     int result;
01028     int sense;
01029 
01030 /*@-boundsread@*/
01031     /* Different names don't overlap. */
01032     if (strcmp(A->N[A->i], B->N[B->i])) {
01033         result = 0;
01034         goto exit;
01035     }
01036 
01037     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
01038 /*@-nullderef@*/
01039     if (!(A->EVR && A->Flags && B->EVR && B->Flags)) {
01040         result = 1;
01041         goto exit;
01042     }
01043 
01044     /* Same name. If either A or B is an existence test, always overlap. */
01045     if (!((A->Flags[A->i] & RPMSENSE_SENSEMASK) && (B->Flags[B->i] & RPMSENSE_SENSEMASK))) {
01046         result = 1;
01047         goto exit;
01048     }
01049 
01050     /* If either EVR is non-existent or empty, always overlap. */
01051     if (!(A->EVR[A->i] && *A->EVR[A->i] && B->EVR[B->i] && *B->EVR[B->i])) {
01052         result = 1;
01053         goto exit;
01054     }
01055 
01056     /* Both AEVR and BEVR exist. */
01057 /*@-boundswrite@*/
01058     aEVR = xstrdup(A->EVR[A->i]);
01059     parseEVR(aEVR, &aE, &aV, &aR);
01060     bEVR = xstrdup(B->EVR[B->i]);
01061     parseEVR(bEVR, &bE, &bV, &bR);
01062 /*@=boundswrite@*/
01063 
01064     /* Compare {A,B} [epoch:]version[-release] */
01065     sense = 0;
01066     if (aE && *aE && bE && *bE)
01067         sense = rpmvercmp(aE, bE);
01068     else if (aE && *aE && atol(aE) > 0) {
01069         if (!B->nopromote) {
01070             int lvl = (_rpmds_unspecified_epoch_noise  ? RPMMESS_WARNING : RPMMESS_DEBUG);
01071             rpmMessage(lvl, _("The \"B\" dependency needs an epoch (assuming same epoch as \"A\")\n\tA = \"%s\"\tB = \"%s\"\n"),
01072                 aDepend, bDepend);
01073             sense = 0;
01074         } else
01075             sense = 1;
01076     } else if (bE && *bE && atol(bE) > 0)
01077         sense = -1;
01078 
01079     if (sense == 0) {
01080         sense = rpmvercmp(aV, bV);
01081         if (sense == 0 && aR && *aR && bR && *bR)
01082             sense = rpmvercmp(aR, bR);
01083     }
01084 /*@=boundsread@*/
01085     aEVR = _free(aEVR);
01086     bEVR = _free(bEVR);
01087 
01088     /* Detect overlap of {A,B} range. */
01089     result = 0;
01090     if (sense < 0 && ((A->Flags[A->i] & RPMSENSE_GREATER) || (B->Flags[B->i] & RPMSENSE_LESS))) {
01091         result = 1;
01092     } else if (sense > 0 && ((A->Flags[A->i] & RPMSENSE_LESS) || (B->Flags[B->i] & RPMSENSE_GREATER))) {
01093         result = 1;
01094     } else if (sense == 0 &&
01095         (((A->Flags[A->i] & RPMSENSE_EQUAL) && (B->Flags[B->i] & RPMSENSE_EQUAL)) ||
01096          ((A->Flags[A->i] & RPMSENSE_LESS) && (B->Flags[B->i] & RPMSENSE_LESS)) ||
01097          ((A->Flags[A->i] & RPMSENSE_GREATER) && (B->Flags[B->i] & RPMSENSE_GREATER)))) {
01098         result = 1;
01099     }
01100 /*@=nullderef@*/
01101 
01102 exit:
01103     if (_noisy_range_comparison_debug_message)
01104     rpmMessage(RPMMESS_DEBUG, _("  %s    A %s\tB %s\n"),
01105         (result ? _("YES") : _("NO ")), aDepend, bDepend);
01106     return result;
01107 }
01108 
01109 void rpmdsProblem(rpmps ps, const char * pkgNEVR, const rpmds ds,
01110         const fnpyKey * suggestedKeys, int adding)
01111 {
01112     const char * Name =  rpmdsN(ds);
01113     const char * DNEVR = rpmdsDNEVR(ds);
01114     const char * EVR = rpmdsEVR(ds);
01115     rpmProblemType type;
01116     fnpyKey key;
01117 
01118     if (ps == NULL) return;
01119 
01120     /*@-branchstate@*/
01121     if (Name == NULL) Name = "?N?";
01122     if (EVR == NULL) EVR = "?EVR?";
01123     if (DNEVR == NULL) DNEVR = "? ?N? ?OP? ?EVR?";
01124     /*@=branchstate@*/
01125 
01126     rpmMessage(RPMMESS_DEBUG, _("package %s has unsatisfied %s: %s\n"),
01127             pkgNEVR, ds->Type, DNEVR+2);
01128 
01129     switch ((unsigned)DNEVR[0]) {
01130     case 'C':   type = RPMPROB_CONFLICT;        break;
01131     default:
01132     case 'R':   type = RPMPROB_REQUIRES;        break;
01133     }
01134 
01135     key = (suggestedKeys ? suggestedKeys[0] : NULL);
01136     rpmpsAppend(ps, type, pkgNEVR, key, NULL, NULL, DNEVR, adding);
01137 }
01138 
01139 int rpmdsAnyMatchesDep (const Header h, const rpmds req, int nopromote)
01140 {
01141     int scareMem = 0;
01142     rpmds provides = NULL;
01143     int result = 0;
01144 
01145     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
01146     if (req->EVR == NULL || req->Flags == NULL)
01147         return 1;
01148 
01149 /*@-boundsread@*/
01150     if (!(req->Flags[req->i] & RPMSENSE_SENSEMASK) || !req->EVR[req->i] || *req->EVR[req->i] == '\0')
01151         return 1;
01152 /*@=boundsread@*/
01153 
01154     /* Get provides information from header */
01155     provides = rpmdsInit(rpmdsNew(h, RPMTAG_PROVIDENAME, scareMem));
01156     if (provides == NULL)
01157         goto exit;      /* XXX should never happen */
01158     if (nopromote)
01159         (void) rpmdsSetNoPromote(provides, nopromote);
01160 
01161     /*
01162      * Rpm prior to 3.0.3 did not have versioned provides.
01163      * If no provides version info is available, match any/all requires
01164      * with same name.
01165      */
01166     if (provides->EVR == NULL) {
01167         result = 1;
01168         goto exit;
01169     }
01170 
01171     result = 0;
01172     if (provides != NULL)
01173     while (rpmdsNext(provides) >= 0) {
01174 
01175         /* Filter out provides that came along for the ride. */
01176 /*@-boundsread@*/
01177         if (strcmp(provides->N[provides->i], req->N[req->i]))
01178             continue;
01179 /*@=boundsread@*/
01180 
01181         result = rpmdsCompare(provides, req);
01182 
01183         /* If this provide matches the require, we're done. */
01184         if (result)
01185             break;
01186     }
01187 
01188 exit:
01189     provides = rpmdsFree(provides);
01190 
01191     return result;
01192 }
01193 
01194 int rpmdsNVRMatchesDep(const Header h, const rpmds req, int nopromote)
01195 {
01196     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
01197     const char * pkgN, * v, * r;
01198     int_32 * epoch;
01199     const char * pkgEVR;
01200     char * t;
01201     int_32 pkgFlags = RPMSENSE_EQUAL;
01202     rpmds pkg;
01203     int rc = 1; /* XXX assume match, names already match here */
01204 
01205     /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
01206     if (req->EVR == NULL || req->Flags == NULL)
01207         return rc;
01208 
01209 /*@-boundsread@*/
01210     if (!((req->Flags[req->i] & RPMSENSE_SENSEMASK) && req->EVR[req->i] && *req->EVR[req->i]))
01211         return rc;
01212 /*@=boundsread@*/
01213 
01214     /* Get package information from header */
01215     (void) headerNVR(h, &pkgN, &v, &r);
01216 
01217 /*@-boundswrite@*/
01218     t = alloca(21 + strlen(v) + 1 + strlen(r) + 1);
01219     pkgEVR = t;
01220     *t = '\0';
01221     if (hge(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
01222         sprintf(t, "%d:", *epoch);
01223         while (*t != '\0')
01224             t++;
01225     }
01226     (void) stpcpy( stpcpy( stpcpy(t, v) , "-") , r);
01227 /*@=boundswrite@*/
01228 
01229     if ((pkg = rpmdsSingle(RPMTAG_PROVIDENAME, pkgN, pkgEVR, pkgFlags)) != NULL) {
01230         if (nopromote)
01231             (void) rpmdsSetNoPromote(pkg, nopromote);
01232         rc = rpmdsCompare(pkg, req);
01233         pkg = rpmdsFree(pkg);
01234     }
01235 
01236     return rc;
01237 }

Generated on Fri Apr 2 18:06:16 2010 for rpm by  doxygen 1.4.7