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