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 = "redhatbuilddependency";
00119
00125 static int archFilter(const char * arch)
00126
00127
00128 {
00129 static int oneshot = 0;
00130 int negate = 0;
00131 int rc = 0;
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
00153 if (_rpmds_debug < 0)
00154 fprintf(stderr, "=== strcmp(\"%s\", \"%s\") negate %d rc %d\n", arch, myarch, negate, rc);
00155
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
00164 if (_rpmds_debug < 0)
00165 fprintf(stderr, "=== archScore(\"%s\") %d negate %d rc %d\n", arch, archScore, negate, rc);
00166
00167 }
00168 return rc;
00169 }
00170
00177
00178 static rpmds rpmdsFilter( rpmds ds,
00179 const char * token)
00180
00181
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
00217 if (_rpmds_debug < 0)
00218 fprintf(stderr, "*** f \"%s\"\n", f);
00219
00220 g = f + 1;
00221 state = 0;
00222 gN = NULL;
00223 ignore = 1;
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
00234 switch (state) {
00235 case 0:
00236 gN = xstrdup(buf);
00237 break;
00238 default:
00239
00240 if (archFilter(buf))
00241 ignore = 0;
00242 break;
00243 }
00244
00245 state++;
00246 }
00247 if (ignore) {
00248 int Count = rpmdsCount(fds);
00249
00250 if (_rpmds_debug < 0)
00251 fprintf(stderr, "*** deleting N[%d:%d] = \"%s\"\n", i, Count, N);
00252
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
00264 char * t = (char *) N;
00265 (void) strcpy(t, gN);
00266
00267
00268 if (_rpmds_debug < 0)
00269 fprintf(stderr, "*** unwrapping N[%d] = \"%s\"\n", i, N);
00270
00271 }
00272 gN = _free(gN);
00273 }
00274 fds = rpmdsFree(fds);
00275
00276 exit:
00277
00278 return ds;
00279
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
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
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
00351 ds->Color = xcalloc(Count, sizeof(*ds->Color));
00352 ds->Refs = xcalloc(Count, sizeof(*ds->Refs));
00353
00354
00355 if (_rpmds_debug < 0)
00356 fprintf(stderr, "*** ds %p\t%s[%d]\n", ds, ds->Type, ds->Count);
00357
00358
00359 }
00360
00361
00362 exit:
00363
00364 ds = rpmdsLink(ds, (ds ? ds->Type : NULL));
00365
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
00381 if (ds->N[ds->i]) nb += strlen(ds->N[ds->i]);
00382
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
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
00395
00396
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
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
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
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
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
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->N = N;
00480 ds->Nt = -1;
00481 ds->EVR = EVR;
00482 ds->EVRt = -1;
00483
00484 ds->Flags = xmalloc(sizeof(*ds->Flags)); ds->Flags[0] = Flags;
00485
00486 ds->i = 0;
00487 { char pre[2];
00488
00489 pre[0] = ds->Type[0];
00490
00491 pre[1] = '\0';
00492
00493 ds->DNEVR = rpmdsNewDNEVR(pre, ds);
00494
00495 }
00496
00497 exit:
00498 return rpmdsLink(ds, (ds ? ds->Type : NULL));
00499 }
00500
00501 rpmds rpmdsSingle(rpmTag tagN, const char * N, const char * EVR, int_32 Flags)
00502 {
00503 rpmds ds = NULL;
00504 const char * Type;
00505
00506 if (tagN == RPMTAG_PROVIDENAME) {
00507 Type = "Provides";
00508 } else
00509 if (tagN == RPMTAG_REQUIRENAME) {
00510 Type = "Requires";
00511 } else
00512 if (tagN == RPMTAG_CONFLICTNAME) {
00513 Type = "Conflicts";
00514 } else
00515 if (tagN == RPMTAG_OBSOLETENAME) {
00516 Type = "Obsoletes";
00517 } else
00518 if (tagN == RPMTAG_TRIGGERNAME) {
00519 Type = "Trigger";
00520 } else
00521 goto exit;
00522
00523 ds = xcalloc(1, sizeof(*ds));
00524 ds->h = NULL;
00525 ds->Type = Type;
00526 ds->tagN = tagN;
00527 { time_t now = time(NULL);
00528 ds->BT = now;
00529 }
00530 ds->Count = 1;
00531
00532
00533 ds->N = xmalloc(sizeof(*ds->N)); ds->N[0] = N;
00534 ds->Nt = -1;
00535 ds->EVR = xmalloc(sizeof(*ds->EVR)); ds->EVR[0] = EVR;
00536 ds->EVRt = -1;
00537
00538 ds->Flags = xmalloc(sizeof(*ds->Flags)); ds->Flags[0] = Flags;
00539
00540 ds->i = 0;
00541 { char t[2];
00542
00543 t[0] = ds->Type[0];
00544
00545 t[1] = '\0';
00546 ds->DNEVR = rpmdsNewDNEVR(t, ds);
00547 }
00548
00549 exit:
00550 return rpmdsLink(ds, (ds ? ds->Type : NULL));
00551 }
00552
00553 int rpmdsCount(const rpmds ds)
00554 {
00555 return (ds != NULL ? ds->Count : 0);
00556 }
00557
00558 int rpmdsIx(const rpmds ds)
00559 {
00560 return (ds != NULL ? ds->i : -1);
00561 }
00562
00563 int rpmdsSetIx(rpmds ds, int ix)
00564 {
00565 int i = -1;
00566
00567 if (ds != NULL) {
00568 i = ds->i;
00569 ds->i = ix;
00570 }
00571 return i;
00572 }
00573
00574 const char * rpmdsDNEVR(const rpmds ds)
00575 {
00576 const char * DNEVR = NULL;
00577
00578 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00579
00580 if (ds->DNEVR != NULL)
00581 DNEVR = ds->DNEVR;
00582
00583 }
00584 return DNEVR;
00585 }
00586
00587 const char * rpmdsN(const rpmds ds)
00588 {
00589 const char * N = NULL;
00590
00591 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00592
00593 if (ds->N != NULL)
00594 N = ds->N[ds->i];
00595
00596 }
00597 return N;
00598 }
00599
00600 const char * rpmdsEVR(const rpmds ds)
00601 {
00602 const char * EVR = NULL;
00603
00604 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00605
00606 if (ds->EVR != NULL)
00607 EVR = ds->EVR[ds->i];
00608
00609 }
00610 return EVR;
00611 }
00612
00613 int_32 rpmdsFlags(const rpmds ds)
00614 {
00615 int_32 Flags = 0;
00616
00617 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00618
00619 if (ds->Flags != NULL)
00620 Flags = ds->Flags[ds->i];
00621
00622 }
00623 return Flags;
00624 }
00625
00626 rpmTag rpmdsTagN(const rpmds ds)
00627 {
00628 rpmTag tagN = 0;
00629
00630 if (ds != NULL)
00631 tagN = ds->tagN;
00632 return tagN;
00633 }
00634
00635 time_t rpmdsBT(const rpmds ds)
00636 {
00637 time_t BT = 0;
00638 if (ds != NULL && ds->BT > 0)
00639 BT = ds->BT;
00640 return BT;
00641 }
00642
00643 time_t rpmdsSetBT(const rpmds ds, time_t BT)
00644 {
00645 time_t oBT = 0;
00646 if (ds != NULL) {
00647 oBT = ds->BT;
00648 ds->BT = BT;
00649 }
00650 return oBT;
00651 }
00652
00653 int rpmdsNoPromote(const rpmds ds)
00654 {
00655 int nopromote = 0;
00656
00657 if (ds != NULL)
00658 nopromote = ds->nopromote;
00659 return nopromote;
00660 }
00661
00662 int rpmdsSetNoPromote(rpmds ds, int nopromote)
00663 {
00664 int onopromote = 0;
00665
00666 if (ds != NULL) {
00667 onopromote = ds->nopromote;
00668 ds->nopromote = nopromote;
00669 }
00670 return onopromote;
00671 }
00672
00673 uint_32 rpmdsColor(const rpmds ds)
00674 {
00675 uint_32 Color = 0;
00676
00677 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00678
00679 if (ds->Color != NULL)
00680 Color = ds->Color[ds->i];
00681
00682 }
00683 return Color;
00684 }
00685
00686 uint_32 rpmdsSetColor(const rpmds ds, uint_32 color)
00687 {
00688 uint_32 ocolor = 0;
00689
00690 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00691
00692 if (ds->Color != NULL) {
00693 ocolor = ds->Color[ds->i];
00694 ds->Color[ds->i] = color;
00695 }
00696
00697 }
00698 return ocolor;
00699 }
00700
00701 int_32 rpmdsRefs(const rpmds ds)
00702 {
00703 int_32 Refs = 0;
00704
00705 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00706
00707 if (ds->Refs != NULL)
00708 Refs = ds->Refs[ds->i];
00709
00710 }
00711 return Refs;
00712 }
00713
00714 int_32 rpmdsSetRefs(const rpmds ds, int_32 refs)
00715 {
00716 int_32 orefs = 0;
00717
00718 if (ds != NULL && ds->i >= 0 && ds->i < ds->Count) {
00719
00720 if (ds->Refs != NULL) {
00721 orefs = ds->Refs[ds->i];
00722 ds->Refs[ds->i] = refs;
00723 }
00724
00725 }
00726 return orefs;
00727 }
00728
00729 void rpmdsNotify(rpmds ds, const char * where, int rc)
00730 {
00731 if (!(ds != NULL && ds->i >= 0 && ds->i < ds->Count))
00732 return;
00733 if (!(ds->Type != NULL && ds->DNEVR != NULL))
00734 return;
00735
00736 rpmMessage(RPMMESS_DEBUG, "%9s: %-45s %-s %s\n", ds->Type,
00737 (!strcmp(ds->DNEVR, "cached") ? ds->DNEVR : ds->DNEVR+2),
00738 (rc ? _("NO ") : _("YES")),
00739 (where != NULL ? where : ""));
00740 }
00741
00742 int rpmdsNext( rpmds ds)
00743
00744 {
00745 int i = -1;
00746
00747 if (ds != NULL && ++ds->i >= 0) {
00748 if (ds->i < ds->Count) {
00749 char t[2];
00750 i = ds->i;
00751 ds->DNEVR = _free(ds->DNEVR);
00752 t[0] = ((ds->Type != NULL) ? ds->Type[0] : '\0');
00753 t[1] = '\0';
00754
00755 ds->DNEVR = rpmdsNewDNEVR(t, ds);
00756
00757
00758 } else
00759 ds->i = -1;
00760
00761
00762 if (_rpmds_debug < 0 && i != -1)
00763 fprintf(stderr, "*** ds %p\t%s[%d]: %s\n", ds, (ds->Type ? ds->Type : "?Type?"), i, (ds->DNEVR ? ds->DNEVR : "?DNEVR?"));
00764
00765
00766 }
00767
00768 return i;
00769 }
00770
00771 rpmds rpmdsInit( rpmds ds)
00772
00773 {
00774 if (ds != NULL)
00775 ds->i = -1;
00776
00777 return ds;
00778
00779 }
00780
00781
00782 static
00783 const char ** rpmdsDupArgv( const char ** argv, int argc)
00784
00785 {
00786 const char ** av;
00787 size_t nb = 0;
00788 int ac = 0;
00789 char * t;
00790
00791 if (argv == NULL)
00792 return NULL;
00793 for (ac = 0; ac < argc; ac++) {
00794 assert(argv[ac] != NULL);
00795 nb += strlen(argv[ac]) + 1;
00796 }
00797 nb += (ac + 1) * sizeof(*av);
00798
00799 av = xmalloc(nb);
00800 t = (char *) (av + ac + 1);
00801 for (ac = 0; ac < argc; ac++) {
00802 av[ac] = t;
00803 t = stpcpy(t, argv[ac]) + 1;
00804 }
00805 av[ac] = NULL;
00806
00807 return av;
00808
00809 }
00810
00811
00812
00813 static rpmds rpmdsDup(const rpmds ods)
00814
00815 {
00816 rpmds ds = xcalloc(1, sizeof(*ds));
00817 size_t nb;
00818
00819 ds->h = (ods->h != NULL ? headerLink(ods->h) : NULL);
00820
00821 ds->Type = ods->Type;
00822
00823 ds->tagN = ods->tagN;
00824 ds->Count = ods->Count;
00825 ds->i = ods->i;
00826 ds->l = ods->l;
00827 ds->u = ods->u;
00828
00829 nb = (ds->Count+1) * sizeof(*ds->N);
00830 ds->N = (ds->h != NULL
00831 ? memcpy(xmalloc(nb), ods->N, nb)
00832 : rpmdsDupArgv(ods->N, ods->Count) );
00833 ds->Nt = ods->Nt;
00834
00835
00836 assert(ods->EVR != NULL);
00837 assert(ods->Flags != NULL);
00838
00839 nb = (ds->Count+1) * sizeof(*ds->EVR);
00840 ds->EVR = (ds->h != NULL
00841 ? memcpy(xmalloc(nb), ods->EVR, nb)
00842 : rpmdsDupArgv(ods->EVR, ods->Count) );
00843 ds->EVRt = ods->EVRt;
00844
00845 nb = (ds->Count * sizeof(*ds->Flags));
00846 ds->Flags = (ds->h != NULL
00847 ? ods->Flags
00848 : memcpy(xmalloc(nb), ods->Flags, nb) );
00849 ds->Ft = ods->Ft;
00850
00851
00852 return rpmdsLink(ds, (ds ? ds->Type : NULL));
00853
00854
00855 }
00856
00857 int rpmdsFind(rpmds ds, const rpmds ods)
00858 {
00859 int comparison;
00860
00861 if (ds == NULL || ods == NULL)
00862 return -1;
00863
00864 ds->l = 0;
00865 ds->u = ds->Count;
00866 while (ds->l < ds->u) {
00867 ds->i = (ds->l + ds->u) / 2;
00868
00869 comparison = strcmp(ods->N[ods->i], ds->N[ds->i]);
00870
00871
00872
00873 if (comparison == 0 && ods->EVR && ds->EVR)
00874 comparison = strcmp(ods->EVR[ods->i], ds->EVR[ds->i]);
00875 if (comparison == 0 && ods->Flags && ds->Flags)
00876 comparison = (ods->Flags[ods->i] - ds->Flags[ds->i]);
00877
00878
00879 if (comparison < 0)
00880 ds->u = ds->i;
00881 else if (comparison > 0)
00882 ds->l = ds->i + 1;
00883 else
00884 return ds->i;
00885 }
00886 return -1;
00887 }
00888
00889 int rpmdsMerge(rpmds * dsp, rpmds ods)
00890 {
00891 rpmds ds;
00892 const char ** N;
00893 const char ** EVR;
00894 int_32 * Flags;
00895 int j;
00896 int save;
00897
00898 if (dsp == NULL || ods == NULL)
00899 return -1;
00900
00901
00902
00903 if (*dsp == NULL) {
00904 save = ods->Count;
00905 ods->Count = 1;
00906 *dsp = rpmdsDup(ods);
00907 ods->Count = save;
00908 }
00909
00910 ds = *dsp;
00911 if (ds == NULL)
00912 return -1;
00913
00914
00915
00916
00917 save = ods->i;
00918 ods = rpmdsInit(ods);
00919 if (ods != NULL)
00920 while (rpmdsNext(ods) >= 0) {
00921
00922
00923
00924 if (rpmdsFind(ds, ods) >= 0)
00925 continue;
00926
00927
00928
00929
00930 for (j = ds->Count; j > ds->u; j--)
00931 ds->N[j] = ds->N[j-1];
00932 ds->N[ds->u] = ods->N[ods->i];
00933 N = rpmdsDupArgv(ds->N, ds->Count+1);
00934 ds->N = _free(ds->N);
00935 ds->N = N;
00936
00937
00938
00939 assert(ods->EVR != NULL);
00940 assert(ods->Flags != NULL);
00941
00942 for (j = ds->Count; j > ds->u; j--)
00943 ds->EVR[j] = ds->EVR[j-1];
00944 ds->EVR[ds->u] = ods->EVR[ods->i];
00945 EVR = rpmdsDupArgv(ds->EVR, ds->Count+1);
00946 ds->EVR = _free(ds->EVR);
00947 ds->EVR = EVR;
00948
00949 Flags = xmalloc((ds->Count+1) * sizeof(*Flags));
00950 if (ds->u > 0)
00951 memcpy(Flags, ds->Flags, ds->u * sizeof(*Flags));
00952 if (ds->u < ds->Count)
00953 memcpy(Flags + ds->u + 1, ds->Flags + ds->u, (ds->Count - ds->u) * sizeof(*Flags));
00954 Flags[ds->u] = ods->Flags[ods->i];
00955 ds->Flags = _free(ds->Flags);
00956 ds->Flags = Flags;
00957
00958
00959 ds->i = ds->Count;
00960 ds->Count++;
00961
00962 }
00963
00964 ods->i = save;
00965
00966 return 0;
00967 }
00968
00976 static
00977 void parseEVR(char * evr,
00978 const char ** ep,
00979 const char ** vp,
00980 const char ** rp)
00981
00982
00983 {
00984 const char *epoch;
00985 const char *version;
00986 const char *release;
00987 char *s, *se;
00988
00989 s = evr;
00990 while (*s && xisdigit(*s)) s++;
00991 se = strrchr(s, '-');
00992
00993 if (*s == ':') {
00994 epoch = evr;
00995 *s++ = '\0';
00996 version = s;
00997
00998 if (*epoch == '\0') epoch = "0";
00999
01000 } else {
01001 epoch = NULL;
01002 version = evr;
01003 }
01004 if (se) {
01005
01006 *se++ = '\0';
01007
01008 release = se;
01009 } else {
01010 release = NULL;
01011 }
01012
01013 if (ep) *ep = epoch;
01014 if (vp) *vp = version;
01015 if (rp) *rp = release;
01016 }
01017
01018 int rpmdsCompare(const rpmds A, const rpmds B)
01019 {
01020 const char *aDepend = (A->DNEVR != NULL ? xstrdup(A->DNEVR+2) : "");
01021 const char *bDepend = (B->DNEVR != NULL ? xstrdup(B->DNEVR+2) : "");
01022 char *aEVR, *bEVR;
01023 const char *aE, *aV, *aR, *bE, *bV, *bR;
01024 int result;
01025 int sense;
01026
01027
01028
01029 if (strcmp(A->N[A->i], B->N[B->i])) {
01030 result = 0;
01031 goto exit;
01032 }
01033
01034
01035
01036 if (!(A->EVR && A->Flags && B->EVR && B->Flags)) {
01037 result = 1;
01038 goto exit;
01039 }
01040
01041
01042 if (!((A->Flags[A->i] & RPMSENSE_SENSEMASK) && (B->Flags[B->i] & RPMSENSE_SENSEMASK))) {
01043 result = 1;
01044 goto exit;
01045 }
01046
01047
01048 if (!(A->EVR[A->i] && *A->EVR[A->i] && B->EVR[B->i] && *B->EVR[B->i])) {
01049 result = 1;
01050 goto exit;
01051 }
01052
01053
01054
01055 aEVR = xstrdup(A->EVR[A->i]);
01056 parseEVR(aEVR, &aE, &aV, &aR);
01057 bEVR = xstrdup(B->EVR[B->i]);
01058 parseEVR(bEVR, &bE, &bV, &bR);
01059
01060
01061
01062 sense = 0;
01063 if (aE && *aE && bE && *bE)
01064 sense = rpmvercmp(aE, bE);
01065 else if (aE && *aE && atol(aE) > 0) {
01066 if (!B->nopromote) {
01067 int lvl = (_rpmds_unspecified_epoch_noise ? RPMMESS_WARNING : RPMMESS_DEBUG);
01068 rpmMessage(lvl, _("The \"B\" dependency needs an epoch (assuming same epoch as \"A\")\n\tA = \"%s\"\tB = \"%s\"\n"),
01069 aDepend, bDepend);
01070 sense = 0;
01071 } else
01072 sense = 1;
01073 } else if (bE && *bE && atol(bE) > 0)
01074 sense = -1;
01075
01076 if (sense == 0) {
01077 sense = rpmvercmp(aV, bV);
01078 if (sense == 0 && aR && *aR && bR && *bR)
01079 sense = rpmvercmp(aR, bR);
01080 }
01081
01082 aEVR = _free(aEVR);
01083 bEVR = _free(bEVR);
01084
01085
01086 result = 0;
01087 if (sense < 0 && ((A->Flags[A->i] & RPMSENSE_GREATER) || (B->Flags[B->i] & RPMSENSE_LESS))) {
01088 result = 1;
01089 } else if (sense > 0 && ((A->Flags[A->i] & RPMSENSE_LESS) || (B->Flags[B->i] & RPMSENSE_GREATER))) {
01090 result = 1;
01091 } else if (sense == 0 &&
01092 (((A->Flags[A->i] & RPMSENSE_EQUAL) && (B->Flags[B->i] & RPMSENSE_EQUAL)) ||
01093 ((A->Flags[A->i] & RPMSENSE_LESS) && (B->Flags[B->i] & RPMSENSE_LESS)) ||
01094 ((A->Flags[A->i] & RPMSENSE_GREATER) && (B->Flags[B->i] & RPMSENSE_GREATER)))) {
01095 result = 1;
01096 }
01097
01098
01099 exit:
01100 if (_noisy_range_comparison_debug_message)
01101 rpmMessage(RPMMESS_DEBUG, _(" %s A %s\tB %s\n"),
01102 (result ? _("YES") : _("NO ")), aDepend, bDepend);
01103 aDepend = _free(aDepend);
01104 bDepend = _free(bDepend);
01105 return result;
01106 }
01107
01108 void rpmdsProblem(rpmps ps, const char * pkgNEVR, const rpmds ds,
01109 const fnpyKey * suggestedKeys, int adding)
01110 {
01111 const char * Name = rpmdsN(ds);
01112 const char * DNEVR = rpmdsDNEVR(ds);
01113 const char * EVR = rpmdsEVR(ds);
01114 rpmProblemType type;
01115 fnpyKey key;
01116
01117 if (ps == NULL) return;
01118
01119
01120 if (Name == NULL) Name = "?N?";
01121 if (EVR == NULL) EVR = "?EVR?";
01122 if (DNEVR == NULL) DNEVR = "? ?N? ?OP? ?EVR?";
01123
01124
01125 rpmMessage(RPMMESS_DEBUG, _("package %s has unsatisfied %s: %s\n"),
01126 pkgNEVR, ds->Type, DNEVR+2);
01127
01128 switch ((unsigned)DNEVR[0]) {
01129 case 'C': type = RPMPROB_CONFLICT; break;
01130 default:
01131 case 'R': type = RPMPROB_REQUIRES; break;
01132 }
01133
01134 key = (suggestedKeys ? suggestedKeys[0] : NULL);
01135 rpmpsAppend(ps, type, pkgNEVR, key, NULL, NULL, DNEVR, adding);
01136 }
01137
01138 int rpmdsAnyMatchesDep (const Header h, const rpmds req, int nopromote)
01139 {
01140 int scareMem = 0;
01141 rpmds provides = NULL;
01142 int result = 0;
01143
01144
01145 if (req->EVR == NULL || req->Flags == NULL)
01146 return 1;
01147
01148
01149 if (!(req->Flags[req->i] & RPMSENSE_SENSEMASK) || !req->EVR[req->i] || *req->EVR[req->i] == '\0')
01150 return 1;
01151
01152
01153
01154 provides = rpmdsInit(rpmdsNew(h, RPMTAG_PROVIDENAME, scareMem));
01155 if (provides == NULL)
01156 goto exit;
01157 if (nopromote)
01158 (void) rpmdsSetNoPromote(provides, nopromote);
01159
01160
01161
01162
01163
01164
01165 if (provides->EVR == NULL) {
01166 result = 1;
01167 goto exit;
01168 }
01169
01170 result = 0;
01171 if (provides != NULL)
01172 while (rpmdsNext(provides) >= 0) {
01173
01174
01175
01176 if (strcmp(provides->N[provides->i], req->N[req->i]))
01177 continue;
01178
01179
01180 result = rpmdsCompare(provides, req);
01181
01182
01183 if (result)
01184 break;
01185 }
01186
01187 exit:
01188 provides = rpmdsFree(provides);
01189
01190 return result;
01191 }
01192
01193 int rpmdsNVRMatchesDep(const Header h, const rpmds req, int nopromote)
01194 {
01195 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
01196 const char * pkgN, * v, * r;
01197 int_32 * epoch;
01198 const char * pkgEVR;
01199 char * t;
01200 int_32 pkgFlags = RPMSENSE_EQUAL;
01201 rpmds pkg;
01202 int rc = 1;
01203
01204
01205 if (req->EVR == NULL || req->Flags == NULL)
01206 return rc;
01207
01208
01209 if (!((req->Flags[req->i] & RPMSENSE_SENSEMASK) && req->EVR[req->i] && *req->EVR[req->i]))
01210 return rc;
01211
01212
01213
01214 (void) headerNVR(h, &pkgN, &v, &r);
01215
01216
01217 t = alloca(21 + strlen(v) + 1 + strlen(r) + 1);
01218 pkgEVR = t;
01219 *t = '\0';
01220 if (hge(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
01221 sprintf(t, "%d:", *epoch);
01222 while (*t != '\0')
01223 t++;
01224 }
01225 (void) stpcpy( stpcpy( stpcpy(t, v) , "-") , r);
01226
01227
01228 if ((pkg = rpmdsSingle(RPMTAG_PROVIDENAME, pkgN, pkgEVR, pkgFlags)) != NULL) {
01229 if (nopromote)
01230 (void) rpmdsSetNoPromote(pkg, nopromote);
01231 rc = rpmdsCompare(pkg, req);
01232 pkg = rpmdsFree(pkg);
01233 }
01234
01235 return rc;
01236 }