1 /* 2 * Copyright (c) 2007-2009, Novell Inc. 3 * 4 * This program is licensed under the BSD license, read LICENSE.BSD 5 * for further information 6 */ 7 8 /* 9 * pool.c 10 * 11 * The pool contains information about solvables 12 * stored optimized for memory consumption and fast retrieval. 13 */ 14 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <stdarg.h> 18 #include <unistd.h> 19 #include <string.h> 20 21 #include "pool.h" 22 #include "repo.h" 23 #include "poolid.h" 24 #include "poolid_private.h" 25 #include "poolarch.h" 26 #include "util.h" 27 #include "bitmap.h" 28 #include "evr.h" 29 30 #define SOLVABLE_BLOCK 255 31 32 #define KNOWNID_INITIALIZE 33 #include "knownid.h" 34 #undef KNOWNID_INITIALIZE 35 36 /* create pool */ 37 Pool * 38 pool_create(void) 39 { 40 Pool *pool; 41 Solvable *s; 42 43 pool = (Pool *)solv_calloc(1, sizeof(*pool)); 44 45 stringpool_init (&pool->ss, initpool_data); 46 47 /* alloc space for RelDep 0 */ 48 pool->rels = solv_extend_resize(0, 1, sizeof(Reldep), REL_BLOCK); 49 pool->nrels = 1; 50 memset(pool->rels, 0, sizeof(Reldep)); 51 52 /* alloc space for Solvable 0 and system solvable */ 53 pool->solvables = solv_extend_resize(0, 2, sizeof(Solvable), SOLVABLE_BLOCK); 54 pool->nsolvables = 2; 55 memset(pool->solvables, 0, 2 * sizeof(Solvable)); 56 57 queue_init(&pool->vendormap); 58 59 #if defined(DEBIAN) 60 pool->disttype = DISTTYPE_DEB; 61 pool->noarchid = ARCH_ALL; 62 #elif defined(ARCHLINUX) 63 pool->disttype = DISTTYPE_ARCH; 64 pool->noarchid = ARCH_ANY; 65 #elif defined(HAIKU) 66 pool->disttype = DISTTYPE_HAIKU; 67 pool->noarchid = ARCH_ANY; 68 pool->obsoleteusesprovides = 1; 69 #else 70 pool->disttype = DISTTYPE_RPM; 71 pool->noarchid = ARCH_NOARCH; 72 #endif 73 74 /* initialize the system solvable */ 75 s = pool->solvables + SYSTEMSOLVABLE; 76 s->name = SYSTEM_SYSTEM; 77 s->arch = pool->noarchid; 78 s->evr = ID_EMPTY; 79 80 pool->debugmask = SOLV_DEBUG_RESULT; /* FIXME */ 81 #ifdef FEDORA 82 pool->obsoleteusescolors = 1; 83 #endif 84 #ifdef RPM5 85 pool->forbidselfconflicts = 1; 86 pool->obsoleteusesprovides = 1; 87 pool->implicitobsoleteusesprovides = 1; 88 pool->havedistepoch = 1; 89 #endif 90 return pool; 91 } 92 93 94 /* free all the resources of our pool */ 95 void 96 pool_free(Pool *pool) 97 { 98 int i; 99 100 pool_freewhatprovides(pool); 101 pool_freeidhashes(pool); 102 pool_freeallrepos(pool, 1); 103 solv_free(pool->id2arch); 104 solv_free(pool->id2color); 105 solv_free(pool->solvables); 106 stringpool_free(&pool->ss); 107 solv_free(pool->rels); 108 pool_setvendorclasses(pool, 0); 109 queue_free(&pool->vendormap); 110 queue_free(&pool->pooljobs); 111 for (i = 0; i < POOL_TMPSPACEBUF; i++) 112 solv_free(pool->tmpspace.buf[i]); 113 for (i = 0; i < pool->nlanguages; i++) 114 free((char *)pool->languages[i]); 115 solv_free(pool->languages); 116 solv_free(pool->languagecache); 117 solv_free(pool->errstr); 118 solv_free(pool->rootdir); 119 solv_free(pool); 120 } 121 122 void 123 pool_freeallrepos(Pool *pool, int reuseids) 124 { 125 int i; 126 127 pool_freewhatprovides(pool); 128 for (i = 1; i < pool->nrepos; i++) 129 if (pool->repos[i]) 130 repo_freedata(pool->repos[i]); 131 pool->repos = solv_free(pool->repos); 132 pool->nrepos = 0; 133 pool->urepos = 0; 134 /* the first two solvables don't belong to a repo */ 135 pool_free_solvable_block(pool, 2, pool->nsolvables - 2, reuseids); 136 } 137 138 #ifdef MULTI_SEMANTICS 139 void 140 pool_setdisttype(Pool *pool, int disttype) 141 { 142 pool->disttype = disttype; 143 if (disttype == DISTTYPE_RPM) 144 pool->noarchid = ARCH_NOARCH; 145 if (disttype == DISTTYPE_DEB) 146 pool->noarchid = ARCH_ALL; 147 if (disttype == DISTTYPE_ARCH) 148 pool->noarchid = ARCH_ANY; 149 if (disttype == DISTTYPE_HAIKU) 150 pool->noarchid = ARCH_ANY; 151 pool->solvables[SYSTEMSOLVABLE].arch = pool->noarchid; 152 } 153 #endif 154 155 int 156 pool_get_flag(Pool *pool, int flag) 157 { 158 switch (flag) 159 { 160 case POOL_FLAG_PROMOTEEPOCH: 161 return pool->promoteepoch; 162 case POOL_FLAG_FORBIDSELFCONFLICTS: 163 return pool->forbidselfconflicts; 164 case POOL_FLAG_OBSOLETEUSESPROVIDES: 165 return pool->obsoleteusesprovides; 166 case POOL_FLAG_IMPLICITOBSOLETEUSESPROVIDES: 167 return pool->implicitobsoleteusesprovides; 168 case POOL_FLAG_OBSOLETEUSESCOLORS: 169 return pool->obsoleteusescolors; 170 case POOL_FLAG_NOINSTALLEDOBSOLETES: 171 return pool->noinstalledobsoletes; 172 case POOL_FLAG_HAVEDISTEPOCH: 173 return pool->havedistepoch; 174 default: 175 break; 176 } 177 return -1; 178 } 179 180 int 181 pool_set_flag(Pool *pool, int flag, int value) 182 { 183 int old = pool_get_flag(pool, flag); 184 switch (flag) 185 { 186 case POOL_FLAG_PROMOTEEPOCH: 187 pool->promoteepoch = value; 188 break; 189 case POOL_FLAG_FORBIDSELFCONFLICTS: 190 pool->forbidselfconflicts = value; 191 break; 192 case POOL_FLAG_OBSOLETEUSESPROVIDES: 193 pool->obsoleteusesprovides = value; 194 break; 195 case POOL_FLAG_IMPLICITOBSOLETEUSESPROVIDES: 196 pool->implicitobsoleteusesprovides = value; 197 break; 198 case POOL_FLAG_OBSOLETEUSESCOLORS: 199 pool->obsoleteusescolors = value; 200 break; 201 case POOL_FLAG_NOINSTALLEDOBSOLETES: 202 pool->noinstalledobsoletes = value; 203 break; 204 case POOL_FLAG_HAVEDISTEPOCH: 205 pool->havedistepoch = value; 206 break; 207 default: 208 break; 209 } 210 return old; 211 } 212 213 214 Id 215 pool_add_solvable(Pool *pool) 216 { 217 pool->solvables = solv_extend(pool->solvables, pool->nsolvables, 1, sizeof(Solvable), SOLVABLE_BLOCK); 218 memset(pool->solvables + pool->nsolvables, 0, sizeof(Solvable)); 219 return pool->nsolvables++; 220 } 221 222 Id 223 pool_add_solvable_block(Pool *pool, int count) 224 { 225 Id nsolvables = pool->nsolvables; 226 if (!count) 227 return nsolvables; 228 pool->solvables = solv_extend(pool->solvables, pool->nsolvables, count, sizeof(Solvable), SOLVABLE_BLOCK); 229 memset(pool->solvables + nsolvables, 0, sizeof(Solvable) * count); 230 pool->nsolvables += count; 231 return nsolvables; 232 } 233 234 void 235 pool_free_solvable_block(Pool *pool, Id start, int count, int reuseids) 236 { 237 if (!count) 238 return; 239 if (reuseids && start + count == pool->nsolvables) 240 { 241 /* might want to shrink solvable array */ 242 pool->nsolvables = start; 243 return; 244 } 245 memset(pool->solvables + start, 0, sizeof(Solvable) * count); 246 } 247 248 249 void 250 pool_set_installed(Pool *pool, Repo *installed) 251 { 252 if (pool->installed == installed) 253 return; 254 pool->installed = installed; 255 pool_freewhatprovides(pool); 256 } 257 258 static int 259 pool_shrink_whatprovides_sortcmp(const void *ap, const void *bp, void *dp) 260 { 261 int r; 262 Pool *pool = dp; 263 Id oa, ob, *da, *db; 264 oa = pool->whatprovides[*(Id *)ap]; 265 ob = pool->whatprovides[*(Id *)bp]; 266 if (oa == ob) 267 return *(Id *)ap - *(Id *)bp; 268 da = pool->whatprovidesdata + oa; 269 db = pool->whatprovidesdata + ob; 270 while (*db) 271 if ((r = (*da++ - *db++)) != 0) 272 return r; 273 if (*da) 274 return *da; 275 return *(Id *)ap - *(Id *)bp; 276 } 277 278 /* 279 * pool_shrink_whatprovides - unify whatprovides data 280 * 281 * whatprovides_rel must be empty for this to work! 282 * 283 */ 284 static void 285 pool_shrink_whatprovides(Pool *pool) 286 { 287 Id i, n, id; 288 Id *sorted; 289 Id lastid, *last, *dp, *lp; 290 Offset o; 291 int r; 292 293 if (pool->ss.nstrings < 3) 294 return; 295 sorted = solv_malloc2(pool->ss.nstrings, sizeof(Id)); 296 for (i = id = 0; id < pool->ss.nstrings; id++) 297 if (pool->whatprovides[id] >= 4) 298 sorted[i++] = id; 299 n = i; 300 solv_sort(sorted, n, sizeof(Id), pool_shrink_whatprovides_sortcmp, pool); 301 last = 0; 302 lastid = 0; 303 for (i = 0; i < n; i++) 304 { 305 id = sorted[i]; 306 o = pool->whatprovides[id]; 307 dp = pool->whatprovidesdata + o; 308 if (last) 309 { 310 lp = last; 311 while (*dp) 312 if (*dp++ != *lp++) 313 { 314 last = 0; 315 break; 316 } 317 if (last && *lp) 318 last = 0; 319 if (last) 320 { 321 pool->whatprovides[id] = -lastid; 322 continue; 323 } 324 } 325 last = pool->whatprovidesdata + o; 326 lastid = id; 327 } 328 solv_free(sorted); 329 dp = pool->whatprovidesdata + 4; 330 for (id = 1; id < pool->ss.nstrings; id++) 331 { 332 o = pool->whatprovides[id]; 333 if (!o) 334 continue; 335 if ((Id)o < 0) 336 { 337 i = -(Id)o; 338 if (i >= id) 339 abort(); 340 pool->whatprovides[id] = pool->whatprovides[i]; 341 continue; 342 } 343 if (o < 4) 344 continue; 345 lp = pool->whatprovidesdata + o; 346 if (lp < dp) 347 abort(); 348 pool->whatprovides[id] = dp - pool->whatprovidesdata; 349 while ((*dp++ = *lp++) != 0) 350 ; 351 } 352 o = dp - pool->whatprovidesdata; 353 POOL_DEBUG(SOLV_DEBUG_STATS, "shrunk whatprovidesdata from %d to %d\n", pool->whatprovidesdataoff, o); 354 if (pool->whatprovidesdataoff == o) 355 return; 356 r = pool->whatprovidesdataoff - o; 357 pool->whatprovidesdataoff = o; 358 pool->whatprovidesdata = solv_realloc(pool->whatprovidesdata, (o + pool->whatprovidesdataleft) * sizeof(Id)); 359 if (r > pool->whatprovidesdataleft) 360 r = pool->whatprovidesdataleft; 361 memset(pool->whatprovidesdata + o, 0, r * sizeof(Id)); 362 } 363 364 365 /* 366 * pool_createwhatprovides() 367 * 368 * create hashes over pool of solvables to ease provide lookups 369 * 370 */ 371 void 372 pool_createwhatprovides(Pool *pool) 373 { 374 int i, num, np, extra; 375 Offset off; 376 Solvable *s; 377 Id id; 378 Offset *idp, n; 379 Offset *whatprovides; 380 Id *whatprovidesdata, *d; 381 Repo *installed = pool->installed; 382 unsigned int now; 383 384 now = solv_timems(0); 385 POOL_DEBUG(SOLV_DEBUG_STATS, "number of solvables: %d, memory used: %d K\n", pool->nsolvables, pool->nsolvables * (int)sizeof(Solvable) / 1024); 386 POOL_DEBUG(SOLV_DEBUG_STATS, "number of ids: %d + %d\n", pool->ss.nstrings, pool->nrels); 387 POOL_DEBUG(SOLV_DEBUG_STATS, "string memory used: %d K array + %d K data, rel memory used: %d K array\n", pool->ss.nstrings / (1024 / (int)sizeof(Id)), pool->ss.sstrings / 1024, pool->nrels * (int)sizeof(Reldep) / 1024); 388 if (pool->ss.stringhashmask || pool->relhashmask) 389 POOL_DEBUG(SOLV_DEBUG_STATS, "string hash memory: %d K, rel hash memory : %d K\n", (pool->ss.stringhashmask + 1) / (int)(1024/sizeof(Id)), (pool->relhashmask + 1) / (int)(1024/sizeof(Id))); 390 391 pool_freeidhashes(pool); /* XXX: should not be here! */ 392 pool_freewhatprovides(pool); 393 num = pool->ss.nstrings; 394 pool->whatprovides = whatprovides = solv_calloc_block(num, sizeof(Offset), WHATPROVIDES_BLOCK); 395 pool->whatprovides_rel = solv_calloc_block(pool->nrels, sizeof(Offset), WHATPROVIDES_BLOCK); 396 397 /* count providers for each name */ 398 for (i = pool->nsolvables - 1; i > 0; i--) 399 { 400 Id *pp; 401 s = pool->solvables + i; 402 if (!s->provides || !s->repo || s->repo->disabled) 403 continue; 404 /* we always need the installed solvable in the whatprovides data, 405 otherwise obsoletes/conflicts on them won't work */ 406 if (s->repo != installed && !pool_installable(pool, s)) 407 continue; 408 pp = s->repo->idarraydata + s->provides; 409 while ((id = *pp++) != 0) 410 { 411 while (ISRELDEP(id)) 412 { 413 Reldep *rd = GETRELDEP(pool, id); 414 id = rd->name; 415 } 416 whatprovides[id]++; /* inc count of providers */ 417 } 418 } 419 420 off = 4; /* first entry is undef, second is empty list, third is system solvable */ 421 np = 0; /* number of names provided */ 422 for (i = 0, idp = whatprovides; i < num; i++, idp++) 423 { 424 n = *idp; 425 if (!n) /* no providers */ 426 continue; 427 off += n; /* make space for all providers */ 428 *idp = off++; /* now idp points to terminating zero */ 429 np++; /* inc # of provider 'slots' for stats */ 430 } 431 432 POOL_DEBUG(SOLV_DEBUG_STATS, "provide ids: %d\n", np); 433 434 /* reserve some space for relation data */ 435 extra = 2 * pool->nrels; 436 if (extra < 256) 437 extra = 256; 438 439 POOL_DEBUG(SOLV_DEBUG_STATS, "provide space needed: %d + %d\n", off, extra); 440 441 /* alloc space for all providers + extra */ 442 whatprovidesdata = solv_calloc(off + extra, sizeof(Id)); 443 whatprovidesdata[2] = SYSTEMSOLVABLE; 444 445 /* now fill data for all provides */ 446 for (i = pool->nsolvables - 1; i > 0; i--) 447 { 448 Id *pp; 449 s = pool->solvables + i; 450 if (!s->provides || !s->repo || s->repo->disabled) 451 continue; 452 if (s->repo != installed && !pool_installable(pool, s)) 453 continue; 454 455 /* for all provides of this solvable */ 456 pp = s->repo->idarraydata + s->provides; 457 while ((id = *pp++) != 0) 458 { 459 while (ISRELDEP(id)) 460 { 461 Reldep *rd = GETRELDEP(pool, id); 462 id = rd->name; 463 } 464 d = whatprovidesdata + whatprovides[id]; /* offset into whatprovidesdata */ 465 if (*d != i) /* don't add same solvable twice */ 466 { 467 d[-1] = i; 468 whatprovides[id]--; 469 } 470 } 471 } 472 pool->whatprovidesdata = whatprovidesdata; 473 pool->whatprovidesdataoff = off; 474 pool->whatprovidesdataleft = extra; 475 pool_shrink_whatprovides(pool); 476 POOL_DEBUG(SOLV_DEBUG_STATS, "whatprovides memory used: %d K id array, %d K data\n", (pool->ss.nstrings + pool->nrels + WHATPROVIDES_BLOCK) / (int)(1024/sizeof(Id)), (pool->whatprovidesdataoff + pool->whatprovidesdataleft) / (int)(1024/sizeof(Id))); 477 POOL_DEBUG(SOLV_DEBUG_STATS, "createwhatprovides took %d ms\n", solv_timems(now)); 478 } 479 480 /* 481 * free all of our whatprovides data 482 * be careful, everything internalized with pool_queuetowhatprovides is 483 * gone, too 484 */ 485 void 486 pool_freewhatprovides(Pool *pool) 487 { 488 pool->whatprovides = solv_free(pool->whatprovides); 489 pool->whatprovides_rel = solv_free(pool->whatprovides_rel); 490 pool->whatprovidesdata = solv_free(pool->whatprovidesdata); 491 pool->whatprovidesdataoff = 0; 492 pool->whatprovidesdataleft = 0; 493 } 494 495 496 /******************************************************************************/ 497 498 /* 499 * pool_queuetowhatprovides - add queue contents to whatprovidesdata 500 * 501 * used for whatprovides, jobs, learnt rules, selections 502 * input: q: queue of Ids 503 * returns: Offset into whatprovidesdata 504 * 505 */ 506 Id 507 pool_queuetowhatprovides(Pool *pool, Queue *q) 508 { 509 Offset off; 510 int count = q->count; 511 512 if (count == 0) /* queue empty -> 1 */ 513 return 1; 514 if (count == 1 && q->elements[0] == SYSTEMSOLVABLE) 515 return 2; 516 517 /* extend whatprovidesdata if needed, +1 for 0-termination */ 518 if (pool->whatprovidesdataleft < count + 1) 519 { 520 POOL_DEBUG(SOLV_DEBUG_STATS, "growing provides hash data...\n"); 521 pool->whatprovidesdata = solv_realloc(pool->whatprovidesdata, (pool->whatprovidesdataoff + count + 4096) * sizeof(Id)); 522 pool->whatprovidesdataleft = count + 4096; 523 } 524 525 /* copy queue to next free slot */ 526 off = pool->whatprovidesdataoff; 527 memcpy(pool->whatprovidesdata + pool->whatprovidesdataoff, q->elements, count * sizeof(Id)); 528 529 /* adapt count and 0-terminate */ 530 pool->whatprovidesdataoff += count; 531 pool->whatprovidesdata[pool->whatprovidesdataoff++] = 0; 532 pool->whatprovidesdataleft -= count + 1; 533 534 return (Id)off; 535 } 536 537 538 /*************************************************************************/ 539 540 #if defined(MULTI_SEMANTICS) 541 # define EVRCMP_DEPCMP (pool->disttype == DISTTYPE_DEB ? EVRCMP_COMPARE : EVRCMP_MATCH_RELEASE) 542 #elif defined(DEBIAN) 543 # define EVRCMP_DEPCMP EVRCMP_COMPARE 544 #else 545 # define EVRCMP_DEPCMP EVRCMP_MATCH_RELEASE 546 #endif 547 548 /* check if a package's nevr matches a dependency */ 549 550 int 551 pool_match_nevr_rel(Pool *pool, Solvable *s, Id d) 552 { 553 Reldep *rd = GETRELDEP(pool, d); 554 Id name = rd->name; 555 Id evr = rd->evr; 556 int flags = rd->flags; 557 558 if (flags > 7) 559 { 560 switch (flags) 561 { 562 case REL_ARCH: 563 if (s->arch != evr) 564 { 565 if (evr != ARCH_SRC || s->arch != ARCH_NOSRC) 566 return 0; 567 } 568 return pool_match_nevr(pool, s, name); 569 case REL_OR: 570 if (pool_match_nevr(pool, s, name)) 571 return 1; 572 return pool_match_nevr(pool, s, evr); 573 case REL_AND: 574 case REL_WITH: 575 if (!pool_match_nevr(pool, s, name)) 576 return 0; 577 return pool_match_nevr(pool, s, evr); 578 default: 579 return 0; 580 } 581 } 582 if (!pool_match_nevr(pool, s, name)) 583 return 0; 584 if (evr == s->evr) 585 return (flags & REL_EQ) ? 1 : 0; 586 if (!flags) 587 return 0; 588 if (flags == 7) 589 return 1; 590 switch (pool_evrcmp(pool, s->evr, evr, EVRCMP_DEPCMP)) 591 { 592 case -2: 593 return 1; 594 case -1: 595 return (flags & REL_LT) ? 1 : 0; 596 case 0: 597 return (flags & REL_EQ) ? 1 : 0; 598 case 1: 599 return (flags & REL_GT) ? 1 : 0; 600 case 2: 601 return (flags & REL_EQ) ? 1 : 0; 602 default: 603 break; 604 } 605 return 0; 606 } 607 608 #if defined(HAIKU) || defined(MULTI_SEMANTICS) 609 /* forward declaration */ 610 static int pool_match_flags_evr_rel_compat(Pool *pool, Reldep *range, int flags, int evr); 611 #endif 612 613 /* match (flags, evr) against provider (pflags, pevr) */ 614 static inline int 615 pool_match_flags_evr(Pool *pool, int pflags, Id pevr, int flags, int evr) 616 { 617 if (!pflags || !flags || pflags >= 8 || flags >= 8) 618 return 0; 619 if (flags == 7 || pflags == 7) 620 return 1; /* rel provides every version */ 621 if ((pflags & flags & (REL_LT | REL_GT)) != 0) 622 return 1; /* both rels show in the same direction */ 623 if (pevr == evr) 624 return (flags & pflags & REL_EQ) ? 1 : 0; 625 #if defined(HAIKU) || defined(MULTI_SEMANTICS) 626 if (ISRELDEP(pevr)) 627 { 628 Reldep *rd = GETRELDEP(pool, pevr); 629 if (rd->flags == REL_COMPAT) 630 return pool_match_flags_evr_rel_compat(pool, rd, flags, evr); 631 } 632 #endif 633 switch (pool_evrcmp(pool, pevr, evr, EVRCMP_DEPCMP)) 634 { 635 case -2: 636 return (pflags & REL_EQ) ? 1 : 0; 637 case -1: 638 return (flags & REL_LT) || (pflags & REL_GT) ? 1 : 0; 639 case 0: 640 return (flags & pflags & REL_EQ) ? 1 : 0; 641 case 1: 642 return (flags & REL_GT) || (pflags & REL_LT) ? 1 : 0; 643 case 2: 644 return (flags & REL_EQ) ? 1 : 0; 645 default: 646 break; 647 } 648 return 0; 649 } 650 651 #if defined(HAIKU) || defined(MULTI_SEMANTICS) 652 static int 653 pool_match_flags_evr_rel_compat(Pool *pool, Reldep *range, int flags, int evr) 654 { 655 /* range->name is the actual version, range->evr the backwards compatibility 656 version. If flags are '>=' or '>', we match the compatibility version 657 as well, otherwise only the actual version. */ 658 if (!(flags & REL_GT) || (flags & REL_LT)) 659 return pool_match_flags_evr(pool, REL_EQ, range->name, flags, evr); 660 return pool_match_flags_evr(pool, REL_LT | REL_EQ, range->name, flags, evr) && 661 pool_match_flags_evr(pool, REL_GT | REL_EQ, range->evr, REL_EQ, evr); 662 } 663 #endif 664 665 /* match two dependencies (d1 = provider) */ 666 667 int 668 pool_match_dep(Pool *pool, Id d1, Id d2) 669 { 670 Reldep *rd1, *rd2; 671 672 if (d1 == d2) 673 return 1; 674 if (!ISRELDEP(d1)) 675 { 676 if (!ISRELDEP(d2)) 677 return 0; 678 rd2 = GETRELDEP(pool, d2); 679 return pool_match_dep(pool, d1, rd2->name); 680 } 681 rd1 = GETRELDEP(pool, d1); 682 if (!ISRELDEP(d2)) 683 { 684 return pool_match_dep(pool, rd1->name, d2); 685 } 686 rd2 = GETRELDEP(pool, d2); 687 /* first match name */ 688 if (!pool_match_dep(pool, rd1->name, rd2->name)) 689 return 0; 690 /* name matches, check flags and evr */ 691 return pool_match_flags_evr(pool, rd1->flags, rd1->evr, rd2->flags, rd2->evr); 692 } 693 694 /* 695 * addrelproviders 696 * 697 * add packages fulfilling the relation to whatprovides array 698 * no exact providers, do range match 699 * 700 */ 701 702 Id 703 pool_addrelproviders(Pool *pool, Id d) 704 { 705 Reldep *rd = GETRELDEP(pool, d); 706 Reldep *prd; 707 Queue plist; 708 Id buf[16]; 709 Id name = rd->name; 710 Id evr = rd->evr; 711 int flags = rd->flags; 712 Id pid, *pidp; 713 Id p, *pp; 714 715 d = GETRELID(d); 716 queue_init_buffer(&plist, buf, sizeof(buf)/sizeof(*buf)); 717 718 if (flags >= 8) 719 { 720 /* special relation */ 721 Id wp = 0; 722 Id *pp2, *pp3; 723 724 switch (flags) 725 { 726 case REL_AND: 727 case REL_WITH: 728 wp = pool_whatprovides(pool, name); 729 pp2 = pool_whatprovides_ptr(pool, evr); 730 pp = pool->whatprovidesdata + wp; 731 while ((p = *pp++) != 0) 732 { 733 for (pp3 = pp2; *pp3; pp3++) 734 if (*pp3 == p) 735 break; 736 if (*pp3) 737 queue_push(&plist, p); /* found it */ 738 else 739 wp = 0; 740 } 741 break; 742 case REL_OR: 743 wp = pool_whatprovides(pool, name); 744 pp = pool->whatprovidesdata + wp; 745 if (!*pp) 746 wp = pool_whatprovides(pool, evr); 747 else 748 { 749 int cnt; 750 while ((p = *pp++) != 0) 751 queue_push(&plist, p); 752 cnt = plist.count; 753 pp = pool_whatprovides_ptr(pool, evr); 754 while ((p = *pp++) != 0) 755 queue_pushunique(&plist, p); 756 if (plist.count != cnt) 757 wp = 0; 758 } 759 break; 760 case REL_NAMESPACE: 761 if (name == NAMESPACE_OTHERPROVIDERS) 762 { 763 wp = pool_whatprovides(pool, evr); 764 break; 765 } 766 if (pool->nscallback) 767 { 768 /* ask callback which packages provide the dependency 769 * 0: none 770 * 1: the system (aka SYSTEMSOLVABLE) 771 * >1: set of packages, stored as offset on whatprovidesdata 772 */ 773 p = pool->nscallback(pool, pool->nscallbackdata, name, evr); 774 if (p > 1) 775 wp = p; 776 if (p == 1) 777 queue_push(&plist, SYSTEMSOLVABLE); 778 } 779 break; 780 case REL_ARCH: 781 /* small hack: make it possible to match <pkg>.src 782 * we have to iterate over the solvables as src packages do not 783 * provide anything, thus they are not indexed in our 784 * whatprovides hash */ 785 if (evr == ARCH_SRC || evr == ARCH_NOSRC) 786 { 787 Solvable *s; 788 for (p = 1, s = pool->solvables + p; p < pool->nsolvables; p++, s++) 789 { 790 if (!s->repo) 791 continue; 792 if (s->arch != evr && s->arch != ARCH_NOSRC) 793 continue; 794 if (pool_disabled_solvable(pool, s)) 795 continue; 796 if (pool_match_nevr(pool, s, name)) 797 queue_push(&plist, p); 798 } 799 break; 800 } 801 wp = pool_whatprovides(pool, name); 802 pp = pool->whatprovidesdata + wp; 803 while ((p = *pp++) != 0) 804 { 805 Solvable *s = pool->solvables + p; 806 if (s->arch == evr) 807 queue_push(&plist, p); 808 else 809 wp = 0; 810 } 811 break; 812 case REL_FILECONFLICT: 813 pp = pool_whatprovides_ptr(pool, name); 814 while ((p = *pp++) != 0) 815 { 816 Id origd = MAKERELDEP(d); 817 Solvable *s = pool->solvables + p; 818 if (!s->provides) 819 continue; 820 pidp = s->repo->idarraydata + s->provides; 821 while ((pid = *pidp++) != 0) 822 if (pid == origd) 823 break; 824 if (pid) 825 queue_push(&plist, p); 826 } 827 break; 828 default: 829 break; 830 } 831 if (wp) 832 { 833 /* we can reuse an existing entry */ 834 queue_free(&plist); 835 pool->whatprovides_rel[d] = wp; 836 return wp; 837 } 838 } 839 else if (flags) 840 { 841 /* simple version comparison relation */ 842 #if 0 843 POOL_DEBUG(SOLV_DEBUG_STATS, "addrelproviders: what provides %s?\n", pool_dep2str(pool, name)); 844 #endif 845 pp = pool_whatprovides_ptr(pool, name); 846 while (ISRELDEP(name)) 847 { 848 rd = GETRELDEP(pool, name); 849 name = rd->name; 850 } 851 while ((p = *pp++) != 0) 852 { 853 Solvable *s = pool->solvables + p; 854 if (!s->provides) 855 { 856 /* no provides - check nevr */ 857 if (pool_match_nevr_rel(pool, s, MAKERELDEP(d))) 858 queue_push(&plist, p); 859 continue; 860 } 861 /* solvable p provides name in some rels */ 862 pidp = s->repo->idarraydata + s->provides; 863 while ((pid = *pidp++) != 0) 864 { 865 if (!ISRELDEP(pid)) 866 { 867 if (pid != name) 868 continue; /* wrong provides name */ 869 if (pool->disttype == DISTTYPE_DEB) 870 continue; /* unversioned provides can never match versioned deps */ 871 break; 872 } 873 prd = GETRELDEP(pool, pid); 874 if (prd->name != name) 875 continue; /* wrong provides name */ 876 /* right package, both deps are rels. check flags/evr */ 877 if (pool_match_flags_evr(pool, prd->flags, prd->evr, flags, evr)) 878 break; /* matches */ 879 } 880 if (!pid) 881 continue; /* none of the providers matched */ 882 queue_push(&plist, p); 883 } 884 /* make our system solvable provide all unknown rpmlib() stuff */ 885 if (plist.count == 0 && !strncmp(pool_id2str(pool, name), "rpmlib(", 7)) 886 queue_push(&plist, SYSTEMSOLVABLE); 887 } 888 /* add providers to whatprovides */ 889 #if 0 890 POOL_DEBUG(SOLV_DEBUG_STATS, "addrelproviders: adding %d packages to %d\n", plist.count, d); 891 #endif 892 pool->whatprovides_rel[d] = pool_queuetowhatprovides(pool, &plist); 893 queue_free(&plist); 894 895 return pool->whatprovides_rel[d]; 896 } 897 898 /*************************************************************************/ 899 900 void 901 pool_debug(Pool *pool, int type, const char *format, ...) 902 { 903 va_list args; 904 char buf[1024]; 905 906 if ((type & (SOLV_FATAL|SOLV_ERROR)) == 0) 907 { 908 if ((pool->debugmask & type) == 0) 909 return; 910 } 911 va_start(args, format); 912 if (!pool->debugcallback) 913 { 914 if ((type & (SOLV_FATAL|SOLV_ERROR)) == 0 && !(pool->debugmask & SOLV_DEBUG_TO_STDERR)) 915 vprintf(format, args); 916 else 917 vfprintf(stderr, format, args); 918 return; 919 } 920 vsnprintf(buf, sizeof(buf), format, args); 921 va_end(args); 922 pool->debugcallback(pool, pool->debugcallbackdata, type, buf); 923 } 924 925 int 926 pool_error(Pool *pool, int ret, const char *format, ...) 927 { 928 va_list args; 929 int l; 930 va_start(args, format); 931 if (!pool->errstr) 932 { 933 pool->errstra = 1024; 934 pool->errstr = solv_malloc(pool->errstra); 935 } 936 if (!*format) 937 { 938 *pool->errstr = 0; 939 l = 0; 940 } 941 else 942 l = vsnprintf(pool->errstr, pool->errstra, format, args); 943 va_end(args); 944 if (l >= 0 && l + 1 > pool->errstra) 945 { 946 pool->errstra = l + 256; 947 pool->errstr = solv_realloc(pool->errstr, pool->errstra); 948 va_start(args, format); 949 l = vsnprintf(pool->errstr, pool->errstra, format, args); 950 va_end(args); 951 } 952 if (l < 0) 953 strcpy(pool->errstr, "unknown error"); 954 if (pool->debugmask & SOLV_ERROR) 955 pool_debug(pool, SOLV_ERROR, "%s\n", pool->errstr); 956 return ret; 957 } 958 959 char * 960 pool_errstr(Pool *pool) 961 { 962 return pool->errstr ? pool->errstr : "no error"; 963 } 964 965 void 966 pool_setdebuglevel(Pool *pool, int level) 967 { 968 int mask = SOLV_DEBUG_RESULT; 969 if (level > 0) 970 mask |= SOLV_DEBUG_STATS|SOLV_DEBUG_ANALYZE|SOLV_DEBUG_UNSOLVABLE|SOLV_DEBUG_SOLVER|SOLV_DEBUG_TRANSACTION|SOLV_ERROR; 971 if (level > 1) 972 mask |= SOLV_DEBUG_JOB|SOLV_DEBUG_SOLUTIONS|SOLV_DEBUG_POLICY; 973 if (level > 2) 974 mask |= SOLV_DEBUG_PROPAGATE; 975 if (level > 3) 976 mask |= SOLV_DEBUG_RULE_CREATION; 977 mask |= pool->debugmask & SOLV_DEBUG_TO_STDERR; /* keep bit */ 978 pool->debugmask = mask; 979 } 980 981 void pool_setdebugcallback(Pool *pool, void (*debugcallback)(struct _Pool *, void *data, int type, const char *str), void *debugcallbackdata) 982 { 983 pool->debugcallback = debugcallback; 984 pool->debugcallbackdata = debugcallbackdata; 985 } 986 987 void pool_setdebugmask(Pool *pool, int mask) 988 { 989 pool->debugmask = mask; 990 } 991 992 void pool_setloadcallback(Pool *pool, int (*cb)(struct _Pool *, struct _Repodata *, void *), void *loadcbdata) 993 { 994 pool->loadcallback = cb; 995 pool->loadcallbackdata = loadcbdata; 996 } 997 998 /*************************************************************************/ 999 1000 struct searchfiles { 1001 Id *ids; 1002 char **dirs; 1003 char **names; 1004 int nfiles; 1005 Map seen; 1006 }; 1007 1008 #define SEARCHFILES_BLOCK 127 1009 1010 static void 1011 pool_addfileprovides_dep(Pool *pool, Id *ida, struct searchfiles *sf, struct searchfiles *isf) 1012 { 1013 Id dep, sid; 1014 const char *s, *sr; 1015 struct searchfiles *csf; 1016 1017 while ((dep = *ida++) != 0) 1018 { 1019 csf = sf; 1020 while (ISRELDEP(dep)) 1021 { 1022 Reldep *rd; 1023 sid = pool->ss.nstrings + GETRELID(dep); 1024 if (MAPTST(&csf->seen, sid)) 1025 { 1026 dep = 0; 1027 break; 1028 } 1029 MAPSET(&csf->seen, sid); 1030 rd = GETRELDEP(pool, dep); 1031 if (rd->flags < 8) 1032 dep = rd->name; 1033 else if (rd->flags == REL_NAMESPACE) 1034 { 1035 if (rd->name == NAMESPACE_INSTALLED || rd->name == NAMESPACE_SPLITPROVIDES) 1036 { 1037 csf = isf; 1038 if (!csf || MAPTST(&csf->seen, sid)) 1039 { 1040 dep = 0; 1041 break; 1042 } 1043 MAPSET(&csf->seen, sid); 1044 } 1045 dep = rd->evr; 1046 } 1047 else if (rd->flags == REL_FILECONFLICT) 1048 { 1049 dep = 0; 1050 break; 1051 } 1052 else 1053 { 1054 Id ids[2]; 1055 ids[0] = rd->name; 1056 ids[1] = 0; 1057 pool_addfileprovides_dep(pool, ids, csf, isf); 1058 dep = rd->evr; 1059 } 1060 } 1061 if (!dep) 1062 continue; 1063 if (MAPTST(&csf->seen, dep)) 1064 continue; 1065 MAPSET(&csf->seen, dep); 1066 s = pool_id2str(pool, dep); 1067 if (*s != '/') 1068 continue; 1069 csf->ids = solv_extend(csf->ids, csf->nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK); 1070 csf->dirs = solv_extend(csf->dirs, csf->nfiles, 1, sizeof(const char *), SEARCHFILES_BLOCK); 1071 csf->names = solv_extend(csf->names, csf->nfiles, 1, sizeof(const char *), SEARCHFILES_BLOCK); 1072 csf->ids[csf->nfiles] = dep; 1073 sr = strrchr(s, '/'); 1074 csf->names[csf->nfiles] = solv_strdup(sr + 1); 1075 csf->dirs[csf->nfiles] = solv_malloc(sr - s + 1); 1076 if (sr != s) 1077 strncpy(csf->dirs[csf->nfiles], s, sr - s); 1078 csf->dirs[csf->nfiles][sr - s] = 0; 1079 csf->nfiles++; 1080 } 1081 } 1082 1083 struct addfileprovides_cbdata { 1084 int nfiles; 1085 Id *ids; 1086 char **dirs; 1087 char **names; 1088 1089 Id *dids; 1090 1091 Map providedids; 1092 1093 Map useddirs; 1094 }; 1095 1096 static int 1097 addfileprovides_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *value) 1098 { 1099 struct addfileprovides_cbdata *cbd = cbdata; 1100 int i; 1101 1102 if (!cbd->useddirs.size) 1103 { 1104 map_init(&cbd->useddirs, data->dirpool.ndirs + 1); 1105 for (i = 0; i < cbd->nfiles; i++) 1106 { 1107 Id did; 1108 if (MAPTST(&cbd->providedids, cbd->ids[i])) 1109 { 1110 cbd->dids[i] = 0; 1111 continue; 1112 } 1113 did = repodata_str2dir(data, cbd->dirs[i], 0); 1114 cbd->dids[i] = did; 1115 if (did) 1116 MAPSET(&cbd->useddirs, did); 1117 } 1118 repodata_free_dircache(data); 1119 } 1120 if (value->id >= data->dirpool.ndirs || !MAPTST(&cbd->useddirs, value->id)) 1121 return 0; 1122 for (i = 0; i < cbd->nfiles; i++) 1123 { 1124 if (cbd->dids[i] != value->id) 1125 continue; 1126 if (!strcmp(cbd->names[i], value->str)) 1127 break; 1128 } 1129 if (i == cbd->nfiles) 1130 return 0; 1131 s->provides = repo_addid_dep(s->repo, s->provides, cbd->ids[i], SOLVABLE_FILEMARKER); 1132 return 0; 1133 } 1134 1135 static void 1136 pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, struct searchfiles *sf, Repo *repoonly) 1137 { 1138 Id p; 1139 Repodata *data; 1140 Repo *repo; 1141 Queue fileprovidesq; 1142 int i, j, repoid, repodataid; 1143 int provstart, provend; 1144 Map donemap; 1145 int ndone, incomplete; 1146 1147 if (!pool->urepos) 1148 return; 1149 1150 cbd->nfiles = sf->nfiles; 1151 cbd->ids = sf->ids; 1152 cbd->dirs = sf->dirs; 1153 cbd->names = sf->names; 1154 cbd->dids = solv_realloc2(cbd->dids, sf->nfiles, sizeof(Id)); 1155 map_init(&cbd->providedids, pool->ss.nstrings); 1156 1157 repoid = 1; 1158 repo = repoonly ? repoonly : pool->repos[repoid]; 1159 map_init(&donemap, pool->nsolvables); 1160 queue_init(&fileprovidesq); 1161 provstart = provend = 0; 1162 for (;;) 1163 { 1164 if (!repo || repo->disabled) 1165 { 1166 if (repoonly || ++repoid == pool->nrepos) 1167 break; 1168 repo = pool->repos[repoid]; 1169 continue; 1170 } 1171 ndone = 0; 1172 FOR_REPODATAS(repo, repodataid, data) 1173 { 1174 if (ndone >= repo->nsolvables) 1175 break; 1176 1177 if (repodata_lookup_idarray(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &fileprovidesq)) 1178 { 1179 map_empty(&cbd->providedids); 1180 for (i = 0; i < fileprovidesq.count; i++) 1181 MAPSET(&cbd->providedids, fileprovidesq.elements[i]); 1182 provstart = data->start; 1183 provend = data->end; 1184 for (i = 0; i < cbd->nfiles; i++) 1185 if (!MAPTST(&cbd->providedids, cbd->ids[i])) 1186 break; 1187 if (i == cbd->nfiles) 1188 { 1189 /* great! no need to search files */ 1190 for (p = data->start; p < data->end; p++) 1191 if (pool->solvables[p].repo == repo) 1192 { 1193 if (MAPTST(&donemap, p)) 1194 continue; 1195 MAPSET(&donemap, p); 1196 ndone++; 1197 } 1198 continue; 1199 } 1200 } 1201 1202 if (!repodata_has_keyname(data, SOLVABLE_FILELIST)) 1203 continue; 1204 1205 if (data->start < provstart || data->end > provend) 1206 { 1207 map_empty(&cbd->providedids); 1208 provstart = provend = 0; 1209 } 1210 1211 /* check if the data is incomplete */ 1212 incomplete = 0; 1213 if (data->state == REPODATA_AVAILABLE) 1214 { 1215 for (j = 1; j < data->nkeys; j++) 1216 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST) 1217 break; 1218 if (j < data->nkeys) 1219 { 1220 #if 0 1221 for (i = 0; i < cbd->nfiles; i++) 1222 if (!MAPTST(&cbd->providedids, cbd->ids[i]) && !repodata_filelistfilter_matches(data, pool_id2str(pool, cbd->ids[i]))) 1223 printf("need complete filelist because of %s\n", pool_id2str(pool, cbd->ids[i])); 1224 #endif 1225 for (i = 0; i < cbd->nfiles; i++) 1226 if (!MAPTST(&cbd->providedids, cbd->ids[i]) && !repodata_filelistfilter_matches(data, pool_id2str(pool, cbd->ids[i]))) 1227 break; 1228 if (i < cbd->nfiles) 1229 incomplete = 1; 1230 } 1231 } 1232 1233 /* do the search */ 1234 map_init(&cbd->useddirs, 0); 1235 for (p = data->start; p < data->end; p++) 1236 if (pool->solvables[p].repo == repo) 1237 { 1238 if (MAPTST(&donemap, p)) 1239 continue; 1240 repodata_search(data, p, SOLVABLE_FILELIST, 0, addfileprovides_cb, cbd); 1241 if (!incomplete) 1242 { 1243 MAPSET(&donemap, p); 1244 ndone++; 1245 } 1246 } 1247 map_free(&cbd->useddirs); 1248 } 1249 1250 if (repoonly || ++repoid == pool->nrepos) 1251 break; 1252 repo = pool->repos[repoid]; 1253 } 1254 map_free(&donemap); 1255 queue_free(&fileprovidesq); 1256 map_free(&cbd->providedids); 1257 } 1258 1259 void 1260 pool_addfileprovides_queue(Pool *pool, Queue *idq, Queue *idqinst) 1261 { 1262 Solvable *s; 1263 Repo *installed, *repo; 1264 struct searchfiles sf, isf, *isfp; 1265 struct addfileprovides_cbdata cbd; 1266 int i; 1267 unsigned int now; 1268 1269 installed = pool->installed; 1270 now = solv_timems(0); 1271 memset(&sf, 0, sizeof(sf)); 1272 map_init(&sf.seen, pool->ss.nstrings + pool->nrels); 1273 memset(&isf, 0, sizeof(isf)); 1274 map_init(&isf.seen, pool->ss.nstrings + pool->nrels); 1275 1276 if (idq) 1277 queue_empty(idq); 1278 if (idqinst) 1279 queue_empty(idqinst); 1280 isfp = installed ? &isf : 0; 1281 for (i = 1, s = pool->solvables + i; i < pool->nsolvables; i++, s++) 1282 { 1283 repo = s->repo; 1284 if (!repo) 1285 continue; 1286 if (s->obsoletes) 1287 pool_addfileprovides_dep(pool, repo->idarraydata + s->obsoletes, &sf, isfp); 1288 if (s->conflicts) 1289 pool_addfileprovides_dep(pool, repo->idarraydata + s->conflicts, &sf, isfp); 1290 if (s->requires) 1291 pool_addfileprovides_dep(pool, repo->idarraydata + s->requires, &sf, isfp); 1292 if (s->recommends) 1293 pool_addfileprovides_dep(pool, repo->idarraydata + s->recommends, &sf, isfp); 1294 if (s->suggests) 1295 pool_addfileprovides_dep(pool, repo->idarraydata + s->suggests, &sf, isfp); 1296 if (s->supplements) 1297 pool_addfileprovides_dep(pool, repo->idarraydata + s->supplements, &sf, isfp); 1298 if (s->enhances) 1299 pool_addfileprovides_dep(pool, repo->idarraydata + s->enhances, &sf, isfp); 1300 } 1301 map_free(&sf.seen); 1302 map_free(&isf.seen); 1303 POOL_DEBUG(SOLV_DEBUG_STATS, "found %d file dependencies, %d installed file dependencies\n", sf.nfiles, isf.nfiles); 1304 cbd.dids = 0; 1305 if (sf.nfiles) 1306 { 1307 #if 0 1308 for (i = 0; i < sf.nfiles; i++) 1309 POOL_DEBUG(SOLV_DEBUG_STATS, "looking up %s in filelist\n", pool_id2str(pool, sf.ids[i])); 1310 #endif 1311 pool_addfileprovides_search(pool, &cbd, &sf, 0); 1312 if (idq) 1313 for (i = 0; i < sf.nfiles; i++) 1314 queue_push(idq, sf.ids[i]); 1315 if (idqinst) 1316 for (i = 0; i < sf.nfiles; i++) 1317 queue_push(idqinst, sf.ids[i]); 1318 solv_free(sf.ids); 1319 for (i = 0; i < sf.nfiles; i++) 1320 { 1321 solv_free(sf.dirs[i]); 1322 solv_free(sf.names[i]); 1323 } 1324 solv_free(sf.dirs); 1325 solv_free(sf.names); 1326 } 1327 if (isf.nfiles) 1328 { 1329 #if 0 1330 for (i = 0; i < isf.nfiles; i++) 1331 POOL_DEBUG(SOLV_DEBUG_STATS, "looking up %s in installed filelist\n", pool_id2str(pool, isf.ids[i])); 1332 #endif 1333 if (installed) 1334 pool_addfileprovides_search(pool, &cbd, &isf, installed); 1335 if (installed && idqinst) 1336 for (i = 0; i < isf.nfiles; i++) 1337 queue_pushunique(idqinst, isf.ids[i]); 1338 solv_free(isf.ids); 1339 for (i = 0; i < isf.nfiles; i++) 1340 { 1341 solv_free(isf.dirs[i]); 1342 solv_free(isf.names[i]); 1343 } 1344 solv_free(isf.dirs); 1345 solv_free(isf.names); 1346 } 1347 solv_free(cbd.dids); 1348 pool_freewhatprovides(pool); /* as we have added provides */ 1349 POOL_DEBUG(SOLV_DEBUG_STATS, "addfileprovides took %d ms\n", solv_timems(now)); 1350 } 1351 1352 void 1353 pool_addfileprovides(Pool *pool) 1354 { 1355 pool_addfileprovides_queue(pool, 0, 0); 1356 } 1357 1358 void 1359 pool_search(Pool *pool, Id p, Id key, const char *match, int flags, int (*callback)(void *cbdata, Solvable *s, struct _Repodata *data, struct _Repokey *key, struct _KeyValue *kv), void *cbdata) 1360 { 1361 if (p) 1362 { 1363 if (pool->solvables[p].repo) 1364 repo_search(pool->solvables[p].repo, p, key, match, flags, callback, cbdata); 1365 return; 1366 } 1367 /* FIXME: obey callback return value! */ 1368 for (p = 1; p < pool->nsolvables; p++) 1369 if (pool->solvables[p].repo) 1370 repo_search(pool->solvables[p].repo, p, key, match, flags, callback, cbdata); 1371 } 1372 1373 void 1374 pool_clear_pos(Pool *pool) 1375 { 1376 memset(&pool->pos, 0, sizeof(pool->pos)); 1377 } 1378 1379 1380 void 1381 pool_set_languages(Pool *pool, const char **languages, int nlanguages) 1382 { 1383 int i; 1384 1385 pool->languagecache = solv_free(pool->languagecache); 1386 pool->languagecacheother = 0; 1387 if (pool->nlanguages) 1388 { 1389 for (i = 0; i < pool->nlanguages; i++) 1390 free((char *)pool->languages[i]); 1391 free(pool->languages); 1392 } 1393 pool->nlanguages = nlanguages; 1394 if (!nlanguages) 1395 return; 1396 pool->languages = solv_calloc(nlanguages, sizeof(const char **)); 1397 for (i = 0; i < pool->nlanguages; i++) 1398 pool->languages[i] = solv_strdup(languages[i]); 1399 } 1400 1401 Id 1402 pool_id2langid(Pool *pool, Id id, const char *lang, int create) 1403 { 1404 const char *n; 1405 char buf[256], *p; 1406 int l; 1407 1408 if (!lang || !*lang) 1409 return id; 1410 n = pool_id2str(pool, id); 1411 l = strlen(n) + strlen(lang) + 2; 1412 if (l > sizeof(buf)) 1413 p = solv_malloc(strlen(n) + strlen(lang) + 2); 1414 else 1415 p = buf; 1416 sprintf(p, "%s:%s", n, lang); 1417 id = pool_str2id(pool, p, create); 1418 if (p != buf) 1419 free(p); 1420 return id; 1421 } 1422 1423 char * 1424 pool_alloctmpspace(Pool *pool, int len) 1425 { 1426 int n = pool->tmpspace.n; 1427 if (!len) 1428 return 0; 1429 if (len > pool->tmpspace.len[n]) 1430 { 1431 pool->tmpspace.buf[n] = solv_realloc(pool->tmpspace.buf[n], len + 32); 1432 pool->tmpspace.len[n] = len + 32; 1433 } 1434 pool->tmpspace.n = (n + 1) % POOL_TMPSPACEBUF; 1435 return pool->tmpspace.buf[n]; 1436 } 1437 1438 static char * 1439 pool_alloctmpspace_free(Pool *pool, const char *space, int len) 1440 { 1441 if (space) 1442 { 1443 int n, oldn; 1444 n = oldn = pool->tmpspace.n; 1445 for (;;) 1446 { 1447 if (!n--) 1448 n = POOL_TMPSPACEBUF - 1; 1449 if (n == oldn) 1450 break; 1451 if (pool->tmpspace.buf[n] != space) 1452 continue; 1453 if (len > pool->tmpspace.len[n]) 1454 { 1455 pool->tmpspace.buf[n] = solv_realloc(pool->tmpspace.buf[n], len + 32); 1456 pool->tmpspace.len[n] = len + 32; 1457 } 1458 return pool->tmpspace.buf[n]; 1459 } 1460 } 1461 return 0; 1462 } 1463 1464 void 1465 pool_freetmpspace(Pool *pool, const char *space) 1466 { 1467 int n = pool->tmpspace.n; 1468 if (!space) 1469 return; 1470 n = (n + (POOL_TMPSPACEBUF - 1)) % POOL_TMPSPACEBUF; 1471 if (pool->tmpspace.buf[n] == space) 1472 pool->tmpspace.n = n; 1473 } 1474 1475 char * 1476 pool_tmpjoin(Pool *pool, const char *str1, const char *str2, const char *str3) 1477 { 1478 int l1, l2, l3; 1479 char *s, *str; 1480 l1 = str1 ? strlen(str1) : 0; 1481 l2 = str2 ? strlen(str2) : 0; 1482 l3 = str3 ? strlen(str3) : 0; 1483 s = str = pool_alloctmpspace(pool, l1 + l2 + l3 + 1); 1484 if (l1) 1485 { 1486 strcpy(s, str1); 1487 s += l1; 1488 } 1489 if (l2) 1490 { 1491 strcpy(s, str2); 1492 s += l2; 1493 } 1494 if (l3) 1495 { 1496 strcpy(s, str3); 1497 s += l3; 1498 } 1499 *s = 0; 1500 return str; 1501 } 1502 1503 char * 1504 pool_tmpappend(Pool *pool, const char *str1, const char *str2, const char *str3) 1505 { 1506 int l1, l2, l3; 1507 char *s, *str; 1508 1509 l1 = str1 ? strlen(str1) : 0; 1510 l2 = str2 ? strlen(str2) : 0; 1511 l3 = str3 ? strlen(str3) : 0; 1512 str = pool_alloctmpspace_free(pool, str1, l1 + l2 + l3 + 1); 1513 if (str) 1514 str1 = str; 1515 else 1516 str = pool_alloctmpspace(pool, l1 + l2 + l3 + 1); 1517 s = str; 1518 if (l1) 1519 { 1520 if (s != str1) 1521 strcpy(s, str1); 1522 s += l1; 1523 } 1524 if (l2) 1525 { 1526 strcpy(s, str2); 1527 s += l2; 1528 } 1529 if (l3) 1530 { 1531 strcpy(s, str3); 1532 s += l3; 1533 } 1534 *s = 0; 1535 return str; 1536 } 1537 1538 const char * 1539 pool_bin2hex(Pool *pool, const unsigned char *buf, int len) 1540 { 1541 char *s; 1542 if (!len) 1543 return ""; 1544 s = pool_alloctmpspace(pool, 2 * len + 1); 1545 solv_bin2hex(buf, len, s); 1546 return s; 1547 } 1548 1549 /*******************************************************************/ 1550 1551 struct mptree { 1552 Id sibling; 1553 Id child; 1554 const char *comp; 1555 int compl; 1556 Id mountpoint; 1557 }; 1558 1559 struct ducbdata { 1560 DUChanges *mps; 1561 struct mptree *mptree; 1562 int addsub; 1563 int hasdu; 1564 1565 Id *dirmap; 1566 int nmap; 1567 Repodata *olddata; 1568 }; 1569 1570 1571 static int 1572 solver_fill_DU_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *value) 1573 { 1574 struct ducbdata *cbd = cbdata; 1575 Id mp; 1576 1577 if (data != cbd->olddata) 1578 { 1579 Id dn, mp, comp, *dirmap, *dirs; 1580 int i, compl; 1581 const char *compstr; 1582 struct mptree *mptree; 1583 1584 /* create map from dir to mptree */ 1585 cbd->dirmap = solv_free(cbd->dirmap); 1586 cbd->nmap = 0; 1587 dirmap = solv_calloc(data->dirpool.ndirs, sizeof(Id)); 1588 mptree = cbd->mptree; 1589 mp = 0; 1590 for (dn = 2, dirs = data->dirpool.dirs + dn; dn < data->dirpool.ndirs; dn++) 1591 { 1592 comp = *dirs++; 1593 if (comp <= 0) 1594 { 1595 mp = dirmap[-comp]; 1596 continue; 1597 } 1598 if (mp < 0) 1599 { 1600 /* unconnected */ 1601 dirmap[dn] = mp; 1602 continue; 1603 } 1604 if (!mptree[mp].child) 1605 { 1606 dirmap[dn] = -mp; 1607 continue; 1608 } 1609 if (data->localpool) 1610 compstr = stringpool_id2str(&data->spool, comp); 1611 else 1612 compstr = pool_id2str(data->repo->pool, comp); 1613 compl = strlen(compstr); 1614 for (i = mptree[mp].child; i; i = mptree[i].sibling) 1615 if (mptree[i].compl == compl && !strncmp(mptree[i].comp, compstr, compl)) 1616 break; 1617 dirmap[dn] = i ? i : -mp; 1618 } 1619 /* change dirmap to point to mountpoint instead of mptree */ 1620 for (dn = 0; dn < data->dirpool.ndirs; dn++) 1621 { 1622 mp = dirmap[dn]; 1623 dirmap[dn] = mptree[mp > 0 ? mp : -mp].mountpoint; 1624 } 1625 cbd->dirmap = dirmap; 1626 cbd->nmap = data->dirpool.ndirs; 1627 cbd->olddata = data; 1628 } 1629 cbd->hasdu = 1; 1630 if (value->id < 0 || value->id >= cbd->nmap) 1631 return 0; 1632 mp = cbd->dirmap[value->id]; 1633 if (mp < 0) 1634 return 0; 1635 if (cbd->addsub > 0) 1636 { 1637 cbd->mps[mp].kbytes += value->num; 1638 cbd->mps[mp].files += value->num2; 1639 } 1640 else 1641 { 1642 cbd->mps[mp].kbytes -= value->num; 1643 cbd->mps[mp].files -= value->num2; 1644 } 1645 return 0; 1646 } 1647 1648 static void 1649 propagate_mountpoints(struct mptree *mptree, int pos, Id mountpoint) 1650 { 1651 int i; 1652 if (mptree[pos].mountpoint == -1) 1653 mptree[pos].mountpoint = mountpoint; 1654 else 1655 mountpoint = mptree[pos].mountpoint; 1656 for (i = mptree[pos].child; i; i = mptree[i].sibling) 1657 propagate_mountpoints(mptree, i, mountpoint); 1658 } 1659 1660 #define MPTREE_BLOCK 15 1661 1662 void 1663 pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps) 1664 { 1665 char *p; 1666 const char *path, *compstr; 1667 struct mptree *mptree; 1668 int i, nmptree; 1669 int pos, compl; 1670 int mp; 1671 struct ducbdata cbd; 1672 Solvable *s; 1673 Id sp; 1674 Map ignoredu; 1675 Repo *oldinstalled = pool->installed; 1676 1677 memset(&ignoredu, 0, sizeof(ignoredu)); 1678 cbd.mps = mps; 1679 cbd.addsub = 0; 1680 cbd.dirmap = 0; 1681 cbd.nmap = 0; 1682 cbd.olddata = 0; 1683 1684 mptree = solv_extend_resize(0, 1, sizeof(struct mptree), MPTREE_BLOCK); 1685 1686 /* our root node */ 1687 mptree[0].sibling = 0; 1688 mptree[0].child = 0; 1689 mptree[0].comp = 0; 1690 mptree[0].compl = 0; 1691 mptree[0].mountpoint = -1; 1692 nmptree = 1; 1693 1694 /* create component tree */ 1695 for (mp = 0; mp < nmps; mp++) 1696 { 1697 mps[mp].kbytes = 0; 1698 mps[mp].files = 0; 1699 pos = 0; 1700 path = mps[mp].path; 1701 while(*path == '/') 1702 path++; 1703 while (*path) 1704 { 1705 if ((p = strchr(path, '/')) == 0) 1706 { 1707 compstr = path; 1708 compl = strlen(compstr); 1709 path += compl; 1710 } 1711 else 1712 { 1713 compstr = path; 1714 compl = p - path; 1715 path = p + 1; 1716 while(*path == '/') 1717 path++; 1718 } 1719 for (i = mptree[pos].child; i; i = mptree[i].sibling) 1720 if (mptree[i].compl == compl && !strncmp(mptree[i].comp, compstr, compl)) 1721 break; 1722 if (!i) 1723 { 1724 /* create new node */ 1725 mptree = solv_extend(mptree, nmptree, 1, sizeof(struct mptree), MPTREE_BLOCK); 1726 i = nmptree++; 1727 mptree[i].sibling = mptree[pos].child; 1728 mptree[i].child = 0; 1729 mptree[i].comp = compstr; 1730 mptree[i].compl = compl; 1731 mptree[i].mountpoint = -1; 1732 mptree[pos].child = i; 1733 } 1734 pos = i; 1735 } 1736 mptree[pos].mountpoint = mp; 1737 } 1738 1739 propagate_mountpoints(mptree, 0, mptree[0].mountpoint); 1740 1741 #if 0 1742 for (i = 0; i < nmptree; i++) 1743 { 1744 printf("#%d sibling: %d\n", i, mptree[i].sibling); 1745 printf("#%d child: %d\n", i, mptree[i].child); 1746 printf("#%d comp: %s\n", i, mptree[i].comp); 1747 printf("#%d compl: %d\n", i, mptree[i].compl); 1748 printf("#%d mountpont: %d\n", i, mptree[i].mountpoint); 1749 } 1750 #endif 1751 1752 cbd.mptree = mptree; 1753 cbd.addsub = 1; 1754 for (sp = 1, s = pool->solvables + sp; sp < pool->nsolvables; sp++, s++) 1755 { 1756 if (!s->repo || (oldinstalled && s->repo == oldinstalled)) 1757 continue; 1758 if (!MAPTST(installedmap, sp)) 1759 continue; 1760 cbd.hasdu = 0; 1761 repo_search(s->repo, sp, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); 1762 if (!cbd.hasdu && oldinstalled) 1763 { 1764 Id op, opp; 1765 /* no du data available, ignore data of all installed solvables we obsolete */ 1766 if (!ignoredu.map) 1767 map_init(&ignoredu, oldinstalled->end - oldinstalled->start); 1768 if (s->obsoletes) 1769 { 1770 Id obs, *obsp = s->repo->idarraydata + s->obsoletes; 1771 while ((obs = *obsp++) != 0) 1772 FOR_PROVIDES(op, opp, obs) 1773 if (op >= oldinstalled->start && op < oldinstalled->end) 1774 MAPSET(&ignoredu, op - oldinstalled->start); 1775 } 1776 FOR_PROVIDES(op, opp, s->name) 1777 if (pool->solvables[op].name == s->name) 1778 if (op >= oldinstalled->start && op < oldinstalled->end) 1779 MAPSET(&ignoredu, op - oldinstalled->start); 1780 } 1781 } 1782 cbd.addsub = -1; 1783 if (oldinstalled) 1784 { 1785 /* assumes we allways have du data for installed solvables */ 1786 FOR_REPO_SOLVABLES(oldinstalled, sp, s) 1787 { 1788 if (MAPTST(installedmap, sp)) 1789 continue; 1790 if (ignoredu.map && MAPTST(&ignoredu, sp - oldinstalled->start)) 1791 continue; 1792 repo_search(oldinstalled, sp, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); 1793 } 1794 } 1795 if (ignoredu.map) 1796 map_free(&ignoredu); 1797 solv_free(cbd.dirmap); 1798 solv_free(mptree); 1799 } 1800 1801 int 1802 pool_calc_installsizechange(Pool *pool, Map *installedmap) 1803 { 1804 Id sp; 1805 Solvable *s; 1806 int change = 0; 1807 Repo *oldinstalled = pool->installed; 1808 1809 for (sp = 1, s = pool->solvables + sp; sp < pool->nsolvables; sp++, s++) 1810 { 1811 if (!s->repo || (oldinstalled && s->repo == oldinstalled)) 1812 continue; 1813 if (!MAPTST(installedmap, sp)) 1814 continue; 1815 change += solvable_lookup_sizek(s, SOLVABLE_INSTALLSIZE, 0); 1816 } 1817 if (oldinstalled) 1818 { 1819 FOR_REPO_SOLVABLES(oldinstalled, sp, s) 1820 { 1821 if (MAPTST(installedmap, sp)) 1822 continue; 1823 change -= solvable_lookup_sizek(s, SOLVABLE_INSTALLSIZE, 0); 1824 } 1825 } 1826 return change; 1827 } 1828 1829 /* map: 1830 * 1: installed 1831 * 2: conflicts with installed 1832 * 8: interesting (only true if installed) 1833 * 16: undecided 1834 */ 1835 1836 static inline Id dep2name(Pool *pool, Id dep) 1837 { 1838 while (ISRELDEP(dep)) 1839 { 1840 Reldep *rd = rd = GETRELDEP(pool, dep); 1841 dep = rd->name; 1842 } 1843 return dep; 1844 } 1845 1846 static int providedbyinstalled_multiversion(Pool *pool, unsigned char *map, Id n, Id con) 1847 { 1848 Id p, pp; 1849 Solvable *sn = pool->solvables + n; 1850 1851 FOR_PROVIDES(p, pp, sn->name) 1852 { 1853 Solvable *s = pool->solvables + p; 1854 if (s->name != sn->name || s->arch != sn->arch) 1855 continue; 1856 if ((map[p] & 9) != 9) 1857 continue; 1858 if (pool_match_nevr(pool, pool->solvables + p, con)) 1859 continue; 1860 return 1; /* found installed package that doesn't conflict */ 1861 } 1862 return 0; 1863 } 1864 1865 static inline int providedbyinstalled(Pool *pool, unsigned char *map, Id dep, int ispatch, Map *multiversionmap) 1866 { 1867 Id p, pp; 1868 int r = 0; 1869 FOR_PROVIDES(p, pp, dep) 1870 { 1871 if (p == SYSTEMSOLVABLE) 1872 return 1; /* always boring, as never constraining */ 1873 if (ispatch && !pool_match_nevr(pool, pool->solvables + p, dep)) 1874 continue; 1875 if (ispatch && multiversionmap && multiversionmap->size && MAPTST(multiversionmap, p) && ISRELDEP(dep)) 1876 if (providedbyinstalled_multiversion(pool, map, p, dep)) 1877 continue; 1878 if ((map[p] & 9) == 9) 1879 return 9; 1880 r |= map[p] & 17; 1881 } 1882 return r; 1883 } 1884 1885 /* 1886 * pool_trivial_installable - calculate if a set of solvables is 1887 * trivial installable without any other installs/deinstalls of 1888 * packages not belonging to the set. 1889 * 1890 * the state is returned in the result queue: 1891 * 1: solvable is installable without any other package changes 1892 * 0: solvable is not installable 1893 * -1: solvable is installable, but doesn't constrain any installed packages 1894 */ 1895 1896 void 1897 pool_trivial_installable_multiversionmap(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res, Map *multiversionmap) 1898 { 1899 int i, r, m, did; 1900 Id p, *dp, con, *conp, req, *reqp; 1901 unsigned char *map; 1902 Solvable *s; 1903 1904 map = solv_calloc(pool->nsolvables, 1); 1905 for (p = 1; p < pool->nsolvables; p++) 1906 { 1907 if (!MAPTST(installedmap, p)) 1908 continue; 1909 map[p] |= 9; 1910 s = pool->solvables + p; 1911 if (!s->conflicts) 1912 continue; 1913 conp = s->repo->idarraydata + s->conflicts; 1914 while ((con = *conp++) != 0) 1915 { 1916 dp = pool_whatprovides_ptr(pool, con); 1917 for (; *dp; dp++) 1918 map[p] |= 2; /* XXX: self conflict ? */ 1919 } 1920 } 1921 for (i = 0; i < pkgs->count; i++) 1922 map[pkgs->elements[i]] = 16; 1923 1924 for (i = 0, did = 0; did < pkgs->count; i++, did++) 1925 { 1926 if (i == pkgs->count) 1927 i = 0; 1928 p = pkgs->elements[i]; 1929 if ((map[p] & 16) == 0) 1930 continue; 1931 if ((map[p] & 2) != 0) 1932 { 1933 map[p] = 2; 1934 continue; 1935 } 1936 s = pool->solvables + p; 1937 m = 1; 1938 if (s->requires) 1939 { 1940 reqp = s->repo->idarraydata + s->requires; 1941 while ((req = *reqp++) != 0) 1942 { 1943 if (req == SOLVABLE_PREREQMARKER) 1944 continue; 1945 r = providedbyinstalled(pool, map, req, 0, 0); 1946 if (!r) 1947 { 1948 /* decided and miss */ 1949 map[p] = 2; 1950 did = 0; 1951 break; 1952 } 1953 if (r == 16) 1954 break; /* undecided */ 1955 m |= r; /* 1 | 9 | 17 */ 1956 } 1957 if (req) 1958 continue; 1959 if ((m & 9) == 9) 1960 m = 9; 1961 } 1962 if (s->conflicts) 1963 { 1964 int ispatch = 0; /* see solver.c patch handling */ 1965 1966 if (!strncmp("patch:", pool_id2str(pool, s->name), 6)) 1967 ispatch = 1; 1968 conp = s->repo->idarraydata + s->conflicts; 1969 while ((con = *conp++) != 0) 1970 { 1971 if ((providedbyinstalled(pool, map, con, ispatch, multiversionmap) & 1) != 0) 1972 { 1973 map[p] = 2; 1974 did = 0; 1975 break; 1976 } 1977 if ((m == 1 || m == 17) && ISRELDEP(con)) 1978 { 1979 con = dep2name(pool, con); 1980 if ((providedbyinstalled(pool, map, con, ispatch, multiversionmap) & 1) != 0) 1981 m = 9; 1982 } 1983 } 1984 if (con) 1985 continue; /* found a conflict */ 1986 } 1987 #if 0 1988 if (s->repo && s->repo != oldinstalled) 1989 { 1990 Id p2, obs, *obsp, *pp; 1991 Solvable *s2; 1992 if (s->obsoletes) 1993 { 1994 obsp = s->repo->idarraydata + s->obsoletes; 1995 while ((obs = *obsp++) != 0) 1996 { 1997 if ((providedbyinstalled(pool, map, obs, 0, 0) & 1) != 0) 1998 { 1999 map[p] = 2; 2000 break; 2001 } 2002 } 2003 if (obs) 2004 continue; 2005 } 2006 FOR_PROVIDES(p2, pp, s->name) 2007 { 2008 s2 = pool->solvables + p2; 2009 if (s2->name == s->name && (map[p2] & 1) != 0) 2010 { 2011 map[p] = 2; 2012 break; 2013 } 2014 } 2015 if (p2) 2016 continue; 2017 } 2018 #endif 2019 if (m != map[p]) 2020 { 2021 map[p] = m; 2022 did = 0; 2023 } 2024 } 2025 queue_free(res); 2026 queue_init_clone(res, pkgs); 2027 for (i = 0; i < pkgs->count; i++) 2028 { 2029 m = map[pkgs->elements[i]]; 2030 if ((m & 9) == 9) 2031 r = 1; 2032 else if (m & 1) 2033 r = -1; 2034 else 2035 r = 0; 2036 res->elements[i] = r; 2037 } 2038 free(map); 2039 } 2040 2041 void 2042 pool_trivial_installable(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res) 2043 { 2044 pool_trivial_installable_multiversionmap(pool, installedmap, pkgs, res, 0); 2045 } 2046 2047 const char * 2048 pool_lookup_str(Pool *pool, Id entry, Id keyname) 2049 { 2050 if (entry == SOLVID_POS && pool->pos.repo) 2051 return repodata_lookup_str(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname); 2052 if (entry <= 0) 2053 return 0; 2054 return solvable_lookup_str(pool->solvables + entry, keyname); 2055 } 2056 2057 Id 2058 pool_lookup_id(Pool *pool, Id entry, Id keyname) 2059 { 2060 if (entry == SOLVID_POS && pool->pos.repo) 2061 { 2062 Repodata *data = pool->pos.repo->repodata + pool->pos.repodataid; 2063 Id id = repodata_lookup_id(data, SOLVID_POS, keyname); 2064 return data->localpool ? repodata_globalize_id(data, id, 1) : id; 2065 } 2066 if (entry <= 0) 2067 return 0; 2068 return solvable_lookup_id(pool->solvables + entry, keyname); 2069 } 2070 2071 unsigned long long 2072 pool_lookup_num(Pool *pool, Id entry, Id keyname, unsigned long long notfound) 2073 { 2074 if (entry == SOLVID_POS && pool->pos.repo) 2075 { 2076 unsigned long long value; 2077 if (repodata_lookup_num(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname, &value)) 2078 return value; 2079 return notfound; 2080 } 2081 if (entry <= 0) 2082 return notfound; 2083 return solvable_lookup_num(pool->solvables + entry, keyname, notfound); 2084 } 2085 2086 int 2087 pool_lookup_void(Pool *pool, Id entry, Id keyname) 2088 { 2089 if (entry == SOLVID_POS && pool->pos.repo) 2090 return repodata_lookup_void(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname); 2091 if (entry <= 0) 2092 return 0; 2093 return solvable_lookup_void(pool->solvables + entry, keyname); 2094 } 2095 2096 const unsigned char * 2097 pool_lookup_bin_checksum(Pool *pool, Id entry, Id keyname, Id *typep) 2098 { 2099 if (entry == SOLVID_POS && pool->pos.repo) 2100 return repodata_lookup_bin_checksum(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname, typep); 2101 if (entry <= 0) 2102 return 0; 2103 return solvable_lookup_bin_checksum(pool->solvables + entry, keyname, typep); 2104 } 2105 2106 const char * 2107 pool_lookup_checksum(Pool *pool, Id entry, Id keyname, Id *typep) 2108 { 2109 if (entry == SOLVID_POS && pool->pos.repo) 2110 { 2111 const unsigned char *chk = repodata_lookup_bin_checksum(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname, typep); 2112 return chk ? repodata_chk2str(pool->pos.repo->repodata + pool->pos.repodataid, *typep, chk) : 0; 2113 } 2114 if (entry <= 0) 2115 return 0; 2116 return solvable_lookup_checksum(pool->solvables + entry, keyname, typep); 2117 } 2118 2119 const char * 2120 pool_lookup_deltalocation(Pool *pool, Id entry, unsigned int *medianrp) 2121 { 2122 const char *loc; 2123 if (medianrp) 2124 *medianrp = 0; 2125 if (entry != SOLVID_POS) 2126 return 0; 2127 loc = pool_lookup_str(pool, entry, DELTA_LOCATION_DIR); 2128 loc = pool_tmpjoin(pool, loc, loc ? "/" : 0, pool_lookup_str(pool, entry, DELTA_LOCATION_NAME)); 2129 loc = pool_tmpappend(pool, loc, "-", pool_lookup_str(pool, entry, DELTA_LOCATION_EVR)); 2130 loc = pool_tmpappend(pool, loc, ".", pool_lookup_str(pool, entry, DELTA_LOCATION_SUFFIX)); 2131 return loc; 2132 } 2133 2134 static void 2135 add_new_provider(Pool *pool, Id id, Id p) 2136 { 2137 Queue q; 2138 Id *pp; 2139 2140 while (ISRELDEP(id)) 2141 { 2142 Reldep *rd = GETRELDEP(pool, id); 2143 id = rd->name; 2144 } 2145 2146 queue_init(&q); 2147 for (pp = pool->whatprovidesdata + pool->whatprovides[id]; *pp; pp++) 2148 { 2149 if (*pp == p) 2150 { 2151 queue_free(&q); 2152 return; 2153 } 2154 if (*pp > p) 2155 { 2156 queue_push(&q, p); 2157 p = 0; 2158 } 2159 queue_push(&q, *pp); 2160 } 2161 if (p) 2162 queue_push(&q, p); 2163 pool->whatprovides[id] = pool_queuetowhatprovides(pool, &q); 2164 queue_free(&q); 2165 } 2166 2167 void 2168 pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts) 2169 { 2170 int hadhashes = pool->relhashtbl ? 1 : 0; 2171 Solvable *s; 2172 Id fn, p, q, md5; 2173 Id id; 2174 int i; 2175 2176 if (!conflicts->count) 2177 return; 2178 for (i = 0; i < conflicts->count; i += 6) 2179 { 2180 fn = conflicts->elements[i]; 2181 p = conflicts->elements[i + 1]; 2182 md5 = conflicts->elements[i + 2]; 2183 q = conflicts->elements[i + 4]; 2184 id = pool_rel2id(pool, fn, md5, REL_FILECONFLICT, 1); 2185 s = pool->solvables + p; 2186 if (!s->repo) 2187 continue; 2188 s->provides = repo_addid_dep(s->repo, s->provides, id, SOLVABLE_FILEMARKER); 2189 if (pool->whatprovides) 2190 add_new_provider(pool, fn, p); 2191 if (pool->whatprovides_rel) 2192 pool->whatprovides_rel[GETRELID(id)] = 0; /* clear cache */ 2193 s = pool->solvables + q; 2194 if (!s->repo) 2195 continue; 2196 s->conflicts = repo_addid_dep(s->repo, s->conflicts, id, 0); 2197 } 2198 if (!hadhashes) 2199 pool_freeidhashes(pool); 2200 } 2201 2202 char * 2203 pool_prepend_rootdir(Pool *pool, const char *path) 2204 { 2205 if (!path) 2206 return 0; 2207 if (!pool->rootdir) 2208 return solv_strdup(path); 2209 return solv_dupjoin(pool->rootdir, "/", *path == '/' ? path + 1 : path); 2210 } 2211 2212 const char * 2213 pool_prepend_rootdir_tmp(Pool *pool, const char *path) 2214 { 2215 if (!path) 2216 return 0; 2217 if (!pool->rootdir) 2218 return path; 2219 return pool_tmpjoin(pool, pool->rootdir, "/", *path == '/' ? path + 1 : path); 2220 } 2221 2222 void 2223 pool_set_rootdir(Pool *pool, const char *rootdir) 2224 { 2225 solv_free(pool->rootdir); 2226 pool->rootdir = solv_strdup(rootdir); 2227 } 2228 2229 const char * 2230 pool_get_rootdir(Pool *pool) 2231 { 2232 return pool->rootdir; 2233 } 2234 2235 /* only used in libzypp */ 2236 void 2237 pool_set_custom_vendorcheck(Pool *pool, int (*vendorcheck)(Pool *, Solvable *, Solvable *)) 2238 { 2239 pool->custom_vendorcheck = vendorcheck; 2240 } 2241 2242 /* EOF */ 2243