1 /*
2 * Copyright (c) 2008, Novell Inc.
3 *
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
6 */
7
8 /*
9 * solvable.c
10 *
11 * set/retrieve data from solvables
12 */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <stdarg.h>
17 #include <unistd.h>
18 #include <string.h>
19
20 #include "pool.h"
21 #include "repo.h"
22 #include "util.h"
23 #include "policy.h"
24 #include "poolvendor.h"
25 #include "chksum.h"
26 #include "linkedpkg.h"
27
28 const char *
pool_solvable2str(Pool * pool,Solvable * s)29 pool_solvable2str(Pool *pool, Solvable *s)
30 {
31 const char *n, *e, *a;
32 int nl, el, al;
33 char *p;
34 n = pool_id2str(pool, s->name);
35 e = s->evr ? pool_id2str(pool, s->evr) : "";
36 /* XXX: may want to skip the epoch here */
37 a = s->arch ? pool_id2str(pool, s->arch) : "";
38 nl = strlen(n);
39 el = strlen(e);
40 al = strlen(a);
41 if (pool->havedistepoch)
42 {
43 /* strip the distepoch from the evr */
44 const char *de = strrchr(e, '-');
45 if (de && (de = strchr(de, ':')) != 0)
46 el = de - e;
47 }
48 p = pool_alloctmpspace(pool, nl + el + al + 3);
49 strcpy(p, n);
50 if (el)
51 {
52 p[nl++] = '-';
53 strncpy(p + nl, e, el);
54 p[nl + el] = 0;
55 }
56 if (al)
57 {
58 p[nl + el] = pool->disttype == DISTTYPE_HAIKU ? '-' : '.';
59 strcpy(p + nl + el + 1, a);
60 }
61 if (pool->disttype == DISTTYPE_CONDA && solvable_lookup_type(s, SOLVABLE_BUILDFLAVOR))
62 {
63 Queue flavorq;
64 int i;
65 queue_init(&flavorq);
66 solvable_lookup_idarray(s, SOLVABLE_BUILDFLAVOR, &flavorq);
67 for (i = 0; i < flavorq.count; i++)
68 p = pool_tmpappend(pool, p, "-", pool_id2str(pool, flavorq.elements[i]));
69 queue_free(&flavorq);
70 }
71 return p;
72 }
73
74 Id
solvable_lookup_type(Solvable * s,Id keyname)75 solvable_lookup_type(Solvable *s, Id keyname)
76 {
77 if (!s->repo)
78 return 0;
79 return repo_lookup_type(s->repo, s - s->repo->pool->solvables, keyname);
80 }
81
82 Id
solvable_lookup_id(Solvable * s,Id keyname)83 solvable_lookup_id(Solvable *s, Id keyname)
84 {
85 if (!s->repo)
86 return 0;
87 return repo_lookup_id(s->repo, s - s->repo->pool->solvables, keyname);
88 }
89
90 int
solvable_lookup_idarray(Solvable * s,Id keyname,Queue * q)91 solvable_lookup_idarray(Solvable *s, Id keyname, Queue *q)
92 {
93 if (!s->repo)
94 {
95 queue_empty(q);
96 return 0;
97 }
98 return repo_lookup_idarray(s->repo, s - s->repo->pool->solvables, keyname, q);
99 }
100
101 int
solvable_lookup_deparray(Solvable * s,Id keyname,Queue * q,Id marker)102 solvable_lookup_deparray(Solvable *s, Id keyname, Queue *q, Id marker)
103 {
104 if (!s->repo)
105 {
106 queue_empty(q);
107 return 0;
108 }
109 return repo_lookup_deparray(s->repo, s - s->repo->pool->solvables, keyname, q, marker);
110 }
111
112 static const char *
solvable_lookup_str_joinarray(Solvable * s,Id keyname,const char * joinstr)113 solvable_lookup_str_joinarray(Solvable *s, Id keyname, const char *joinstr)
114 {
115 Queue q;
116 Id qbuf[10];
117 char *str = 0;
118
119 queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
120 if (solvable_lookup_idarray(s, keyname, &q) && q.count)
121 {
122 Pool *pool = s->repo->pool;
123 if (q.count == 1)
124 str = (char *)pool_id2str(pool, q.elements[0]);
125 else
126 {
127 int i;
128 str = pool_tmpjoin(pool, pool_id2str(pool, q.elements[0]), 0, 0);
129 for (i = 1; i < q.count; i++)
130 str = pool_tmpappend(pool, str, joinstr, pool_id2str(pool, q.elements[i]));
131 }
132 }
133 queue_free(&q);
134 return str;
135 }
136
137 const char *
solvable_lookup_str(Solvable * s,Id keyname)138 solvable_lookup_str(Solvable *s, Id keyname)
139 {
140 const char *str;
141 if (!s->repo)
142 return 0;
143 str = repo_lookup_str(s->repo, s - s->repo->pool->solvables, keyname);
144 if (!str && (keyname == SOLVABLE_LICENSE || keyname == SOLVABLE_GROUP || keyname == SOLVABLE_BUILDFLAVOR))
145 str = solvable_lookup_str_joinarray(s, keyname, ", ");
146 return str;
147 }
148
149 static const char *
solvable_lookup_str_base(Solvable * s,Id keyname,Id basekeyname,int usebase)150 solvable_lookup_str_base(Solvable *s, Id keyname, Id basekeyname, int usebase)
151 {
152 Pool *pool;
153 const char *str, *basestr;
154 Id p, pp, name;
155 Solvable *s2;
156 int pass;
157
158 if (!s->repo)
159 return 0;
160 pool = s->repo->pool;
161 str = solvable_lookup_str(s, keyname);
162 if (str || keyname == basekeyname)
163 return str;
164 basestr = solvable_lookup_str(s, basekeyname);
165 if (!basestr)
166 return 0;
167 /* search for a solvable with same name and same base that has the
168 * translation */
169 if (!pool->whatprovides)
170 return usebase ? basestr : 0;
171 name = s->name;
172 /* we do this in two passes, first same vendor, then all other vendors */
173 for (pass = 0; pass < 2; pass++)
174 {
175 FOR_PROVIDES(p, pp, name)
176 {
177 s2 = pool->solvables + p;
178 if (s2->name != name)
179 continue;
180 if ((s->vendor == s2->vendor) != (pass == 0))
181 continue;
182 str = solvable_lookup_str(s2, basekeyname);
183 if (!str || strcmp(str, basestr))
184 continue;
185 str = solvable_lookup_str(s2, keyname);
186 if (str)
187 return str;
188 }
189 #ifdef ENABLE_LINKED_PKGS
190 /* autopattern/product translation magic */
191 if (pass)
192 {
193 const char *n = pool_id2str(pool, name);
194 if (*n == 'p')
195 {
196 if (!strncmp("pattern:", n, 8) && (name = find_autopattern_name(pool, s)) != 0)
197 pass = -1;
198 if (!strncmp("product:", n, 8) && (name = find_autoproduct_name(pool, s)) != 0)
199 pass = -1;
200 }
201 }
202 #endif
203 }
204 return usebase ? basestr : 0;
205 }
206
207 const char *
solvable_lookup_str_poollang(Solvable * s,Id keyname)208 solvable_lookup_str_poollang(Solvable *s, Id keyname)
209 {
210 Pool *pool;
211 int i, cols;
212 const char *str;
213 Id *row;
214
215 if (!s->repo)
216 return 0;
217 pool = s->repo->pool;
218 if (!pool->nlanguages)
219 return solvable_lookup_str(s, keyname);
220 cols = pool->nlanguages + 1;
221 if (!pool->languagecache)
222 {
223 pool->languagecache = solv_calloc(cols * ID_NUM_INTERNAL, sizeof(Id));
224 pool->languagecacheother = 0;
225 }
226 if (keyname >= ID_NUM_INTERNAL)
227 {
228 row = pool->languagecache + ID_NUM_INTERNAL * cols;
229 for (i = 0; i < pool->languagecacheother; i++, row += cols)
230 if (*row == keyname)
231 break;
232 if (i >= pool->languagecacheother)
233 {
234 pool->languagecache = solv_realloc2(pool->languagecache, pool->languagecacheother + 1, cols * sizeof(Id));
235 row = pool->languagecache + cols * (ID_NUM_INTERNAL + pool->languagecacheother++);
236 *row = keyname;
237 }
238 }
239 else
240 row = pool->languagecache + keyname * cols;
241 row++; /* skip keyname */
242 for (i = 0; i < pool->nlanguages; i++, row++)
243 {
244 if (!*row)
245 *row = pool_id2langid(pool, keyname, pool->languages[i], 1);
246 str = solvable_lookup_str_base(s, *row, keyname, 0);
247 if (str)
248 return str;
249 }
250 return solvable_lookup_str(s, keyname);
251 }
252
253 const char *
solvable_lookup_str_lang(Solvable * s,Id keyname,const char * lang,int usebase)254 solvable_lookup_str_lang(Solvable *s, Id keyname, const char *lang, int usebase)
255 {
256 Id id;
257 if (!s->repo)
258 return 0;
259 id = pool_id2langid(s->repo->pool, keyname, lang, 0);
260 if (id)
261 return solvable_lookup_str_base(s, id, keyname, usebase);
262 if (!usebase)
263 return 0;
264 return solvable_lookup_str(s, keyname);
265 }
266
267 unsigned long long
solvable_lookup_num(Solvable * s,Id keyname,unsigned long long notfound)268 solvable_lookup_num(Solvable *s, Id keyname, unsigned long long notfound)
269 {
270 if (!s->repo)
271 return notfound;
272 return repo_lookup_num(s->repo, s - s->repo->pool->solvables, keyname, notfound);
273 }
274
275 unsigned long long
solvable_lookup_sizek(Solvable * s,Id keyname,unsigned long long notfound)276 solvable_lookup_sizek(Solvable *s, Id keyname, unsigned long long notfound)
277 {
278 unsigned long long size;
279 if (!s->repo)
280 return notfound;
281 size = solvable_lookup_num(s, keyname, (unsigned long long)-1);
282 return size == (unsigned long long)-1 ? notfound : ((size + 1023) >> 10);
283 }
284
285 int
solvable_lookup_void(Solvable * s,Id keyname)286 solvable_lookup_void(Solvable *s, Id keyname)
287 {
288 if (!s->repo)
289 return 0;
290 return repo_lookup_void(s->repo, s - s->repo->pool->solvables, keyname);
291 }
292
293 int
solvable_lookup_bool(Solvable * s,Id keyname)294 solvable_lookup_bool(Solvable *s, Id keyname)
295 {
296 Id type;
297 if (!s->repo)
298 return 0;
299 /* historic nonsense: there are two ways of storing a bool, as num == 1 or void. test both. */
300 type = repo_lookup_type(s->repo, s - s->repo->pool->solvables, keyname);
301 if (type == REPOKEY_TYPE_VOID)
302 return 1;
303 if (type == REPOKEY_TYPE_NUM || type == REPOKEY_TYPE_CONSTANT)
304 return repo_lookup_num(s->repo, s - s->repo->pool->solvables, keyname, 0) == 1;
305 return 0;
306 }
307
308 const unsigned char *
solvable_lookup_bin_checksum(Solvable * s,Id keyname,Id * typep)309 solvable_lookup_bin_checksum(Solvable *s, Id keyname, Id *typep)
310 {
311 if (!s->repo)
312 {
313 *typep = 0;
314 return 0;
315 }
316 return repo_lookup_bin_checksum(s->repo, s - s->repo->pool->solvables, keyname, typep);
317 }
318
319 const char *
solvable_lookup_checksum(Solvable * s,Id keyname,Id * typep)320 solvable_lookup_checksum(Solvable *s, Id keyname, Id *typep)
321 {
322 const unsigned char *chk = solvable_lookup_bin_checksum(s, keyname, typep);
323 return chk ? pool_bin2hex(s->repo->pool, chk, solv_chksum_len(*typep)) : 0;
324 }
325
326 unsigned int
solvable_lookup_count(Solvable * s,Id keyname)327 solvable_lookup_count(Solvable *s, Id keyname)
328 {
329 return s->repo ? repo_lookup_count(s->repo, s - s->repo->pool->solvables, keyname) : 0;
330 }
331
332 static inline const char *
evrid2vrstr(Pool * pool,Id evrid)333 evrid2vrstr(Pool *pool, Id evrid)
334 {
335 const char *p, *evr = pool_id2str(pool, evrid);
336 if (!evr)
337 return evr;
338 for (p = evr; *p >= '0' && *p <= '9'; p++)
339 ;
340 return p != evr && *p == ':' && p[1] ? p + 1 : evr;
341 }
342
343 const char *
solvable_lookup_location(Solvable * s,unsigned int * medianrp)344 solvable_lookup_location(Solvable *s, unsigned int *medianrp)
345 {
346 Pool *pool;
347 int l = 0;
348 char *loc;
349 const char *mediadir, *mediafile;
350
351 if (medianrp)
352 *medianrp = 0;
353 if (!s->repo)
354 return 0;
355 pool = s->repo->pool;
356 if (medianrp)
357 *medianrp = solvable_lookup_num(s, SOLVABLE_MEDIANR, 0);
358 if (solvable_lookup_void(s, SOLVABLE_MEDIADIR))
359 mediadir = pool_id2str(pool, s->arch);
360 else
361 mediadir = solvable_lookup_str(s, SOLVABLE_MEDIADIR);
362 if (mediadir)
363 l = strlen(mediadir) + 1;
364 if (solvable_lookup_void(s, SOLVABLE_MEDIAFILE))
365 {
366 const char *name, *evr, *arch;
367 name = pool_id2str(pool, s->name);
368 evr = evrid2vrstr(pool, s->evr);
369 arch = pool_id2str(pool, s->arch);
370 /* name-vr.arch.rpm */
371 loc = pool_alloctmpspace(pool, l + strlen(name) + strlen(evr) + strlen(arch) + 7);
372 if (mediadir)
373 sprintf(loc, "%s/%s-%s.%s.rpm", mediadir, name, evr, arch);
374 else
375 sprintf(loc, "%s-%s.%s.rpm", name, evr, arch);
376 }
377 else
378 {
379 mediafile = solvable_lookup_str(s, SOLVABLE_MEDIAFILE);
380 if (!mediafile)
381 return 0;
382 loc = pool_alloctmpspace(pool, l + strlen(mediafile) + 1);
383 if (mediadir)
384 sprintf(loc, "%s/%s", mediadir, mediafile);
385 else
386 strcpy(loc, mediafile);
387 }
388 return loc;
389 }
390
391 const char *
solvable_get_location(Solvable * s,unsigned int * medianrp)392 solvable_get_location(Solvable *s, unsigned int *medianrp)
393 {
394 const char *loc = solvable_lookup_location(s, medianrp);
395 if (medianrp && *medianrp == 0)
396 *medianrp = 1; /* compat, to be removed */
397 return loc;
398 }
399
400 const char *
solvable_lookup_sourcepkg(Solvable * s)401 solvable_lookup_sourcepkg(Solvable *s)
402 {
403 Pool *pool;
404 const char *evr, *name;
405 Id archid;
406
407 if (!s->repo)
408 return 0;
409 pool = s->repo->pool;
410 if (solvable_lookup_void(s, SOLVABLE_SOURCENAME))
411 name = pool_id2str(pool, s->name);
412 else
413 name = solvable_lookup_str(s, SOLVABLE_SOURCENAME);
414 if (!name)
415 return 0;
416 archid = solvable_lookup_id(s, SOLVABLE_SOURCEARCH);
417 if (solvable_lookup_void(s, SOLVABLE_SOURCEEVR))
418 evr = evrid2vrstr(pool, s->evr);
419 else
420 evr = solvable_lookup_str(s, SOLVABLE_SOURCEEVR);
421 if (archid == ARCH_SRC || archid == ARCH_NOSRC)
422 {
423 char *str;
424 str = pool_tmpjoin(pool, name, evr ? "-" : 0, evr);
425 str = pool_tmpappend(pool, str, ".", pool_id2str(pool, archid));
426 return pool_tmpappend(pool, str, ".rpm", 0);
427 }
428 else
429 return name; /* FIXME */
430 }
431
432
433 /*****************************************************************************/
434
435 /*
436 * Create maps containing the state of each solvable. Input is a "installed" queue,
437 * it contains all solvable ids that are considered to be installed.
438 *
439 * The created maps can be used for * pool_calc_duchanges() and
440 * pool_calc_installsizechange().
441 *
442 */
443 void
pool_create_state_maps(Pool * pool,Queue * installed,Map * installedmap,Map * conflictsmap)444 pool_create_state_maps(Pool *pool, Queue *installed, Map *installedmap, Map *conflictsmap)
445 {
446 int i;
447 Solvable *s;
448 Id p, *dp;
449 Id *conp, con;
450
451 map_init(installedmap, pool->nsolvables);
452 if (conflictsmap)
453 map_init(conflictsmap, pool->nsolvables);
454 for (i = 0; i < installed->count; i++)
455 {
456 p = installed->elements[i];
457 if (p <= 0) /* makes it work with decisionq */
458 continue;
459 MAPSET(installedmap, p);
460 if (!conflictsmap)
461 continue;
462 s = pool->solvables + p;
463 if (!s->conflicts)
464 continue;
465 conp = s->repo->idarraydata + s->conflicts;
466 while ((con = *conp++) != 0)
467 {
468 dp = pool_whatprovides_ptr(pool, con);
469 for (; *dp; dp++)
470 MAPSET(conflictsmap, *dp);
471 }
472 }
473 }
474
475 /* Tests if two solvables have identical content. Currently
476 * both solvables need to come from the same pool
477 */
478
479 int
solvable_identical(Solvable * s1,Solvable * s2)480 solvable_identical(Solvable *s1, Solvable *s2)
481 {
482 unsigned long long bt1, bt2;
483 Id rq1, rq2;
484 Id *reqp;
485 if (s1->name != s2->name)
486 return 0;
487 if (s1->arch != s2->arch)
488 return 0;
489 if (s1->evr != s2->evr)
490 return 0;
491
492 /* check vendor, map missing vendor to empty string */
493 if ((s1->vendor ? s1->vendor : 1) != (s2->vendor ? s2->vendor : 1))
494 {
495 /* workaround for bug 881493 */
496 if (s1->repo && !strncmp(pool_id2str(s1->repo->pool, s1->name), "product:", 8))
497 return 1;
498 return 0;
499 }
500
501 /* looking good, try some fancier stuff */
502 /* might also look up the package checksum here */
503 bt1 = solvable_lookup_num(s1, SOLVABLE_BUILDTIME, 0);
504 bt2 = solvable_lookup_num(s2, SOLVABLE_BUILDTIME, 0);
505 if (bt1 && bt2)
506 {
507 if (bt1 != bt2)
508 return 0;
509 }
510 else
511 {
512 if (s1->repo)
513 {
514 /* workaround for bugs 881493 and 885830*/
515 const char *n = pool_id2str(s1->repo->pool, s1->name);
516 if (!strncmp(n, "product:", 8) || !strncmp(n, "application:", 12))
517 return 1;
518 }
519 /* look at requires in a last attempt to find recompiled packages */
520 rq1 = rq2 = 0;
521 if (s1->requires)
522 for (reqp = s1->repo->idarraydata + s1->requires; *reqp; reqp++)
523 rq1 ^= *reqp;
524 if (s2->requires)
525 for (reqp = s2->repo->idarraydata + s2->requires; *reqp; reqp++)
526 rq2 ^= *reqp;
527 if (rq1 != rq2)
528 return 0;
529 }
530 if (s1->repo && s1->repo->pool->disttype == DISTTYPE_CONDA)
531 {
532 /* check buildflavor and buildversion */
533 const char *str1, *str2;
534 str1 = solvable_lookup_str(s1, SOLVABLE_BUILDFLAVOR);
535 str2 = solvable_lookup_str(s2, SOLVABLE_BUILDFLAVOR);
536 if (str1 != str2 && (!str1 || !str2 || strcmp(str1, str2) != 0))
537 return 0;
538 str1 = solvable_lookup_str(s1, SOLVABLE_BUILDVERSION);
539 str2 = solvable_lookup_str(s2, SOLVABLE_BUILDVERSION);
540 if (str1 != str2 && (!str1 || !str2 || strcmp(str1, str2) != 0))
541 return 0;
542 }
543 return 1;
544 }
545
546 /* return the self provide dependency of a solvable */
547 Id
solvable_selfprovidedep(Solvable * s)548 solvable_selfprovidedep(Solvable *s)
549 {
550 Pool *pool;
551 Reldep *rd;
552 Id prov, *provp;
553
554 if (!s->repo)
555 return s->name;
556 pool = s->repo->pool;
557 if (s->provides)
558 {
559 provp = s->repo->idarraydata + s->provides;
560 while ((prov = *provp++) != 0)
561 {
562 if (!ISRELDEP(prov))
563 continue;
564 rd = GETRELDEP(pool, prov);
565 if (rd->name == s->name && rd->evr == s->evr && rd->flags == REL_EQ)
566 return prov;
567 }
568 }
569 return pool_rel2id(pool, s->name, s->evr, REL_EQ, 1);
570 }
571
572 /* setter functions, simply call the repo variants */
573 void
solvable_set_id(Solvable * s,Id keyname,Id id)574 solvable_set_id(Solvable *s, Id keyname, Id id)
575 {
576 repo_set_id(s->repo, s - s->repo->pool->solvables, keyname, id);
577 }
578
579 void
solvable_set_num(Solvable * s,Id keyname,unsigned long long num)580 solvable_set_num(Solvable *s, Id keyname, unsigned long long num)
581 {
582 repo_set_num(s->repo, s - s->repo->pool->solvables, keyname, num);
583 }
584
585 void
solvable_set_str(Solvable * s,Id keyname,const char * str)586 solvable_set_str(Solvable *s, Id keyname, const char *str)
587 {
588 repo_set_str(s->repo, s - s->repo->pool->solvables, keyname, str);
589 }
590
591 void
solvable_set_poolstr(Solvable * s,Id keyname,const char * str)592 solvable_set_poolstr(Solvable *s, Id keyname, const char *str)
593 {
594 repo_set_poolstr(s->repo, s - s->repo->pool->solvables, keyname, str);
595 }
596
597 void
solvable_add_poolstr_array(Solvable * s,Id keyname,const char * str)598 solvable_add_poolstr_array(Solvable *s, Id keyname, const char *str)
599 {
600 repo_add_poolstr_array(s->repo, s - s->repo->pool->solvables, keyname, str);
601 }
602
603 void
solvable_add_idarray(Solvable * s,Id keyname,Id id)604 solvable_add_idarray(Solvable *s, Id keyname, Id id)
605 {
606 repo_add_idarray(s->repo, s - s->repo->pool->solvables, keyname, id);
607 }
608
609 void
solvable_add_deparray(Solvable * s,Id keyname,Id dep,Id marker)610 solvable_add_deparray(Solvable *s, Id keyname, Id dep, Id marker)
611 {
612 repo_add_deparray(s->repo, s - s->repo->pool->solvables, keyname, dep, marker);
613 }
614
615 void
solvable_set_idarray(Solvable * s,Id keyname,Queue * q)616 solvable_set_idarray(Solvable *s, Id keyname, Queue *q)
617 {
618 repo_set_idarray(s->repo, s - s->repo->pool->solvables, keyname, q);
619 }
620
621 void
solvable_set_deparray(Solvable * s,Id keyname,Queue * q,Id marker)622 solvable_set_deparray(Solvable *s, Id keyname, Queue *q, Id marker)
623 {
624 repo_set_deparray(s->repo, s - s->repo->pool->solvables, keyname, q, marker);
625 }
626
627 void
solvable_unset(Solvable * s,Id keyname)628 solvable_unset(Solvable *s, Id keyname)
629 {
630 repo_unset(s->repo, s - s->repo->pool->solvables, keyname);
631 }
632
633 /* return true if a dependency intersects dep in the keyname array */
634 int
solvable_matchesdep(Solvable * s,Id keyname,Id dep,int marker)635 solvable_matchesdep(Solvable *s, Id keyname, Id dep, int marker)
636 {
637 int i;
638 Pool *pool = s->repo->pool;
639 Queue q;
640
641 if (keyname == SOLVABLE_NAME)
642 return pool_match_nevr(pool, s, dep) ? 1 : 0; /* nevr match hack */
643 queue_init(&q);
644 solvable_lookup_deparray(s, keyname, &q, marker);
645 for (i = 0; i < q.count; i++)
646 if (pool_match_dep(pool, q.elements[i], dep))
647 break;
648 i = i == q.count ? 0 : 1;
649 queue_free(&q);
650 return i;
651 }
652
653 int
solvable_matchessolvable_int(Solvable * s,Id keyname,int marker,Id solvid,Map * solvidmap,Queue * depq,Map * missc,int reloff,Queue * outdepq)654 solvable_matchessolvable_int(Solvable *s, Id keyname, int marker, Id solvid, Map *solvidmap, Queue *depq, Map *missc, int reloff, Queue *outdepq)
655 {
656 Pool *pool = s->repo->pool;
657 int i, boff;
658 Id *wp;
659
660 if (depq->count)
661 queue_empty(depq);
662 if (outdepq && outdepq->count)
663 queue_empty(outdepq);
664 solvable_lookup_deparray(s, keyname, depq, marker);
665 for (i = 0; i < depq->count; i++)
666 {
667 Id dep = depq->elements[i];
668 boff = ISRELDEP(dep) ? reloff + GETRELID(dep) : dep;
669 if (MAPTST(missc, boff))
670 continue;
671 if (ISRELDEP(dep))
672 {
673 Reldep *rd = GETRELDEP(pool, dep);
674 if (!ISRELDEP(rd->name) && rd->flags < 8)
675 {
676 /* do pre-filtering on the base */
677 if (MAPTST(missc, rd->name))
678 continue;
679 wp = pool_whatprovides_ptr(pool, rd->name);
680 if (solvidmap)
681 {
682 for (; *wp; wp++)
683 if (MAPTST(solvidmap, *wp))
684 break;
685 }
686 else
687 {
688 for (; *wp; wp++)
689 if (*wp == solvid)
690 break;
691 }
692 if (!*wp)
693 {
694 /* the base does not include solvid, no need to check the complete dep */
695 MAPSET(missc, rd->name);
696 MAPSET(missc, boff);
697 continue;
698 }
699 }
700 }
701 wp = pool_whatprovides_ptr(pool, dep);
702 if (solvidmap)
703 {
704 for (; *wp; wp++)
705 if (MAPTST(solvidmap, *wp))
706 break;
707 }
708 else
709 {
710 for (; *wp; wp++)
711 if (*wp == solvid)
712 break;
713 }
714 if (*wp)
715 {
716 if (outdepq)
717 {
718 queue_pushunique(outdepq, dep);
719 continue;
720 }
721 return 1;
722 }
723 MAPSET(missc, boff);
724 }
725 return outdepq && outdepq->count ? 1 : 0;
726 }
727
728 int
solvable_matchessolvable(Solvable * s,Id keyname,Id solvid,Queue * depq,int marker)729 solvable_matchessolvable(Solvable *s, Id keyname, Id solvid, Queue *depq, int marker)
730 {
731 Pool *pool = s->repo->pool;
732 Map missc; /* cache for misses */
733 int res, reloff;
734 Queue qq;
735
736 if (depq && depq->count)
737 queue_empty(depq);
738 if (s - pool->solvables == solvid)
739 return 0; /* no self-matches */
740
741 queue_init(&qq);
742 reloff = pool->ss.nstrings;
743 map_init(&missc, reloff + pool->nrels);
744 res = solvable_matchessolvable_int(s, keyname, marker, solvid, 0, &qq, &missc, reloff, depq);
745 map_free(&missc);
746 queue_free(&qq);
747 return res;
748 }
749