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

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

Generated on Mon Nov 1 21:57:35 2004 for rpm by  doxygen 1.3.9.1