00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <stdarg.h>
00017 #include <unistd.h>
00018 #include <string.h>
00019
00020 #include "pool.h"
00021 #include "repo.h"
00022 #include "util.h"
00023
00024 const char *
00025 solvable2str(Pool *pool, Solvable *s)
00026 {
00027 const char *n, *e, *a;
00028 char *p;
00029 n = id2str(pool, s->name);
00030 e = id2str(pool, s->evr);
00031 a = id2str(pool, s->arch);
00032 p = pool_alloctmpspace(pool, strlen(n) + strlen(e) + strlen(a) + 3);
00033 sprintf(p, "%s-%s.%s", n, e, a);
00034 return p;
00035 }
00036
00037 Id
00038 solvable_lookup_id(Solvable *s, Id keyname)
00039 {
00040 if (!s->repo)
00041 return 0;
00042 return repo_lookup_id(s->repo, s - s->repo->pool->solvables, keyname);
00043 }
00044
00045 int
00046 solvable_lookup_idarray(Solvable *s, Id keyname, Queue *q)
00047 {
00048 Dataiterator di;
00049 int found = 0;
00050
00051 queue_empty(q);
00052 if (!s->repo)
00053 return 0;
00054 dataiterator_init(&di, s->repo->pool, s->repo, s - s->repo->pool->solvables, keyname, 0, SEARCH_ARRAYSENTINEL);
00055 while (dataiterator_step(&di))
00056 {
00057 if (di.key->type != REPOKEY_TYPE_IDARRAY && di.key->type != REPOKEY_TYPE_REL_IDARRAY)
00058 continue;
00059 found = 1;
00060 if (di.kv.eof)
00061 break;
00062 queue_push(q, di.kv.id);
00063 }
00064 dataiterator_free(&di);
00065 return found;
00066 }
00067
00068 const char *
00069 solvable_lookup_str(Solvable *s, Id keyname)
00070 {
00071 if (!s->repo)
00072 return 0;
00073 return repo_lookup_str(s->repo, s - s->repo->pool->solvables, keyname);
00074 }
00075
00076 static const char *
00077 solvable_lookup_str_base(Solvable *s, Id keyname, Id basekeyname, int usebase)
00078 {
00079 Pool *pool;
00080 const char *str, *basestr;
00081 Id p, pp;
00082 Solvable *s2;
00083 int pass;
00084
00085 if (!s->repo)
00086 return 0;
00087 pool = s->repo->pool;
00088 str = solvable_lookup_str(s, keyname);
00089 if (str || keyname == basekeyname)
00090 return str;
00091 basestr = solvable_lookup_str(s, basekeyname);
00092 if (!basestr)
00093 return 0;
00094
00095
00096 if (!pool->whatprovides)
00097 return usebase ? basestr : 0;
00098
00099 for (pass = 0; pass < 2; pass++)
00100 {
00101 FOR_PROVIDES(p, pp, s->name)
00102 {
00103 s2 = pool->solvables + p;
00104 if (s2->name != s->name)
00105 continue;
00106 if ((s->vendor == s2->vendor) != (pass == 0))
00107 continue;
00108 str = solvable_lookup_str(s2, basekeyname);
00109 if (!str || strcmp(str, basestr))
00110 continue;
00111 str = solvable_lookup_str(s2, keyname);
00112 if (str)
00113 return str;
00114 }
00115 }
00116 return usebase ? basestr : 0;
00117 }
00118
00119 const char *
00120 solvable_lookup_str_poollang(Solvable *s, Id keyname)
00121 {
00122 Pool *pool;
00123 int i, cols;
00124 const char *str;
00125 Id *row;
00126
00127 if (!s->repo)
00128 return 0;
00129 pool = s->repo->pool;
00130 if (!pool->nlanguages)
00131 return solvable_lookup_str(s, keyname);
00132 cols = pool->nlanguages + 1;
00133 if (!pool->languagecache)
00134 {
00135 pool->languagecache = sat_calloc(cols * ID_NUM_INTERNAL, sizeof(Id));
00136 pool->languagecacheother = 0;
00137 }
00138 if (keyname >= ID_NUM_INTERNAL)
00139 {
00140 row = pool->languagecache + ID_NUM_INTERNAL * cols;
00141 for (i = 0; i < pool->languagecacheother; i++, row += cols)
00142 if (*row == keyname)
00143 break;
00144 if (i >= pool->languagecacheother)
00145 {
00146 pool->languagecache = sat_realloc2(pool->languagecache, pool->languagecacheother + 1, cols * sizeof(Id));
00147 row = pool->languagecache + cols * (ID_NUM_INTERNAL + pool->languagecacheother++);
00148 *row = keyname;
00149 }
00150 }
00151 else
00152 row = pool->languagecache + keyname * cols;
00153 row++;
00154 for (i = 0; i < pool->nlanguages; i++, row++)
00155 {
00156 if (!*row)
00157 *row = pool_id2langid(pool, keyname, pool->languages[i], 1);
00158 str = solvable_lookup_str_base(s, *row, keyname, 0);
00159 if (str)
00160 return str;
00161 }
00162 return solvable_lookup_str(s, keyname);
00163 }
00164
00165 const char *
00166 solvable_lookup_str_lang(Solvable *s, Id keyname, const char *lang, int usebase)
00167 {
00168 if (s->repo)
00169 {
00170 Id id = pool_id2langid(s->repo->pool, keyname, lang, 0);
00171 if (id)
00172 return solvable_lookup_str_base(s, id, keyname, usebase);
00173 if (!usebase)
00174 return 0;
00175 }
00176 return solvable_lookup_str(s, keyname);
00177 }
00178
00179 unsigned int
00180 solvable_lookup_num(Solvable *s, Id keyname, unsigned int notfound)
00181 {
00182 if (!s->repo)
00183 return 0;
00184 return repo_lookup_num(s->repo, s - s->repo->pool->solvables, keyname, notfound);
00185 }
00186
00187 int
00188 solvable_lookup_void(Solvable *s, Id keyname)
00189 {
00190 if (!s->repo)
00191 return 0;
00192 return repo_lookup_void(s->repo, s - s->repo->pool->solvables, keyname);
00193 }
00194
00195 int
00196 solvable_lookup_bool(Solvable *s, Id keyname)
00197 {
00198 Repo *repo = s->repo;
00199 Pool *pool;
00200 Repodata *data;
00201 int i, j, n;
00202
00203 if (!repo)
00204 return 0;
00205 pool = repo->pool;
00206 n = s - pool->solvables;
00207 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
00208 {
00209 if (n < data->start || n >= data->end)
00210 continue;
00211
00212 for (j = 1; j < data->nkeys; j++)
00213 {
00214 if (data->keys[j].name == keyname
00215 && (data->keys[j].type == REPOKEY_TYPE_U32
00216 || data->keys[j].type == REPOKEY_TYPE_NUM
00217 || data->keys[j].type == REPOKEY_TYPE_CONSTANT
00218 || data->keys[j].type == REPOKEY_TYPE_VOID))
00219 {
00220 unsigned int value;
00221 if (repodata_lookup_num(data, n, keyname, &value))
00222 return value == 1;
00223 if (repodata_lookup_void(data, n, keyname))
00224 return 1;
00225 }
00226 }
00227 }
00228 return 0;
00229 }
00230
00231 const unsigned char *
00232 solvable_lookup_bin_checksum(Solvable *s, Id keyname, Id *typep)
00233 {
00234 Repo *repo = s->repo;
00235
00236 if (!repo)
00237 {
00238 *typep = 0;
00239 return 0;
00240 }
00241 return repo_lookup_bin_checksum(repo, s - repo->pool->solvables, keyname, typep);
00242 }
00243
00244 const char *
00245 solvable_lookup_checksum(Solvable *s, Id keyname, Id *typep)
00246 {
00247 const unsigned char *chk = solvable_lookup_bin_checksum(s, keyname, typep);
00248
00249 return chk ? repodata_chk2str(s->repo->repodata, *typep, chk) : 0;
00250 }
00251
00252 static inline const char *
00253 evrid2vrstr(Pool *pool, Id evrid)
00254 {
00255 const char *p, *evr = id2str(pool, evrid);
00256 if (!evr)
00257 return evr;
00258 for (p = evr; *p >= '0' && *p <= '9'; p++)
00259 ;
00260 return p != evr && *p == ':' ? p + 1 : evr;
00261 }
00262
00263 char *
00264 solvable_get_location(Solvable *s, unsigned int *medianrp)
00265 {
00266 Pool *pool;
00267 int l = 0;
00268 char *loc;
00269 const char *mediadir, *mediafile;
00270
00271 *medianrp = 0;
00272 if (!s->repo)
00273 return 0;
00274 pool = s->repo->pool;
00275 *medianrp = solvable_lookup_num(s, SOLVABLE_MEDIANR, 1);
00276 if (solvable_lookup_void(s, SOLVABLE_MEDIADIR))
00277 mediadir = id2str(pool, s->arch);
00278 else
00279 mediadir = solvable_lookup_str(s, SOLVABLE_MEDIADIR);
00280 if (mediadir)
00281 l = strlen(mediadir) + 1;
00282 if (solvable_lookup_void(s, SOLVABLE_MEDIAFILE))
00283 {
00284 const char *name, *evr, *arch;
00285 name = id2str(pool, s->name);
00286 evr = evrid2vrstr(pool, s->evr);
00287 arch = id2str(pool, s->arch);
00288
00289 loc = pool_alloctmpspace(pool, l + strlen(name) + strlen(evr) + strlen(arch) + 7);
00290 if (mediadir)
00291 sprintf(loc, "%s/%s-%s.%s.rpm", mediadir, name, evr, arch);
00292 else
00293 sprintf(loc, "%s-%s.%s.rpm", name, evr, arch);
00294 }
00295 else
00296 {
00297 mediafile = solvable_lookup_str(s, SOLVABLE_MEDIAFILE);
00298 if (!mediafile)
00299 return 0;
00300 loc = pool_alloctmpspace(pool, l + strlen(mediafile) + 1);
00301 if (mediadir)
00302 sprintf(loc, "%s/%s", mediadir, mediafile);
00303 else
00304 strcpy(loc, mediafile);
00305 }
00306 return loc;
00307 }
00308
00309
00310
00311 static inline Id dep2name(Pool *pool, Id dep)
00312 {
00313 while (ISRELDEP(dep))
00314 {
00315 Reldep *rd = rd = GETRELDEP(pool, dep);
00316 dep = rd->name;
00317 }
00318 return dep;
00319 }
00320
00321 static inline int providedbyinstalled(Pool *pool, Map *installed, Id dep)
00322 {
00323 Id p, pp;
00324 FOR_PROVIDES(p, pp, dep)
00325 {
00326 if (p == SYSTEMSOLVABLE)
00327 return -1;
00328 if (MAPTST(installed, p))
00329 return 1;
00330 }
00331 return 0;
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 int
00351 solvable_trivial_installable_map(Solvable *s, Map *installedmap, Map *conflictsmap)
00352 {
00353 Pool *pool = s->repo->pool;
00354 Solvable *s2;
00355 Id p, pp, *dp;
00356 Id *reqp, req;
00357 Id *conp, con;
00358 Id *obsp, obs;
00359 int r, interesting = 0;
00360
00361 if (conflictsmap && MAPTST(conflictsmap, s - pool->solvables))
00362 return 0;
00363 if (s->requires)
00364 {
00365 reqp = s->repo->idarraydata + s->requires;
00366 while ((req = *reqp++) != 0)
00367 {
00368 if (req == SOLVABLE_PREREQMARKER)
00369 continue;
00370 r = providedbyinstalled(pool, installedmap, req);
00371 if (!r)
00372 return 0;
00373 if (r > 0)
00374 interesting = 1;
00375 }
00376 }
00377 if (s->conflicts)
00378 {
00379 conp = s->repo->idarraydata + s->conflicts;
00380 while ((con = *conp++) != 0)
00381 {
00382 if (providedbyinstalled(pool, installedmap, con))
00383 return 0;
00384 if (!interesting && ISRELDEP(con))
00385 {
00386 con = dep2name(pool, con);
00387 if (providedbyinstalled(pool, installedmap, con))
00388 interesting = 1;
00389 }
00390 }
00391 }
00392 if (s->repo)
00393 {
00394 Repo *installed = 0;
00395 if (s->obsoletes && s->repo != installed)
00396 {
00397 obsp = s->repo->idarraydata + s->obsoletes;
00398 while ((obs = *obsp++) != 0)
00399 {
00400 if (providedbyinstalled(pool, installedmap, obs))
00401 return 0;
00402 }
00403 }
00404 if (s->repo != installed)
00405 {
00406 FOR_PROVIDES(p, pp, s->name)
00407 {
00408 s2 = pool->solvables + p;
00409 if (s2->repo == installed && s2->name == s->name)
00410 return 0;
00411 }
00412 }
00413 }
00414 if (!conflictsmap)
00415 {
00416 int i;
00417
00418 p = s - pool->solvables;
00419 for (i = 1; i < pool->nsolvables; i++)
00420 {
00421 if (!MAPTST(installedmap, i))
00422 continue;
00423 s2 = pool->solvables + i;
00424 if (!s2->conflicts)
00425 continue;
00426 conp = s2->repo->idarraydata + s2->conflicts;
00427 while ((con = *conp++) != 0)
00428 {
00429 dp = pool_whatprovides_ptr(pool, con);
00430 for (; *dp; dp++)
00431 if (*dp == p)
00432 return 0;
00433 }
00434 }
00435 }
00436 return interesting ? 1 : -1;
00437 }
00438
00439
00440
00441
00442
00443
00444 int
00445 solvable_trivial_installable_queue(Solvable *s, Queue *installed)
00446 {
00447 Pool *pool = s->repo->pool;
00448 int i;
00449 Id p;
00450 Map installedmap;
00451 int r;
00452
00453 map_init(&installedmap, pool->nsolvables);
00454 for (i = 0; i < installed->count; i++)
00455 {
00456 p = installed->elements[i];
00457 if (p > 0)
00458 MAPSET(&installedmap, p);
00459 }
00460 r = solvable_trivial_installable_map(s, &installedmap, 0);
00461 map_free(&installedmap);
00462 return r;
00463 }
00464
00465
00466
00467
00468
00469
00470 int
00471 solvable_trivial_installable_repo(Solvable *s, Repo *installed)
00472 {
00473 Pool *pool = s->repo->pool;
00474 Id p;
00475 Solvable *s2;
00476 Map installedmap;
00477 int r;
00478
00479 map_init(&installedmap, pool->nsolvables);
00480 FOR_REPO_SOLVABLES(installed, p, s2)
00481 MAPSET(&installedmap, p);
00482 r = solvable_trivial_installable_map(s, &installedmap, 0);
00483 map_free(&installedmap);
00484 return r;
00485 }
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 void
00499 pool_create_state_maps(Pool *pool, Queue *installed, Map *installedmap, Map *conflictsmap)
00500 {
00501 int i;
00502 Solvable *s;
00503 Id p, *dp;
00504 Id *conp, con;
00505
00506 map_init(installedmap, pool->nsolvables);
00507 if (conflictsmap)
00508 map_init(conflictsmap, pool->nsolvables);
00509 for (i = 0; i < installed->count; i++)
00510 {
00511 p = installed->elements[i];
00512 if (p <= 0)
00513 continue;
00514 MAPSET(installedmap, p);
00515 if (!conflictsmap)
00516 continue;
00517 s = pool->solvables + p;
00518 if (!s->conflicts)
00519 continue;
00520 conp = s->repo->idarraydata + s->conflicts;
00521 while ((con = *conp++) != 0)
00522 {
00523 dp = pool_whatprovides_ptr(pool, con);
00524 for (; *dp; dp++)
00525 MAPSET(conflictsmap, *dp);
00526 }
00527 }
00528 }
00529
00530
00531
00532
00533 int
00534 solvable_identical(Solvable *s1, Solvable *s2)
00535 {
00536 unsigned int bt1, bt2;
00537 Id rq1, rq2;
00538 Id *reqp;
00539
00540 if (s1->name != s2->name)
00541 return 0;
00542 if (s1->arch != s2->arch)
00543 return 0;
00544 if (s1->evr != s2->evr)
00545 return 0;
00546
00547 if ((s1->vendor ? s1->vendor : 1) != (s2->vendor ? s2->vendor : 1))
00548 return 0;
00549
00550
00551
00552 bt1 = solvable_lookup_num(s1, SOLVABLE_BUILDTIME, 0);
00553 bt2 = solvable_lookup_num(s2, SOLVABLE_BUILDTIME, 0);
00554 if (bt1 && bt2)
00555 {
00556 if (bt1 != bt2)
00557 return 0;
00558 }
00559 else
00560 {
00561
00562 rq1 = rq2 = 0;
00563 if (s1->requires)
00564 for (reqp = s1->repo->idarraydata + s1->requires; *reqp; reqp++)
00565 rq1 ^= *reqp;
00566 if (s2->requires)
00567 for (reqp = s2->repo->idarraydata + s2->requires; *reqp; reqp++)
00568 rq2 ^= *reqp;
00569 if (rq1 != rq2)
00570 return 0;
00571 }
00572 return 1;
00573 }
00574
00575
00576 Id
00577 solvable_selfprovidedep(Solvable *s)
00578 {
00579 Pool *pool;
00580 Reldep *rd;
00581 Id prov, *provp;
00582
00583 if (!s->repo)
00584 return s->name;
00585 pool = s->repo->pool;
00586 if (s->provides)
00587 {
00588 provp = s->repo->idarraydata + s->provides;
00589 while ((prov = *provp++) != 0)
00590 {
00591 if (!ISRELDEP(prov))
00592 continue;
00593 rd = GETRELDEP(pool, prov);
00594 if (rd->name == s->name && rd->evr == s->evr && rd->flags == REL_EQ)
00595 return prov;
00596 }
00597 }
00598 return rel2id(pool, s->name, s->evr, REL_EQ, 1);
00599 }