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