Bug Summary

File:src/pool.c
Warning:line 1703, column 7
Null pointer passed as an argument to a 'nonnull' parameter

Annotated Source Code

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 "poolvendor.h"
23#include "repo.h"
24#include "poolid.h"
25#include "poolid_private.h"
26#include "poolarch.h"
27#include "util.h"
28#include "bitmap.h"
29#include "evr.h"
30
31#define SOLVABLE_BLOCK255 255
32
33#undef LIBSOLV_KNOWNID_H
34#define KNOWNID_INITIALIZE
35#include "knownid.h"
36#undef KNOWNID_INITIALIZE
37
38/* create pool */
39Pool *
40pool_create(void)
41{
42 Pool *pool;
43 Solvable *s;
44
45 pool = (Pool *)solv_calloc(1, sizeof(*pool));
46
47 stringpool_init (&pool->ss, initpool_data);
48
49 /* alloc space for RelDep 0 */
50 pool->rels = solv_extend_resize(0, 1, sizeof(Reldep), REL_BLOCK1023);
51 pool->nrels = 1;
52 memset(pool->rels, 0, sizeof(Reldep));
53
54 /* alloc space for Solvable 0 and system solvable */
55 pool->solvables = solv_extend_resize(0, 2, sizeof(Solvable), SOLVABLE_BLOCK255);
56 pool->nsolvables = 2;
57 memset(pool->solvables, 0, 2 * sizeof(Solvable));
58
59 queue_init(&pool->vendormap);
60 queue_init(&pool->pooljobs);
61 queue_init(&pool->lazywhatprovidesq);
62
63#if defined(DEBIAN)
64 pool->disttype = DISTTYPE_DEB1;
65 pool->noarchid = ARCH_ALL;
66#elif defined(ARCHLINUX)
67 pool->disttype = DISTTYPE_ARCH2;
68 pool->noarchid = ARCH_ANY;
69#elif defined(HAIKU)
70 pool->disttype = DISTTYPE_HAIKU3;
71 pool->noarchid = ARCH_ANY;
72 pool->obsoleteusesprovides = 1;
73#else
74 pool->disttype = DISTTYPE_RPM0;
75 pool->noarchid = ARCH_NOARCH;
76#endif
77
78 /* initialize the system solvable */
79 s = pool->solvables + SYSTEMSOLVABLE1;
80 s->name = SYSTEM_SYSTEM;
81 s->arch = pool->noarchid;
82 s->evr = ID_EMPTY;
83
84 pool->debugmask = SOLV_DEBUG_RESULT(1<<10); /* FIXME */
85#if defined(FEDORA) || defined(MAGEIA)
86 pool->implicitobsoleteusescolors = 1;
87#endif
88#ifdef RPM5
89 pool->noobsoletesmultiversion = 1;
90 pool->forbidselfconflicts = 1;
91 pool->obsoleteusesprovides = 1;
92 pool->implicitobsoleteusesprovides = 1;
93 pool->havedistepoch = 1;
94#endif
95 return pool;
96}
97
98
99/* free all the resources of our pool */
100void
101pool_free(Pool *pool)
102{
103 int i;
104
105 pool_freewhatprovides(pool);
106 pool_freeidhashes(pool);
107 pool_freeallrepos(pool, 1);
108 solv_free(pool->id2arch);
109 solv_free(pool->id2color);
110 solv_free(pool->solvables);
111 stringpool_free(&pool->ss);
112 solv_free(pool->rels);
113 pool_setvendorclasses(pool, 0);
114 queue_free(&pool->vendormap);
115 queue_free(&pool->pooljobs);
116 queue_free(&pool->lazywhatprovidesq);
117 for (i = 0; i < POOL_TMPSPACEBUF16; i++)
118 solv_free(pool->tmpspace.buf[i]);
119 for (i = 0; i < pool->nlanguages; i++)
120 free((char *)pool->languages[i]);
121 solv_free((void *)pool->languages);
122 solv_free(pool->languagecache);
123 solv_free(pool->errstr);
124 solv_free(pool->rootdir);
125 solv_free(pool);
126}
127
128void
129pool_freeallrepos(Pool *pool, int reuseids)
130{
131 int i;
132
133 pool_freewhatprovides(pool);
134 for (i = 1; i < pool->nrepos; i++)
135 if (pool->repos[i])
136 repo_freedata(pool->repos[i]);
137 pool->repos = solv_free(pool->repos);
138 pool->nrepos = 0;
139 pool->urepos = 0;
140 /* the first two solvables don't belong to a repo */
141 pool_free_solvable_block(pool, 2, pool->nsolvables - 2, reuseids);
142}
143
144int
145pool_setdisttype(Pool *pool, int disttype)
146{
147#ifdef MULTI_SEMANTICS
148 int olddisttype = pool->disttype;
149 switch(disttype)
150 {
151 case DISTTYPE_RPM0:
152 pool->noarchid = ARCH_NOARCH;
153 break;
154 case DISTTYPE_DEB1:
155 pool->noarchid = ARCH_ALL;
156 break;
157 case DISTTYPE_ARCH2:
158 case DISTTYPE_HAIKU3:
159 pool->noarchid = ARCH_ANY;
160 break;
161 default:
162 return -1;
163 }
164 pool->disttype = disttype;
165 pool->solvables[SYSTEMSOLVABLE1].arch = pool->noarchid;
166 return olddisttype;
167#else
168 return pool->disttype == disttype ? disttype : -1;
169#endif
170}
171
172int
173pool_get_flag(Pool *pool, int flag)
174{
175 switch (flag)
176 {
177 case POOL_FLAG_PROMOTEEPOCH1:
178 return pool->promoteepoch;
179 case POOL_FLAG_FORBIDSELFCONFLICTS2:
180 return pool->forbidselfconflicts;
181 case POOL_FLAG_OBSOLETEUSESPROVIDES3:
182 return pool->obsoleteusesprovides;
183 case POOL_FLAG_IMPLICITOBSOLETEUSESPROVIDES4:
184 return pool->implicitobsoleteusesprovides;
185 case POOL_FLAG_OBSOLETEUSESCOLORS5:
186 return pool->obsoleteusescolors;
187 case POOL_FLAG_IMPLICITOBSOLETEUSESCOLORS10:
188 return pool->implicitobsoleteusescolors;
189 case POOL_FLAG_NOINSTALLEDOBSOLETES6:
190 return pool->noinstalledobsoletes;
191 case POOL_FLAG_HAVEDISTEPOCH7:
192 return pool->havedistepoch;
193 case POOL_FLAG_NOOBSOLETESMULTIVERSION8:
194 return pool->noobsoletesmultiversion;
195 case POOL_FLAG_ADDFILEPROVIDESFILTERED9:
196 return pool->addfileprovidesfiltered;
197 case POOL_FLAG_NOWHATPROVIDESAUX11:
198 return pool->nowhatprovidesaux;
199 default:
200 break;
201 }
202 return -1;
203}
204
205int
206pool_set_flag(Pool *pool, int flag, int value)
207{
208 int old = pool_get_flag(pool, flag);
209 switch (flag)
210 {
211 case POOL_FLAG_PROMOTEEPOCH1:
212 pool->promoteepoch = value;
213 break;
214 case POOL_FLAG_FORBIDSELFCONFLICTS2:
215 pool->forbidselfconflicts = value;
216 break;
217 case POOL_FLAG_OBSOLETEUSESPROVIDES3:
218 pool->obsoleteusesprovides = value;
219 break;
220 case POOL_FLAG_IMPLICITOBSOLETEUSESPROVIDES4:
221 pool->implicitobsoleteusesprovides = value;
222 break;
223 case POOL_FLAG_OBSOLETEUSESCOLORS5:
224 pool->obsoleteusescolors = value;
225 break;
226 case POOL_FLAG_IMPLICITOBSOLETEUSESCOLORS10:
227 pool->implicitobsoleteusescolors = value;
228 break;
229 case POOL_FLAG_NOINSTALLEDOBSOLETES6:
230 pool->noinstalledobsoletes = value;
231 break;
232 case POOL_FLAG_HAVEDISTEPOCH7:
233 pool->havedistepoch = value;
234 break;
235 case POOL_FLAG_NOOBSOLETESMULTIVERSION8:
236 pool->noobsoletesmultiversion = value;
237 break;
238 case POOL_FLAG_ADDFILEPROVIDESFILTERED9:
239 pool->addfileprovidesfiltered = value;
240 break;
241 case POOL_FLAG_NOWHATPROVIDESAUX11:
242 pool->nowhatprovidesaux = value;
243 break;
244 default:
245 break;
246 }
247 return old;
248}
249
250
251Id
252pool_add_solvable(Pool *pool)
253{
254 pool->solvables = solv_extend(pool->solvables, pool->nsolvables, 1, sizeof(Solvable), SOLVABLE_BLOCK255);
255 memset(pool->solvables + pool->nsolvables, 0, sizeof(Solvable));
256 return pool->nsolvables++;
257}
258
259Id
260pool_add_solvable_block(Pool *pool, int count)
261{
262 Id nsolvables = pool->nsolvables;
263 if (!count)
264 return nsolvables;
265 pool->solvables = solv_extend(pool->solvables, pool->nsolvables, count, sizeof(Solvable), SOLVABLE_BLOCK255);
266 memset(pool->solvables + nsolvables, 0, sizeof(Solvable) * count);
267 pool->nsolvables += count;
268 return nsolvables;
269}
270
271void
272pool_free_solvable_block(Pool *pool, Id start, int count, int reuseids)
273{
274 if (!count)
275 return;
276 if (reuseids && start + count == pool->nsolvables)
277 {
278 /* might want to shrink solvable array */
279 pool->nsolvables = start;
280 return;
281 }
282 memset(pool->solvables + start, 0, sizeof(Solvable) * count);
283}
284
285
286void
287pool_set_installed(Pool *pool, Repo *installed)
288{
289 if (pool->installed == installed)
290 return;
291 pool->installed = installed;
292 pool_freewhatprovides(pool);
293}
294
295static int
296pool_shrink_whatprovides_sortcmp(const void *ap, const void *bp, void *dp)
297{
298 int r;
299 Pool *pool = dp;
300 Id oa, ob, *da, *db;
301 oa = pool->whatprovides[*(Id *)ap];
302 ob = pool->whatprovides[*(Id *)bp];
303 if (oa == ob)
304 return *(Id *)ap - *(Id *)bp;
305 da = pool->whatprovidesdata + oa;
306 db = pool->whatprovidesdata + ob;
307 while (*db)
308 if ((r = (*da++ - *db++)) != 0)
309 return r;
310 if (*da)
311 return *da;
312 return *(Id *)ap - *(Id *)bp;
313}
314
315/*
316 * pool_shrink_whatprovides - unify whatprovides data
317 *
318 * whatprovides_rel must be empty for this to work!
319 *
320 */
321static void
322pool_shrink_whatprovides(Pool *pool)
323{
324 Id i, n, id;
325 Id *sorted;
326 Id lastid, *last, *dp, *lp;
327 Offset o;
328 int r;
329
330 if (pool->ss.nstrings < 3)
331 return;
332 sorted = solv_malloc2(pool->ss.nstrings, sizeof(Id));
333 for (i = id = 0; id < pool->ss.nstrings; id++)
334 if (pool->whatprovides[id] >= 4)
335 sorted[i++] = id;
336 n = i;
337 solv_sort(sorted, n, sizeof(Id), pool_shrink_whatprovides_sortcmp, pool);
338 last = 0;
339 lastid = 0;
340 for (i = 0; i < n; i++)
341 {
342 id = sorted[i];
343 o = pool->whatprovides[id];
344 dp = pool->whatprovidesdata + o;
345 if (last)
346 {
347 lp = last;
348 while (*dp)
349 if (*dp++ != *lp++)
350 {
351 last = 0;
352 break;
353 }
354 if (last && *lp)
355 last = 0;
356 if (last)
357 {
358 pool->whatprovides[id] = -lastid;
359 continue;
360 }
361 }
362 last = pool->whatprovidesdata + o;
363 lastid = id;
364 }
365 solv_free(sorted);
366 dp = pool->whatprovidesdata + 4;
367 for (id = 1; id < pool->ss.nstrings; id++)
368 {
369 o = pool->whatprovides[id];
370 if (!o)
371 continue;
372 if ((Id)o < 0)
373 {
374 i = -(Id)o;
375 if (i >= id)
376 abort();
377 pool->whatprovides[id] = pool->whatprovides[i];
378 continue;
379 }
380 if (o < 4)
381 continue;
382 lp = pool->whatprovidesdata + o;
383 if (lp < dp)
384 abort();
385 pool->whatprovides[id] = dp - pool->whatprovidesdata;
386 while ((*dp++ = *lp++) != 0)
387 ;
388 }
389 o = dp - pool->whatprovidesdata;
390 POOL_DEBUG(SOLV_DEBUG_STATS, "shrunk whatprovidesdata from %d to %d\n", pool->whatprovidesdataoff, o)do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "shrunk whatprovidesdata from %d to %d\n"
, pool->whatprovidesdataoff, o);} while (0)
;
391 if (pool->whatprovidesdataoff == o)
392 return;
393 r = pool->whatprovidesdataoff - o;
394 pool->whatprovidesdataoff = o;
395 pool->whatprovidesdata = solv_realloc(pool->whatprovidesdata, (o + pool->whatprovidesdataleft) * sizeof(Id));
396 if (r > pool->whatprovidesdataleft)
397 r = pool->whatprovidesdataleft;
398 memset(pool->whatprovidesdata + o, 0, r * sizeof(Id));
399}
400
401/* this gets rid of all the zeros in the aux */
402static void
403pool_shrink_whatprovidesaux(Pool *pool)
404{
405 int num = pool->whatprovidesauxoff;
406 Id id;
407 Offset newoff;
408 Id *op, *wp = pool->whatprovidesauxdata + 1;
409 int i;
410
411 for (i = 0; i < num; i++)
412 {
413 Offset o = pool->whatprovidesaux[i];
414 if (o < 2)
415 continue;
416 op = pool->whatprovidesauxdata + o;
417 pool->whatprovidesaux[i] = wp - pool->whatprovidesauxdata;
418 if (op < wp)
419 abort();
420 while ((id = *op++) != 0)
421 *wp++ = id;
422 }
423 newoff = wp - pool->whatprovidesauxdata;
424 pool->whatprovidesauxdata = solv_realloc(pool->whatprovidesauxdata, newoff * sizeof(Id));
425 POOL_DEBUG(SOLV_DEBUG_STATS, "shrunk whatprovidesauxdata from %d to %d\n", pool->whatprovidesauxdataoff, newoff)do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "shrunk whatprovidesauxdata from %d to %d\n"
, pool->whatprovidesauxdataoff, newoff);} while (0)
;
426 pool->whatprovidesauxdataoff = newoff;
427}
428
429
430/*
431 * pool_createwhatprovides()
432 *
433 * create hashes over pool of solvables to ease provide lookups
434 *
435 */
436void
437pool_createwhatprovides(Pool *pool)
438{
439 int i, num, np, extra;
440 Offset off;
441 Solvable *s;
442 Id id;
443 Offset *idp, n;
444 Offset *whatprovides;
445 Id *whatprovidesdata, *dp, *whatprovidesauxdata;
446 Offset *whatprovidesaux;
447 Repo *installed = pool->installed;
448 unsigned int now;
449
450 now = solv_timems(0);
451 POOL_DEBUG(SOLV_DEBUG_STATS, "number of solvables: %d, memory used: %d K\n", pool->nsolvables, pool->nsolvables * (int)sizeof(Solvable) / 1024)do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "number of solvables: %d, memory used: %d K\n"
, pool->nsolvables, pool->nsolvables * (int)sizeof(Solvable
) / 1024);} while (0)
;
452 POOL_DEBUG(SOLV_DEBUG_STATS, "number of ids: %d + %d\n", pool->ss.nstrings, pool->nrels)do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "number of ids: %d + %d\n", pool->ss
.nstrings, pool->nrels);} while (0)
;
453 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)do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "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
);} while (0)
;
454 if (pool->ss.stringhashmask || pool->relhashmask)
455 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)))do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "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)));} while (
0)
;
456
457 pool_freeidhashes(pool); /* XXX: should not be here! */
458 pool_freewhatprovides(pool);
459 num = pool->ss.nstrings;
460 pool->whatprovides = whatprovides = solv_calloc_block(num, sizeof(Offset), WHATPROVIDES_BLOCK1023);
461 pool->whatprovides_rel = solv_calloc_block(pool->nrels, sizeof(Offset), WHATPROVIDES_BLOCK1023);
462
463 /* count providers for each name */
464 for (i = pool->nsolvables - 1; i > 0; i--)
465 {
466 Id *pp;
467 s = pool->solvables + i;
468 if (!s->provides || !s->repo || s->repo->disabled)
469 continue;
470 /* we always need the installed solvable in the whatprovides data,
471 otherwise obsoletes/conflicts on them won't work */
472 if (s->repo != installed && !pool_installable(pool, s))
473 continue;
474 pp = s->repo->idarraydata + s->provides;
475 while ((id = *pp++) != 0)
476 {
477 while (ISRELDEP(id)(((id) & 0x80000000) != 0))
478 {
479 Reldep *rd = GETRELDEP(pool, id)((pool)->rels + ((id) ^ 0x80000000));
480 id = rd->name;
481 }
482 whatprovides[id]++; /* inc count of providers */
483 }
484 }
485
486 off = 4; /* first entry is undef, second is empty list, third is system solvable */
487 np = 0; /* number of names provided */
488 for (i = 0, idp = whatprovides; i < num; i++, idp++)
489 {
490 n = *idp;
491 if (!n) /* no providers */
492 {
493 *idp = 1; /* offset for empty list */
494 continue;
495 }
496 off += n; /* make space for all providers */
497 *idp = off++; /* now idp points to terminating zero */
498 np++; /* inc # of provider 'slots' for stats */
499 }
500
501 POOL_DEBUG(SOLV_DEBUG_STATS, "provide ids: %d\n", np)do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "provide ids: %d\n", np);} while (0)
;
502
503 /* reserve some space for relation data */
504 extra = 2 * pool->nrels;
505 if (extra < 256)
506 extra = 256;
507
508 POOL_DEBUG(SOLV_DEBUG_STATS, "provide space needed: %d + %d\n", off, extra)do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "provide space needed: %d + %d\n", off
, extra);} while (0)
;
509
510 /* alloc space for all providers + extra */
511 whatprovidesdata = solv_calloc(off + extra, sizeof(Id));
512 whatprovidesdata[2] = SYSTEMSOLVABLE1;
513
514 /* alloc aux vector */
515 whatprovidesauxdata = 0;
516 if (!pool->nowhatprovidesaux)
517 {
518 pool->whatprovidesaux = whatprovidesaux = solv_calloc(num, sizeof(Offset));
519 pool->whatprovidesauxoff = num;
520 pool->whatprovidesauxdataoff = off;
521 pool->whatprovidesauxdata = whatprovidesauxdata = solv_calloc(pool->whatprovidesauxdataoff, sizeof(Id));
522 }
523
524 /* now fill data for all provides */
525 for (i = pool->nsolvables - 1; i > 0; i--)
526 {
527 Id *pp;
528 s = pool->solvables + i;
529 if (!s->provides || !s->repo || s->repo->disabled)
530 continue;
531 if (s->repo != installed && !pool_installable(pool, s))
532 continue;
533
534 /* for all provides of this solvable */
535 pp = s->repo->idarraydata + s->provides;
536 while ((id = *pp++) != 0)
537 {
538 Id auxid = id;
539 while (ISRELDEP(id)(((id) & 0x80000000) != 0))
540 {
541 Reldep *rd = GETRELDEP(pool, id)((pool)->rels + ((id) ^ 0x80000000));
542 id = rd->name;
543 }
544 dp = whatprovidesdata + whatprovides[id]; /* offset into whatprovidesdata */
545 if (*dp != i) /* don't add same solvable twice */
546 {
547 dp[-1] = i;
548 whatprovides[id]--;
549 }
550 else
551 auxid = 1;
552 if (whatprovidesauxdata)
553 whatprovidesauxdata[whatprovides[id]] = auxid;
554 }
555 }
556 if (pool->whatprovidesaux)
557 memcpy(pool->whatprovidesaux, pool->whatprovides, num * sizeof(Id));
558 pool->whatprovidesdata = whatprovidesdata;
559 pool->whatprovidesdataoff = off;
560 pool->whatprovidesdataleft = extra;
561 pool_shrink_whatprovides(pool);
562 if (pool->whatprovidesaux)
563 pool_shrink_whatprovidesaux(pool);
564 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)))do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "whatprovides memory used: %d K id array, %d K data\n"
, (pool->ss.nstrings + pool->nrels + 1023) / (int)(1024
/sizeof(Id)), (pool->whatprovidesdataoff + pool->whatprovidesdataleft
) / (int)(1024/sizeof(Id)));} while (0)
;
565 if (pool->whatprovidesaux)
566 POOL_DEBUG(SOLV_DEBUG_STATS, "whatprovidesaux memory used: %d K id array, %d K data\n", pool->whatprovidesauxoff / (int)(1024/sizeof(Id)), pool->whatprovidesauxdataoff / (int)(1024/sizeof(Id)))do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "whatprovidesaux memory used: %d K id array, %d K data\n"
, pool->whatprovidesauxoff / (int)(1024/sizeof(Id)), pool->
whatprovidesauxdataoff / (int)(1024/sizeof(Id)));} while (0)
;
567
568 queue_empty(&pool->lazywhatprovidesq);
569 if ((!pool->addedfileprovides && pool->disttype == DISTTYPE_RPM0) || pool->addedfileprovides == 1)
570 {
571 if (!pool->addedfileprovides)
572 POOL_DEBUG(SOLV_DEBUG_STATS, "WARNING: pool_addfileprovides was not called, this may result in slow operation\n")do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "WARNING: pool_addfileprovides was not called, this may result in slow operation\n"
);} while (0)
;
573 /* lazyly add file provides */
574 for (i = 1; i < num; i++)
575 {
576 const char *str = pool->ss.stringspace + pool->ss.strings[i];
577 if (str[0] != '/')
578 continue;
579 if (pool->addedfileprovides == 1 && repodata_filelistfilter_matches(0, str))
580 continue;
581 /* setup lazy adding, but remember old value */
582 if (pool->whatprovides[i] > 1)
583 queue_push2(&pool->lazywhatprovidesq, i, pool->whatprovides[i]);
584 pool->whatprovides[i] = 0;
585 if (pool->whatprovidesaux)
586 pool->whatprovidesaux[i] = 0; /* sorry */
587 }
588 POOL_DEBUG(SOLV_DEBUG_STATS, "lazywhatprovidesq size: %d entries\n", pool->lazywhatprovidesq.count / 2)do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "lazywhatprovidesq size: %d entries\n"
, pool->lazywhatprovidesq.count / 2);} while (0)
;
589 }
590
591 POOL_DEBUG(SOLV_DEBUG_STATS, "createwhatprovides took %d ms\n", solv_timems(now))do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "createwhatprovides took %d ms\n", solv_timems
(now));} while (0)
;
592}
593
594/*
595 * free all of our whatprovides data
596 * be careful, everything internalized with pool_queuetowhatprovides is
597 * gone, too
598 */
599void
600pool_freewhatprovides(Pool *pool)
601{
602 pool->whatprovides = solv_free(pool->whatprovides);
603 pool->whatprovides_rel = solv_free(pool->whatprovides_rel);
604 pool->whatprovidesdata = solv_free(pool->whatprovidesdata);
605 pool->whatprovidesdataoff = 0;
606 pool->whatprovidesdataleft = 0;
607 pool->whatprovidesaux = solv_free(pool->whatprovidesaux);
608 pool->whatprovidesauxdata = solv_free(pool->whatprovidesauxdata);
609 pool->whatprovidesauxoff = 0;
610 pool->whatprovidesauxdataoff = 0;
611}
612
613
614/******************************************************************************/
615
616/*
617 * pool_queuetowhatprovides - add queue contents to whatprovidesdata
618 *
619 * used for whatprovides, jobs, learnt rules, selections
620 * input: q: queue of Ids
621 * returns: Offset into whatprovidesdata
622 *
623 */
624
625Id
626pool_ids2whatprovides(Pool *pool, Id *ids, int count)
627{
628 Offset off;
629
630 if (count == 0) /* queue empty -> 1 */
631 return 1;
632 if (count == 1 && *ids == SYSTEMSOLVABLE1)
633 return 2;
634
635 /* extend whatprovidesdata if needed, +1 for 0-termination */
636 if (pool->whatprovidesdataleft < count + 1)
637 {
638 POOL_DEBUG(SOLV_DEBUG_STATS, "growing provides hash data...\n")do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "growing provides hash data...\n");} while
(0)
;
639 pool->whatprovidesdata = solv_realloc(pool->whatprovidesdata, (pool->whatprovidesdataoff + count + 4096) * sizeof(Id));
640 pool->whatprovidesdataleft = count + 4096;
641 }
642
643 /* copy queue to next free slot */
644 off = pool->whatprovidesdataoff;
645 memcpy(pool->whatprovidesdata + pool->whatprovidesdataoff, ids, count * sizeof(Id));
646
647 /* adapt count and 0-terminate */
648 pool->whatprovidesdataoff += count;
649 pool->whatprovidesdata[pool->whatprovidesdataoff++] = 0;
650 pool->whatprovidesdataleft -= count + 1;
651
652 return (Id)off;
653}
654
655Id
656pool_queuetowhatprovides(Pool *pool, Queue *q)
657{
658 int count = q->count;
659 if (count == 0) /* queue empty -> 1 */
660 return 1;
661 if (count == 1 && q->elements[0] == SYSTEMSOLVABLE1)
662 return 2;
663 return pool_ids2whatprovides(pool, q->elements, count);
664}
665
666
667/*************************************************************************/
668
669#if defined(MULTI_SEMANTICS)
670# define EVRCMP_DEPCMP1 (pool->disttype == DISTTYPE_DEB1 ? EVRCMP_COMPARE0 : EVRCMP_MATCH_RELEASE1)
671#elif defined(DEBIAN)
672# define EVRCMP_DEPCMP1 EVRCMP_COMPARE0
673#else
674# define EVRCMP_DEPCMP1 EVRCMP_MATCH_RELEASE1
675#endif
676
677/* check if a package's nevr matches a dependency */
678/* semi-private, called from public pool_match_nevr */
679
680int
681pool_match_nevr_rel(Pool *pool, Solvable *s, Id d)
682{
683 Reldep *rd = GETRELDEP(pool, d)((pool)->rels + ((d) ^ 0x80000000));
684 Id name = rd->name;
685 Id evr = rd->evr;
686 int flags = rd->flags;
687
688 if (flags > 7)
689 {
690 switch (flags)
691 {
692 case REL_ARCH20:
693 if (s->arch != evr)
694 {
695 if (evr != ARCH_SRC || s->arch != ARCH_NOSRC)
696 return 0;
697 }
698 return pool_match_nevr(pool, s, name);
699 case REL_OR17:
700 if (pool_match_nevr(pool, s, name))
701 return 1;
702 return pool_match_nevr(pool, s, evr);
703 case REL_AND16:
704 case REL_WITH18:
705 if (!pool_match_nevr(pool, s, name))
706 return 0;
707 return pool_match_nevr(pool, s, evr);
708 case REL_MULTIARCH25:
709 if (evr != ARCH_ANY)
710 return 0;
711 /* XXX : need to check for Multi-Arch: allowed! */
712 return pool_match_nevr(pool, s, name);
713 default:
714 return 0;
715 }
716 }
717 if (!pool_match_nevr(pool, s, name))
718 return 0;
719 if (evr == s->evr)
720 return (flags & REL_EQ2) ? 1 : 0;
721 if (!flags)
722 return 0;
723 if (flags == 7)
724 return 1;
725 switch (pool_evrcmp(pool, s->evr, evr, EVRCMP_DEPCMP1))
726 {
727 case -2:
728 return 1;
729 case -1:
730 return (flags & REL_LT4) ? 1 : 0;
731 case 0:
732 return (flags & REL_EQ2) ? 1 : 0;
733 case 1:
734 return (flags & REL_GT1) ? 1 : 0;
735 case 2:
736 return (flags & REL_EQ2) ? 1 : 0;
737 default:
738 break;
739 }
740 return 0;
741}
742
743#if defined(HAIKU) || defined(MULTI_SEMANTICS)
744/* forward declaration */
745static int pool_match_flags_evr_rel_compat(Pool *pool, Reldep *range, int flags, int evr);
746#endif
747
748/* match (flags, evr) against provider (pflags, pevr) */
749static inline int
750pool_match_flags_evr(Pool *pool, int pflags, Id pevr, int flags, int evr)
751{
752 if (!pflags || !flags || pflags >= 8 || flags >= 8)
753 return 0;
754 if (flags == 7 || pflags == 7)
755 return 1; /* rel provides every version */
756 if ((pflags & flags & (REL_LT4 | REL_GT1)) != 0)
757 return 1; /* both rels show in the same direction */
758 if (pevr == evr)
759 return (flags & pflags & REL_EQ2) ? 1 : 0;
760#if defined(HAIKU) || defined(MULTI_SEMANTICS)
761 if (ISRELDEP(pevr)(((pevr) & 0x80000000) != 0))
762 {
763 Reldep *rd = GETRELDEP(pool, pevr)((pool)->rels + ((pevr) ^ 0x80000000));
764 if (rd->flags == REL_COMPAT23)
765 return pool_match_flags_evr_rel_compat(pool, rd, flags, evr);
766 }
767#endif
768 switch (pool_evrcmp(pool, pevr, evr, EVRCMP_DEPCMP1))
769 {
770 case -2:
771 return (pflags & REL_EQ2) ? 1 : 0;
772 case -1:
773 return (flags & REL_LT4) || (pflags & REL_GT1) ? 1 : 0;
774 case 0:
775 return (flags & pflags & REL_EQ2) ? 1 : 0;
776 case 1:
777 return (flags & REL_GT1) || (pflags & REL_LT4) ? 1 : 0;
778 case 2:
779 return (flags & REL_EQ2) ? 1 : 0;
780 default:
781 break;
782 }
783 return 0;
784}
785
786#if defined(HAIKU) || defined(MULTI_SEMANTICS)
787static int
788pool_match_flags_evr_rel_compat(Pool *pool, Reldep *range, int flags, int evr)
789{
790 /* range->name is the actual version, range->evr the backwards compatibility
791 version. If flags are '>=' or '>', we match the compatibility version
792 as well, otherwise only the actual version. */
793 if (!(flags & REL_GT1) || (flags & REL_LT4))
794 return pool_match_flags_evr(pool, REL_EQ2, range->name, flags, evr);
795 return pool_match_flags_evr(pool, REL_LT4 | REL_EQ2, range->name, flags, evr) &&
796 pool_match_flags_evr(pool, REL_GT1 | REL_EQ2, range->evr, REL_EQ2, evr);
797}
798#endif
799
800/* public (i.e. not inlined) version of pool_match_flags_evr */
801int
802pool_intersect_evrs(Pool *pool, int pflags, Id pevr, int flags, Id evr)
803{
804 return pool_match_flags_evr(pool, pflags, pevr, flags, evr);
805}
806
807/* match two dependencies (d1 = provider) */
808
809int
810pool_match_dep(Pool *pool, Id d1, Id d2)
811{
812 Reldep *rd1, *rd2;
813
814 if (d1 == d2)
815 return 1;
816
817 if (ISRELDEP(d1)(((d1) & 0x80000000) != 0))
818 {
819 /* we use potentially matches for complex deps */
820 rd1 = GETRELDEP(pool, d1)((pool)->rels + ((d1) ^ 0x80000000));
821 if (rd1->flags == REL_AND16 || rd1->flags == REL_OR17 || rd1->flags == REL_WITH18 || rd1->flags == REL_COND22)
822 {
823 if (pool_match_dep(pool, rd1->name, d2))
824 return 1;
825 if (rd1->flags == REL_COND22 && ISRELDEP(rd1->evr)(((rd1->evr) & 0x80000000) != 0))
826 {
827 rd1 = GETRELDEP(pool, rd1->evr)((pool)->rels + ((rd1->evr) ^ 0x80000000));
828 if (rd1->flags != REL_ELSE26)
829 return 0;
830 }
831 if (rd1->flags != REL_COND22 && pool_match_dep(pool, rd1->evr, d2))
832 return 1;
833 return 0;
834 }
835 }
836 if (ISRELDEP(d2)(((d2) & 0x80000000) != 0))
837 {
838 /* we use potentially matches for complex deps */
839 rd2 = GETRELDEP(pool, d2)((pool)->rels + ((d2) ^ 0x80000000));
840 if (rd2->flags == REL_AND16 || rd2->flags == REL_OR17 || rd2->flags == REL_WITH18 || rd2->flags == REL_COND22)
841 {
842 if (pool_match_dep(pool, d1, rd2->name))
843 return 1;
844 if (rd2->flags == REL_COND22 && ISRELDEP(rd2->evr)(((rd2->evr) & 0x80000000) != 0))
845 {
846 rd2 = GETRELDEP(pool, rd2->evr)((pool)->rels + ((rd2->evr) ^ 0x80000000));
847 if (rd2->flags != REL_ELSE26)
848 return 0;
849 }
850 if (rd2->flags != REL_COND22 && pool_match_dep(pool, d1, rd2->evr))
851 return 1;
852 return 0;
853 }
854 }
855 if (!ISRELDEP(d1)(((d1) & 0x80000000) != 0))
856 {
857 if (!ISRELDEP(d2)(((d2) & 0x80000000) != 0))
858 return 0;
859 rd2 = GETRELDEP(pool, d2)((pool)->rels + ((d2) ^ 0x80000000));
860 return pool_match_dep(pool, d1, rd2->name);
861 }
862 rd1 = GETRELDEP(pool, d1)((pool)->rels + ((d1) ^ 0x80000000));
863 if (!ISRELDEP(d2)(((d2) & 0x80000000) != 0))
864 {
865 return pool_match_dep(pool, rd1->name, d2);
866 }
867 rd2 = GETRELDEP(pool, d2)((pool)->rels + ((d2) ^ 0x80000000));
868 /* first match name */
869 if (!pool_match_dep(pool, rd1->name, rd2->name))
870 return 0;
871 /* name matches, check flags and evr */
872 return pool_intersect_evrs(pool, rd1->flags, rd1->evr, rd2->flags, rd2->evr);
873}
874
875Id
876pool_searchlazywhatprovidesq(Pool *pool, Id d)
877{
878 int start = 0;
879 int end = pool->lazywhatprovidesq.count;
880 Id *elements;
881 if (!end)
882 return 0;
883 elements = pool->lazywhatprovidesq.elements;
884 while (end - start > 16)
885 {
886 int mid = (start + end) / 2 & ~1;
887 if (elements[mid] == d)
888 return elements[mid + 1];
889 if (elements[mid] < d)
890 start = mid + 2;
891 else
892 end = mid;
893 }
894 for (; start < end; start += 2)
895 if (elements[start] == d)
896 return elements[start + 1];
897 return 0;
898}
899
900/*
901 * addstdproviders
902 *
903 * lazy populating of the whatprovides array, non relation case
904 */
905static Id
906pool_addstdproviders(Pool *pool, Id d)
907{
908 const char *str;
909 Queue q;
910 Id qbuf[16];
911 Dataiterator di;
912 Id oldoffset;
913
914 if (pool->addedfileprovides == 2)
915 {
916 pool->whatprovides[d] = 1;
917 return 1;
918 }
919 str = pool->ss.stringspace + pool->ss.strings[d];
920 if (*str != '/')
921 {
922 pool->whatprovides[d] = 1;
923 return 1;
924 }
925 queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
926 dataiterator_init(&di, pool, 0, 0, SOLVABLE_FILELIST, str, SEARCH_STRING1|SEARCH_FILES(1<<17)|SEARCH_COMPLETE_FILELIST(1<<12));
927 for (; dataiterator_step(&di); dataiterator_skip_solvable(&di))
928 {
929 Solvable *s = pool->solvables + di.solvid;
930 /* XXX: maybe should add a provides dependency to the solvables
931 * OTOH this is only needed for rel deps that filter the provides,
932 * and those should not use filelist entries */
933 if (s->repo->disabled)
934 continue;
935 if (s->repo != pool->installed && !pool_installable(pool, s))
936 continue;
937 queue_push(&q, di.solvid);
938 }
939 dataiterator_free(&di);
940 oldoffset = pool_searchlazywhatprovidesq(pool, d);
941 if (!q.count)
942 pool->whatprovides[d] = oldoffset ? oldoffset : 1;
943 else
944 {
945 if (oldoffset)
946 {
947 Id *oo = pool->whatprovidesdata + oldoffset;
948 int i;
949 /* unify both queues. easy, as we know both are sorted */
950 for (i = 0; i < q.count; i++)
951 {
952 if (*oo > q.elements[i])
953 continue;
954 if (*oo < q.elements[i])
955 queue_insert(&q, i, *oo);
956 oo++;
957 if (!*oo)
958 break;
959 }
960 while (*oo)
961 queue_push(&q, *oo++);
962 if (q.count == oo - (pool->whatprovidesdata + oldoffset))
963 {
964 /* end result has same size as oldoffset -> no new entries */
965 queue_free(&q);
966 pool->whatprovides[d] = oldoffset;
967 return oldoffset;
968 }
969 }
970 pool->whatprovides[d] = pool_queuetowhatprovides(pool, &q);
971 }
972 queue_free(&q);
973 return pool->whatprovides[d];
974}
975
976
977static inline int
978pool_is_kind(Pool *pool, Id name, Id kind)
979{
980 const char *n;
981 if (!kind)
982 return 1;
983 n = pool_id2str(pool, name);
984 if (kind != 1)
985 {
986 const char *kn = pool_id2str(pool, kind);
987 int knl = strlen(kn);
988 return !strncmp(n, kn, knl) && n[knl] == ':' ? 1 : 0;
989 }
990 else
991 {
992 if (*n == ':')
993 return 1;
994 while(*n >= 'a' && *n <= 'z')
995 n++;
996 return *n == ':' ? 0 : 1;
997 }
998}
999
1000/*
1001 * rpm eq magic:
1002 *
1003 * some dependencies are of the from "foo = md5sum", like the
1004 * buildid provides. There's not much we can do to speed up
1005 * getting the providers, because rpm's complex evr comparison
1006 * rules get in the way. But we can use the first character(s)
1007 * of the md5sum to do a simple pre-check.
1008 */
1009static inline int
1010rpmeqmagic(Pool *pool, Id evr)
1011{
1012 const char *s = pool_id2str(pool, evr);
1013 if (*s == '0')
1014 {
1015 while (*s == '0' && s[1] >= '0' && s[1] <= '9')
1016 s++;
1017 /* ignore epoch 0 */
1018 if (*s == '0' && s[1] == ':')
1019 {
1020 s += 2;
1021 while (*s == '0' && s[1] >= '0' && s[1] <= '9')
1022 s++;
1023 }
1024 }
1025 if (*s >= '0' && *s <= '9')
1026 {
1027 if (s[1] >= '0' && s[1] <= '9')
1028 return *s + (s[1] << 8);
1029 return *s;
1030 }
1031 if ((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z'))
1032 {
1033 if ((s[1] >= 'a' && s[1] <= 'z') || (s[1] >= 'A' && s[1] <= 'Z'))
1034 return *s + (s[1] << 8);
1035 return *s;
1036 }
1037 return -1;
1038}
1039
1040static inline int
1041rpmeqmagic_init(Pool *pool, int flags, Id evr)
1042{
1043 if (flags != REL_EQ2 || pool->disttype != DISTTYPE_RPM0 || pool->promoteepoch || ISRELDEP(evr)(((evr) & 0x80000000) != 0))
1044 return -1;
1045 else
1046 return rpmeqmagic(pool, evr);
1047}
1048
1049static inline int
1050rpmeqmagic_cantmatch(Pool *pool, int flags, Id evr, int eqmagic)
1051{
1052 int peqmagic = rpmeqmagic(pool, evr);
1053 if (peqmagic > 0 && peqmagic != eqmagic)
1054 return 1;
1055 return 0;
1056}
1057
1058/*
1059 * addrelproviders
1060 *
1061 * add packages fulfilling the relation to whatprovides array
1062 *
1063 * some words about REL_AND and REL_IF: we assume the best case
1064 * here, so that you get a "potential" result if you ask for a match.
1065 * E.g. if you ask for "whatrequires A" and package X contains
1066 * "Requires: A & B", you'll get "X" as an answer.
1067 */
1068Id
1069pool_addrelproviders(Pool *pool, Id d)
1070{
1071 Reldep *rd;
1072 Reldep *prd;
1073 Queue plist;
1074 Id buf[16];
1075 Id name, evr, flags;
1076 Id pid, *pidp;
1077 Id p, *pp;
1078
1079 if (!ISRELDEP(d)(((d) & 0x80000000) != 0))
1080 return pool_addstdproviders(pool, d);
1081 rd = GETRELDEP(pool, d)((pool)->rels + ((d) ^ 0x80000000));
1082 name = rd->name;
1083 evr = rd->evr;
1084 flags = rd->flags;
1085 d = GETRELID(d)((d) ^ 0x80000000);
1086 queue_init_buffer(&plist, buf, sizeof(buf)/sizeof(*buf));
1087
1088 if (flags >= 8)
1089 {
1090 /* special relation */
1091 Id wp = 0;
1092 Id *pp2, *pp3;
1093
1094 switch (flags)
1095 {
1096 case REL_WITH18:
1097 wp = pool_whatprovides(pool, name);
1098 pp2 = pool_whatprovides_ptr(pool, evr);
1099 pp = pool->whatprovidesdata + wp;
1100 while ((p = *pp++) != 0)
1101 {
1102 for (pp3 = pp2; *pp3; pp3++)
1103 if (*pp3 == p)
1104 break;
1105 if (*pp3)
1106 queue_push(&plist, p); /* found it */
1107 else
1108 wp = 0;
1109 }
1110 break;
1111
1112 case REL_AND16:
1113 case REL_OR17:
1114 case REL_COND22:
1115 if (flags == REL_COND22)
1116 {
1117 if (ISRELDEP(evr)(((evr) & 0x80000000) != 0))
1118 {
1119 Reldep *rd2 = GETRELDEP(pool, evr)((pool)->rels + ((evr) ^ 0x80000000));
1120 evr = rd2->flags == REL_ELSE26 ? rd2->evr : 0;
1121 }
1122 else
1123 evr = 0; /* assume cond is true */
1124 }
1125 wp = pool_whatprovides(pool, name);
1126 if (!pool->whatprovidesdata[wp])
1127 wp = evr ? pool_whatprovides(pool, evr) : 1;
1128 else if (evr)
1129 {
1130 /* sorted merge */
1131 pp2 = pool_whatprovides_ptr(pool, evr);
1132 pp = pool->whatprovidesdata + wp;
1133 while (*pp && *pp2)
1134 {
1135 if (*pp < *pp2)
1136 queue_push(&plist, *pp++);
1137 else
1138 {
1139 if (*pp == *pp2)
1140 pp++;
1141 queue_push(&plist, *pp2++);
1142 }
1143 }
1144 while (*pp)
1145 queue_push(&plist, *pp++);
1146 while (*pp2)
1147 queue_push(&plist, *pp2++);
1148 /* if the number of elements did not change, we can reuse wp */
1149 if (pp - (pool->whatprovidesdata + wp) != plist.count)
1150 wp = 0;
1151 }
1152 break;
1153
1154 case REL_NAMESPACE19:
1155 if (name == NAMESPACE_OTHERPROVIDERS)
1156 {
1157 wp = pool_whatprovides(pool, evr);
1158 break;
1159 }
1160 if (pool->nscallback)
1161 {
1162 /* ask callback which packages provide the dependency
1163 * 0: none
1164 * 1: the system (aka SYSTEMSOLVABLE)
1165 * >1: set of packages, stored as offset on whatprovidesdata
1166 */
1167 p = pool->nscallback(pool, pool->nscallbackdata, name, evr);
1168 if (p > 1)
1169 wp = p;
1170 if (p == 1)
1171 queue_push(&plist, SYSTEMSOLVABLE1);
1172 }
1173 break;
1174 case REL_ARCH20:
1175 /* small hack: make it possible to match <pkg>.src
1176 * we have to iterate over the solvables as src packages do not
1177 * provide anything, thus they are not indexed in our
1178 * whatprovides hash */
1179 if (evr == ARCH_SRC || evr == ARCH_NOSRC)
1180 {
1181 Solvable *s;
1182 for (p = 1, s = pool->solvables + p; p < pool->nsolvables; p++, s++)
1183 {
1184 if (!s->repo)
1185 continue;
1186 if (s->arch != evr && s->arch != ARCH_NOSRC)
1187 continue;
1188 if (pool_disabled_solvable(pool, s))
1189 continue;
1190 if (!name || pool_match_nevr(pool, s, name))
1191 queue_push(&plist, p);
1192 }
1193 break;
1194 }
1195 if (!name)
1196 {
1197 FOR_POOL_SOLVABLES(p)for (p = 2; p < pool->nsolvables; p++) if (pool->solvables
[p].repo == 0) continue; else
1198 {
1199 Solvable *s = pool->solvables + p;
1200 if (s->repo != pool->installed && !pool_installable(pool, s))
1201 continue;
1202 if (s->arch == evr)
1203 queue_push(&plist, p);
1204 }
1205 break;
1206 }
1207 wp = pool_whatprovides(pool, name);
1208 pp = pool->whatprovidesdata + wp;
1209 while ((p = *pp++) != 0)
1210 {
1211 Solvable *s = pool->solvables + p;
1212 if (s->arch == evr)
1213 queue_push(&plist, p);
1214 else
1215 wp = 0;
1216 }
1217 break;
1218 case REL_MULTIARCH25:
1219 if (evr != ARCH_ANY)
1220 break;
1221 /* XXX : need to check for Multi-Arch: allowed! */
1222 wp = pool_whatprovides(pool, name);
1223 break;
1224 case REL_KIND24:
1225 /* package kind filtering */
1226 if (!name)
1227 {
1228 FOR_POOL_SOLVABLES(p)for (p = 2; p < pool->nsolvables; p++) if (pool->solvables
[p].repo == 0) continue; else
1229 {
1230 Solvable *s = pool->solvables + p;
1231 if (s->repo != pool->installed && !pool_installable(pool, s))
1232 continue;
1233 if (pool_is_kind(pool, s->name, evr))
1234 queue_push(&plist, p);
1235 }
1236 break;
1237 }
1238 wp = pool_whatprovides(pool, name);
1239 pp = pool->whatprovidesdata + wp;
1240 while ((p = *pp++) != 0)
1241 {
1242 Solvable *s = pool->solvables + p;
1243 if (pool_is_kind(pool, s->name, evr))
1244 queue_push(&plist, p);
1245 else
1246 wp = 0;
1247 }
1248 break;
1249 case REL_FILECONFLICT21:
1250 pp = pool_whatprovides_ptr(pool, name);
1251 while ((p = *pp++) != 0)
1252 {
1253 Id origd = MAKERELDEP(d)((d) | 0x80000000);
1254 Solvable *s = pool->solvables + p;
1255 if (!s->provides)
1256 continue;
1257 pidp = s->repo->idarraydata + s->provides;
1258 while ((pid = *pidp++) != 0)
1259 if (pid == origd)
1260 break;
1261 if (pid)
1262 queue_push(&plist, p);
1263 }
1264 break;
1265 default:
1266 break;
1267 }
1268 if (wp)
1269 {
1270 /* we can reuse an existing entry */
1271 queue_free(&plist);
1272 pool->whatprovides_rel[d] = wp;
1273 return wp;
1274 }
1275 }
1276 else if (flags)
1277 {
1278 Id *ppaux = 0;
1279 int eqmagic = 0;
1280 /* simple version comparison relation */
1281#if 0
1282 POOL_DEBUG(SOLV_DEBUG_STATS, "addrelproviders: what provides %s?\n", pool_dep2str(pool, name))do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "addrelproviders: what provides %s?\n"
, pool_dep2str(pool, name));} while (0)
;
1283#endif
1284 pp = pool_whatprovides_ptr(pool, name);
1285 if (!ISRELDEP(name)(((name) & 0x80000000) != 0) && name < pool->whatprovidesauxoff)
1286 ppaux = pool->whatprovidesaux[name] ? pool->whatprovidesauxdata + pool->whatprovidesaux[name] : 0;
1287 while (ISRELDEP(name)(((name) & 0x80000000) != 0))
1288 {
1289 rd = GETRELDEP(pool, name)((pool)->rels + ((name) ^ 0x80000000));
1290 name = rd->name;
1291 }
1292 while ((p = *pp++) != 0)
1293 {
1294 Solvable *s = pool->solvables + p;
1295 if (ppaux)
1296 {
1297 pid = *ppaux++;
1298 if (pid && pid != 1)
1299 {
1300#if 0
1301 POOL_DEBUG(SOLV_DEBUG_STATS, "addrelproviders: aux hit %d %s\n", p, pool_dep2str(pool, pid))do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "addrelproviders: aux hit %d %s\n", p,
pool_dep2str(pool, pid));} while (0)
;
1302#endif
1303 if (!ISRELDEP(pid)(((pid) & 0x80000000) != 0))
1304 {
1305 if (pid != name)
1306 continue; /* wrong provides name */
1307 if (pool->disttype == DISTTYPE_DEB1)
1308 continue; /* unversioned provides can never match versioned deps */
1309 }
1310 else
1311 {
1312 prd = GETRELDEP(pool, pid)((pool)->rels + ((pid) ^ 0x80000000));
1313 if (prd->name != name)
1314 continue; /* wrong provides name */
1315 if (!eqmagic)
1316 eqmagic = rpmeqmagic_init(pool, flags, evr);
1317 if (eqmagic > 0 && prd->flags == REL_EQ2 && !ISRELDEP(prd->evr)(((prd->evr) & 0x80000000) != 0) &&
1318 rpmeqmagic_cantmatch(pool, prd->flags, prd->evr, eqmagic))
1319 continue;
1320 /* right package, both deps are rels. check flags/evr */
1321 if (!pool_match_flags_evr(pool, prd->flags, prd->evr, flags, evr))
1322 continue;
1323 }
1324 queue_push(&plist, p);
1325 continue;
1326 }
1327 }
1328 if (!s->provides)
1329 {
1330 /* no provides - check nevr */
1331 if (pool_match_nevr_rel(pool, s, MAKERELDEP(d)((d) | 0x80000000)))
1332 queue_push(&plist, p);
1333 continue;
1334 }
1335 /* solvable p provides name in some rels */
1336 if (!eqmagic)
1337 eqmagic = rpmeqmagic_init(pool, flags, evr);
1338 pidp = s->repo->idarraydata + s->provides;
1339 while ((pid = *pidp++) != 0)
1340 {
1341 if (!ISRELDEP(pid)(((pid) & 0x80000000) != 0))
1342 {
1343 if (pid != name)
1344 continue; /* wrong provides name */
1345 if (pool->disttype == DISTTYPE_DEB1)
1346 continue; /* unversioned provides can never match versioned deps */
1347 break;
1348 }
1349 prd = GETRELDEP(pool, pid)((pool)->rels + ((pid) ^ 0x80000000));
1350 if (prd->name != name)
1351 continue; /* wrong provides name */
1352 /* right package, both deps are rels. check flags/evr */
1353 if (eqmagic > 0 && prd->flags == REL_EQ2 && !ISRELDEP(prd->evr)(((prd->evr) & 0x80000000) != 0) &&
1354 rpmeqmagic_cantmatch(pool, prd->flags, prd->evr, eqmagic))
1355 continue;
1356 if (pool_match_flags_evr(pool, prd->flags, prd->evr, flags, evr))
1357 break; /* matches */
1358 }
1359 if (!pid)
1360 continue; /* none of the providers matched */
1361 queue_push(&plist, p);
1362 }
1363 /* make our system solvable provide all unknown rpmlib() stuff */
1364 if (plist.count == 0 && !strncmp(pool_id2str(pool, name), "rpmlib(", 7))
1365 queue_push(&plist, SYSTEMSOLVABLE1);
1366 }
1367 /* add providers to whatprovides */
1368#if 0
1369 POOL_DEBUG(SOLV_DEBUG_STATS, "addrelproviders: adding %d packages to %d\n", plist.count, d)do {if ((pool->debugmask & ((1<<3))) != 0) pool_debug
(pool, ((1<<3)), "addrelproviders: adding %d packages to %d\n"
, plist.count, d);} while (0)
;
1370#endif
1371 pool->whatprovides_rel[d] = pool_queuetowhatprovides(pool, &plist);
1372 queue_free(&plist);
1373
1374 return pool->whatprovides_rel[d];
1375}
1376
1377void
1378pool_flush_namespaceproviders(Pool *pool, Id ns, Id evr)
1379{
1380 int nrels = pool->nrels;
1381 Id d;
1382 Reldep *rd;
1383
1384 if (!pool->whatprovides_rel)
1385 return;
1386 for (d = 1, rd = pool->rels + d; d < nrels; d++, rd++)
1387 {
1388 if (rd->flags != REL_NAMESPACE19 || rd->name == NAMESPACE_OTHERPROVIDERS)
1389 continue;
1390 if (ns && rd->name != ns)
1391 continue;
1392 if (evr && rd->evr != evr)
1393 continue;
1394 pool->whatprovides_rel[d] = 0;
1395 }
1396}
1397
1398/* intersect dependencies in keyname with dep, return list of matching packages */
1399void
1400pool_whatmatchesdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker)
1401{
1402 Id p;
1403 Queue qq;
1404 int i;
1405
1406 queue_empty(q);
1407 if (keyname == SOLVABLE_NAME)
1408 {
1409 Id pp;
1410 FOR_PROVIDES(p, pp, dep)for (pp = pool_whatprovides(pool, dep) ; (p = pool->whatprovidesdata
[pp++]) != 0; )
1411 if (pool_match_dep(pool, p, dep))
1412 queue_push(q, p);
1413 return;
1414 }
1415 queue_init(&qq);
1416 FOR_POOL_SOLVABLES(p)for (p = 2; p < pool->nsolvables; p++) if (pool->solvables
[p].repo == 0) continue; else
1417 {
1418 Solvable *s = pool->solvables + p;
1419 if (s->repo->disabled)
1420 continue;
1421 if (s->repo != pool->installed && !pool_installable(pool, s))
1422 continue;
1423 if (qq.count)
1424 queue_empty(&qq);
1425 solvable_lookup_deparray(s, keyname, &qq, marker);
1426 for (i = 0; i < qq.count; i++)
1427 if (pool_match_dep(pool, qq.elements[i], dep))
1428 {
1429 queue_push(q, p);
1430 break;
1431 }
1432 }
1433 queue_free(&qq);
1434}
1435
1436/* check if keyname contains dep, return list of matching packages */
1437void
1438pool_whatcontainsdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker)
1439{
1440 Id p;
1441 Queue qq;
1442 int i;
1443
1444 queue_empty(q);
1445 if (!dep)
1446 return;
1447 queue_init(&qq);
1448 FOR_POOL_SOLVABLES(p)for (p = 2; p < pool->nsolvables; p++) if (pool->solvables
[p].repo == 0) continue; else
1449 {
1450 Solvable *s = pool->solvables + p;
1451 if (s->repo->disabled)
1452 continue;
1453 if (s->repo != pool->installed && !pool_installable(pool, s))
1454 continue;
1455 if (qq.count)
1456 queue_empty(&qq);
1457 solvable_lookup_deparray(s, keyname, &qq, marker);
1458 for (i = 0; i < qq.count; i++)
1459 if (qq.elements[i] == dep)
1460 {
1461 queue_push(q, p);
1462 break;
1463 }
1464 }
1465 queue_free(&qq);
1466}
1467
1468/*************************************************************************/
1469
1470void
1471pool_debug(Pool *pool, int type, const char *format, ...)
1472{
1473 va_list args;
1474 char buf[1024];
1475
1476 if ((type & (SOLV_FATAL(1<<0)|SOLV_ERROR(1<<1))) == 0)
1477 {
1478 if ((pool->debugmask & type) == 0)
1479 return;
1480 }
1481 va_start(args, format)__builtin_va_start(args, format);
1482 if (!pool->debugcallback)
1483 {
1484 if ((type & (SOLV_FATAL(1<<0)|SOLV_ERROR(1<<1))) == 0 && !(pool->debugmask & SOLV_DEBUG_TO_STDERR(1<<30)))
1485 vprintf(format, args);
1486 else
1487 vfprintf(stderrstderr, format, args);
1488 return;
1489 }
1490 vsnprintf(buf, sizeof(buf), format, args);
1491 va_end(args)__builtin_va_end(args);
1492 pool->debugcallback(pool, pool->debugcallbackdata, type, buf);
1493}
1494
1495int
1496pool_error(Pool *pool, int ret, const char *format, ...)
1497{
1498 va_list args;
1499 int l;
1500 va_start(args, format)__builtin_va_start(args, format);
1501 if (!pool->errstr)
1502 {
1503 pool->errstra = 1024;
1504 pool->errstr = solv_malloc(pool->errstra);
1505 }
1506 if (!*format)
1507 {
1508 *pool->errstr = 0;
1509 l = 0;
1510 }
1511 else
1512 l = vsnprintf(pool->errstr, pool->errstra, format, args);
1513 va_end(args)__builtin_va_end(args);
1514 if (l >= 0 && l + 1 > pool->errstra)
1515 {
1516 pool->errstra = l + 256;
1517 pool->errstr = solv_realloc(pool->errstr, pool->errstra);
1518 va_start(args, format)__builtin_va_start(args, format);
1519 l = vsnprintf(pool->errstr, pool->errstra, format, args);
1520 va_end(args)__builtin_va_end(args);
1521 }
1522 if (l < 0)
1523 strcpy(pool->errstr, "unknown error");
1524 if (pool->debugmask & SOLV_ERROR(1<<1))
1525 pool_debug(pool, SOLV_ERROR(1<<1), "%s\n", pool->errstr);
1526 return ret;
1527}
1528
1529char *
1530pool_errstr(Pool *pool)
1531{
1532 return pool->errstr ? pool->errstr : "no error";
1533}
1534
1535void
1536pool_setdebuglevel(Pool *pool, int level)
1537{
1538 int mask = SOLV_DEBUG_RESULT(1<<10);
1539 if (level > 0)
1540 mask |= SOLV_DEBUG_STATS(1<<3)|SOLV_DEBUG_ANALYZE(1<<6)|SOLV_DEBUG_UNSOLVABLE(1<<7)|SOLV_DEBUG_SOLVER(1<<12)|SOLV_DEBUG_TRANSACTION(1<<13)|SOLV_ERROR(1<<1);
1541 if (level > 1)
1542 mask |= SOLV_DEBUG_JOB(1<<11)|SOLV_DEBUG_SOLUTIONS(1<<8)|SOLV_DEBUG_POLICY(1<<9);
1543 if (level > 2)
1544 mask |= SOLV_DEBUG_PROPAGATE(1<<5);
1545 if (level > 3)
1546 mask |= SOLV_DEBUG_RULE_CREATION(1<<4);
1547 mask |= pool->debugmask & SOLV_DEBUG_TO_STDERR(1<<30); /* keep bit */
1548 pool->debugmask = mask;
1549}
1550
1551void pool_setdebugcallback(Pool *pool, void (*debugcallback)(struct _Pool *, void *data, int type, const char *str), void *debugcallbackdata)
1552{
1553 pool->debugcallback = debugcallback;
1554 pool->debugcallbackdata = debugcallbackdata;
1555}
1556
1557void pool_setdebugmask(Pool *pool, int mask)
1558{
1559 pool->debugmask = mask;
1560}
1561
1562void pool_setloadcallback(Pool *pool, int (*cb)(struct _Pool *, struct _Repodata *, void *), void *loadcbdata)
1563{
1564 pool->loadcallback = cb;
1565 pool->loadcallbackdata = loadcbdata;
1566}
1567
1568void pool_setnamespacecallback(Pool *pool, Id (*cb)(struct _Pool *, void *, Id, Id), void *nscbdata)
1569{
1570 pool->nscallback = cb;
1571 pool->nscallbackdata = nscbdata;
1572}
1573
1574void
1575pool_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)
1576{
1577 if (p)
1578 {
1579 if (pool->solvables[p].repo)
1580 repo_search(pool->solvables[p].repo, p, key, match, flags, callback, cbdata);
1581 return;
1582 }
1583 /* FIXME: obey callback return value! */
1584 for (p = 1; p < pool->nsolvables; p++)
1585 if (pool->solvables[p].repo)
1586 repo_search(pool->solvables[p].repo, p, key, match, flags, callback, cbdata);
1587}
1588
1589void
1590pool_clear_pos(Pool *pool)
1591{
1592 memset(&pool->pos, 0, sizeof(pool->pos));
1593}
1594
1595void
1596pool_set_languages(Pool *pool, const char **languages, int nlanguages)
1597{
1598 int i;
1599
1600 pool->languagecache = solv_free(pool->languagecache);
1601 pool->languagecacheother = 0;
1602 for (i = 0; i < pool->nlanguages; i++)
1603 free((char *)pool->languages[i]);
1604 pool->languages = solv_free((void *)pool->languages);
1605 pool->nlanguages = nlanguages;
1606 if (!nlanguages)
1607 return;
1608 pool->languages = solv_calloc(nlanguages, sizeof(const char **));
1609 for (i = 0; i < pool->nlanguages; i++)
1610 pool->languages[i] = solv_strdup(languages[i]);
1611}
1612
1613Id
1614pool_id2langid(Pool *pool, Id id, const char *lang, int create)
1615{
1616 const char *n;
1617 char buf[256], *p;
1618 int l;
1619
1620 if (!lang || !*lang)
1621 return id;
1622 n = pool_id2str(pool, id);
1623 l = strlen(n) + strlen(lang) + 2;
1624 if (l > sizeof(buf))
1625 p = solv_malloc(strlen(n) + strlen(lang) + 2);
1626 else
1627 p = buf;
1628 sprintf(p, "%s:%s", n, lang);
1629 id = pool_str2id(pool, p, create);
1630 if (p != buf)
1631 free(p);
1632 return id;
1633}
1634
1635char *
1636pool_alloctmpspace(Pool *pool, int len)
1637{
1638 int n = pool->tmpspace.n;
1639 if (!len)
1640 return 0;
1641 if (len > pool->tmpspace.len[n])
1642 {
1643 pool->tmpspace.buf[n] = solv_realloc(pool->tmpspace.buf[n], len + 32);
1644 pool->tmpspace.len[n] = len + 32;
1645 }
1646 pool->tmpspace.n = (n + 1) % POOL_TMPSPACEBUF16;
1647 return pool->tmpspace.buf[n];
1648}
1649
1650static char *
1651pool_alloctmpspace_free(Pool *pool, const char *space, int len)
1652{
1653 if (space)
1654 {
1655 int n, oldn;
1656 n = oldn = pool->tmpspace.n;
1657 for (;;)
1658 {
1659 if (!n--)
1660 n = POOL_TMPSPACEBUF16 - 1;
1661 if (n == oldn)
1662 break;
1663 if (pool->tmpspace.buf[n] != space)
1664 continue;
1665 if (len > pool->tmpspace.len[n])
1666 {
1667 pool->tmpspace.buf[n] = solv_realloc(pool->tmpspace.buf[n], len + 32);
1668 pool->tmpspace.len[n] = len + 32;
1669 }
1670 return pool->tmpspace.buf[n];
1671 }
1672 }
1673 return 0;
1674}
1675
1676void
1677pool_freetmpspace(Pool *pool, const char *space)
1678{
1679 int n = pool->tmpspace.n;
1680 if (!space)
1681 return;
1682 n = (n + (POOL_TMPSPACEBUF16 - 1)) % POOL_TMPSPACEBUF16;
1683 if (pool->tmpspace.buf[n] == space)
1684 pool->tmpspace.n = n;
1685}
1686
1687char *
1688pool_tmpjoin(Pool *pool, const char *str1, const char *str2, const char *str3)
1689{
1690 int l1, l2, l3;
1691 char *s, *str;
1692 l1 = str1 ? strlen(str1) : 0;
8
'?' condition is true
1693 l2 = str2 ? strlen(str2) : 0;
9
'?' condition is true
1694 l3 = str3 ? strlen(str3) : 0;
10
'?' condition is true
1695 s = str = pool_alloctmpspace(pool, l1 + l2 + l3 + 1);
11
Null pointer value stored to 's'
1696 if (l1)
12
Assuming 'l1' is 0
13
Taking false branch
1697 {
1698 strcpy(s, str1);
1699 s += l1;
1700 }
1701 if (l2)
14
Taking true branch
1702 {
1703 strcpy(s, str2);
15
Null pointer passed as an argument to a 'nonnull' parameter
1704 s += l2;
1705 }
1706 if (l3)
1707 {
1708 strcpy(s, str3);
1709 s += l3;
1710 }
1711 *s = 0;
1712 return str;
1713}
1714
1715char *
1716pool_tmpappend(Pool *pool, const char *str1, const char *str2, const char *str3)
1717{
1718 int l1, l2, l3;
1719 char *s, *str;
1720
1721 l1 = str1 ? strlen(str1) : 0;
1722 l2 = str2 ? strlen(str2) : 0;
1723 l3 = str3 ? strlen(str3) : 0;
1724 str = pool_alloctmpspace_free(pool, str1, l1 + l2 + l3 + 1);
1725 if (str)
1726 str1 = str;
1727 else
1728 str = pool_alloctmpspace(pool, l1 + l2 + l3 + 1);
1729 s = str;
1730 if (l1)
1731 {
1732 if (s != str1)
1733 strcpy(s, str1);
1734 s += l1;
1735 }
1736 if (l2)
1737 {
1738 strcpy(s, str2);
1739 s += l2;
1740 }
1741 if (l3)
1742 {
1743 strcpy(s, str3);
1744 s += l3;
1745 }
1746 *s = 0;
1747 return str;
1748}
1749
1750const char *
1751pool_bin2hex(Pool *pool, const unsigned char *buf, int len)
1752{
1753 char *s;
1754 if (!len)
1755 return "";
1756 s = pool_alloctmpspace(pool, 2 * len + 1);
1757 solv_bin2hex(buf, len, s);
1758 return s;
1759}
1760
1761const char *
1762pool_lookup_str(Pool *pool, Id entry, Id keyname)
1763{
1764 if (entry == SOLVID_POS-2 && pool->pos.repo)
1765 return repo_lookup_str(pool->pos.repo, pool->pos.repodataid ? entry : pool->pos.solvid, keyname);
1766 if (entry <= 0)
1767 return 0;
1768 return solvable_lookup_str(pool->solvables + entry, keyname);
1769}
1770
1771Id
1772pool_lookup_id(Pool *pool, Id entry, Id keyname)
1773{
1774 if (entry == SOLVID_POS-2 && pool->pos.repo)
1775 return repo_lookup_id(pool->pos.repo, pool->pos.repodataid ? entry : pool->pos.solvid, keyname);
1776 if (entry <= 0)
1777 return 0;
1778 return solvable_lookup_id(pool->solvables + entry, keyname);
1779}
1780
1781unsigned long long
1782pool_lookup_num(Pool *pool, Id entry, Id keyname, unsigned long long notfound)
1783{
1784 if (entry == SOLVID_POS-2 && pool->pos.repo)
1785 return repo_lookup_num(pool->pos.repo, pool->pos.repodataid ? entry : pool->pos.solvid, keyname, notfound);
1786 if (entry <= 0)
1787 return notfound;
1788 return solvable_lookup_num(pool->solvables + entry, keyname, notfound);
1789}
1790
1791int
1792pool_lookup_void(Pool *pool, Id entry, Id keyname)
1793{
1794 if (entry == SOLVID_POS-2 && pool->pos.repo)
1795 return repo_lookup_void(pool->pos.repo, pool->pos.repodataid ? entry : pool->pos.solvid, keyname);
1796 if (entry <= 0)
1797 return 0;
1798 return solvable_lookup_void(pool->solvables + entry, keyname);
1799}
1800
1801const unsigned char *
1802pool_lookup_bin_checksum(Pool *pool, Id entry, Id keyname, Id *typep)
1803{
1804 if (entry == SOLVID_POS-2 && pool->pos.repo)
1805 return repo_lookup_bin_checksum(pool->pos.repo, pool->pos.repodataid ? entry : pool->pos.solvid, keyname, typep);
1806 if (entry <= 0)
1807 return 0;
1808 return solvable_lookup_bin_checksum(pool->solvables + entry, keyname, typep);
1809}
1810
1811const char *
1812pool_lookup_checksum(Pool *pool, Id entry, Id keyname, Id *typep)
1813{
1814 if (entry == SOLVID_POS-2 && pool->pos.repo)
1815 return repo_lookup_checksum(pool->pos.repo, pool->pos.repodataid ? entry : pool->pos.solvid, keyname, typep);
1816 if (entry <= 0)
1817 return 0;
1818 return solvable_lookup_checksum(pool->solvables + entry, keyname, typep);
1819}
1820
1821int
1822pool_lookup_idarray(Pool *pool, Id entry, Id keyname, Queue *q)
1823{
1824 if (entry == SOLVID_POS-2 && pool->pos.repo)
1825 return repo_lookup_idarray(pool->pos.repo, pool->pos.repodataid ? entry : pool->pos.solvid, keyname, q);
1826 if (entry <= 0)
1827 return 0;
1828 return solvable_lookup_idarray(pool->solvables + entry, keyname, q);
1829}
1830
1831const char *
1832pool_lookup_deltalocation(Pool *pool, Id entry, unsigned int *medianrp)
1833{
1834 const char *loc;
1835 if (medianrp)
1836 *medianrp = 0;
1837 if (entry != SOLVID_POS-2)
1838 return 0;
1839 loc = pool_lookup_str(pool, entry, DELTA_LOCATION_DIR);
1840 loc = pool_tmpjoin(pool, loc, loc ? "/" : 0, pool_lookup_str(pool, entry, DELTA_LOCATION_NAME));
1841 loc = pool_tmpappend(pool, loc, "-", pool_lookup_str(pool, entry, DELTA_LOCATION_EVR));
1842 loc = pool_tmpappend(pool, loc, ".", pool_lookup_str(pool, entry, DELTA_LOCATION_SUFFIX));
1843 return loc;
1844}
1845
1846static void
1847add_new_provider(Pool *pool, Id id, Id p)
1848{
1849 Queue q;
1850 Id *pp;
1851
1852 while (ISRELDEP(id)(((id) & 0x80000000) != 0))
1853 {
1854 Reldep *rd = GETRELDEP(pool, id)((pool)->rels + ((id) ^ 0x80000000));
1855 id = rd->name;
1856 }
1857
1858 queue_init(&q);
1859 for (pp = pool->whatprovidesdata + pool->whatprovides[id]; *pp; pp++)
1860 {
1861 if (*pp == p)
1862 {
1863 queue_free(&q);
1864 return;
1865 }
1866 if (*pp > p)
1867 {
1868 queue_push(&q, p);
1869 p = 0;
1870 }
1871 queue_push(&q, *pp);
1872 }
1873 if (p)
1874 queue_push(&q, p);
1875 pool->whatprovides[id] = pool_queuetowhatprovides(pool, &q);
1876 if (id < pool->whatprovidesauxoff)
1877 pool->whatprovidesaux[id] = 0; /* sorry */
1878 queue_free(&q);
1879}
1880
1881void
1882pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts)
1883{
1884 int hadhashes = pool->relhashtbl ? 1 : 0;
1885 Solvable *s;
1886 Id fn, p, q, md5;
1887 Id id;
1888 int i;
1889
1890 if (!conflicts->count)
1891 return;
1892 for (i = 0; i < conflicts->count; i += 6)
1893 {
1894 fn = conflicts->elements[i];
1895 p = conflicts->elements[i + 1];
1896 md5 = conflicts->elements[i + 2];
1897 q = conflicts->elements[i + 4];
1898 id = pool_rel2id(pool, fn, md5, REL_FILECONFLICT21, 1);
1899 s = pool->solvables + p;
1900 if (!s->repo)
1901 continue;
1902 s->provides = repo_addid_dep(s->repo, s->provides, id, SOLVABLE_FILEMARKER);
1903 if (pool->whatprovides)
1904 add_new_provider(pool, fn, p);
1905 if (pool->whatprovides_rel)
1906 pool->whatprovides_rel[GETRELID(id)((id) ^ 0x80000000)] = 0; /* clear cache */
1907 s = pool->solvables + q;
1908 if (!s->repo)
1909 continue;
1910 s->conflicts = repo_addid_dep(s->repo, s->conflicts, id, 0);
1911 }
1912 if (!hadhashes)
1913 pool_freeidhashes(pool);
1914}
1915
1916char *
1917pool_prepend_rootdir(Pool *pool, const char *path)
1918{
1919 if (!path)
1920 return 0;
1921 if (!pool->rootdir)
1922 return solv_strdup(path);
1923 return solv_dupjoin(pool->rootdir, "/", *path == '/' ? path + 1 : path);
1924}
1925
1926const char *
1927pool_prepend_rootdir_tmp(Pool *pool, const char *path)
1928{
1929 if (!path)
1
Assuming 'path' is non-null
2
Taking false branch
1930 return 0;
1931 if (!pool->rootdir)
3
Assuming the condition is false
4
Taking false branch
1932 return path;
1933 return pool_tmpjoin(pool, pool->rootdir, "/", *path == '/' ? path + 1 : path);
5
Assuming the condition is false
6
'?' condition is false
7
Calling 'pool_tmpjoin'
1934}
1935
1936void
1937pool_set_rootdir(Pool *pool, const char *rootdir)
1938{
1939 solv_free(pool->rootdir);
1940 pool->rootdir = solv_strdup(rootdir);
1941}
1942
1943const char *
1944pool_get_rootdir(Pool *pool)
1945{
1946 return pool->rootdir;
1947}
1948
1949/* only used in libzypp */
1950void
1951pool_set_custom_vendorcheck(Pool *pool, int (*vendorcheck)(Pool *, Solvable *, Solvable *))
1952{
1953 pool->custom_vendorcheck = vendorcheck;
1954}
1955
1956/* EOF */