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
00017 static int _noisy_range_comparison_debug_message = 0;
00018
00019
00020 int _rpmds_debug = 0;
00021
00022
00023 int _rpmds_nopromote = 1;
00024
00025
00026
00027 int _rpmds_unspecified_epoch_noise = 0;
00028
00029
00030 rpmds XrpmdsUnlink(rpmds ds, const char * msg, const char * fn, unsigned ln)
00031 {
00032 if (ds == NULL) return NULL;
00033
00034 if (_rpmds_debug && msg != NULL)
00035 fprintf(stderr, "--> ds %p -- %d %s at %s:%u\n", ds, ds->nrefs, msg, fn, ln);
00036
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
00047 if (_rpmds_debug && msg != NULL)
00048 fprintf(stderr, "--> ds %p ++ %d %s at %s:%u\n", ds, ds->nrefs, msg, fn, ln);
00049
00050
00051 return ds;
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
00066 if (_rpmds_debug < 0)
00067 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
00068
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
00093 if (ds->Count > 0) {
00094 ds->N = hfd(ds->N, ds->Nt);
00095 ds->EVR = hfd(ds->EVR, ds->EVRt);
00096
00097 ds->Flags = (ds->h != NULL ? hfd(ds->Flags, ds->Ft) : _free(ds->Flags));
00098
00099 ds->h = headerFree(ds->h);
00100 }
00101
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
00109
00110 memset(ds, 0, sizeof(*ds));
00111
00112 ds = _free(ds);
00113
00114 return NULL;
00115 }
00116
00117
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;
00130 int rc = 0;
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
00152 if (_rpmds_debug < 0)
00153 fprintf(stderr, "=== strcmp(\"%s\", \"%s\") negate %d rc %d\n", arch, myarch, negate, rc);
00154
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
00163 if (_rpmds_debug < 0)
00164 fprintf(stderr, "=== archScore(\"%s\") %d negate %d rc %d\n", arch, archScore, negate, rc);
00165
00166 }
00167 return rc;
00168 }
00169
00176 static rpmds rpmdsFilter( rpmds ds,
00177 const char * token)
00178
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
00214 if (_rpmds_debug < 0)
00215 fprintf(stderr, "*** f \"%s\"\n", f);
00216
00217 g = f + 1;
00218 state = 0;
00219 gN = NULL;
00220 ignore = 1;
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
00231 switch (state) {
00232 case 0:
00233 gN = xstrdup(buf);
00234 break;
00235 default:
00236
00237 if (archFilter(buf))
00238 ignore = 0;
00239 break;
00240 }
00241
00242 state++;
00243 }
00244 if (ignore) {
00245 int Count = rpmdsCount(fds);
00246
00247 if (_rpmds_debug < 0)
00248 fprintf(stderr, "*** deleting N[%d:%d] = \"%s\"\n", i, Count, N);
00249
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
00261 char * t = (char *) N;
00262 (void) strcpy(t, gN);
00263
00264
00265 if (_rpmds_debug < 0)
00266 fprintf(stderr, "*** unwrapping N[%d] = \"%s\"\n", i, N);
00267
00268 }
00269 gN = _free(gN);
00270 }
00271 fds = rpmdsFree(fds);
00272
00273 exit:
00274
00275 return ds;
00276
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
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
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
00348 ds->Color = xcalloc(Count, sizeof(*ds->Color));
00349 ds->Refs = xcalloc(Count, sizeof(*ds->Refs));
00350
00351
00352 if (_rpmds_debug < 0)
00353 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
00354
00355
00356 }
00357
00358
00359 exit:
00360
00361 ds = rpmdsLink(ds, (ds ? ds->Type : NULL));
00362
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
00378 if (ds->N[ds->i]) nb += strlen(ds->N[ds->i]);
00379
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
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
00392
00393
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
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
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
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
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
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;
00478 ds->EVR = EVR;
00479 ds->EVRt = -1;
00480
00481 ds->Flags = xmalloc(sizeof(*ds->Flags)); ds->Flags[0] = Flags;
00482
00483 ds->i = 0;
00484 { char pre[2];
00485
00486 pre[0] = ds->Type[0];
00487
00488 pre[1] = '\0';
00489
00490 ds->DNEVR = rpmdsNewDNEVR(pre, ds);
00491
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
00529
00530 ds->N = xmalloc(sizeof(*ds->N)); ds->N[0] = N;
00531 ds->Nt = -1;
00532 ds->EVR = xmalloc(sizeof(*ds->EVR)); ds->EVR[0] = EVR;
00533 ds->EVRt = -1;
00534
00535 ds->Flags = xmalloc(sizeof(*ds->Flags)); ds->Flags[0] = Flags;
00536
00537 ds->i = 0;
00538 { char t[2];
00539
00540 t[0] = ds->Type[0];
00541
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
00577 if (ds->DNEVR != NULL)
00578 DNEVR = ds->DNEVR;
00579
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
00590 if (ds->N != NULL)
00591 N = ds->N[ds->i];
00592
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
00603 if (ds->EVR != NULL)
00604 EVR = ds->EVR[ds->i];
00605
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
00616 if (ds->Flags != NULL)
00617 Flags = ds->Flags[ds->i];
00618
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
00676 if (ds->Color != NULL)
00677 Color = ds->Color[ds->i];
00678
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
00689 if (ds->Color != NULL) {
00690 ocolor = ds->Color[ds->i];
00691 ds->Color[ds->i] = color;
00692 }
00693
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
00704 if (ds->Refs != NULL)
00705 Refs = ds->Refs[ds->i];
00706
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
00717 if (ds->Refs != NULL) {
00718 orefs = ds->Refs[ds->i];
00719 ds->Refs[ds->i] = refs;
00720 }
00721
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( rpmds ds)
00740
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
00752 ds->DNEVR = rpmdsNewDNEVR(t, ds);
00753
00754
00755 } else
00756 ds->i = -1;
00757
00758
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
00762
00763 }
00764
00765 return i;
00766 }
00767
00768 rpmds rpmdsInit( rpmds ds)
00769
00770 {
00771 if (ds != NULL)
00772 ds->i = -1;
00773
00774 return ds;
00775
00776 }
00777
00778
00779 static
00780 const char ** rpmdsDupArgv( 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
00804 return av;
00805
00806 }
00807
00808
00809
00810 static rpmds rpmdsDup(const rpmds ods)
00811
00812 {
00813 rpmds ds = xcalloc(1, sizeof(*ds));
00814 size_t nb;
00815
00816 ds->h = (ods->h != NULL ? headerLink(ods->h) : NULL);
00817
00818 ds->Type = ods->Type;
00819
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
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
00849 return rpmdsLink(ds, (ds ? ds->Type : NULL));
00850
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
00869
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
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
00899
00900 if (*dsp == NULL) {
00901 save = ods->Count;
00902 ods->Count = 1;
00903 *dsp = rpmdsDup(ods);
00904 ods->Count = save;
00905 }
00906
00907 ds = *dsp;
00908 if (ds == NULL)
00909 return -1;
00910
00911
00912
00913
00914 save = ods->i;
00915 ods = rpmdsInit(ods);
00916 if (ods != NULL)
00917 while (rpmdsNext(ods) >= 0) {
00918
00919
00920
00921 if (rpmdsFind(ds, ods) >= 0)
00922 continue;
00923
00924
00925
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
00935
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
00955
00956 ds->i = ds->Count;
00957 ds->Count++;
00958
00959 }
00960
00961 ods->i = save;
00962
00963 return 0;
00964 }
00965
00973 static
00974 void parseEVR(char * evr,
00975 const char ** ep,
00976 const char ** vp,
00977 const char ** rp)
00978
00979
00980 {
00981 const char *epoch;
00982 const char *version;
00983 const char *release;
00984 char *s, *se;
00985
00986 s = evr;
00987 while (*s && xisdigit(*s)) s++;
00988 se = strrchr(s, '-');
00989
00990 if (*s == ':') {
00991 epoch = evr;
00992 *s++ = '\0';
00993 version = s;
00994
00995 if (*epoch == '\0') epoch = "0";
00996
00997 } else {
00998 epoch = NULL;
00999 version = evr;
01000 }
01001 if (se) {
01002
01003 *se++ = '\0';
01004
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
01025
01026 if (strcmp(A->N[A->i], B->N[B->i])) {
01027 result = 0;
01028 goto exit;
01029 }
01030
01031
01032
01033 if (!(A->EVR && A->Flags && B->EVR && B->Flags)) {
01034 result = 1;
01035 goto exit;
01036 }
01037
01038
01039 if (!((A->Flags[A->i] & RPMSENSE_SENSEMASK) && (B->Flags[B->i] & RPMSENSE_SENSEMASK))) {
01040 result = 1;
01041 goto exit;
01042 }
01043
01044
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
01051
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
01057
01058
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
01080 aEVR = _free(aEVR);
01081 bEVR = _free(bEVR);
01082
01083
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
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
01118 if (Name == NULL) Name = "?N?";
01119 if (EVR == NULL) EVR = "?EVR?";
01120 if (DNEVR == NULL) DNEVR = "? ?N? ?OP? ?EVR?";
01121
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
01143 if (req->EVR == NULL || req->Flags == NULL)
01144 return 1;
01145
01146
01147 if (!(req->Flags[req->i] & RPMSENSE_SENSEMASK) || !req->EVR[req->i] || *req->EVR[req->i] == '\0')
01148 return 1;
01149
01150
01151
01152 provides = rpmdsInit(rpmdsNew(h, RPMTAG_PROVIDENAME, scareMem));
01153 if (provides == NULL)
01154 goto exit;
01155 if (nopromote)
01156 (void) rpmdsSetNoPromote(provides, nopromote);
01157
01158
01159
01160
01161
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
01173
01174 if (strcmp(provides->N[provides->i], req->N[req->i]))
01175 continue;
01176
01177
01178 result = rpmdsCompare(provides, req);
01179
01180
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;
01201
01202
01203 if (req->EVR == NULL || req->Flags == NULL)
01204 return rc;
01205
01206
01207 if (!((req->Flags[req->i] & RPMSENSE_SENSEMASK) && req->EVR[req->i] && *req->EVR[req->i]))
01208 return rc;
01209
01210
01211
01212 (void) headerNVR(h, &pkgN, &v, &r);
01213
01214
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
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 }