00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #define _GNU_SOURCE
00018 #include <string.h>
00019 #include <fnmatch.h>
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <unistd.h>
00024 #include <assert.h>
00025 #include <regex.h>
00026
00027 #include "repo.h"
00028 #include "pool.h"
00029 #include "poolid_private.h"
00030 #include "util.h"
00031 #include "hash.h"
00032 #include "chksum.h"
00033
00034 #include "repopack.h"
00035 #include "repopage.h"
00036
00037 extern unsigned int compress_buf (const unsigned char *in, unsigned int in_len,
00038 unsigned char *out, unsigned int out_len);
00039 extern unsigned int unchecked_decompress_buf (const unsigned char *in,
00040 unsigned int in_len,
00041 unsigned char *out,
00042 unsigned int out_len);
00043
00044 #define REPODATA_BLOCK 255
00045
00046
00047 void
00048 repodata_initdata(Repodata *data, Repo *repo, int localpool)
00049 {
00050 memset(data, 0, sizeof (*data));
00051 data->repo = repo;
00052 data->localpool = localpool;
00053 if (localpool)
00054 stringpool_init_empty(&data->spool);
00055 data->keys = sat_calloc(1, sizeof(Repokey));
00056 data->nkeys = 1;
00057 data->schemata = sat_calloc(1, sizeof(Id));
00058 data->schemadata = sat_calloc(1, sizeof(Id));
00059 data->nschemata = 1;
00060 data->schemadatalen = 1;
00061 repopagestore_init(&data->store);
00062 }
00063
00064 void
00065 repodata_freedata(Repodata *data)
00066 {
00067 int i;
00068
00069 sat_free(data->keys);
00070
00071 sat_free(data->schemata);
00072 sat_free(data->schemadata);
00073 sat_free(data->schematahash);
00074
00075 stringpool_free(&data->spool);
00076 dirpool_free(&data->dirpool);
00077
00078 sat_free(data->mainschemaoffsets);
00079 sat_free(data->incoredata);
00080 sat_free(data->incoreoffset);
00081 sat_free(data->verticaloffset);
00082
00083 repopagestore_free(&data->store);
00084
00085 sat_free(data->vincore);
00086
00087 if (data->attrs)
00088 for (i = 0; i < data->end - data->start; i++)
00089 sat_free(data->attrs[i]);
00090 sat_free(data->attrs);
00091 if (data->xattrs)
00092 for (i = 0; i < data->nxattrs; i++)
00093 sat_free(data->xattrs[i]);
00094 sat_free(data->xattrs);
00095
00096 sat_free(data->attrdata);
00097 sat_free(data->attriddata);
00098 }
00099
00100 Repodata *
00101 repodata_create(Repo *repo, int localpool)
00102 {
00103 Repodata *data;
00104
00105 repo->nrepodata++;
00106 repo->repodata = sat_realloc2(repo->repodata, repo->nrepodata, sizeof(*data));
00107 data = repo->repodata + repo->nrepodata - 1;
00108 repodata_initdata(data, repo, localpool);
00109 return data;
00110 }
00111
00112 void
00113 repodata_free(Repodata *data)
00114 {
00115 Repo *repo = data->repo;
00116 int i = data - repo->repodata;
00117 repodata_freedata(data);
00118 if (i < repo->nrepodata - 1)
00119 memmove(repo->repodata + i, repo->repodata + i + 1, (repo->nrepodata - 1 - i) * sizeof(Repodata));
00120 repo->nrepodata--;
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130 Id
00131 repodata_key2id(Repodata *data, Repokey *key, int create)
00132 {
00133 Id keyid;
00134
00135 for (keyid = 1; keyid < data->nkeys; keyid++)
00136 if (data->keys[keyid].name == key->name && data->keys[keyid].type == key->type)
00137 {
00138 if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != data->keys[keyid].size)
00139 continue;
00140 break;
00141 }
00142 if (keyid == data->nkeys)
00143 {
00144 if (!create)
00145 return 0;
00146
00147 data->keys = sat_realloc2(data->keys, data->nkeys + 1, sizeof(Repokey));
00148 data->keys[data->nkeys++] = *key;
00149 if (data->verticaloffset)
00150 {
00151 data->verticaloffset = sat_realloc2(data->verticaloffset, data->nkeys, sizeof(Id));
00152 data->verticaloffset[data->nkeys - 1] = 0;
00153 }
00154 data->keybits[(key->name >> 3) & (sizeof(data->keybits) - 1)] |= 1 << (key->name & 7);
00155 }
00156 return keyid;
00157 }
00158
00159
00160
00161
00162
00163
00164 #define SCHEMATA_BLOCK 31
00165 #define SCHEMATADATA_BLOCK 255
00166
00167 Id
00168 repodata_schema2id(Repodata *data, Id *schema, int create)
00169 {
00170 int h, len, i;
00171 Id *sp, cid;
00172 Id *schematahash;
00173
00174 if ((schematahash = data->schematahash) == 0)
00175 {
00176 data->schematahash = schematahash = sat_calloc(256, sizeof(Id));
00177 for (i = 0; i < data->nschemata; i++)
00178 {
00179 for (sp = data->schemadata + data->schemata[i], h = 0; *sp; len++)
00180 h = h * 7 + *sp++;
00181 h &= 255;
00182 schematahash[h] = i + 1;
00183 }
00184 data->schemadata = sat_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
00185 data->schemata = sat_extend_resize(data->schemata, data->nschemata, sizeof(Id), SCHEMATA_BLOCK);
00186 }
00187
00188 for (sp = schema, len = 0, h = 0; *sp; len++)
00189 h = h * 7 + *sp++;
00190 h &= 255;
00191 len++;
00192
00193 cid = schematahash[h];
00194 if (cid)
00195 {
00196 cid--;
00197 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
00198 return cid;
00199
00200 for (cid = 0; cid < data->nschemata; cid++)
00201 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
00202 return cid;
00203 }
00204
00205 if (!create)
00206 return 0;
00207 data->schemadata = sat_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
00208 data->schemata = sat_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
00209
00210 memcpy(data->schemadata + data->schemadatalen, schema, len * sizeof(Id));
00211 data->schemata[data->nschemata] = data->schemadatalen;
00212 data->schemadatalen += len;
00213 schematahash[h] = data->nschemata + 1;
00214 #if 0
00215 fprintf(stderr, "schema2id: new schema\n");
00216 #endif
00217 return data->nschemata++;
00218 }
00219
00220 void
00221 repodata_free_schemahash(Repodata *data)
00222 {
00223 data->schematahash = sat_free(data->schematahash);
00224
00225 data->schemata = sat_realloc2(data->schemata, data->nschemata, sizeof(Id));
00226 data->schemadata = sat_realloc2(data->schemadata, data->schemadatalen, sizeof(Id));
00227 }
00228
00229
00230
00231
00232
00233
00234 Id
00235 repodata_str2dir(Repodata *data, const char *dir, int create)
00236 {
00237 Id id, parent;
00238 const char *dire;
00239
00240 parent = 0;
00241 while (*dir == '/' && dir[1] == '/')
00242 dir++;
00243 if (*dir == '/' && !dir[1])
00244 {
00245 if (data->dirpool.ndirs)
00246 return 1;
00247 return dirpool_add_dir(&data->dirpool, 0, 1, create);
00248 }
00249 while (*dir)
00250 {
00251 dire = strchrnul(dir, '/');
00252 if (data->localpool)
00253 id = stringpool_strn2id(&data->spool, dir, dire - dir, create);
00254 else
00255 id = strn2id(data->repo->pool, dir, dire - dir, create);
00256 if (!id)
00257 return 0;
00258 parent = dirpool_add_dir(&data->dirpool, parent, id, create);
00259 if (!parent)
00260 return 0;
00261 if (!*dire)
00262 break;
00263 dir = dire + 1;
00264 while (*dir == '/')
00265 dir++;
00266 }
00267 return parent;
00268 }
00269
00270 const char *
00271 repodata_dir2str(Repodata *data, Id did, const char *suf)
00272 {
00273 Pool *pool = data->repo->pool;
00274 int l = 0;
00275 Id parent, comp;
00276 const char *comps;
00277 char *p;
00278
00279 if (!did)
00280 return suf ? suf : "";
00281 parent = did;
00282 while (parent)
00283 {
00284 comp = dirpool_compid(&data->dirpool, parent);
00285 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
00286 l += strlen(comps);
00287 parent = dirpool_parent(&data->dirpool, parent);
00288 if (parent)
00289 l++;
00290 }
00291 if (suf)
00292 l += strlen(suf) + 1;
00293 p = pool_alloctmpspace(pool, l + 1) + l;
00294 *p = 0;
00295 if (suf)
00296 {
00297 p -= strlen(suf);
00298 strcpy(p, suf);
00299 *--p = '/';
00300 }
00301 parent = did;
00302 while (parent)
00303 {
00304 comp = dirpool_compid(&data->dirpool, parent);
00305 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
00306 l = strlen(comps);
00307 p -= l;
00308 strncpy(p, comps, l);
00309 parent = dirpool_parent(&data->dirpool, parent);
00310 if (parent)
00311 *--p = '/';
00312 }
00313 return p;
00314 }
00315
00316
00317
00318
00319
00320
00321 static inline unsigned char *
00322 data_skip_schema(Repodata *data, unsigned char *dp, Id schema)
00323 {
00324 Id *keyp = data->schemadata + data->schemata[schema];
00325 for (; *keyp; keyp++)
00326 dp = data_skip_key(data, dp, data->keys + *keyp);
00327 return dp;
00328 }
00329
00330 unsigned char *
00331 data_skip_key(Repodata *data, unsigned char *dp, Repokey *key)
00332 {
00333 int nentries, schema;
00334 switch(key->type)
00335 {
00336 case REPOKEY_TYPE_FIXARRAY:
00337 dp = data_read_id(dp, &nentries);
00338 if (!nentries)
00339 return dp;
00340 dp = data_read_id(dp, &schema);
00341 while (nentries--)
00342 dp = data_skip_schema(data, dp, schema);
00343 return dp;
00344 case REPOKEY_TYPE_FLEXARRAY:
00345 dp = data_read_id(dp, &nentries);
00346 while (nentries--)
00347 {
00348 dp = data_read_id(dp, &schema);
00349 dp = data_skip_schema(data, dp, schema);
00350 }
00351 return dp;
00352 default:
00353 if (key->storage == KEY_STORAGE_INCORE)
00354 dp = data_skip(dp, key->type);
00355 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
00356 {
00357 dp = data_skip(dp, REPOKEY_TYPE_ID);
00358 dp = data_skip(dp, REPOKEY_TYPE_ID);
00359 }
00360 return dp;
00361 }
00362 }
00363
00364 static unsigned char *
00365 forward_to_key(Repodata *data, Id keyid, Id *keyp, unsigned char *dp)
00366 {
00367 Id k;
00368
00369 if (!keyid)
00370 return 0;
00371 if (data->mainschemaoffsets && dp == data->incoredata + data->mainschemaoffsets[0] && keyp == data->schemadata + data->schemata[data->mainschema])
00372 {
00373 int i;
00374 for (i = 0; (k = *keyp++) != 0; i++)
00375 if (k == keyid)
00376 return data->incoredata + data->mainschemaoffsets[i];
00377 return 0;
00378 }
00379 while ((k = *keyp++) != 0)
00380 {
00381 if (k == keyid)
00382 return dp;
00383 if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
00384 {
00385 dp = data_skip(dp, REPOKEY_TYPE_ID);
00386 dp = data_skip(dp, REPOKEY_TYPE_ID);
00387 continue;
00388 }
00389 if (data->keys[k].storage != KEY_STORAGE_INCORE)
00390 continue;
00391 dp = data_skip_key(data, dp, data->keys + k);
00392 }
00393 return 0;
00394 }
00395
00396 static unsigned char *
00397 get_vertical_data(Repodata *data, Repokey *key, Id off, Id len)
00398 {
00399 unsigned char *dp;
00400 if (!len)
00401 return 0;
00402 if (off >= data->lastverticaloffset)
00403 {
00404 off -= data->lastverticaloffset;
00405 if (off + len > data->vincorelen)
00406 return 0;
00407 return data->vincore + off;
00408 }
00409 if (off + len > key->size)
00410 return 0;
00411
00412 off += data->verticaloffset[key - data->keys];
00413
00414 dp = repopagestore_load_page_range(&data->store, off / BLOB_PAGESIZE, (off + len - 1) / BLOB_PAGESIZE);
00415 if (dp)
00416 dp += off % BLOB_PAGESIZE;
00417 return dp;
00418 }
00419
00420 static inline unsigned char *
00421 get_data(Repodata *data, Repokey *key, unsigned char **dpp, int advance)
00422 {
00423 unsigned char *dp = *dpp;
00424
00425 if (!dp)
00426 return 0;
00427 if (key->storage == KEY_STORAGE_INCORE)
00428 {
00429 if (advance)
00430 *dpp = data_skip_key(data, dp, key);
00431 return dp;
00432 }
00433 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
00434 {
00435 Id off, len;
00436 dp = data_read_id(dp, &off);
00437 dp = data_read_id(dp, &len);
00438 if (advance)
00439 *dpp = dp;
00440 return get_vertical_data(data, key, off, len);
00441 }
00442 return 0;
00443 }
00444
00445 static int
00446 load_repodata(Repodata *data)
00447 {
00448 if (data->loadcallback)
00449 {
00450 data->loadcallback(data);
00451 if (data->state == REPODATA_AVAILABLE)
00452 return 1;
00453 }
00454 data->state = REPODATA_ERROR;
00455 return 0;
00456 }
00457
00458 static inline int
00459 maybe_load_repodata(Repodata *data, Id keyname)
00460 {
00461 if (keyname && !repodata_precheck_keyname(data, keyname))
00462 return 0;
00463 switch(data->state)
00464 {
00465 case REPODATA_STUB:
00466 if (keyname)
00467 {
00468 int i;
00469 for (i = 0; i < data->nkeys; i++)
00470 if (keyname == data->keys[i].name)
00471 break;
00472 if (i == data->nkeys)
00473 return 0;
00474 }
00475 return load_repodata(data);
00476 case REPODATA_ERROR:
00477 return 0;
00478 case REPODATA_AVAILABLE:
00479 case REPODATA_LOADING:
00480 return 1;
00481 default:
00482 data->state = REPODATA_ERROR;
00483 return 0;
00484 }
00485 }
00486
00487 static inline unsigned char *
00488 solvid2data(Repodata *data, Id solvid, Id *schemap)
00489 {
00490 unsigned char *dp = data->incoredata;
00491 if (!dp)
00492 return 0;
00493 if (solvid == SOLVID_META)
00494 dp += 1;
00495 else if (solvid == SOLVID_POS)
00496 {
00497 Pool *pool = data->repo->pool;
00498 if (data->repo != pool->pos.repo)
00499 return 0;
00500 if (data != data->repo->repodata + pool->pos.repodataid)
00501 return 0;
00502 *schemap = pool->pos.schema;
00503 return data->incoredata + pool->pos.dp;
00504 }
00505 else
00506 {
00507 if (solvid < data->start || solvid >= data->end)
00508 return 0;
00509 dp += data->incoreoffset[solvid - data->start];
00510 }
00511 return data_read_id(dp, schemap);
00512 }
00513
00514
00515
00516
00517
00518 static inline unsigned char *
00519 find_key_data(Repodata *data, Id solvid, Id keyname, Repokey **keypp)
00520 {
00521 unsigned char *dp;
00522 Id schema, *keyp, *kp;
00523 Repokey *key;
00524
00525 if (!maybe_load_repodata(data, keyname))
00526 return 0;
00527 dp = solvid2data(data, solvid, &schema);
00528 if (!dp)
00529 return 0;
00530 keyp = data->schemadata + data->schemata[schema];
00531 for (kp = keyp; *kp; kp++)
00532 if (data->keys[*kp].name == keyname)
00533 break;
00534 if (!*kp)
00535 return 0;
00536 *keypp = key = data->keys + *kp;
00537 if (key->type == REPOKEY_TYPE_VOID || key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID)
00538 return dp;
00539 dp = forward_to_key(data, *kp, keyp, dp);
00540 if (!dp)
00541 return 0;
00542 return get_data(data, key, &dp, 0);
00543 }
00544
00545
00546 Id
00547 repodata_lookup_id(Repodata *data, Id solvid, Id keyname)
00548 {
00549 unsigned char *dp;
00550 Repokey *key;
00551 Id id;
00552
00553 dp = find_key_data(data, solvid, keyname, &key);
00554 if (!dp)
00555 return 0;
00556 if (key->type == REPOKEY_TYPE_CONSTANTID)
00557 return key->size;
00558 if (key->type != REPOKEY_TYPE_ID)
00559 return 0;
00560 dp = data_read_id(dp, &id);
00561 return id;
00562 }
00563
00564 Id
00565 repodata_globalize_id(Repodata *data, Id id, int create)
00566 {
00567 if (!id || !data || !data->localpool)
00568 return id;
00569 return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
00570 }
00571
00572 const char *
00573 repodata_lookup_str(Repodata *data, Id solvid, Id keyname)
00574 {
00575 unsigned char *dp;
00576 Repokey *key;
00577 Id id;
00578
00579 dp = find_key_data(data, solvid, keyname, &key);
00580 if (!dp)
00581 return 0;
00582 if (key->type == REPOKEY_TYPE_STR)
00583 return (const char *)dp;
00584 if (key->type == REPOKEY_TYPE_CONSTANTID)
00585 return id2str(data->repo->pool, key->size);
00586 if (key->type == REPOKEY_TYPE_ID)
00587 dp = data_read_id(dp, &id);
00588 else
00589 return 0;
00590 if (data->localpool)
00591 return data->spool.stringspace + data->spool.strings[id];
00592 return id2str(data->repo->pool, id);
00593 }
00594
00595 int
00596 repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned int *value)
00597 {
00598 unsigned char *dp;
00599 Repokey *key;
00600 KeyValue kv;
00601
00602 *value = 0;
00603 dp = find_key_data(data, solvid, keyname, &key);
00604 if (!dp)
00605 return 0;
00606 if (key->type == REPOKEY_TYPE_NUM
00607 || key->type == REPOKEY_TYPE_U32
00608 || key->type == REPOKEY_TYPE_CONSTANT)
00609 {
00610 dp = data_fetch(dp, &kv, key);
00611 *value = kv.num;
00612 return 1;
00613 }
00614 return 0;
00615 }
00616
00617 int
00618 repodata_lookup_void(Repodata *data, Id solvid, Id keyname)
00619 {
00620 Id schema;
00621 Id *keyp;
00622 unsigned char *dp;
00623
00624 if (!maybe_load_repodata(data, keyname))
00625 return 0;
00626 dp = solvid2data(data, solvid, &schema);
00627 if (!dp)
00628 return 0;
00629
00630 for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++)
00631 if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID)
00632 return 1;
00633 return 0;
00634 }
00635
00636 const unsigned char *
00637 repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep)
00638 {
00639 unsigned char *dp;
00640 Repokey *key;
00641
00642 dp = find_key_data(data, solvid, keyname, &key);
00643 if (!dp)
00644 return 0;
00645 *typep = key->type;
00646 return dp;
00647 }
00648
00649 int
00650 repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
00651 {
00652 unsigned char *dp;
00653 Repokey *key;
00654 Id id;
00655 int eof = 0;
00656
00657 queue_empty(q);
00658 dp = find_key_data(data, solvid, keyname, &key);
00659 if (!dp)
00660 return 0;
00661 for (;;)
00662 {
00663 dp = data_read_ideof(dp, &id, &eof);
00664 queue_push(q, id);
00665 if (eof)
00666 break;
00667 }
00668 return 1;
00669 }
00670
00671
00672
00673
00674
00675
00676 int
00677 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
00678 {
00679 switch (key->type)
00680 {
00681 case REPOKEY_TYPE_ID:
00682 case REPOKEY_TYPE_CONSTANTID:
00683 case REPOKEY_TYPE_IDARRAY:
00684 if (data && data->localpool)
00685 kv->str = stringpool_id2str(&data->spool, kv->id);
00686 else
00687 kv->str = id2str(pool, kv->id);
00688 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
00689 {
00690 const char *s;
00691 for (s = kv->str; *s >= 'a' && *s <= 'z'; s++)
00692 ;
00693 if (*s == ':' && s > kv->str)
00694 kv->str = s + 1;
00695 }
00696 return 1;
00697 case REPOKEY_TYPE_STR:
00698 return 1;
00699 case REPOKEY_TYPE_DIRSTRARRAY:
00700 if (!(flags & SEARCH_FILES))
00701 return 1;
00702
00703 kv->str = repodata_dir2str(data, kv->id, kv->str);
00704
00705
00706
00707 kv->id = 0;
00708 return 1;
00709 case REPOKEY_TYPE_MD5:
00710 case REPOKEY_TYPE_SHA1:
00711 case REPOKEY_TYPE_SHA256:
00712 if (!(flags & SEARCH_CHECKSUMS))
00713 return 0;
00714 kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str);
00715 return 1;
00716 default:
00717 return 0;
00718 }
00719 }
00720
00721
00722 struct subschema_data {
00723 Solvable *s;
00724 void *cbdata;
00725 KeyValue *parent;
00726 };
00727
00728
00729 void
00730 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
00731 {
00732 Id schema;
00733 Repokey *key;
00734 Id keyid, *kp, *keyp;
00735 unsigned char *dp, *ddp;
00736 int onekey = 0;
00737 int stop;
00738 KeyValue kv;
00739 Solvable *s;
00740
00741 if (!maybe_load_repodata(data, keyname))
00742 return;
00743 if (solvid == SOLVID_SUBSCHEMA)
00744 {
00745 struct subschema_data *subd = cbdata;
00746 cbdata = subd->cbdata;
00747 s = subd->s;
00748 schema = subd->parent->id;
00749 dp = (unsigned char *)subd->parent->str;
00750 kv.parent = subd->parent;
00751 }
00752 else
00753 {
00754 schema = 0;
00755 dp = solvid2data(data, solvid, &schema);
00756 if (!dp)
00757 return;
00758 s = data->repo->pool->solvables + solvid;
00759 kv.parent = 0;
00760 }
00761 keyp = data->schemadata + data->schemata[schema];
00762 if (keyname)
00763 {
00764
00765 for (kp = keyp; *kp; kp++)
00766 if (data->keys[*kp].name == keyname)
00767 break;
00768 if (!*kp)
00769 return;
00770 dp = forward_to_key(data, *kp, keyp, dp);
00771 if (!dp)
00772 return;
00773 keyp = kp;
00774 onekey = 1;
00775 }
00776 while ((keyid = *keyp++) != 0)
00777 {
00778 stop = 0;
00779 key = data->keys + keyid;
00780 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
00781
00782 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
00783 {
00784 struct subschema_data subd;
00785 int nentries;
00786 Id schema = 0;
00787
00788 subd.cbdata = cbdata;
00789 subd.s = s;
00790 subd.parent = &kv;
00791 ddp = data_read_id(ddp, &nentries);
00792 kv.num = nentries;
00793 kv.entry = 0;
00794 kv.eof = 0;
00795 while (ddp && nentries > 0)
00796 {
00797 if (!--nentries)
00798 kv.eof = 1;
00799 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
00800 ddp = data_read_id(ddp, &schema);
00801 kv.id = schema;
00802 kv.str = (char *)ddp;
00803 stop = callback(cbdata, s, data, key, &kv);
00804 if (stop > SEARCH_NEXT_KEY)
00805 return;
00806 if (stop && stop != SEARCH_ENTERSUB)
00807 break;
00808 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
00809 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
00810 ddp = data_skip_schema(data, ddp, schema);
00811 kv.entry++;
00812 }
00813 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
00814 {
00815
00816 kv.eof = 2;
00817 kv.str = (char *)ddp;
00818 stop = callback(cbdata, s, data, key, &kv);
00819 if (stop > SEARCH_NEXT_KEY)
00820 return;
00821 }
00822 if (onekey)
00823 return;
00824 continue;
00825 }
00826 kv.entry = 0;
00827 do
00828 {
00829 ddp = data_fetch(ddp, &kv, key);
00830 if (!ddp)
00831 break;
00832 stop = callback(cbdata, s, data, key, &kv);
00833 kv.entry++;
00834 }
00835 while (!kv.eof && !stop);
00836 if (onekey || stop > SEARCH_NEXT_KEY)
00837 return;
00838 }
00839 }
00840
00841 void
00842 repodata_setpos_kv(Repodata *data, KeyValue *kv)
00843 {
00844 Pool *pool = data->repo->pool;
00845 if (!kv)
00846 pool_clear_pos(pool);
00847 else
00848 {
00849 pool->pos.repo = data->repo;
00850 pool->pos.repodataid = data - data->repo->repodata;
00851 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
00852 pool->pos.schema = kv->id;
00853 }
00854 }
00855
00856
00857
00858
00859
00860 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
00861 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
00862 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
00863 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
00864 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
00865 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00866 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00867 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00868 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00869 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00870 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00871 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00872 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
00873 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
00874 };
00875
00876 static inline Id *
00877 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
00878 {
00879 kv->id = keyname;
00880 switch (keyname)
00881 {
00882 case SOLVABLE_NAME:
00883 kv->eof = 1;
00884 return &s->name;
00885 case SOLVABLE_ARCH:
00886 kv->eof = 1;
00887 return &s->arch;
00888 case SOLVABLE_EVR:
00889 kv->eof = 1;
00890 return &s->evr;
00891 case SOLVABLE_VENDOR:
00892 kv->eof = 1;
00893 return &s->vendor;
00894 case SOLVABLE_PROVIDES:
00895 kv->eof = 0;
00896 return s->provides ? s->repo->idarraydata + s->provides : 0;
00897 case SOLVABLE_OBSOLETES:
00898 kv->eof = 0;
00899 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
00900 case SOLVABLE_CONFLICTS:
00901 kv->eof = 0;
00902 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
00903 case SOLVABLE_REQUIRES:
00904 kv->eof = 0;
00905 return s->requires ? s->repo->idarraydata + s->requires : 0;
00906 case SOLVABLE_RECOMMENDS:
00907 kv->eof = 0;
00908 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
00909 case SOLVABLE_SUPPLEMENTS:
00910 kv->eof = 0;
00911 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
00912 case SOLVABLE_SUGGESTS:
00913 kv->eof = 0;
00914 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
00915 case SOLVABLE_ENHANCES:
00916 kv->eof = 0;
00917 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
00918 case RPM_RPMDBID:
00919 kv->eof = 1;
00920 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
00921 default:
00922 return 0;
00923 }
00924 }
00925
00926 int
00927 datamatcher_init(Datamatcher *ma, const char *match, int flags)
00928 {
00929 ma->match = match;
00930 ma->flags = flags;
00931 ma->error = 0;
00932 ma->matchdata = 0;
00933 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
00934 {
00935 ma->matchdata = sat_calloc(1, sizeof(regex_t));
00936 ma->error = regcomp((regex_t *)ma->matchdata, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
00937 if (ma->error)
00938 {
00939 sat_free(ma->matchdata);
00940 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
00941 }
00942 }
00943 return ma->error;
00944 }
00945
00946 void
00947 datamatcher_free(Datamatcher *ma)
00948 {
00949 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
00950 {
00951 regfree(ma->matchdata);
00952 ma->matchdata = sat_free(ma->matchdata);
00953 }
00954 }
00955
00956 int
00957 datamatcher_match(Datamatcher *ma, const char *str)
00958 {
00959 int l;
00960 switch ((ma->flags & SEARCH_STRINGMASK))
00961 {
00962 case SEARCH_SUBSTRING:
00963 if (ma->flags & SEARCH_NOCASE)
00964 {
00965 if (!strcasestr(str, ma->match))
00966 return 0;
00967 }
00968 else
00969 {
00970 if (!strstr(str, ma->match))
00971 return 0;
00972 }
00973 break;
00974 case SEARCH_STRING:
00975 if (ma->flags & SEARCH_NOCASE)
00976 {
00977 if (strcasecmp(ma->match, str))
00978 return 0;
00979 }
00980 else
00981 {
00982 if (strcmp(ma->match, str))
00983 return 0;
00984 }
00985 break;
00986 case SEARCH_STRINGSTART:
00987 if (ma->flags & SEARCH_NOCASE)
00988 {
00989 if (strncasecmp(ma->match, str, strlen(ma->match)))
00990 return 0;
00991 }
00992 else
00993 {
00994 if (strncmp(ma->match, str, strlen(ma->match)))
00995 return 0;
00996 }
00997 break;
00998 case SEARCH_STRINGEND:
00999 l = strlen(str) - strlen(ma->match);
01000 if (l < 0)
01001 return 0;
01002 if (ma->flags & SEARCH_NOCASE)
01003 {
01004 if (strcasecmp(ma->match, str + l))
01005 return 0;
01006 }
01007 else
01008 {
01009 if (strcmp(ma->match, str + l))
01010 return 0;
01011 }
01012 break;
01013 case SEARCH_GLOB:
01014 if (fnmatch(ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
01015 return 0;
01016 break;
01017 case SEARCH_REGEX:
01018 if (regexec((const regex_t *)ma->matchdata, str, 0, NULL, 0))
01019 return 0;
01020 break;
01021 default:
01022 return 0;
01023 }
01024 return 1;
01025 }
01026
01027 int
01028 repodata_filelistfilter_matches(Repodata *data, const char *str)
01029 {
01030
01031
01032 if (strstr(str, "bin/"))
01033 return 1;
01034 if (!strncmp(str, "/etc/", 5))
01035 return 1;
01036 if (!strcmp(str, "/usr/lib/sendmail"))
01037 return 1;
01038 return 0;
01039 }
01040
01041
01042 enum {
01043 di_bye,
01044
01045 di_enterrepo,
01046 di_entersolvable,
01047 di_enterrepodata,
01048 di_enterschema,
01049 di_enterkey,
01050
01051 di_nextattr,
01052 di_nextkey,
01053 di_nextrepodata,
01054 di_nextsolvable,
01055 di_nextrepo,
01056
01057 di_enterarray,
01058 di_nextarrayelement,
01059
01060 di_entersub,
01061 di_leavesub,
01062
01063 di_nextsolvableattr,
01064 di_nextsolvablekey,
01065 di_entersolvablekey
01066 };
01067
01068
01069 int
01070 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
01071 {
01072 memset(di, 0, sizeof(*di));
01073 di->pool = pool;
01074 di->flags = flags & ~SEARCH_THISSOLVID;
01075 if (!pool || (repo && repo->pool != pool))
01076 {
01077 di->state = di_bye;
01078 return -1;
01079 }
01080 if (match)
01081 {
01082 int error;
01083 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
01084 {
01085 di->state = di_bye;
01086 return error;
01087 }
01088 }
01089 di->keyname = keyname;
01090 di->keynames[0] = keyname;
01091 dataiterator_set_search(di, repo, p);
01092 return 0;
01093 }
01094
01095 void
01096 dataiterator_init_clone(Dataiterator *di, Dataiterator *from)
01097 {
01098 *di = *from;
01099 memset(&di->matcher, 0, sizeof(di->matcher));
01100 if (from->matcher.match)
01101 datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags);
01102 if (di->nparents)
01103 {
01104
01105 int i;
01106 for (i = 1; i < di->nparents; i++)
01107 di->parents[i].kv.parent = &di->parents[i - 1].kv;
01108 di->kv.parent = &di->parents[di->nparents - 1].kv;
01109 }
01110 }
01111
01112 int
01113 dataiterator_set_match(Dataiterator *di, const char *match, int flags)
01114 {
01115 di->flags = (flags & ~SEARCH_THISSOLVID) | (di->flags & SEARCH_THISSOLVID);
01116 datamatcher_free(&di->matcher);
01117 memset(&di->matcher, 0, sizeof(di->matcher));
01118 if (match)
01119 {
01120 int error;
01121 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
01122 {
01123 di->state = di_bye;
01124 return error;
01125 }
01126 }
01127 return 0;
01128 }
01129
01130 void
01131 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
01132 {
01133 di->repo = repo;
01134 di->repoid = -1;
01135 di->flags &= ~SEARCH_THISSOLVID;
01136 di->nparents = 0;
01137 di->rootlevel = 0;
01138 di->repodataid = 0;
01139 if (!di->pool->nrepos)
01140 {
01141 di->state = di_bye;
01142 return;
01143 }
01144 if (!repo)
01145 {
01146 di->repoid = 0;
01147 di->repo = di->pool->repos[0];
01148 }
01149 di->state = di_enterrepo;
01150 if (p)
01151 dataiterator_jump_to_solvid(di, p);
01152 }
01153
01154 void
01155 dataiterator_set_keyname(Dataiterator *di, Id keyname)
01156 {
01157 di->nkeynames = 0;
01158 di->keyname = keyname;
01159 di->keynames[0] = keyname;
01160 }
01161
01162 void
01163 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
01164 {
01165 int i;
01166
01167 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
01168 {
01169 di->state = di_bye;
01170 return;
01171 }
01172 for (i = di->nkeynames + 1; i > 0; i--)
01173 di->keynames[i] = di->keynames[i - 1];
01174 di->keynames[0] = di->keyname = keyname;
01175 di->nkeynames++;
01176 }
01177
01178 void
01179 dataiterator_free(Dataiterator *di)
01180 {
01181 if (di->matcher.match)
01182 datamatcher_free(&di->matcher);
01183 }
01184
01185 static inline unsigned char *
01186 dataiterator_find_keyname(Dataiterator *di, Id keyname)
01187 {
01188 Id *keyp = di->keyp;
01189 Repokey *keys = di->data->keys;
01190 unsigned char *dp;
01191
01192 for (keyp = di->keyp; *keyp; keyp++)
01193 if (keys[*keyp].name == keyname)
01194 break;
01195 if (!*keyp)
01196 return 0;
01197 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
01198 if (!dp)
01199 return 0;
01200 di->keyp = keyp;
01201 return dp;
01202 }
01203
01204 static int
01205 dataiterator_filelistcheck(Dataiterator *di)
01206 {
01207 int j;
01208 int needcomplete = 0;
01209 Repodata *data = di->data;
01210
01211 if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
01212 if (!di->matcher.match || (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING || !repodata_filelistfilter_matches(di->data, di->matcher.match))
01213 needcomplete = 1;
01214 if (data->state != REPODATA_AVAILABLE)
01215 return needcomplete ? 1 : 0;
01216 for (j = 1; j < data->nkeys; j++)
01217 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
01218 break;
01219 return j == data->nkeys && !needcomplete ? 0 : 1;
01220 }
01221
01222 int
01223 dataiterator_step(Dataiterator *di)
01224 {
01225 Id schema;
01226
01227 for (;;)
01228 {
01229 switch (di->state)
01230 {
01231 case di_enterrepo: di_enterrepo:
01232 if (!di->repo)
01233 goto di_bye;
01234 if (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS))
01235 goto di_nextrepo;
01236 if (!(di->flags & SEARCH_THISSOLVID))
01237 {
01238 di->solvid = di->repo->start - 1;
01239 goto di_nextsolvable;
01240 }
01241
01242
01243 case di_entersolvable: di_entersolvable:
01244 if (di->repodataid >= 0)
01245 {
01246 di->repodataid = 0;
01247 if (di->solvid > 0 && !(di->flags & SEARCH_NO_STORAGE_SOLVABLE) && (!di->keyname || (di->keyname >= SOLVABLE_NAME && di->keyname <= RPM_RPMDBID)) && di->nparents - di->rootlevel == di->nkeynames)
01248 {
01249 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
01250 di->data = 0;
01251 goto di_entersolvablekey;
01252 }
01253 }
01254
01255
01256 case di_enterrepodata: di_enterrepodata:
01257 if (di->repodataid >= 0)
01258 {
01259 if (di->repodataid >= di->repo->nrepodata)
01260 goto di_nextsolvable;
01261 di->data = di->repo->repodata + di->repodataid;
01262 }
01263 if (di->repodataid >= 0 && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
01264 goto di_nextrepodata;
01265 if (!maybe_load_repodata(di->data, di->keyname))
01266 goto di_nextrepodata;
01267 di->dp = solvid2data(di->data, di->solvid, &schema);
01268 if (!di->dp)
01269 goto di_nextrepodata;
01270 if (di->solvid == SOLVID_POS)
01271 di->solvid = di->pool->pos.solvid;
01272
01273 di->keyp = di->data->schemadata + di->data->schemata[schema];
01274
01275
01276 case di_enterschema: di_enterschema:
01277 if (di->keyname)
01278 di->dp = dataiterator_find_keyname(di, di->keyname);
01279 if (!di->dp || !*di->keyp)
01280 {
01281 if (di->kv.parent)
01282 goto di_leavesub;
01283 goto di_nextrepodata;
01284 }
01285
01286
01287 case di_enterkey: di_enterkey:
01288 di->kv.entry = -1;
01289 di->key = di->data->keys + *di->keyp;
01290 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
01291 if (!di->ddp)
01292 goto di_nextkey;
01293 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
01294 goto di_enterarray;
01295 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
01296 goto di_nextkey;
01297
01298
01299 case di_nextattr:
01300 di->kv.entry++;
01301 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
01302 if (di->kv.eof)
01303 di->state = di_nextkey;
01304 else
01305 di->state = di_nextattr;
01306 break;
01307
01308 case di_nextkey: di_nextkey:
01309 if (!di->keyname && *++di->keyp)
01310 goto di_enterkey;
01311 if (di->kv.parent)
01312 goto di_leavesub;
01313
01314
01315 case di_nextrepodata: di_nextrepodata:
01316 if (di->repodataid >= 0 && ++di->repodataid < di->repo->nrepodata)
01317 goto di_enterrepodata;
01318
01319
01320 case di_nextsolvable: di_nextsolvable:
01321 if (!(di->flags & SEARCH_THISSOLVID))
01322 {
01323 if (di->solvid < 0)
01324 di->solvid = di->repo->start;
01325 else
01326 di->solvid++;
01327 for (; di->solvid < di->repo->end; di->solvid++)
01328 {
01329 if (di->pool->solvables[di->solvid].repo == di->repo)
01330 goto di_entersolvable;
01331 }
01332 }
01333
01334
01335 case di_nextrepo: di_nextrepo:
01336 if (di->repoid >= 0)
01337 {
01338 di->repoid++;
01339 di->repodataid = 0;
01340 if (di->repoid < di->pool->nrepos)
01341 {
01342 di->repo = di->pool->repos[di->repoid];
01343 goto di_enterrepo;
01344 }
01345 }
01346
01347
01348 case di_bye: di_bye:
01349 di->state = di_bye;
01350 return 0;
01351
01352 case di_enterarray: di_enterarray:
01353 if (di->key->name == REPOSITORY_SOLVABLES)
01354 goto di_nextkey;
01355 di->ddp = data_read_id(di->ddp, &di->kv.num);
01356 di->kv.eof = 0;
01357 di->kv.entry = -1;
01358
01359
01360 case di_nextarrayelement: di_nextarrayelement:
01361 di->kv.entry++;
01362 if (di->kv.entry)
01363 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
01364 if (di->kv.entry == di->kv.num)
01365 {
01366 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
01367 goto di_nextkey;
01368 if (!(di->flags & SEARCH_ARRAYSENTINEL))
01369 goto di_nextkey;
01370 di->kv.str = (char *)di->ddp;
01371 di->kv.eof = 2;
01372 di->state = di_nextkey;
01373 break;
01374 }
01375 if (di->kv.entry == di->kv.num - 1)
01376 di->kv.eof = 1;
01377 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
01378 di->ddp = data_read_id(di->ddp, &di->kv.id);
01379 di->kv.str = (char *)di->ddp;
01380 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
01381 goto di_entersub;
01382 if ((di->flags & SEARCH_SUB) != 0)
01383 di->state = di_entersub;
01384 else
01385 di->state = di_nextarrayelement;
01386 break;
01387
01388 case di_entersub: di_entersub:
01389 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
01390 goto di_nextarrayelement;
01391 di->parents[di->nparents].kv = di->kv;
01392 di->parents[di->nparents].dp = di->dp;
01393 di->parents[di->nparents].keyp = di->keyp;
01394 di->dp = (unsigned char *)di->kv.str;
01395 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
01396 memset(&di->kv, 0, sizeof(di->kv));
01397 di->kv.parent = &di->parents[di->nparents].kv;
01398 di->nparents++;
01399 di->keyname = di->keynames[di->nparents - di->rootlevel];
01400 goto di_enterschema;
01401
01402 case di_leavesub: di_leavesub:
01403 if (di->nparents - 1 < di->rootlevel)
01404 goto di_bye;
01405 di->nparents--;
01406 di->dp = di->parents[di->nparents].dp;
01407 di->kv = di->parents[di->nparents].kv;
01408 di->keyp = di->parents[di->nparents].keyp;
01409 di->key = di->data->keys + *di->keyp;
01410 di->ddp = (unsigned char *)di->kv.str;
01411 di->keyname = di->keynames[di->nparents - di->rootlevel];
01412 goto di_nextarrayelement;
01413
01414
01415
01416 case di_nextsolvableattr:
01417 di->kv.id = *di->idp++;
01418 di->kv.entry++;
01419 if (!*di->idp)
01420 {
01421 di->kv.eof = 1;
01422 di->state = di_nextsolvablekey;
01423 }
01424 break;
01425
01426 case di_nextsolvablekey: di_nextsolvablekey:
01427 if (di->keyname || di->key->name == RPM_RPMDBID)
01428 goto di_enterrepodata;
01429 di->key++;
01430
01431
01432 case di_entersolvablekey: di_entersolvablekey:
01433 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
01434 if (!di->idp || !di->idp[0])
01435 goto di_nextsolvablekey;
01436 di->kv.id = di->idp[0];
01437 di->kv.num = di->idp[0];
01438 di->idp++;
01439 if (!di->kv.eof && !di->idp[0])
01440 di->kv.eof = 1;
01441 di->kv.entry = 0;
01442 if (di->kv.eof)
01443 di->state = di_nextsolvablekey;
01444 else
01445 di->state = di_nextsolvableattr;
01446 break;
01447 }
01448
01449 if (di->matcher.match)
01450 {
01451
01452 if (di->keyname == SOLVABLE_FILELIST && di->key->type == REPOKEY_TYPE_DIRSTRARRAY && di->matcher.match && (di->matcher.flags & (SEARCH_FILES|SEARCH_NOCASE|SEARCH_STRINGMASK)) == (SEARCH_FILES|SEARCH_STRING))
01453 {
01454 int l = strlen(di->matcher.match) - strlen(di->kv.str);
01455 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
01456 continue;
01457 }
01458 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
01459 {
01460 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
01461 return 1;
01462 continue;
01463 }
01464 if (!datamatcher_match(&di->matcher, di->kv.str))
01465 continue;
01466 }
01467
01468 return 1;
01469 }
01470 }
01471
01472 void
01473 dataiterator_entersub(Dataiterator *di)
01474 {
01475 if (di->state == di_nextarrayelement)
01476 di->state = di_entersub;
01477 }
01478
01479 void
01480 dataiterator_setpos(Dataiterator *di)
01481 {
01482 if (di->kv.eof == 2)
01483 {
01484 pool_clear_pos(di->pool);
01485 return;
01486 }
01487 di->pool->pos.solvid = di->solvid;
01488 di->pool->pos.repo = di->repo;
01489 di->pool->pos.repodataid = di->data - di->repo->repodata;
01490 di->pool->pos.schema = di->kv.id;
01491 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
01492 }
01493
01494 void
01495 dataiterator_setpos_parent(Dataiterator *di)
01496 {
01497 if (!di->kv.parent || di->kv.parent->eof == 2)
01498 {
01499 pool_clear_pos(di->pool);
01500 return;
01501 }
01502 di->pool->pos.solvid = di->solvid;
01503 di->pool->pos.repo = di->repo;
01504 di->pool->pos.repodataid = di->data - di->repo->repodata;
01505 di->pool->pos.schema = di->kv.parent->id;
01506 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
01507 }
01508
01509
01510 void
01511 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
01512 {
01513 di->state = from->state;
01514 di->flags &= ~SEARCH_THISSOLVID;
01515 di->flags |= (from->flags & SEARCH_THISSOLVID);
01516 di->repo = from->repo;
01517 di->data = from->data;
01518 di->dp = from->dp;
01519 di->ddp = from->ddp;
01520 di->idp = from->idp;
01521 di->keyp = from->keyp;
01522 di->key = from->key;
01523 di->kv = from->kv;
01524 di->repodataid = from->repodataid;
01525 di->solvid = from->solvid;
01526 di->repoid = from->repoid;
01527 di->rootlevel = from->rootlevel;
01528 memcpy(di->parents, from->parents, sizeof(from->parents));
01529 di->nparents = from->nparents;
01530 if (di->nparents)
01531 {
01532 int i;
01533 for (i = 1; i < di->nparents; i++)
01534 di->parents[i].kv.parent = &di->parents[i - 1].kv;
01535 di->kv.parent = &di->parents[di->nparents - 1].kv;
01536 }
01537 }
01538
01539 void
01540 dataiterator_seek(Dataiterator *di, int whence)
01541 {
01542 if ((whence & DI_SEEK_STAY) != 0)
01543 di->rootlevel = di->nparents;
01544 switch (whence & ~DI_SEEK_STAY)
01545 {
01546 case DI_SEEK_CHILD:
01547 if (di->state != di_nextarrayelement)
01548 break;
01549 if ((whence & DI_SEEK_STAY) != 0)
01550 di->rootlevel = di->nparents + 1;
01551 di->state = di_entersub;
01552 break;
01553 case DI_SEEK_PARENT:
01554 if (!di->nparents)
01555 {
01556 di->state = di_bye;
01557 break;
01558 }
01559 di->nparents--;
01560 if (di->rootlevel > di->nparents)
01561 di->rootlevel = di->nparents;
01562 di->dp = di->parents[di->nparents].dp;
01563 di->kv = di->parents[di->nparents].kv;
01564 di->keyp = di->parents[di->nparents].keyp;
01565 di->key = di->data->keys + *di->keyp;
01566 di->ddp = (unsigned char *)di->kv.str;
01567 di->keyname = di->keynames[di->nparents - di->rootlevel];
01568 di->state = di_nextarrayelement;
01569 break;
01570 case DI_SEEK_REWIND:
01571 if (!di->nparents)
01572 {
01573 di->state = di_bye;
01574 break;
01575 }
01576 di->dp = (unsigned char *)di->kv.parent->str;
01577 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
01578 di->state = di_enterschema;
01579 break;
01580 default:
01581 break;
01582 }
01583 }
01584
01585 void
01586 dataiterator_skip_attribute(Dataiterator *di)
01587 {
01588 if (di->state == di_nextsolvableattr)
01589 di->state = di_nextsolvablekey;
01590 else
01591 di->state = di_nextkey;
01592 }
01593
01594 void
01595 dataiterator_skip_solvable(Dataiterator *di)
01596 {
01597 di->nparents = 0;
01598 di->kv.parent = 0;
01599 di->rootlevel = 0;
01600 di->keyname = di->keynames[0];
01601 di->state = di_nextsolvable;
01602 }
01603
01604 void
01605 dataiterator_skip_repo(Dataiterator *di)
01606 {
01607 di->nparents = 0;
01608 di->kv.parent = 0;
01609 di->rootlevel = 0;
01610 di->keyname = di->keynames[0];
01611 di->state = di_nextrepo;
01612 }
01613
01614 void
01615 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
01616 {
01617 di->nparents = 0;
01618 di->kv.parent = 0;
01619 di->rootlevel = 0;
01620 di->keyname = di->keynames[0];
01621 if (solvid == SOLVID_POS)
01622 {
01623 di->repo = di->pool->pos.repo;
01624 if (!di->repo)
01625 {
01626 di->state = di_bye;
01627 return;
01628 }
01629 di->repoid = -1;
01630 di->data = di->repo->repodata + di->pool->pos.repodataid;
01631 di->repodataid = -1;
01632 di->solvid = solvid;
01633 di->state = di_enterrepo;
01634 di->flags |= SEARCH_THISSOLVID;
01635 return;
01636 }
01637 if (solvid > 0)
01638 {
01639 di->repo = di->pool->solvables[solvid].repo;
01640 di->repoid = -1;
01641 }
01642 else if (di->repoid >= 0)
01643 {
01644 if (!di->pool->nrepos)
01645 {
01646 di->state = di_bye;
01647 return;
01648 }
01649 di->repo = di->pool->repos[0];
01650 di->repoid = 0;
01651 }
01652 di->repodataid = 0;
01653 di->solvid = solvid;
01654 if (solvid)
01655 di->flags |= SEARCH_THISSOLVID;
01656 di->state = di_enterrepo;
01657 }
01658
01659 void
01660 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
01661 {
01662 di->nparents = 0;
01663 di->kv.parent = 0;
01664 di->rootlevel = 0;
01665 di->repo = repo;
01666 di->repoid = -1;
01667 di->repodataid = 0;
01668 di->solvid = 0;
01669 di->flags &= ~SEARCH_THISSOLVID;
01670 di->state = di_enterrepo;
01671 }
01672
01673 int
01674 dataiterator_match(Dataiterator *di, Datamatcher *ma)
01675 {
01676 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
01677 return 0;
01678 if (!ma)
01679 return 1;
01680 return datamatcher_match(ma, di->kv.str);
01681 }
01682
01683
01684
01685
01686
01687
01688 void
01689 repodata_extend(Repodata *data, Id p)
01690 {
01691 if (data->start == data->end)
01692 data->start = data->end = p;
01693 if (p >= data->end)
01694 {
01695 int old = data->end - data->start;
01696 int new = p - data->end + 1;
01697 if (data->attrs)
01698 {
01699 data->attrs = sat_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
01700 memset(data->attrs + old, 0, new * sizeof(Id *));
01701 }
01702 data->incoreoffset = sat_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
01703 memset(data->incoreoffset + old, 0, new * sizeof(Id));
01704 data->end = p + 1;
01705 }
01706 if (p < data->start)
01707 {
01708 int old = data->end - data->start;
01709 int new = data->start - p;
01710 if (data->attrs)
01711 {
01712 data->attrs = sat_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
01713 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
01714 memset(data->attrs, 0, new * sizeof(Id *));
01715 }
01716 data->incoreoffset = sat_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
01717 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
01718 memset(data->incoreoffset, 0, new * sizeof(Id));
01719 data->start = p;
01720 }
01721 }
01722
01723
01724 void
01725 repodata_shrink(Repodata *data, int end)
01726 {
01727 int i;
01728
01729 if (data->end <= end)
01730 return;
01731 if (data->start >= end)
01732 {
01733 if (data->attrs)
01734 {
01735 for (i = 0; i < data->end - data->start; i++)
01736 sat_free(data->attrs[i]);
01737 data->attrs = sat_free(data->attrs);
01738 }
01739 data->incoreoffset = sat_free(data->incoreoffset);
01740 data->start = data->end = 0;
01741 return;
01742 }
01743 if (data->attrs)
01744 {
01745 for (i = end; i < data->end; i++)
01746 sat_free(data->attrs[i - data->start]);
01747 data->attrs = sat_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
01748 }
01749 if (data->incoreoffset)
01750 data->incoreoffset = sat_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
01751 data->end = end;
01752 }
01753
01754
01755 void
01756 repodata_extend_block(Repodata *data, Id start, Id num)
01757 {
01758 if (!num)
01759 return;
01760 if (!data->incoreoffset)
01761 {
01762 data->incoreoffset = sat_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
01763 data->start = start;
01764 data->end = start + num;
01765 return;
01766 }
01767 repodata_extend(data, start);
01768 if (num > 1)
01769 repodata_extend(data, start + num - 1);
01770 }
01771
01772
01773
01774
01775 #define REPODATA_ATTRS_BLOCK 31
01776 #define REPODATA_ATTRDATA_BLOCK 1023
01777 #define REPODATA_ATTRIDDATA_BLOCK 63
01778
01779
01780 Id
01781 repodata_new_handle(Repodata *data)
01782 {
01783 if (!data->nxattrs)
01784 {
01785 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
01786 data->nxattrs = 2;
01787 }
01788 data->xattrs = sat_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
01789 data->xattrs[data->nxattrs] = 0;
01790 return -(data->nxattrs++);
01791 }
01792
01793 static inline Id **
01794 repodata_get_attrp(Repodata *data, Id handle)
01795 {
01796 if (handle == SOLVID_META)
01797 {
01798 if (!data->xattrs)
01799 {
01800 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
01801 data->nxattrs = 2;
01802 }
01803 }
01804 if (handle < 0)
01805 return data->xattrs - handle;
01806 if (handle < data->start || handle >= data->end)
01807 repodata_extend(data, handle);
01808 if (!data->attrs)
01809 data->attrs = sat_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
01810 return data->attrs + (handle - data->start);
01811 }
01812
01813 static void
01814 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
01815 {
01816 Id *pp;
01817 Id *ap, **app;
01818 int i;
01819
01820 app = repodata_get_attrp(data, handle);
01821 ap = *app;
01822 i = 0;
01823 if (ap)
01824 {
01825
01826
01827 for (pp = ap; *pp; pp += 2)
01828 if (data->keys[*pp].name == data->keys[keyid].name)
01829 break;
01830 if (*pp)
01831 {
01832 if (overwrite)
01833 {
01834 pp[0] = keyid;
01835 pp[1] = val;
01836 }
01837 return;
01838 }
01839 i = pp - ap;
01840 }
01841 ap = sat_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
01842 *app = ap;
01843 pp = ap + i;
01844 *pp++ = keyid;
01845 *pp++ = val;
01846 *pp = 0;
01847 }
01848
01849
01850 static void
01851 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
01852 {
01853 Id keyid;
01854
01855 keyid = repodata_key2id(data, key, 1);
01856 repodata_insert_keyid(data, solvid, keyid, val, 1);
01857 }
01858
01859 void
01860 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
01861 {
01862 Repokey key;
01863 key.name = keyname;
01864 key.type = REPOKEY_TYPE_ID;
01865 key.size = 0;
01866 key.storage = KEY_STORAGE_INCORE;
01867 repodata_set(data, solvid, &key, id);
01868 }
01869
01870 void
01871 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
01872 {
01873 Repokey key;
01874 key.name = keyname;
01875 key.type = REPOKEY_TYPE_NUM;
01876 key.size = 0;
01877 key.storage = KEY_STORAGE_INCORE;
01878 repodata_set(data, solvid, &key, (Id)num);
01879 }
01880
01881 void
01882 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
01883 {
01884 Repokey key;
01885 Id id;
01886 if (data->localpool)
01887 id = stringpool_str2id(&data->spool, str, 1);
01888 else
01889 id = str2id(data->repo->pool, str, 1);
01890 key.name = keyname;
01891 key.type = REPOKEY_TYPE_ID;
01892 key.size = 0;
01893 key.storage = KEY_STORAGE_INCORE;
01894 repodata_set(data, solvid, &key, id);
01895 }
01896
01897 void
01898 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
01899 {
01900 Repokey key;
01901 key.name = keyname;
01902 key.type = REPOKEY_TYPE_CONSTANT;
01903 key.size = constant;
01904 key.storage = KEY_STORAGE_INCORE;
01905 repodata_set(data, solvid, &key, 0);
01906 }
01907
01908 void
01909 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
01910 {
01911 Repokey key;
01912 key.name = keyname;
01913 key.type = REPOKEY_TYPE_CONSTANTID;
01914 key.size = id;
01915 key.storage = KEY_STORAGE_INCORE;
01916 repodata_set(data, solvid, &key, 0);
01917 }
01918
01919 void
01920 repodata_set_void(Repodata *data, Id solvid, Id keyname)
01921 {
01922 Repokey key;
01923 key.name = keyname;
01924 key.type = REPOKEY_TYPE_VOID;
01925 key.size = 0;
01926 key.storage = KEY_STORAGE_INCORE;
01927 repodata_set(data, solvid, &key, 0);
01928 }
01929
01930 void
01931 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
01932 {
01933 Repokey key;
01934 int l;
01935
01936 l = strlen(str) + 1;
01937 key.name = keyname;
01938 key.type = REPOKEY_TYPE_STR;
01939 key.size = 0;
01940 key.storage = KEY_STORAGE_INCORE;
01941 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
01942 memcpy(data->attrdata + data->attrdatalen, str, l);
01943 repodata_set(data, solvid, &key, data->attrdatalen);
01944 data->attrdatalen += l;
01945 }
01946
01947 void
01948 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
01949 {
01950 Repokey key;
01951 unsigned char *dp;
01952
01953 key.name = keyname;
01954 key.type = REPOKEY_TYPE_BINARY;
01955 key.size = 0;
01956 key.storage = KEY_STORAGE_INCORE;
01957 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
01958 dp = data->attrdata + data->attrdatalen;
01959 if (len >= (1 << 14))
01960 {
01961 if (len >= (1 << 28))
01962 *dp++ = (len >> 28) | 128;
01963 if (len >= (1 << 21))
01964 *dp++ = (len >> 21) | 128;
01965 *dp++ = (len >> 14) | 128;
01966 }
01967 if (len >= (1 << 7))
01968 *dp++ = (len >> 7) | 128;
01969 *dp++ = len & 127;
01970 if (len)
01971 memcpy(dp, buf, len);
01972 repodata_set(data, solvid, &key, data->attrdatalen);
01973 data->attrdatalen = dp + len - data->attrdata;
01974 }
01975
01976
01977
01978 static void
01979 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
01980 {
01981 int oldsize;
01982 Id *ida, *pp, **ppp;
01983
01984
01985 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
01986 {
01987
01988 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
01989 data->attriddatalen--;
01990 data->lastdatalen += entrysize;
01991 return;
01992 }
01993
01994 ppp = repodata_get_attrp(data, handle);
01995 pp = *ppp;
01996 if (pp)
01997 for (; *pp; pp += 2)
01998 if (data->keys[*pp].name == keyname && data->keys[*pp].type == keytype)
01999 break;
02000 if (!pp || !*pp)
02001 {
02002
02003 Repokey key;
02004 key.name = keyname;
02005 key.type = keytype;
02006 key.size = 0;
02007 key.storage = KEY_STORAGE_INCORE;
02008 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
02009 repodata_set(data, handle, &key, data->attriddatalen);
02010 data->lasthandle = 0;
02011 return;
02012 }
02013 oldsize = 0;
02014 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
02015 oldsize += entrysize;
02016 if (ida + 1 == data->attriddata + data->attriddatalen)
02017 {
02018
02019 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
02020 data->attriddatalen--;
02021 }
02022 else
02023 {
02024
02025 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
02026 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
02027 pp[1] = data->attriddatalen;
02028 data->attriddatalen += oldsize;
02029 }
02030 data->lasthandle = handle;
02031 data->lastkey = *pp;
02032 data->lastdatalen = data->attriddatalen + entrysize + 1;
02033 }
02034
02035 void
02036 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
02037 const unsigned char *str)
02038 {
02039 Repokey key;
02040 int l;
02041
02042 if (!(l = sat_chksum_len(type)))
02043 return;
02044 key.name = keyname;
02045 key.type = type;
02046 key.size = 0;
02047 key.storage = KEY_STORAGE_INCORE;
02048 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
02049 memcpy(data->attrdata + data->attrdatalen, str, l);
02050 repodata_set(data, solvid, &key, data->attrdatalen);
02051 data->attrdatalen += l;
02052 }
02053
02054 static int
02055 hexstr2bytes(unsigned char *buf, const char *str, int buflen)
02056 {
02057 int i;
02058 for (i = 0; i < buflen; i++)
02059 {
02060 #define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
02061 : ((c)>='a' && (c)<='f') ? ((c)-('a'-10)) \
02062 : ((c)>='A' && (c)<='F') ? ((c)-('A'-10)) \
02063 : -1)
02064 int v = c2h(*str);
02065 str++;
02066 if (v < 0)
02067 return 0;
02068 buf[i] = v;
02069 v = c2h(*str);
02070 str++;
02071 if (v < 0)
02072 return 0;
02073 buf[i] = (buf[i] << 4) | v;
02074 #undef c2h
02075 }
02076 return buflen;
02077 }
02078
02079 void
02080 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
02081 const char *str)
02082 {
02083 unsigned char buf[64];
02084 int l;
02085
02086 if (!(l = sat_chksum_len(type)))
02087 return;
02088 if (hexstr2bytes(buf, str, l) != l)
02089 return;
02090 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
02091 }
02092
02093 const char *
02094 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
02095 {
02096 int i, l;
02097 char *str, *s;
02098
02099 if (!(l = sat_chksum_len(type)))
02100 return "";
02101 s = str = pool_alloctmpspace(data->repo->pool, 2 * l + 1);
02102 for (i = 0; i < l; i++)
02103 {
02104 unsigned char v = buf[i];
02105 unsigned char w = v >> 4;
02106 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
02107 w = v & 15;
02108 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
02109 }
02110 *s = 0;
02111 return str;
02112 }
02113
02114
02115 static inline const char *
02116 evrid2vrstr(Pool *pool, Id evrid)
02117 {
02118 const char *p, *evr = id2str(pool, evrid);
02119 if (!evr)
02120 return evr;
02121 for (p = evr; *p >= '0' && *p <= '9'; p++)
02122 ;
02123 return p != evr && *p == ':' ? p + 1 : evr;
02124 }
02125
02126 void
02127 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
02128 {
02129 Pool *pool = data->repo->pool;
02130 Solvable *s;
02131 const char *str, *fp;
02132 int l = 0;
02133
02134 if (medianr)
02135 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
02136 if (!dir)
02137 {
02138 if ((dir = strrchr(file, '/')) != 0)
02139 {
02140 l = dir - file;
02141 dir = file;
02142 file = dir + l + 1;
02143 if (!l)
02144 l++;
02145 }
02146 }
02147 else
02148 l = strlen(dir);
02149 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
02150 {
02151 dir += 2;
02152 l -= 2;
02153 }
02154 if (l == 1 && dir[0] == '.')
02155 l = 0;
02156 s = pool->solvables + solvid;
02157 if (dir && l)
02158 {
02159 str = id2str(pool, s->arch);
02160 if (!strncmp(dir, str, l) && !str[l])
02161 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
02162 else if (!dir[l])
02163 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
02164 else
02165 {
02166 char *dir2 = strdup(dir);
02167 dir2[l] = 0;
02168 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
02169 free(dir2);
02170 }
02171 }
02172 fp = file;
02173 str = id2str(pool, s->name);
02174 l = strlen(str);
02175 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
02176 {
02177 fp += l + 1;
02178 str = evrid2vrstr(pool, s->evr);
02179 l = strlen(str);
02180 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
02181 {
02182 fp += l + 1;
02183 str = id2str(pool, s->arch);
02184 l = strlen(str);
02185 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
02186 {
02187 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
02188 return;
02189 }
02190 }
02191 }
02192 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
02193 }
02194
02195 void
02196 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
02197 {
02198 assert(dir);
02199 #if 0
02200 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
02201 #endif
02202 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
02203 data->attriddata[data->attriddatalen++] = dir;
02204 data->attriddata[data->attriddatalen++] = num;
02205 data->attriddata[data->attriddatalen++] = num2;
02206 data->attriddata[data->attriddatalen++] = 0;
02207 }
02208
02209 void
02210 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
02211 {
02212 Id stroff;
02213 int l;
02214
02215 assert(dir);
02216 l = strlen(str) + 1;
02217 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
02218 memcpy(data->attrdata + data->attrdatalen, str, l);
02219 stroff = data->attrdatalen;
02220 data->attrdatalen += l;
02221
02222 #if 0
02223 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
02224 #endif
02225 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
02226 data->attriddata[data->attriddatalen++] = dir;
02227 data->attriddata[data->attriddatalen++] = stroff;
02228 data->attriddata[data->attriddatalen++] = 0;
02229 }
02230
02231 void
02232 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
02233 {
02234 #if 0
02235 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
02236 #endif
02237 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
02238 data->attriddata[data->attriddatalen++] = id;
02239 data->attriddata[data->attriddatalen++] = 0;
02240 }
02241
02242 void
02243 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
02244 const char *str)
02245 {
02246 Id id;
02247 if (data->localpool)
02248 id = stringpool_str2id(&data->spool, str, 1);
02249 else
02250 id = str2id(data->repo->pool, str, 1);
02251 repodata_add_idarray(data, solvid, keyname, id);
02252 }
02253
02254 void
02255 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
02256 {
02257 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
02258 data->attriddata[data->attriddatalen++] = ghandle;
02259 data->attriddata[data->attriddatalen++] = 0;
02260 }
02261
02262 void
02263 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
02264 {
02265 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
02266 data->attriddata[data->attriddatalen++] = ghandle;
02267 data->attriddata[data->attriddatalen++] = 0;
02268 }
02269
02270 void
02271 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
02272 {
02273 Id *pp, *ap, **app;
02274 app = repodata_get_attrp(data, solvid);
02275 ap = *app;
02276 if (!ap)
02277 return;
02278 for (; *ap; ap += 2)
02279 if (data->keys[*ap].name == keyname)
02280 break;
02281 if (!*ap)
02282 return;
02283 pp = ap;
02284 ap += 2;
02285 for (; *ap; ap += 2)
02286 {
02287 if (data->keys[*ap].name == keyname)
02288 continue;
02289 *pp++ = ap[0];
02290 *pp++ = ap[1];
02291 }
02292 *pp = 0;
02293 }
02294
02295
02296 void
02297 repodata_merge_attrs(Repodata *data, Id dest, Id src)
02298 {
02299 Id *keyp;
02300 if (dest == src || !(keyp = data->attrs[src - data->start]))
02301 return;
02302 for (; *keyp; keyp += 2)
02303 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
02304 }
02305
02306 void
02307 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
02308 {
02309 Id *keyp;
02310 if (dest == src || !(keyp = data->attrs[src - data->start]))
02311 return;
02312 for (; *keyp; keyp += 2)
02313 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
02314 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
02315 }
02316
02317
02318
02319
02320
02321
02322
02323 #define EXTDATA_BLOCK 1023
02324
02325 struct extdata {
02326 unsigned char *buf;
02327 int len;
02328 };
02329
02330 static void
02331 data_addid(struct extdata *xd, Id x)
02332 {
02333 unsigned char *dp;
02334
02335 xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
02336 dp = xd->buf + xd->len;
02337
02338 if (x >= (1 << 14))
02339 {
02340 if (x >= (1 << 28))
02341 *dp++ = (x >> 28) | 128;
02342 if (x >= (1 << 21))
02343 *dp++ = (x >> 21) | 128;
02344 *dp++ = (x >> 14) | 128;
02345 }
02346 if (x >= (1 << 7))
02347 *dp++ = (x >> 7) | 128;
02348 *dp++ = x & 127;
02349 xd->len = dp - xd->buf;
02350 }
02351
02352 static void
02353 data_addideof(struct extdata *xd, Id x, int eof)
02354 {
02355 if (x >= 64)
02356 x = (x & 63) | ((x & ~63) << 1);
02357 data_addid(xd, (eof ? x : x | 64));
02358 }
02359
02360 static void
02361 data_addblob(struct extdata *xd, unsigned char *blob, int len)
02362 {
02363 xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
02364 memcpy(xd->buf + xd->len, blob, len);
02365 xd->len += len;
02366 }
02367
02368
02369
02370 static void
02371 repodata_serialize_key(Repodata *data, struct extdata *newincore,
02372 struct extdata *newvincore,
02373 Id *schema,
02374 Repokey *key, Id val)
02375 {
02376
02377
02378 Id *ida;
02379 struct extdata *xd;
02380 unsigned int oldvincorelen = 0;
02381 Id schemaid, *sp;
02382
02383 xd = newincore;
02384 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
02385 {
02386 xd = newvincore;
02387 oldvincorelen = xd->len;
02388 }
02389 switch (key->type)
02390 {
02391 case REPOKEY_TYPE_VOID:
02392 case REPOKEY_TYPE_CONSTANT:
02393 case REPOKEY_TYPE_CONSTANTID:
02394 break;
02395 case REPOKEY_TYPE_STR:
02396 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
02397 break;
02398 case REPOKEY_TYPE_MD5:
02399 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
02400 break;
02401 case REPOKEY_TYPE_SHA1:
02402 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
02403 break;
02404 case REPOKEY_TYPE_SHA256:
02405 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
02406 break;
02407 case REPOKEY_TYPE_ID:
02408 case REPOKEY_TYPE_NUM:
02409 case REPOKEY_TYPE_DIR:
02410 data_addid(xd, val);
02411 break;
02412 case REPOKEY_TYPE_BINARY:
02413 {
02414 Id len;
02415 unsigned char *dp = data_read_id(data->attrdata + val, &len);
02416 dp += len;
02417 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
02418 }
02419 break;
02420 case REPOKEY_TYPE_IDARRAY:
02421 for (ida = data->attriddata + val; *ida; ida++)
02422 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
02423 break;
02424 case REPOKEY_TYPE_DIRNUMNUMARRAY:
02425 for (ida = data->attriddata + val; *ida; ida += 3)
02426 {
02427 data_addid(xd, ida[0]);
02428 data_addid(xd, ida[1]);
02429 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
02430 }
02431 break;
02432 case REPOKEY_TYPE_DIRSTRARRAY:
02433 for (ida = data->attriddata + val; *ida; ida += 2)
02434 {
02435 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
02436 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
02437 }
02438 break;
02439 case REPOKEY_TYPE_FIXARRAY:
02440 {
02441 int num = 0;
02442 schemaid = 0;
02443 for (ida = data->attriddata + val; *ida; ida++)
02444 {
02445 #if 0
02446 fprintf(stderr, "serialize struct %d\n", *ida);
02447 #endif
02448 sp = schema;
02449 Id *kp = data->xattrs[-*ida];
02450 if (!kp)
02451 continue;
02452 num++;
02453 for (;*kp; kp += 2)
02454 {
02455 #if 0
02456 fprintf(stderr, " %s:%d\n", id2str(data->repo->pool, data->keys[*kp].name), kp[1]);
02457 #endif
02458 *sp++ = *kp;
02459 }
02460 *sp = 0;
02461 if (!schemaid)
02462 schemaid = repodata_schema2id(data, schema, 1);
02463 else if (schemaid != repodata_schema2id(data, schema, 0))
02464 {
02465 pool_debug(data->repo->pool, SAT_FATAL, "fixarray substructs with different schemas\n");
02466 exit(1);
02467 }
02468 #if 0
02469 fprintf(stderr, " schema %d\n", schemaid);
02470 #endif
02471 }
02472 if (!num)
02473 break;
02474 data_addid(xd, num);
02475 data_addid(xd, schemaid);
02476 for (ida = data->attriddata + val; *ida; ida++)
02477 {
02478 Id *kp = data->xattrs[-*ida];
02479 if (!kp)
02480 continue;
02481 for (;*kp; kp += 2)
02482 {
02483 repodata_serialize_key(data, newincore, newvincore,
02484 schema, data->keys + *kp, kp[1]);
02485 }
02486 }
02487 break;
02488 }
02489 case REPOKEY_TYPE_FLEXARRAY:
02490 {
02491 int num = 0;
02492 for (ida = data->attriddata + val; *ida; ida++)
02493 num++;
02494 data_addid(xd, num);
02495 for (ida = data->attriddata + val; *ida; ida++)
02496 {
02497 Id *kp = data->xattrs[-*ida];
02498 if (!kp)
02499 {
02500 data_addid(xd, 0);
02501 continue;
02502 }
02503 sp = schema;
02504 for (;*kp; kp += 2)
02505 *sp++ = *kp;
02506 *sp = 0;
02507 schemaid = repodata_schema2id(data, schema, 1);
02508 data_addid(xd, schemaid);
02509 kp = data->xattrs[-*ida];
02510 for (;*kp; kp += 2)
02511 {
02512 repodata_serialize_key(data, newincore, newvincore,
02513 schema, data->keys + *kp, kp[1]);
02514 }
02515 }
02516 break;
02517 }
02518 default:
02519 pool_debug(data->repo->pool, SAT_FATAL, "don't know how to handle type %d\n", key->type);
02520 exit(1);
02521 }
02522 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
02523 {
02524
02525 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
02526 oldvincorelen = xd->len - oldvincorelen;
02527 data_addid(newincore, oldvincorelen);
02528 }
02529 }
02530
02531 void
02532 repodata_internalize(Repodata *data)
02533 {
02534 Repokey *key, solvkey;
02535 Id entry, nentry;
02536 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
02537 unsigned char *dp, *ndp;
02538 int newschema, oldcount;
02539 struct extdata newincore;
02540 struct extdata newvincore;
02541 Id solvkeyid;
02542
02543 if (!data->attrs && !data->xattrs)
02544 return;
02545
02546 newvincore.buf = data->vincore;
02547 newvincore.len = data->vincorelen;
02548
02549
02550 memset(&solvkey, 0, sizeof(solvkey));
02551 solvkey.name = REPOSITORY_SOLVABLES;
02552 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
02553 solvkey.size = 0;
02554 solvkey.storage = KEY_STORAGE_INCORE;
02555 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
02556
02557 schema = sat_malloc2(data->nkeys, sizeof(Id));
02558 seen = sat_malloc2(data->nkeys, sizeof(Id));
02559
02560
02561
02562 nentry = data->end - data->start;
02563 memset(&newincore, 0, sizeof(newincore));
02564 data_addid(&newincore, 0);
02565
02566 data->mainschema = 0;
02567 data->mainschemaoffsets = sat_free(data->mainschemaoffsets);
02568
02569
02570
02571 for (entry = -1; entry < nentry; entry++)
02572 {
02573 memset(seen, 0, data->nkeys * sizeof(Id));
02574 oldschema = 0;
02575 dp = data->incoredata;
02576 if (dp)
02577 {
02578 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
02579 dp = data_read_id(dp, &oldschema);
02580 }
02581 #if 0
02582 fprintf(stderr, "oldschema %d\n", oldschema);
02583 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
02584 fprintf(stderr, "schemadata %p\n", data->schemadata);
02585 #endif
02586
02587 newschema = 0;
02588 oldcount = 0;
02589 sp = schema;
02590 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
02591 {
02592 if (seen[*keyp])
02593 {
02594 pool_debug(data->repo->pool, SAT_FATAL, "Inconsistent old data (key occured twice).\n");
02595 exit(1);
02596 }
02597 seen[*keyp] = -1;
02598 *sp++ = *keyp;
02599 oldcount++;
02600 }
02601 if (entry >= 0)
02602 keyp = data->attrs ? data->attrs[entry] : 0;
02603 else
02604 {
02605
02606 *sp = 0;
02607 for (sp = keyp = schema; *sp; sp++)
02608 if (*sp != solvkeyid)
02609 *keyp++ = *sp;
02610 else
02611 oldcount--;
02612 sp = keyp;
02613 seen[solvkeyid] = 0;
02614 keyp = data->xattrs ? data->xattrs[1] : 0;
02615 }
02616 if (keyp)
02617 for (; *keyp; keyp += 2)
02618 {
02619 if (!seen[*keyp])
02620 {
02621 newschema = 1;
02622 *sp++ = *keyp;
02623 }
02624 seen[*keyp] = keyp[1] + 1;
02625 }
02626 if (entry < 0 && data->end != data->start)
02627 {
02628 *sp++ = solvkeyid;
02629 newschema = 1;
02630 }
02631 *sp = 0;
02632 if (newschema)
02633
02634
02635
02636
02637
02638 schemaid = repodata_schema2id(data, schema, 1);
02639 else
02640 schemaid = oldschema;
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650 if (entry >= 0)
02651 data->incoreoffset[entry] = newincore.len;
02652 data_addid(&newincore, schemaid);
02653 if (entry == -1)
02654 {
02655 data->mainschema = schemaid;
02656 data->mainschemaoffsets = sat_calloc(sp - schema, sizeof(Id));
02657 }
02658 keypstart = data->schemadata + data->schemata[schemaid];
02659 for (keyp = keypstart; *keyp; keyp++)
02660 {
02661 if (entry == -1)
02662 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
02663 if (*keyp == solvkeyid)
02664 {
02665
02666 data_addid(&newincore, data->end - data->start);
02667 break;
02668 }
02669 key = data->keys + *keyp;
02670 #if 0
02671 fprintf(stderr, "internalize %d(%d):%s:%s\n", entry, entry + data->start, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
02672 #endif
02673 ndp = dp;
02674 if (oldcount)
02675 {
02676
02677 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
02678 {
02679 ndp = data_skip(dp, REPOKEY_TYPE_ID);
02680 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
02681 }
02682 else if (key->storage == KEY_STORAGE_INCORE)
02683 ndp = data_skip_key(data, dp, key);
02684 oldcount--;
02685 }
02686 if (seen[*keyp] == -1)
02687 {
02688
02689
02690
02691 if (dp != ndp)
02692 data_addblob(&newincore, dp, ndp - dp);
02693 seen[*keyp] = 0;
02694 }
02695 else if (seen[*keyp])
02696 {
02697
02698
02699 repodata_serialize_key(data, &newincore, &newvincore,
02700 schema, key, seen[*keyp] - 1);
02701 }
02702 dp = ndp;
02703 }
02704 if (entry >= 0 && data->attrs && data->attrs[entry])
02705 data->attrs[entry] = sat_free(data->attrs[entry]);
02706 }
02707
02708 for (entry = 0; entry < data->nxattrs; entry++)
02709 if (data->xattrs[entry])
02710 sat_free(data->xattrs[entry]);
02711 data->xattrs = sat_free(data->xattrs);
02712 data->nxattrs = 0;
02713
02714 data->lasthandle = 0;
02715 data->lastkey = 0;
02716 data->lastdatalen = 0;
02717 sat_free(schema);
02718 sat_free(seen);
02719 repodata_free_schemahash(data);
02720
02721 sat_free(data->incoredata);
02722 data->incoredata = newincore.buf;
02723 data->incoredatalen = newincore.len;
02724 data->incoredatafree = 0;
02725
02726 sat_free(data->vincore);
02727 data->vincore = newvincore.buf;
02728 data->vincorelen = newvincore.len;
02729
02730 data->attrs = sat_free(data->attrs);
02731 data->attrdata = sat_free(data->attrdata);
02732 data->attriddata = sat_free(data->attriddata);
02733 data->attrdatalen = 0;
02734 data->attriddatalen = 0;
02735 }
02736
02737 void
02738 repodata_disable_paging(Repodata *data)
02739 {
02740 if (maybe_load_repodata(data, 0))
02741 repopagestore_disable_paging(&data->store);
02742 }
02743
02744 static void
02745 repodata_load_stub(Repodata *data)
02746 {
02747 Repo *repo = data->repo;
02748 Pool *pool = repo->pool;
02749 int r;
02750
02751 if (!pool->loadcallback)
02752 {
02753 data->state = REPODATA_ERROR;
02754 return;
02755 }
02756 data->state = REPODATA_LOADING;
02757 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
02758 if (!r)
02759 data->state = REPODATA_ERROR;
02760 }
02761
02762 void
02763 repodata_create_stubs(Repodata *data)
02764 {
02765 Repo *repo = data->repo;
02766 Pool *pool = repo->pool;
02767 Repodata *sdata;
02768 int *stubdataids;
02769 Dataiterator di;
02770 Id xkeyname = 0;
02771 int i, cnt = 0;
02772 int repodataid;
02773 int datastart, dataend;
02774
02775 repodataid = data - repo->repodata;
02776 datastart = data->start;
02777 dataend = data->end;
02778 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
02779 while (dataiterator_step(&di))
02780 {
02781 if (di.data - repo->repodata != repodataid)
02782 continue;
02783 cnt++;
02784 }
02785 dataiterator_free(&di);
02786 if (!cnt)
02787 return;
02788 stubdataids = sat_calloc(cnt, sizeof(*stubdataids));
02789 for (i = 0; i < cnt; i++)
02790 {
02791 sdata = repo_add_repodata(repo, 0);
02792 if (dataend > datastart)
02793 repodata_extend_block(sdata, datastart, dataend - datastart);
02794 stubdataids[i] = sdata - repo->repodata;
02795 sdata->state = REPODATA_STUB;
02796 sdata->loadcallback = repodata_load_stub;
02797 }
02798 i = 0;
02799 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
02800 sdata = 0;
02801 while (dataiterator_step(&di))
02802 {
02803 if (di.data - repo->repodata != repodataid)
02804 continue;
02805 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
02806 {
02807 dataiterator_entersub(&di);
02808 sdata = repo->repodata + stubdataids[i++];
02809 xkeyname = 0;
02810 continue;
02811 }
02812 switch (di.key->type)
02813 {
02814 case REPOKEY_TYPE_ID:
02815 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
02816 break;
02817 case REPOKEY_TYPE_CONSTANTID:
02818 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
02819 break;
02820 case REPOKEY_TYPE_STR:
02821 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
02822 break;
02823 case REPOKEY_TYPE_VOID:
02824 repodata_set_void(sdata, SOLVID_META, di.key->name);
02825 break;
02826 case REPOKEY_TYPE_NUM:
02827 repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num);
02828 break;
02829 case REPOKEY_TYPE_MD5:
02830 case REPOKEY_TYPE_SHA1:
02831 case REPOKEY_TYPE_SHA256:
02832 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
02833 break;
02834 case REPOKEY_TYPE_IDARRAY:
02835 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
02836 if (di.key->name == REPOSITORY_KEYS)
02837 {
02838 Repokey xkey;
02839
02840 if (!xkeyname)
02841 {
02842 if (!di.kv.eof)
02843 xkeyname = di.kv.id;
02844 continue;
02845 }
02846 xkey.name = xkeyname;
02847 xkey.type = di.kv.id;
02848 xkey.storage = KEY_STORAGE_INCORE;
02849 xkey.size = 0;
02850 repodata_key2id(sdata, &xkey, 1);
02851 xkeyname = 0;
02852 }
02853 }
02854 }
02855 dataiterator_free(&di);
02856 for (i = 0; i < cnt; i++)
02857 repodata_internalize(repo->repodata + stubdataids[i]);
02858 sat_free(stubdataids);
02859 }
02860
02861
02862
02863