00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #define _GNU_SOURCE
00016 #include <string.h>
00017 #include <fnmatch.h>
00018
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021
00022
00023
00024 #include "repo.h"
00025 #include "pool.h"
00026 #include "poolid_private.h"
00027 #include "util.h"
00028 #include "chksum.h"
00029
00030 #define IDARRAY_BLOCK 4095
00031
00032
00033
00034
00035
00036
00037
00038 Repo *
00039 repo_create(Pool *pool, const char *name)
00040 {
00041 Repo *repo;
00042
00043 pool_freewhatprovides(pool);
00044 repo = (Repo *)sat_calloc(1, sizeof(*repo));
00045 pool->repos = (Repo **)sat_realloc2(pool->repos, pool->nrepos + 1, sizeof(Repo *));
00046 pool->repos[pool->nrepos++] = repo;
00047 repo->repoid = pool->nrepos;
00048 repo->name = name ? strdup(name) : 0;
00049 repo->pool = pool;
00050 repo->start = pool->nsolvables;
00051 repo->end = pool->nsolvables;
00052 repo->nsolvables = 0;
00053 return repo;
00054 }
00055
00056 static void
00057 repo_freedata(Repo *repo)
00058 {
00059 int i;
00060 for (i = 0; i < repo->nrepodata; i++)
00061 repodata_freedata(repo->repodata + i);
00062 sat_free(repo->repodata);
00063 sat_free(repo->idarraydata);
00064 sat_free(repo->rpmdbid);
00065 sat_free((char *)repo->name);
00066 sat_free(repo);
00067 }
00068
00069
00070
00071 void
00072 repo_empty(Repo *repo, int reuseids)
00073 {
00074 Pool *pool = repo->pool;
00075 Solvable *s;
00076 int i;
00077
00078 pool_freewhatprovides(pool);
00079 if (reuseids && repo->end == pool->nsolvables)
00080 {
00081
00082
00083 for (i = repo->end - 1, s = pool->solvables + i; i >= repo->start; i--, s--)
00084 if (s->repo != repo)
00085 break;
00086 pool_free_solvable_block(pool, i + 1, repo->end - (i + 1), reuseids);
00087 }
00088
00089 for (i = repo->start, s = pool->solvables + i; i < repo->end; i++, s++)
00090 if (s->repo == repo)
00091 memset(s, 0, sizeof(*s));
00092 repo->nsolvables = 0;
00093
00094
00095 repo->idarraydata = sat_free(repo->idarraydata);
00096 repo->idarraysize = 0;
00097 repo->lastoff = 0;
00098 repo->rpmdbid = sat_free(repo->rpmdbid);
00099 for (i = 0; i < repo->nrepodata; i++)
00100 repodata_freedata(repo->repodata + i);
00101 sat_free(repo->repodata);
00102 repo->repodata = 0;
00103 repo->nrepodata = 0;
00104 }
00105
00106
00107
00108
00109
00110
00111 void
00112 repo_free(Repo *repo, int reuseids)
00113 {
00114 Pool *pool = repo->pool;
00115 int i;
00116
00117 if (repo == pool->installed)
00118 pool->installed = 0;
00119 repo_empty(repo, reuseids);
00120 for (i = 0; i < pool->nrepos; i++)
00121 if (pool->repos[i] == repo)
00122 break;
00123 if (i == pool->nrepos)
00124 return;
00125 if (i < pool->nrepos - 1)
00126 {
00127 memmove(pool->repos + i, pool->repos + i + 1, (pool->nrepos - 1 - i) * sizeof(Repo *));
00128
00129 for (; i < pool->nrepos - 1; i++)
00130 pool->repos[i]->repoid = i + 1;
00131 }
00132 pool->nrepos--;
00133 repo_freedata(repo);
00134 }
00135
00136 void
00137 repo_freeallrepos(Pool *pool, int reuseids)
00138 {
00139 int i;
00140
00141 pool_freewhatprovides(pool);
00142 for (i = 0; i < pool->nrepos; i++)
00143 repo_freedata(pool->repos[i]);
00144 pool->repos = sat_free(pool->repos);
00145 pool->nrepos = 0;
00146
00147 pool_free_solvable_block(pool, 2, pool->nsolvables - 2, reuseids);
00148 }
00149
00150 void repo_free_solvable_block(Repo *repo, Id start, int count, int reuseids)
00151 {
00152 Solvable *s;
00153 Repodata *data;
00154 int i;
00155 if (start + count == repo->end)
00156 repo->end -= count;
00157 repo->nsolvables -= count;
00158 for (s = repo->pool->solvables + start, i = count; i--; s++)
00159 s->repo = 0;
00160 pool_free_solvable_block(repo->pool, start, count, reuseids);
00161 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
00162 if (data->end > repo->end)
00163 repodata_shrink(data, repo->end);
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 #define REPO_SIDEDATA_BLOCK 63
00175
00176 void *
00177 repo_sidedata_create(Repo *repo, size_t size)
00178 {
00179 return sat_calloc_block(repo->end - repo->start, size, REPO_SIDEDATA_BLOCK);
00180 }
00181
00182 void *
00183 repo_sidedata_extend(Repo *repo, void *b, size_t size, Id p, int count)
00184 {
00185 int n = repo->end - repo->start;
00186 if (p < repo->start)
00187 {
00188 int d = repo->start - p;
00189 b = sat_extend(b, n, d, size, REPO_SIDEDATA_BLOCK);
00190 memmove((char *)b + d * size, b, n * size);
00191 memset(b, 0, d * size);
00192 n += d;
00193 }
00194 if (p + count > repo->end)
00195 {
00196 int d = p + count - repo->end;
00197 b = sat_extend(b, n, d, size, REPO_SIDEDATA_BLOCK);
00198 memset((char *)b + n * size, 0, d * size);
00199 }
00200 return b;
00201 }
00202
00203
00204
00205
00206
00207
00208
00209 Offset
00210 repo_addid(Repo *repo, Offset olddeps, Id id)
00211 {
00212 Id *idarray;
00213 int idarraysize;
00214 int i;
00215
00216 idarray = repo->idarraydata;
00217 idarraysize = repo->idarraysize;
00218
00219 if (!idarray)
00220 {
00221 idarraysize = 1;
00222 idarray = sat_extend_resize(0, 1, sizeof(Id), IDARRAY_BLOCK);
00223 idarray[0] = 0;
00224 repo->lastoff = 0;
00225 }
00226
00227 if (!olddeps)
00228 {
00229 olddeps = idarraysize;
00230 idarray = sat_extend(idarray, idarraysize, 1, sizeof(Id), IDARRAY_BLOCK);
00231 }
00232 else if (olddeps == repo->lastoff)
00233 idarraysize--;
00234 else
00235 {
00236 i = olddeps;
00237 olddeps = idarraysize;
00238 for (; idarray[i]; i++)
00239 {
00240 idarray = sat_extend(idarray, idarraysize, 1, sizeof(Id), IDARRAY_BLOCK);
00241 idarray[idarraysize++] = idarray[i];
00242 }
00243 idarray = sat_extend(idarray, idarraysize, 1, sizeof(Id), IDARRAY_BLOCK);
00244 }
00245
00246 idarray[idarraysize++] = id;
00247 idarray = sat_extend(idarray, idarraysize, 1, sizeof(Id), IDARRAY_BLOCK);
00248 idarray[idarraysize++] = 0;
00249
00250 repo->idarraydata = idarray;
00251 repo->idarraysize = idarraysize;
00252 repo->lastoff = olddeps;
00253
00254 return olddeps;
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 Offset
00267 repo_addid_dep(Repo *repo, Offset olddeps, Id id, Id marker)
00268 {
00269 Id oid, *oidp, *markerp;
00270 int before;
00271
00272 if (!olddeps)
00273 {
00274 if (marker > 0)
00275 olddeps = repo_addid(repo, olddeps, marker);
00276 return repo_addid(repo, olddeps, id);
00277 }
00278
00279 if (!marker)
00280 {
00281 for (oidp = repo->idarraydata + olddeps; (oid = *oidp) != ID_NULL; oidp++)
00282 {
00283 if (oid == id)
00284 return olddeps;
00285 }
00286 return repo_addid(repo, olddeps, id);
00287 }
00288
00289 before = 0;
00290 markerp = 0;
00291 if (marker < 0)
00292 {
00293 before = 1;
00294 marker = -marker;
00295 }
00296 for (oidp = repo->idarraydata + olddeps; (oid = *oidp) != ID_NULL; oidp++)
00297 {
00298 if (oid == marker)
00299 markerp = oidp;
00300 else if (oid == id)
00301 break;
00302 }
00303
00304 if (oid)
00305 {
00306 if (markerp || before)
00307 return olddeps;
00308
00309 markerp = oidp++;
00310 for (; (oid = *oidp) != ID_NULL; oidp++)
00311 if (oid == marker)
00312 break;
00313 if (!oid)
00314 {
00315
00316 oidp--;
00317 if (markerp < oidp)
00318 memmove(markerp, markerp + 1, (oidp - markerp) * sizeof(Id));
00319 *oidp = marker;
00320 return repo_addid(repo, olddeps, id);
00321 }
00322 while (oidp[1])
00323 oidp++;
00324 memmove(markerp, markerp + 1, (oidp - markerp) * sizeof(Id));
00325 *oidp = id;
00326 return olddeps;
00327 }
00328
00329 if (!before && !markerp)
00330 olddeps = repo_addid(repo, olddeps, marker);
00331 else if (before && markerp)
00332 {
00333 *markerp++ = id;
00334 id = *--oidp;
00335 if (markerp < oidp)
00336 memmove(markerp + 1, markerp, (oidp - markerp) * sizeof(Id));
00337 *markerp = marker;
00338 }
00339 return repo_addid(repo, olddeps, id);
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 Offset
00352 repo_reserve_ids(Repo *repo, Offset olddeps, int num)
00353 {
00354 num++;
00355
00356 if (!repo->idarraysize)
00357 {
00358 repo->idarraysize = 1;
00359 repo->idarraydata = sat_extend_resize(0, 1 + num, sizeof(Id), IDARRAY_BLOCK);
00360 repo->idarraydata[0] = 0;
00361 repo->lastoff = 1;
00362 return 1;
00363 }
00364
00365 if (olddeps && olddeps != repo->lastoff)
00366 {
00367
00368
00369
00370
00371
00372 Id *idstart, *idend;
00373 int count;
00374
00375 for (idstart = idend = repo->idarraydata + olddeps; *idend++; )
00376 ;
00377 count = idend - idstart - 1 + num;
00378
00379 repo->idarraydata = sat_extend(repo->idarraydata, repo->idarraysize, count, sizeof(Id), IDARRAY_BLOCK);
00380
00381 olddeps = repo->lastoff = repo->idarraysize;
00382 memcpy(repo->idarraydata + olddeps, idstart, count - num);
00383 repo->idarraysize = olddeps + count - num;
00384
00385 return olddeps;
00386 }
00387
00388 if (olddeps)
00389 repo->idarraysize--;
00390
00391
00392 repo->idarraydata = sat_extend(repo->idarraydata, repo->idarraysize, num, sizeof(Id), IDARRAY_BLOCK);
00393
00394
00395 repo->lastoff = olddeps ? olddeps : repo->idarraysize;
00396
00397 return repo->lastoff;
00398 }
00399
00400
00401
00402 Offset
00403 repo_fix_supplements(Repo *repo, Offset provides, Offset supplements, Offset freshens)
00404 {
00405 Pool *pool = repo->pool;
00406 Id id, idp, idl;
00407 char buf[1024], *p, *dep;
00408 int i, l;
00409
00410 if (provides)
00411 {
00412 for (i = provides; repo->idarraydata[i]; i++)
00413 {
00414 id = repo->idarraydata[i];
00415 if (ISRELDEP(id))
00416 continue;
00417 dep = (char *)id2str(pool, id);
00418 if (!strncmp(dep, "locale(", 7) && strlen(dep) < sizeof(buf) - 2)
00419 {
00420 idp = 0;
00421 strcpy(buf + 2, dep);
00422 dep = buf + 2 + 7;
00423 if ((p = strchr(dep, ':')) != 0 && p != dep)
00424 {
00425 *p++ = 0;
00426 idp = str2id(pool, dep, 1);
00427 dep = p;
00428 }
00429 id = 0;
00430 while ((p = strchr(dep, ';')) != 0)
00431 {
00432 if (p == dep)
00433 {
00434 dep = p + 1;
00435 continue;
00436 }
00437 *p++ = 0;
00438 #if 0
00439 strncpy(dep - 9, "language:", 9);
00440 idl = str2id(pool, dep - 9, 1);
00441 #else
00442 idl = str2id(pool, dep, 1);
00443 idl = rel2id(pool, NAMESPACE_LANGUAGE, idl, REL_NAMESPACE, 1);
00444 #endif
00445 if (id)
00446 id = rel2id(pool, id, idl, REL_OR, 1);
00447 else
00448 id = idl;
00449 dep = p;
00450 }
00451 if (dep[0] && dep[1])
00452 {
00453 for (p = dep; *p && *p != ')'; p++)
00454 ;
00455 *p = 0;
00456 #if 0
00457 strncpy(dep - 9, "language:", 9);
00458 idl = str2id(pool, dep - 9, 1);
00459 #else
00460 idl = str2id(pool, dep, 1);
00461 idl = rel2id(pool, NAMESPACE_LANGUAGE, idl, REL_NAMESPACE, 1);
00462 #endif
00463 if (id)
00464 id = rel2id(pool, id, idl, REL_OR, 1);
00465 else
00466 id = idl;
00467 }
00468 if (idp)
00469 id = rel2id(pool, idp, id, REL_AND, 1);
00470 if (id)
00471 supplements = repo_addid_dep(repo, supplements, id, 0);
00472 }
00473 else if ((p = strchr(dep, ':')) != 0 && p != dep && p[1] == '/' && strlen(dep) < sizeof(buf))
00474 {
00475 strcpy(buf, dep);
00476 p = buf + (p - dep);
00477 *p++ = 0;
00478 idp = str2id(pool, buf, 1);
00479
00480 l = strlen(p);
00481 while (l > 1 && p[l - 1] == '/')
00482 p[--l] = 0;
00483 id = str2id(pool, p, 1);
00484 id = rel2id(pool, idp, id, REL_WITH, 1);
00485 id = rel2id(pool, NAMESPACE_SPLITPROVIDES, id, REL_NAMESPACE, 1);
00486 supplements = repo_addid_dep(repo, supplements, id, 0);
00487 }
00488 }
00489 }
00490 if (supplements)
00491 {
00492 for (i = supplements; repo->idarraydata[i]; i++)
00493 {
00494 id = repo->idarraydata[i];
00495 if (ISRELDEP(id))
00496 continue;
00497 dep = (char *)id2str(pool, id);
00498 if (!strncmp(dep, "system:modalias(", 16))
00499 dep += 7;
00500 if (!strncmp(dep, "modalias(", 9) && dep[9] && dep[10] && strlen(dep) < sizeof(buf))
00501 {
00502 strcpy(buf, dep);
00503 p = strchr(buf + 9, ':');
00504 if (p && p != buf + 9 && strchr(p + 1, ':'))
00505 {
00506 *p++ = 0;
00507 idp = str2id(pool, buf + 9, 1);
00508 p[strlen(p) - 1] = 0;
00509 id = str2id(pool, p, 1);
00510 id = rel2id(pool, NAMESPACE_MODALIAS, id, REL_NAMESPACE, 1);
00511 id = rel2id(pool, idp, id, REL_AND, 1);
00512 }
00513 else
00514 {
00515 p = buf + 9;
00516 p[strlen(p) - 1] = 0;
00517 id = str2id(pool, p, 1);
00518 id = rel2id(pool, NAMESPACE_MODALIAS, id, REL_NAMESPACE, 1);
00519 }
00520 if (id)
00521 repo->idarraydata[i] = id;
00522 }
00523 else if (!strncmp(dep, "packageand(", 11) && strlen(dep) < sizeof(buf))
00524 {
00525 strcpy(buf, dep);
00526 id = 0;
00527 dep = buf + 11;
00528 while ((p = strchr(dep, ':')) != 0)
00529 {
00530 if (p == dep)
00531 {
00532 dep = p + 1;
00533 continue;
00534 }
00535 *p++ = 0;
00536 idp = str2id(pool, dep, 1);
00537 if (id)
00538 id = rel2id(pool, id, idp, REL_AND, 1);
00539 else
00540 id = idp;
00541 dep = p;
00542 }
00543 if (dep[0] && dep[1])
00544 {
00545 dep[strlen(dep) - 1] = 0;
00546 idp = str2id(pool, dep, 1);
00547 if (id)
00548 id = rel2id(pool, id, idp, REL_AND, 1);
00549 else
00550 id = idp;
00551 }
00552 if (id)
00553 repo->idarraydata[i] = id;
00554 }
00555 else if (!strncmp(dep, "filesystem(", 11) && strlen(dep) < sizeof(buf))
00556 {
00557 strcpy(buf, dep + 11);
00558 if ((p = strrchr(buf, ')')) != 0)
00559 *p = 0;
00560 id = str2id(pool, buf, 1);
00561 id = rel2id(pool, NAMESPACE_FILESYSTEM, id, REL_NAMESPACE, 1);
00562 repo->idarraydata[i] = id;
00563 }
00564 }
00565 }
00566 if (freshens && repo->idarraydata[freshens])
00567 {
00568 Id idsupp = 0, idfresh = 0;
00569 if (!supplements)
00570 return freshens;
00571 for (i = supplements; repo->idarraydata[i]; i++)
00572 {
00573 if (!idsupp)
00574 idsupp = repo->idarraydata[i];
00575 else
00576 idsupp = rel2id(pool, idsupp, repo->idarraydata[i], REL_OR, 1);
00577 }
00578 for (i = freshens; repo->idarraydata[i]; i++)
00579 {
00580 if (!idfresh)
00581 idfresh = repo->idarraydata[i];
00582 else
00583 idfresh = rel2id(pool, idfresh, repo->idarraydata[i], REL_OR, 1);
00584 }
00585 if (!idsupp)
00586 idsupp = idfresh;
00587 else
00588 idsupp = rel2id(pool, idsupp, idfresh, REL_AND, 1);
00589 supplements = repo_addid_dep(repo, 0, idsupp, 0);
00590 }
00591 return supplements;
00592 }
00593
00594 Offset
00595 repo_fix_conflicts(Repo *repo, Offset conflicts)
00596 {
00597 char buf[1024], *p, *dep;
00598 Pool *pool = repo->pool;
00599 Id id;
00600 int i;
00601
00602 if (!conflicts)
00603 return conflicts;
00604 for (i = conflicts; repo->idarraydata[i]; i++)
00605 {
00606 id = repo->idarraydata[i];
00607 if (ISRELDEP(id))
00608 continue;
00609 dep = (char *)id2str(pool, id);
00610 if (!strncmp(dep, "otherproviders(", 15) && strlen(dep) < sizeof(buf) - 2)
00611 {
00612 strcpy(buf, dep + 15);
00613 if ((p = strchr(buf, ')')) != 0)
00614 *p = 0;
00615 id = str2id(pool, buf, 1);
00616 id = rel2id(pool, NAMESPACE_OTHERPROVIDERS, id, REL_NAMESPACE, 1);
00617 repo->idarraydata[i] = id;
00618 }
00619 }
00620 return conflicts;
00621 }
00622
00623 struct matchdata
00624 {
00625 Pool *pool;
00626 int flags;
00627 Datamatcher matcher;
00628 int stop;
00629 int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv);
00630 void *callback_data;
00631 };
00632
00633 int
00634 repo_matchvalue(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv)
00635 {
00636 struct matchdata *md = cbdata;
00637
00638 if (md->matcher.match)
00639 {
00640 if (!repodata_stringify(md->pool, data, key, kv, md->flags))
00641 return 0;
00642 if (!datamatcher_match(&md->matcher, kv->str))
00643 return 0;
00644 }
00645 md->stop = md->callback(md->callback_data, s, data, key, kv);
00646 return md->stop;
00647 }
00648
00649
00650 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
00651 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
00652 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
00653 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
00654 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
00655 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00656 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00657 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00658 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00659 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00660 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00661 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00662 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00663 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
00664 };
00665
00666 static void
00667 domatch_idarray(Solvable *s, Id keyname, struct matchdata *md, Id *ida)
00668 {
00669 KeyValue kv;
00670 kv.entry = 0;
00671 kv.parent = 0;
00672 for (; *ida && !md->stop; ida++)
00673 {
00674 kv.id = *ida;
00675 kv.eof = ida[1] ? 0 : 1;
00676 repo_matchvalue(md, s, 0, solvablekeys + (keyname - SOLVABLE_NAME), &kv);
00677 kv.entry++;
00678 }
00679 }
00680
00681 static void
00682 repo_search_md(Repo *repo, Id p, Id keyname, struct matchdata *md)
00683 {
00684 KeyValue kv;
00685 Pool *pool = repo->pool;
00686 Repodata *data;
00687 int i, j, flags;
00688 Solvable *s;
00689
00690 kv.parent = 0;
00691 md->stop = 0;
00692 if (!p)
00693 {
00694 for (p = repo->start, s = repo->pool->solvables + p; p < repo->end; p++, s++)
00695 {
00696 if (s->repo == repo)
00697 repo_search_md(repo, p, keyname, md);
00698 if (md->stop > SEARCH_NEXT_SOLVABLE)
00699 break;
00700 }
00701 return;
00702 }
00703 else if (p < 0)
00704
00705
00706 return;
00707 flags = md->flags;
00708 if (!(flags & SEARCH_NO_STORAGE_SOLVABLE))
00709 {
00710 s = pool->solvables + p;
00711 switch(keyname)
00712 {
00713 case 0:
00714 case SOLVABLE_NAME:
00715 if (s->name)
00716 {
00717 kv.id = s->name;
00718 repo_matchvalue(md, s, 0, solvablekeys + 0, &kv);
00719 }
00720 if (keyname || md->stop > SEARCH_NEXT_KEY)
00721 return;
00722 case SOLVABLE_ARCH:
00723 if (s->arch)
00724 {
00725 kv.id = s->arch;
00726 repo_matchvalue(md, s, 0, solvablekeys + 1, &kv);
00727 }
00728 if (keyname || md->stop > SEARCH_NEXT_KEY)
00729 return;
00730 case SOLVABLE_EVR:
00731 if (s->evr)
00732 {
00733 kv.id = s->evr;
00734 repo_matchvalue(md, s, 0, solvablekeys + 2, &kv);
00735 }
00736 if (keyname || md->stop > SEARCH_NEXT_KEY)
00737 return;
00738 case SOLVABLE_VENDOR:
00739 if (s->vendor)
00740 {
00741 kv.id = s->vendor;
00742 repo_matchvalue(md, s, 0, solvablekeys + 3, &kv);
00743 }
00744 if (keyname || md->stop > SEARCH_NEXT_KEY)
00745 return;
00746 case SOLVABLE_PROVIDES:
00747 if (s->provides)
00748 domatch_idarray(s, SOLVABLE_PROVIDES, md, repo->idarraydata + s->provides);
00749 if (keyname || md->stop > SEARCH_NEXT_KEY)
00750 return;
00751 case SOLVABLE_OBSOLETES:
00752 if (s->obsoletes)
00753 domatch_idarray(s, SOLVABLE_OBSOLETES, md, repo->idarraydata + s->obsoletes);
00754 if (keyname || md->stop > SEARCH_NEXT_KEY)
00755 return;
00756 case SOLVABLE_CONFLICTS:
00757 if (s->conflicts)
00758 domatch_idarray(s, SOLVABLE_CONFLICTS, md, repo->idarraydata + s->conflicts);
00759 if (keyname || md->stop > SEARCH_NEXT_KEY)
00760 return;
00761 case SOLVABLE_REQUIRES:
00762 if (s->requires)
00763 domatch_idarray(s, SOLVABLE_REQUIRES, md, repo->idarraydata + s->requires);
00764 if (keyname || md->stop > SEARCH_NEXT_KEY)
00765 return;
00766 case SOLVABLE_RECOMMENDS:
00767 if (s->recommends)
00768 domatch_idarray(s, SOLVABLE_RECOMMENDS, md, repo->idarraydata + s->recommends);
00769 if (keyname || md->stop > SEARCH_NEXT_KEY)
00770 return;
00771 case SOLVABLE_SUPPLEMENTS:
00772 if (s->supplements)
00773 domatch_idarray(s, SOLVABLE_SUPPLEMENTS, md, repo->idarraydata + s->supplements);
00774 if (keyname || md->stop > SEARCH_NEXT_KEY)
00775 return;
00776 case SOLVABLE_SUGGESTS:
00777 if (s->suggests)
00778 domatch_idarray(s, SOLVABLE_SUGGESTS, md, repo->idarraydata + s->suggests);
00779 if (keyname || md->stop > SEARCH_NEXT_KEY)
00780 return;
00781 case SOLVABLE_ENHANCES:
00782 if (s->enhances)
00783 domatch_idarray(s, SOLVABLE_ENHANCES, md, repo->idarraydata + s->enhances);
00784 if (keyname || md->stop > SEARCH_NEXT_KEY)
00785 return;
00786 case RPM_RPMDBID:
00787 if (repo->rpmdbid)
00788 {
00789 kv.num = repo->rpmdbid[p - repo->start];
00790 repo_matchvalue(md, s, 0, solvablekeys + (RPM_RPMDBID - SOLVABLE_NAME), &kv);
00791 }
00792 if (keyname || md->stop > SEARCH_NEXT_KEY)
00793 return;
00794 break;
00795 default:
00796 break;
00797 }
00798 }
00799
00800 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
00801 {
00802 if (p < data->start || p >= data->end)
00803 continue;
00804 if (keyname && !repodata_precheck_keyname(data, keyname))
00805 continue;
00806 if (keyname == SOLVABLE_FILELIST && !(md->flags & SEARCH_COMPLETE_FILELIST))
00807 {
00808
00809 if (data->state != REPODATA_AVAILABLE)
00810 continue;
00811 for (j = 1; j < data->nkeys; j++)
00812 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
00813 break;
00814 if (j == data->nkeys)
00815 continue;
00816 }
00817 if (data->state == REPODATA_STUB)
00818 {
00819 if (keyname)
00820 {
00821 for (j = 1; j < data->nkeys; j++)
00822 if (keyname == data->keys[j].name)
00823 break;
00824 if (j == data->nkeys)
00825 continue;
00826 }
00827
00828 if (data->loadcallback)
00829 data->loadcallback(data);
00830 else
00831 data->state = REPODATA_ERROR;
00832 }
00833 if (data->state == REPODATA_ERROR)
00834 continue;
00835 repodata_search(data, p, keyname, md->flags, repo_matchvalue, md);
00836 if (md->stop > SEARCH_NEXT_KEY)
00837 break;
00838 }
00839 }
00840
00841 void
00842 repo_search(Repo *repo, Id p, Id keyname, const char *match, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
00843 {
00844 struct matchdata md;
00845
00846 if (repo->disabled && !(flags & SEARCH_DISABLED_REPOS))
00847 return;
00848 memset(&md, 0, sizeof(md));
00849 md.pool = repo->pool;
00850 md.flags = flags;
00851 md.callback = callback;
00852 md.callback_data = cbdata;
00853 if (match)
00854 datamatcher_init(&md.matcher, match, flags);
00855 repo_search_md(repo, p, keyname, &md);
00856 if (match)
00857 datamatcher_free(&md.matcher);
00858 }
00859
00860 const char *
00861 repo_lookup_str(Repo *repo, Id entry, Id keyname)
00862 {
00863 Pool *pool = repo->pool;
00864 Repodata *data;
00865 int i;
00866 const char *str;
00867
00868 if (entry >= 0)
00869 {
00870 switch (keyname)
00871 {
00872 case SOLVABLE_NAME:
00873 return id2str(pool, pool->solvables[entry].name);
00874 case SOLVABLE_ARCH:
00875 return id2str(pool, pool->solvables[entry].arch);
00876 case SOLVABLE_EVR:
00877 return id2str(pool, pool->solvables[entry].evr);
00878 case SOLVABLE_VENDOR:
00879 return id2str(pool, pool->solvables[entry].vendor);
00880 }
00881 }
00882 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
00883 {
00884 if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
00885 continue;
00886 if (!repodata_precheck_keyname(data, keyname))
00887 continue;
00888 str = repodata_lookup_str(data, entry, keyname);
00889 if (str)
00890 return str;
00891 if (repodata_lookup_type(data, entry, keyname))
00892 return 0;
00893 }
00894 return 0;
00895 }
00896
00897
00898 unsigned int
00899 repo_lookup_num(Repo *repo, Id entry, Id keyname, unsigned int notfound)
00900 {
00901 Repodata *data;
00902 int i;
00903 unsigned int value;
00904
00905 if (entry >= 0)
00906 {
00907 if (keyname == RPM_RPMDBID)
00908 {
00909 if (repo->rpmdbid && entry >= repo->start && entry < repo->end)
00910 return repo->rpmdbid[entry - repo->start];
00911 return notfound;
00912 }
00913 }
00914 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
00915 {
00916 if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
00917 continue;
00918 if (!repodata_precheck_keyname(data, keyname))
00919 continue;
00920 if (repodata_lookup_num(data, entry, keyname, &value))
00921 return value;
00922 if (repodata_lookup_type(data, entry, keyname))
00923 return notfound;
00924 }
00925 return notfound;
00926 }
00927
00928 Id
00929 repo_lookup_id(Repo *repo, Id entry, Id keyname)
00930 {
00931 Repodata *data;
00932 int i;
00933 Id id;
00934
00935 if (entry >= 0)
00936 {
00937 switch (keyname)
00938 {
00939 case SOLVABLE_NAME:
00940 return repo->pool->solvables[entry].name;
00941 case SOLVABLE_ARCH:
00942 return repo->pool->solvables[entry].arch;
00943 case SOLVABLE_EVR:
00944 return repo->pool->solvables[entry].evr;
00945 case SOLVABLE_VENDOR:
00946 return repo->pool->solvables[entry].vendor;
00947 }
00948 }
00949 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
00950 {
00951 if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
00952 continue;
00953 if (!repodata_precheck_keyname(data, keyname))
00954 continue;
00955 id = repodata_lookup_id(data, entry, keyname);
00956 if (id)
00957 return data->localpool ? repodata_globalize_id(data, id, 1) : id;
00958 if (repodata_lookup_type(data, entry, keyname))
00959 return 0;
00960 }
00961 return 0;
00962 }
00963
00964 static int
00965 lookup_idarray_solvable(Repo *repo, Offset off, Queue *q)
00966 {
00967 Id *p;
00968
00969 queue_empty(q);
00970 if (off)
00971 for (p = repo->idarraydata + off; *p; p++)
00972 queue_push(q, *p);
00973 return 1;
00974 }
00975
00976 int
00977 repo_lookup_idarray(Repo *repo, Id entry, Id keyname, Queue *q)
00978 {
00979 Repodata *data;
00980 int i;
00981 if (entry >= 0)
00982 {
00983 switch (keyname)
00984 {
00985 case SOLVABLE_PROVIDES:
00986 return lookup_idarray_solvable(repo, repo->pool->solvables[entry].provides, q);
00987 case SOLVABLE_OBSOLETES:
00988 return lookup_idarray_solvable(repo, repo->pool->solvables[entry].obsoletes, q);
00989 case SOLVABLE_CONFLICTS:
00990 return lookup_idarray_solvable(repo, repo->pool->solvables[entry].conflicts, q);
00991 case SOLVABLE_REQUIRES:
00992 return lookup_idarray_solvable(repo, repo->pool->solvables[entry].requires, q);
00993 case SOLVABLE_RECOMMENDS:
00994 return lookup_idarray_solvable(repo, repo->pool->solvables[entry].recommends, q);
00995 case SOLVABLE_SUGGESTS:
00996 return lookup_idarray_solvable(repo, repo->pool->solvables[entry].suggests, q);
00997 case SOLVABLE_SUPPLEMENTS:
00998 return lookup_idarray_solvable(repo, repo->pool->solvables[entry].supplements, q);
00999 case SOLVABLE_ENHANCES:
01000 return lookup_idarray_solvable(repo, repo->pool->solvables[entry].enhances, q);
01001 }
01002 }
01003 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
01004 {
01005 if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
01006 continue;
01007 if (!repodata_precheck_keyname(data, keyname))
01008 continue;
01009 if (repodata_lookup_idarray(data, entry, keyname, q))
01010 {
01011 if (data->localpool)
01012 {
01013 for (i = 0; i < q->count; i++)
01014 q->elements[i] = repodata_globalize_id(data, q->elements[i], 1);
01015 }
01016 return 1;
01017 }
01018 if (repodata_lookup_type(data, entry, keyname))
01019 break;
01020 }
01021 queue_empty(q);
01022 return 0;
01023 }
01024
01025 const unsigned char *
01026 repo_lookup_bin_checksum(Repo *repo, Id entry, Id keyname, Id *typep)
01027 {
01028 Repodata *data;
01029 int i;
01030 const unsigned char *chk;
01031
01032 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
01033 {
01034 if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
01035 continue;
01036 if (!repodata_precheck_keyname(data, keyname))
01037 continue;
01038 chk = repodata_lookup_bin_checksum(data, entry, keyname, typep);
01039 if (chk)
01040 return chk;
01041 if (repodata_lookup_type(data, entry, keyname))
01042 return 0;
01043 }
01044 *typep = 0;
01045 return 0;
01046 }
01047
01048 const char *
01049 repo_lookup_checksum(Repo *repo, Id entry, Id keyname, Id *typep)
01050 {
01051 const unsigned char *chk = repo_lookup_bin_checksum(repo, entry, keyname, typep);
01052 return chk ? pool_bin2hex(repo->pool, chk, sat_chksum_len(*typep)) : 0;
01053 }
01054
01055 int
01056 repo_lookup_void(Repo *repo, Id entry, Id keyname)
01057 {
01058 Repodata *data;
01059 int i;
01060 Id type;
01061
01062 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
01063 {
01064 if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
01065 continue;
01066 if (!repodata_precheck_keyname(data, keyname))
01067 continue;
01068 type = repodata_lookup_type(data, entry, keyname);
01069 if (type)
01070 return type == REPOKEY_TYPE_VOID;
01071 }
01072 return 0;
01073 }
01074
01075 Id
01076 repo_lookup_type(Repo *repo, Id entry, Id keyname)
01077 {
01078 Repodata *data;
01079 int i;
01080 Id type;
01081
01082 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
01083 {
01084 if (entry != SOLVID_META && (entry < data->start || entry >= data->end))
01085 continue;
01086 if (!repodata_precheck_keyname(data, keyname))
01087 continue;
01088 type = repodata_lookup_type(data, entry, keyname);
01089 if (type)
01090 return type == REPOKEY_TYPE_DELETED ? 0 : type;
01091 }
01092 return 0;
01093 }
01094
01095
01096
01097 Repodata *
01098 repo_add_repodata(Repo *repo, int flags)
01099 {
01100 int i;
01101 if ((flags & REPO_USE_LOADING) != 0)
01102 {
01103 for (i = repo->nrepodata - 1; i >= 0; i--)
01104 if (repo->repodata[i].state == REPODATA_LOADING)
01105 {
01106 Repodata *data = repo->repodata + i;
01107
01108
01109 if (!(flags & REPO_REUSE_REPODATA))
01110 repodata_empty(data, (flags & REPO_LOCALPOOL) ? 1 : 0);
01111 return data;
01112 }
01113 return 0;
01114 }
01115 if ((flags & REPO_REUSE_REPODATA) != 0)
01116 {
01117 for (i = repo->nrepodata - 1; i >= 0; i--)
01118 if (repo->repodata[i].state != REPODATA_STUB)
01119 return repo->repodata + i;
01120 }
01121 return repodata_create(repo, (flags & REPO_LOCALPOOL) ? 1 : 0);
01122 }
01123
01124 Repodata *
01125 repo_last_repodata(Repo *repo)
01126 {
01127 int i;
01128 for (i = repo->nrepodata - 1; i >= 0; i--)
01129 if (repo->repodata[i].state != REPODATA_STUB)
01130 return repo->repodata + i;
01131 return repo_add_repodata(repo, 0);
01132 }
01133
01134 void
01135 repo_set_id(Repo *repo, Id p, Id keyname, Id id)
01136 {
01137 Repodata *data;
01138 if (p >= 0)
01139 {
01140 switch (keyname)
01141 {
01142 case SOLVABLE_NAME:
01143 repo->pool->solvables[p].name = id;
01144 return;
01145 case SOLVABLE_ARCH:
01146 repo->pool->solvables[p].arch = id;
01147 return;
01148 case SOLVABLE_EVR:
01149 repo->pool->solvables[p].evr = id;
01150 return;
01151 case SOLVABLE_VENDOR:
01152 repo->pool->solvables[p].vendor = id;
01153 return;
01154 }
01155 }
01156 data = repo_last_repodata(repo);
01157 if (data->localpool)
01158 id = repodata_localize_id(data, id, 1);
01159 repodata_set_id(data, p, keyname, id);
01160 }
01161
01162 void
01163 repo_set_num(Repo *repo, Id p, Id keyname, unsigned int num)
01164 {
01165 Repodata *data;
01166 if (p >= 0)
01167 {
01168 if (keyname == RPM_RPMDBID)
01169 {
01170 if (!repo->rpmdbid)
01171 repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id));
01172 repo->rpmdbid[p] = num;
01173 return;
01174 }
01175 }
01176 data = repo_last_repodata(repo);
01177 repodata_set_num(data, p, keyname, num);
01178 }
01179
01180 void
01181 repo_set_str(Repo *repo, Id p, Id keyname, const char *str)
01182 {
01183 Repodata *data;
01184 if (p >= 0)
01185 {
01186 switch (keyname)
01187 {
01188 case SOLVABLE_NAME:
01189 case SOLVABLE_ARCH:
01190 case SOLVABLE_EVR:
01191 case SOLVABLE_VENDOR:
01192 repo_set_id(repo, p, keyname, str2id(repo->pool, str, 1));
01193 return;
01194 }
01195 }
01196 data = repo_last_repodata(repo);
01197 repodata_set_str(data, p, keyname, str);
01198 }
01199
01200 void
01201 repo_set_poolstr(Repo *repo, Id p, Id keyname, const char *str)
01202 {
01203 Repodata *data;
01204 if (p >= 0)
01205 {
01206 switch (keyname)
01207 {
01208 case SOLVABLE_NAME:
01209 case SOLVABLE_ARCH:
01210 case SOLVABLE_EVR:
01211 case SOLVABLE_VENDOR:
01212 repo_set_id(repo, p, keyname, str2id(repo->pool, str, 1));
01213 return;
01214 }
01215 }
01216 data = repo_last_repodata(repo);
01217 repodata_set_poolstr(data, p, keyname, str);
01218 }
01219
01220 void
01221 repo_add_poolstr_array(Repo *repo, Id p, Id keyname, const char *str)
01222 {
01223 Repodata *data = repo_last_repodata(repo);
01224 repodata_add_poolstr_array(data, p, keyname, str);
01225 }
01226
01227 void
01228 repo_internalize(Repo *repo)
01229 {
01230 int i;
01231 Repodata *data;
01232
01233 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
01234 if (data->attrs || data->xattrs)
01235 repodata_internalize(data);
01236 }
01237
01238 void
01239 repo_disable_paging(Repo *repo)
01240 {
01241 int i;
01242 Repodata *data;
01243
01244 for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
01245 repodata_disable_paging(data);
01246 }
01247
01248
01249
01250