2 * Copyright (c) 2007, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * Manage data coming from one repository
13 * a repository can contain multiple repodata entries, consisting of
14 * different sets of keys and different sets of solvables
29 #include "poolid_private.h"
37 #define REPODATA_BLOCK 255
39 static unsigned char *data_skip_key(Repodata *data, unsigned char *dp, Repokey *key);
42 repodata_initdata(Repodata *data, Repo *repo, int localpool)
44 memset(data, 0, sizeof (*data));
46 data->localpool = localpool;
48 stringpool_init_empty(&data->spool);
49 /* dirpool_init(&data->dirpool); just zeros out again */
50 data->keys = solv_calloc(1, sizeof(Repokey));
52 data->schemata = solv_calloc(1, sizeof(Id));
53 data->schemadata = solv_calloc(1, sizeof(Id));
55 data->schemadatalen = 1;
56 repopagestore_init(&data->store);
60 repodata_freedata(Repodata *data)
64 solv_free(data->keys);
66 solv_free(data->schemata);
67 solv_free(data->schemadata);
68 solv_free(data->schematahash);
70 stringpool_free(&data->spool);
71 dirpool_free(&data->dirpool);
73 solv_free(data->mainschemaoffsets);
74 solv_free(data->incoredata);
75 solv_free(data->incoreoffset);
76 solv_free(data->verticaloffset);
78 repopagestore_free(&data->store);
80 solv_free(data->vincore);
83 for (i = 0; i < data->end - data->start; i++)
84 solv_free(data->attrs[i]);
85 solv_free(data->attrs);
87 for (i = 0; i < data->nxattrs; i++)
88 solv_free(data->xattrs[i]);
89 solv_free(data->xattrs);
91 solv_free(data->attrdata);
92 solv_free(data->attriddata);
96 repodata_create(Repo *repo, int localpool)
100 if (!repo->nrepodata)
102 repo->nrepodata = 2; /* start with id 1 */
103 repo->repodata = solv_calloc(repo->nrepodata, sizeof(*data));
108 repo->repodata = solv_realloc2(repo->repodata, repo->nrepodata, sizeof(*data));
110 data = repo->repodata + repo->nrepodata - 1;
111 repodata_initdata(data, repo, localpool);
116 repodata_free(Repodata *data)
118 Repo *repo = data->repo;
119 int i = data - repo->repodata;
120 repodata_freedata(data);
121 if (i < repo->nrepodata - 1)
122 memmove(repo->repodata + i, repo->repodata + i + 1, (repo->nrepodata - 1 - i) * sizeof(Repodata));
124 if (repo->nrepodata == 1)
126 repo->repodata = solv_free(repo->repodata);
132 repodata_empty(Repodata *data, int localpool)
134 void (*loadcallback)(Repodata *) = data->loadcallback;
135 int state = data->state;
136 repodata_freedata(data);
137 repodata_initdata(data, data->repo, localpool);
139 data->loadcallback = loadcallback;
143 /***************************************************************
144 * key pool management
147 /* this is not so time critical that we need a hash, so we do a simple
150 repodata_key2id(Repodata *data, Repokey *key, int create)
154 for (keyid = 1; keyid < data->nkeys; keyid++)
155 if (data->keys[keyid].name == key->name && data->keys[keyid].type == key->type)
157 if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != data->keys[keyid].size)
161 if (keyid == data->nkeys)
165 /* allocate new key */
166 data->keys = solv_realloc2(data->keys, data->nkeys + 1, sizeof(Repokey));
167 data->keys[data->nkeys++] = *key;
168 if (data->verticaloffset)
170 data->verticaloffset = solv_realloc2(data->verticaloffset, data->nkeys, sizeof(Id));
171 data->verticaloffset[data->nkeys - 1] = 0;
173 data->keybits[(key->name >> 3) & (sizeof(data->keybits) - 1)] |= 1 << (key->name & 7);
179 /***************************************************************
180 * schema pool management
183 #define SCHEMATA_BLOCK 31
184 #define SCHEMATADATA_BLOCK 255
187 repodata_schema2id(Repodata *data, Id *schema, int create)
194 return 0; /* XXX: allow empty schema? */
195 if ((schematahash = data->schematahash) == 0)
197 data->schematahash = schematahash = solv_calloc(256, sizeof(Id));
198 for (i = 1; i < data->nschemata; i++)
200 for (sp = data->schemadata + data->schemata[i], h = 0; *sp; len++)
205 data->schemadata = solv_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
206 data->schemata = solv_extend_resize(data->schemata, data->nschemata, sizeof(Id), SCHEMATA_BLOCK);
209 for (sp = schema, len = 0, h = 0; *sp; len++)
214 cid = schematahash[h];
217 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
219 /* cache conflict, do a slow search */
220 for (cid = 1; cid < data->nschemata; cid++)
221 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
227 data->schemadata = solv_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
228 data->schemata = solv_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
230 memcpy(data->schemadata + data->schemadatalen, schema, len * sizeof(Id));
231 data->schemata[data->nschemata] = data->schemadatalen;
232 data->schemadatalen += len;
233 schematahash[h] = data->nschemata;
235 fprintf(stderr, "schema2id: new schema\n");
237 return data->nschemata++;
241 repodata_free_schemahash(Repodata *data)
243 data->schematahash = solv_free(data->schematahash);
245 data->schemata = solv_realloc2(data->schemata, data->nschemata, sizeof(Id));
246 data->schemadata = solv_realloc2(data->schemadata, data->schemadatalen, sizeof(Id));
250 /***************************************************************
251 * dir pool management
254 #ifndef HAVE_STRCHRNUL
255 static inline const char *strchrnul(const char *str, char x)
257 const char *p = strchr(str, x);
258 return p ? p : str + strlen(str);
263 repodata_str2dir(Repodata *data, const char *dir, int create)
269 while (*dir == '/' && dir[1] == '/')
271 if (*dir == '/' && !dir[1])
273 if (data->dirpool.ndirs)
275 return dirpool_add_dir(&data->dirpool, 0, 1, create);
279 dire = strchrnul(dir, '/');
281 id = stringpool_strn2id(&data->spool, dir, dire - dir, create);
283 id = pool_strn2id(data->repo->pool, dir, dire - dir, create);
286 parent = dirpool_add_dir(&data->dirpool, parent, id, create);
299 repodata_dir2str(Repodata *data, Id did, const char *suf)
301 Pool *pool = data->repo->pool;
308 return suf ? suf : "";
312 comp = dirpool_compid(&data->dirpool, parent);
313 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
315 parent = dirpool_parent(&data->dirpool, parent);
320 l += strlen(suf) + 1;
321 p = pool_alloctmpspace(pool, l + 1) + l;
332 comp = dirpool_compid(&data->dirpool, parent);
333 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
336 strncpy(p, comps, l);
337 parent = dirpool_parent(&data->dirpool, parent);
345 /***************************************************************
349 static inline unsigned char *
350 data_skip_schema(Repodata *data, unsigned char *dp, Id schema)
352 Id *keyp = data->schemadata + data->schemata[schema];
353 for (; *keyp; keyp++)
354 dp = data_skip_key(data, dp, data->keys + *keyp);
358 static unsigned char *
359 data_skip_key(Repodata *data, unsigned char *dp, Repokey *key)
361 int nentries, schema;
364 case REPOKEY_TYPE_FIXARRAY:
365 dp = data_read_id(dp, &nentries);
368 dp = data_read_id(dp, &schema);
370 dp = data_skip_schema(data, dp, schema);
372 case REPOKEY_TYPE_FLEXARRAY:
373 dp = data_read_id(dp, &nentries);
376 dp = data_read_id(dp, &schema);
377 dp = data_skip_schema(data, dp, schema);
381 if (key->storage == KEY_STORAGE_INCORE)
382 dp = data_skip(dp, key->type);
383 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
385 dp = data_skip(dp, REPOKEY_TYPE_ID);
386 dp = data_skip(dp, REPOKEY_TYPE_ID);
392 static unsigned char *
393 forward_to_key(Repodata *data, Id keyid, Id *keyp, unsigned char *dp)
399 if (data->mainschemaoffsets && dp == data->incoredata + data->mainschemaoffsets[0] && keyp == data->schemadata + data->schemata[data->mainschema])
402 for (i = 0; (k = *keyp++) != 0; i++)
404 return data->incoredata + data->mainschemaoffsets[i];
407 while ((k = *keyp++) != 0)
411 if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
413 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip offset */
414 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip length */
417 if (data->keys[k].storage != KEY_STORAGE_INCORE)
419 dp = data_skip_key(data, dp, data->keys + k);
424 static unsigned char *
425 get_vertical_data(Repodata *data, Repokey *key, Id off, Id len)
430 if (off >= data->lastverticaloffset)
432 off -= data->lastverticaloffset;
433 if (off + len > data->vincorelen)
435 return data->vincore + off;
437 if (off + len > key->size)
439 /* we now have the offset, go into vertical */
440 off += data->verticaloffset[key - data->keys];
441 /* fprintf(stderr, "key %d page %d\n", key->name, off / REPOPAGE_BLOBSIZE); */
442 dp = repopagestore_load_page_range(&data->store, off / REPOPAGE_BLOBSIZE, (off + len - 1) / REPOPAGE_BLOBSIZE);
444 dp += off % REPOPAGE_BLOBSIZE;
448 static inline unsigned char *
449 get_data(Repodata *data, Repokey *key, unsigned char **dpp, int advance)
451 unsigned char *dp = *dpp;
455 if (key->storage == KEY_STORAGE_INCORE)
458 *dpp = data_skip_key(data, dp, key);
461 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
464 dp = data_read_id(dp, &off);
465 dp = data_read_id(dp, &len);
468 return get_vertical_data(data, key, off, len);
474 load_repodata(Repodata *data)
476 if (data->loadcallback)
478 data->loadcallback(data);
479 if (data->state == REPODATA_AVAILABLE)
482 data->state = REPODATA_ERROR;
487 maybe_load_repodata(Repodata *data, Id keyname)
489 if (keyname && !repodata_precheck_keyname(data, keyname))
490 return 0; /* do not bother... */
497 for (i = 1; i < data->nkeys; i++)
498 if (keyname == data->keys[i].name)
500 if (i == data->nkeys)
503 return load_repodata(data);
506 case REPODATA_AVAILABLE:
507 case REPODATA_LOADING:
510 data->state = REPODATA_ERROR;
515 static inline unsigned char *
516 solvid2data(Repodata *data, Id solvid, Id *schemap)
518 unsigned char *dp = data->incoredata;
521 if (solvid == SOLVID_META) /* META */
523 else if (solvid == SOLVID_POS) /* META */
525 Pool *pool = data->repo->pool;
526 if (data->repo != pool->pos.repo)
528 if (data != data->repo->repodata + pool->pos.repodataid)
530 *schemap = pool->pos.schema;
531 return data->incoredata + pool->pos.dp;
535 if (solvid < data->start || solvid >= data->end)
537 dp += data->incoreoffset[solvid - data->start];
539 return data_read_id(dp, schemap);
542 /************************************************************************
546 static inline unsigned char *
547 find_key_data(Repodata *data, Id solvid, Id keyname, Repokey **keypp)
550 Id schema, *keyp, *kp;
553 if (!maybe_load_repodata(data, keyname))
555 dp = solvid2data(data, solvid, &schema);
558 keyp = data->schemadata + data->schemata[schema];
559 for (kp = keyp; *kp; kp++)
560 if (data->keys[*kp].name == keyname)
564 *keypp = key = data->keys + *kp;
565 if (key->type == REPOKEY_TYPE_DELETED)
567 if (key->type == REPOKEY_TYPE_VOID || key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID)
568 return dp; /* no need to forward... */
569 dp = forward_to_key(data, *kp, keyp, dp);
572 return get_data(data, key, &dp, 0);
576 repodata_lookup_type(Repodata *data, Id solvid, Id keyname)
578 Id schema, *keyp, *kp;
579 if (!maybe_load_repodata(data, keyname))
581 if (!solvid2data(data, solvid, &schema))
583 keyp = data->schemadata + data->schemata[schema];
584 for (kp = keyp; *kp; kp++)
585 if (data->keys[*kp].name == keyname)
586 return data->keys[*kp].type;
591 repodata_lookup_id(Repodata *data, Id solvid, Id keyname)
597 dp = find_key_data(data, solvid, keyname, &key);
600 if (key->type == REPOKEY_TYPE_CONSTANTID)
602 if (key->type != REPOKEY_TYPE_ID)
604 dp = data_read_id(dp, &id);
609 repodata_lookup_str(Repodata *data, Id solvid, Id keyname)
615 dp = find_key_data(data, solvid, keyname, &key);
618 if (key->type == REPOKEY_TYPE_STR)
619 return (const char *)dp;
620 if (key->type == REPOKEY_TYPE_CONSTANTID)
622 else if (key->type == REPOKEY_TYPE_ID)
623 dp = data_read_id(dp, &id);
627 return stringpool_id2str(&data->spool, id);
628 return pool_id2str(data->repo->pool, id);
632 repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned int *value)
639 dp = find_key_data(data, solvid, keyname, &key);
642 if (key->type == REPOKEY_TYPE_NUM
643 || key->type == REPOKEY_TYPE_U32
644 || key->type == REPOKEY_TYPE_CONSTANT)
647 dp = data_fetch(dp, &kv, key);
655 repodata_lookup_void(Repodata *data, Id solvid, Id keyname)
661 if (!maybe_load_repodata(data, keyname))
663 dp = solvid2data(data, solvid, &schema);
666 /* can't use find_key_data as we need to test the type */
667 for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++)
668 if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID)
673 const unsigned char *
674 repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep)
679 dp = find_key_data(data, solvid, keyname, &key);
687 repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
695 dp = find_key_data(data, solvid, keyname, &key);
698 if (key->type != REPOKEY_TYPE_IDARRAY && key->type != REPOKEY_TYPE_REL_IDARRAY)
702 dp = data_read_ideof(dp, &id, &eof);
711 repodata_globalize_id(Repodata *data, Id id, int create)
713 if (!id || !data || !data->localpool)
715 return pool_str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
719 repodata_localize_id(Repodata *data, Id id, int create)
721 if (!id || !data || !data->localpool)
723 return stringpool_str2id(&data->spool, pool_id2str(data->repo->pool, id), create);
727 /************************************************************************
733 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
737 case REPOKEY_TYPE_ID:
738 case REPOKEY_TYPE_CONSTANTID:
739 case REPOKEY_TYPE_IDARRAY:
740 if (data && data->localpool)
741 kv->str = stringpool_id2str(&data->spool, kv->id);
743 kv->str = pool_id2str(pool, kv->id);
744 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
747 for (s = kv->str; *s >= 'a' && *s <= 'z'; s++)
749 if (*s == ':' && s > kv->str)
753 case REPOKEY_TYPE_STR:
755 case REPOKEY_TYPE_DIRSTRARRAY:
756 if (!(flags & SEARCH_FILES))
757 return 1; /* match just the basename */
758 /* Put the full filename into kv->str. */
759 kv->str = repodata_dir2str(data, kv->id, kv->str);
760 /* And to compensate for that put the "empty" directory into
761 kv->id, so that later calls to repodata_dir2str on this data
762 come up with the same filename again. */
765 case REPOKEY_TYPE_MD5:
766 case REPOKEY_TYPE_SHA1:
767 case REPOKEY_TYPE_SHA256:
768 if (!(flags & SEARCH_CHECKSUMS))
769 return 0; /* skip em */
770 kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str);
778 struct subschema_data {
784 /* search a specific repodata */
786 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
790 Id keyid, *kp, *keyp;
791 unsigned char *dp, *ddp;
797 if (!maybe_load_repodata(data, keyname))
799 if (solvid == SOLVID_SUBSCHEMA)
801 struct subschema_data *subd = cbdata;
802 cbdata = subd->cbdata;
804 schema = subd->parent->id;
805 dp = (unsigned char *)subd->parent->str;
806 kv.parent = subd->parent;
811 dp = solvid2data(data, solvid, &schema);
814 s = data->repo->pool->solvables + solvid;
817 keyp = data->schemadata + data->schemata[schema];
820 /* search for a specific key */
821 for (kp = keyp; *kp; kp++)
822 if (data->keys[*kp].name == keyname)
826 dp = forward_to_key(data, *kp, keyp, dp);
832 while ((keyid = *keyp++) != 0)
835 key = data->keys + keyid;
836 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
838 if (key->type == REPOKEY_TYPE_DELETED)
840 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
842 struct subschema_data subd;
846 subd.cbdata = cbdata;
849 ddp = data_read_id(ddp, &nentries);
853 while (ddp && nentries > 0)
857 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
858 ddp = data_read_id(ddp, &schema);
860 kv.str = (char *)ddp;
861 stop = callback(cbdata, s, data, key, &kv);
862 if (stop > SEARCH_NEXT_KEY)
864 if (stop && stop != SEARCH_ENTERSUB)
866 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
867 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
868 ddp = data_skip_schema(data, ddp, schema);
871 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
875 kv.str = (char *)ddp;
876 stop = callback(cbdata, s, data, key, &kv);
877 if (stop > SEARCH_NEXT_KEY)
887 ddp = data_fetch(ddp, &kv, key);
890 stop = callback(cbdata, s, data, key, &kv);
893 while (!kv.eof && !stop);
894 if (onekey || stop > SEARCH_NEXT_KEY)
900 repodata_setpos_kv(Repodata *data, KeyValue *kv)
902 Pool *pool = data->repo->pool;
904 pool_clear_pos(pool);
907 pool->pos.repo = data->repo;
908 pool->pos.repodataid = data - data->repo->repodata;
909 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
910 pool->pos.schema = kv->id;
914 /************************************************************************
915 * data iterator functions
918 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
919 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
920 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
921 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
922 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
923 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
924 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
925 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
926 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
927 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
928 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
929 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
930 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
931 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
935 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
949 case SOLVABLE_VENDOR:
952 case SOLVABLE_PROVIDES:
954 return s->provides ? s->repo->idarraydata + s->provides : 0;
955 case SOLVABLE_OBSOLETES:
957 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
958 case SOLVABLE_CONFLICTS:
960 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
961 case SOLVABLE_REQUIRES:
963 return s->requires ? s->repo->idarraydata + s->requires : 0;
964 case SOLVABLE_RECOMMENDS:
966 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
967 case SOLVABLE_SUPPLEMENTS:
969 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
970 case SOLVABLE_SUGGESTS:
972 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
973 case SOLVABLE_ENHANCES:
975 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
978 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
985 datamatcher_init(Datamatcher *ma, const char *match, int flags)
991 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
993 ma->matchdata = solv_calloc(1, sizeof(regex_t));
994 ma->error = regcomp((regex_t *)ma->matchdata, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
997 solv_free(ma->matchdata);
998 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
1005 datamatcher_free(Datamatcher *ma)
1007 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
1009 regfree(ma->matchdata);
1010 ma->matchdata = solv_free(ma->matchdata);
1015 datamatcher_match(Datamatcher *ma, const char *str)
1018 switch ((ma->flags & SEARCH_STRINGMASK))
1020 case SEARCH_SUBSTRING:
1021 if (ma->flags & SEARCH_NOCASE)
1023 if (!strcasestr(str, ma->match))
1028 if (!strstr(str, ma->match))
1033 if (ma->flags & SEARCH_NOCASE)
1035 if (strcasecmp(ma->match, str))
1040 if (strcmp(ma->match, str))
1044 case SEARCH_STRINGSTART:
1045 if (ma->flags & SEARCH_NOCASE)
1047 if (strncasecmp(ma->match, str, strlen(ma->match)))
1052 if (strncmp(ma->match, str, strlen(ma->match)))
1056 case SEARCH_STRINGEND:
1057 l = strlen(str) - strlen(ma->match);
1060 if (ma->flags & SEARCH_NOCASE)
1062 if (strcasecmp(ma->match, str + l))
1067 if (strcmp(ma->match, str + l))
1072 if (fnmatch(ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
1076 if (regexec((const regex_t *)ma->matchdata, str, 0, NULL, 0))
1086 repodata_filelistfilter_matches(Repodata *data, const char *str)
1088 /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */
1089 /* for now hardcoded */
1090 if (strstr(str, "bin/"))
1092 if (!strncmp(str, "/etc/", 5))
1094 if (!strcmp(str, "/usr/lib/sendmail"))
1116 di_nextarrayelement,
1121 di_nextsolvableattr,
1126 /* see repo.h for documentation */
1128 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
1130 memset(di, 0, sizeof(*di));
1132 di->flags = flags & ~SEARCH_THISSOLVID;
1133 if (!pool || (repo && repo->pool != pool))
1141 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1147 di->keyname = keyname;
1148 di->keynames[0] = keyname;
1149 dataiterator_set_search(di, repo, p);
1154 dataiterator_init_clone(Dataiterator *di, Dataiterator *from)
1157 memset(&di->matcher, 0, sizeof(di->matcher));
1158 if (from->matcher.match)
1159 datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags);
1164 for (i = 1; i < di->nparents; i++)
1165 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1166 di->kv.parent = &di->parents[di->nparents - 1].kv;
1171 dataiterator_set_match(Dataiterator *di, const char *match, int flags)
1173 di->flags = (flags & ~SEARCH_THISSOLVID) | (di->flags & SEARCH_THISSOLVID);
1174 datamatcher_free(&di->matcher);
1175 memset(&di->matcher, 0, sizeof(di->matcher));
1179 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1189 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
1193 di->flags &= ~SEARCH_THISSOLVID;
1197 if (!di->pool->urepos)
1205 di->repo = di->pool->repos[di->repoid];
1207 di->state = di_enterrepo;
1209 dataiterator_jump_to_solvid(di, p);
1213 dataiterator_set_keyname(Dataiterator *di, Id keyname)
1216 di->keyname = keyname;
1217 di->keynames[0] = keyname;
1221 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1225 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1227 di->state = di_bye; /* sorry */
1230 for (i = di->nkeynames + 1; i > 0; i--)
1231 di->keynames[i] = di->keynames[i - 1];
1232 di->keynames[0] = di->keyname = keyname;
1237 dataiterator_free(Dataiterator *di)
1239 if (di->matcher.match)
1240 datamatcher_free(&di->matcher);
1243 static inline unsigned char *
1244 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1246 Id *keyp = di->keyp;
1247 Repokey *keys = di->data->keys;
1250 for (keyp = di->keyp; *keyp; keyp++)
1251 if (keys[*keyp].name == keyname)
1255 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1263 dataiterator_filelistcheck(Dataiterator *di)
1266 int needcomplete = 0;
1267 Repodata *data = di->data;
1269 if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
1270 if (!di->matcher.match
1271 || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
1272 && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)
1273 || !repodata_filelistfilter_matches(di->data, di->matcher.match))
1275 if (data->state != REPODATA_AVAILABLE)
1276 return needcomplete ? 1 : 0;
1277 for (j = 1; j < data->nkeys; j++)
1278 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
1280 return j == data->nkeys && !needcomplete ? 0 : 1;
1284 dataiterator_step(Dataiterator *di)
1292 case di_enterrepo: di_enterrepo:
1293 if (!di->repo || (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS)))
1295 if (!(di->flags & SEARCH_THISSOLVID))
1297 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1298 goto di_nextsolvable;
1302 case di_entersolvable: di_entersolvable:
1305 di->repodataid = 1; /* reset repodata iterator */
1306 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)
1308 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1310 goto di_entersolvablekey;
1315 case di_enterrepodata: di_enterrepodata:
1318 if (di->repodataid >= di->repo->nrepodata)
1319 goto di_nextsolvable;
1320 di->data = di->repo->repodata + di->repodataid;
1322 if (di->repodataid && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
1323 goto di_nextrepodata;
1324 if (!maybe_load_repodata(di->data, di->keyname))
1325 goto di_nextrepodata;
1326 di->dp = solvid2data(di->data, di->solvid, &schema);
1328 goto di_nextrepodata;
1329 if (di->solvid == SOLVID_POS)
1330 di->solvid = di->pool->pos.solvid;
1331 /* reset key iterator */
1332 di->keyp = di->data->schemadata + di->data->schemata[schema];
1335 case di_enterschema: di_enterschema:
1337 di->dp = dataiterator_find_keyname(di, di->keyname);
1338 if (!di->dp || !*di->keyp)
1342 goto di_nextrepodata;
1346 case di_enterkey: di_enterkey:
1348 di->key = di->data->keys + *di->keyp;
1349 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1352 if (di->key->type == REPOKEY_TYPE_DELETED)
1354 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1356 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1362 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1364 di->state = di_nextkey;
1366 di->state = di_nextattr;
1369 case di_nextkey: di_nextkey:
1370 if (!di->keyname && *++di->keyp)
1376 case di_nextrepodata: di_nextrepodata:
1377 if (di->repodataid && ++di->repodataid < di->repo->nrepodata)
1378 goto di_enterrepodata;
1381 case di_nextsolvable: di_nextsolvable:
1382 if (!(di->flags & SEARCH_THISSOLVID))
1385 di->solvid = di->repo->start;
1388 for (; di->solvid < di->repo->end; di->solvid++)
1390 if (di->pool->solvables[di->solvid].repo == di->repo)
1391 goto di_entersolvable;
1396 case di_nextrepo: di_nextrepo:
1401 if (di->repoid < di->pool->nrepos)
1403 di->repo = di->pool->repos[di->repoid];
1409 case di_bye: di_bye:
1413 case di_enterarray: di_enterarray:
1414 if (di->key->name == REPOSITORY_SOLVABLES)
1416 di->ddp = data_read_id(di->ddp, &di->kv.num);
1421 case di_nextarrayelement: di_nextarrayelement:
1424 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1425 if (di->kv.entry == di->kv.num)
1427 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1429 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1431 di->kv.str = (char *)di->ddp;
1433 di->state = di_nextkey;
1436 if (di->kv.entry == di->kv.num - 1)
1438 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1439 di->ddp = data_read_id(di->ddp, &di->kv.id);
1440 di->kv.str = (char *)di->ddp;
1441 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1443 if ((di->flags & SEARCH_SUB) != 0)
1444 di->state = di_entersub;
1446 di->state = di_nextarrayelement;
1449 case di_entersub: di_entersub:
1450 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1451 goto di_nextarrayelement; /* sorry, full */
1452 di->parents[di->nparents].kv = di->kv;
1453 di->parents[di->nparents].dp = di->dp;
1454 di->parents[di->nparents].keyp = di->keyp;
1455 di->dp = (unsigned char *)di->kv.str;
1456 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1457 memset(&di->kv, 0, sizeof(di->kv));
1458 di->kv.parent = &di->parents[di->nparents].kv;
1460 di->keyname = di->keynames[di->nparents - di->rootlevel];
1461 goto di_enterschema;
1463 case di_leavesub: di_leavesub:
1464 if (di->nparents - 1 < di->rootlevel)
1467 di->dp = di->parents[di->nparents].dp;
1468 di->kv = di->parents[di->nparents].kv;
1469 di->keyp = di->parents[di->nparents].keyp;
1470 di->key = di->data->keys + *di->keyp;
1471 di->ddp = (unsigned char *)di->kv.str;
1472 di->keyname = di->keynames[di->nparents - di->rootlevel];
1473 goto di_nextarrayelement;
1475 /* special solvable attr handling follows */
1477 case di_nextsolvableattr:
1478 di->kv.id = *di->idp++;
1483 di->state = di_nextsolvablekey;
1487 case di_nextsolvablekey: di_nextsolvablekey:
1488 if (di->keyname || di->key->name == RPM_RPMDBID)
1489 goto di_enterrepodata;
1493 case di_entersolvablekey: di_entersolvablekey:
1494 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1495 if (!di->idp || !di->idp[0])
1496 goto di_nextsolvablekey;
1497 di->kv.id = di->idp[0];
1498 di->kv.num = di->idp[0];
1500 if (!di->kv.eof && !di->idp[0])
1504 di->state = di_nextsolvablekey;
1506 di->state = di_nextsolvableattr;
1510 if (di->matcher.match)
1512 /* simple pre-check so that we don't need to stringify */
1513 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))
1515 int l = strlen(di->matcher.match) - strlen(di->kv.str);
1516 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
1519 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1521 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1525 if (!datamatcher_match(&di->matcher, di->kv.str))
1528 /* found something! */
1534 dataiterator_entersub(Dataiterator *di)
1536 if (di->state == di_nextarrayelement)
1537 di->state = di_entersub;
1541 dataiterator_setpos(Dataiterator *di)
1543 if (di->kv.eof == 2)
1545 pool_clear_pos(di->pool);
1548 di->pool->pos.solvid = di->solvid;
1549 di->pool->pos.repo = di->repo;
1550 di->pool->pos.repodataid = di->data - di->repo->repodata;
1551 di->pool->pos.schema = di->kv.id;
1552 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1556 dataiterator_setpos_parent(Dataiterator *di)
1558 if (!di->kv.parent || di->kv.parent->eof == 2)
1560 pool_clear_pos(di->pool);
1563 di->pool->pos.solvid = di->solvid;
1564 di->pool->pos.repo = di->repo;
1565 di->pool->pos.repodataid = di->data - di->repo->repodata;
1566 di->pool->pos.schema = di->kv.parent->id;
1567 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1570 /* clones just the position, not the search keys/matcher */
1572 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
1574 di->state = from->state;
1575 di->flags &= ~SEARCH_THISSOLVID;
1576 di->flags |= (from->flags & SEARCH_THISSOLVID);
1577 di->repo = from->repo;
1578 di->data = from->data;
1580 di->ddp = from->ddp;
1581 di->idp = from->idp;
1582 di->keyp = from->keyp;
1583 di->key = from->key;
1585 di->repodataid = from->repodataid;
1586 di->solvid = from->solvid;
1587 di->repoid = from->repoid;
1588 di->rootlevel = from->rootlevel;
1589 memcpy(di->parents, from->parents, sizeof(from->parents));
1590 di->nparents = from->nparents;
1594 for (i = 1; i < di->nparents; i++)
1595 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1596 di->kv.parent = &di->parents[di->nparents - 1].kv;
1601 dataiterator_seek(Dataiterator *di, int whence)
1603 if ((whence & DI_SEEK_STAY) != 0)
1604 di->rootlevel = di->nparents;
1605 switch (whence & ~DI_SEEK_STAY)
1608 if (di->state != di_nextarrayelement)
1610 if ((whence & DI_SEEK_STAY) != 0)
1611 di->rootlevel = di->nparents + 1; /* XXX: dangerous! */
1612 di->state = di_entersub;
1614 case DI_SEEK_PARENT:
1621 if (di->rootlevel > di->nparents)
1622 di->rootlevel = di->nparents;
1623 di->dp = di->parents[di->nparents].dp;
1624 di->kv = di->parents[di->nparents].kv;
1625 di->keyp = di->parents[di->nparents].keyp;
1626 di->key = di->data->keys + *di->keyp;
1627 di->ddp = (unsigned char *)di->kv.str;
1628 di->keyname = di->keynames[di->nparents - di->rootlevel];
1629 di->state = di_nextarrayelement;
1631 case DI_SEEK_REWIND:
1637 di->dp = (unsigned char *)di->kv.parent->str;
1638 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
1639 di->state = di_enterschema;
1647 dataiterator_skip_attribute(Dataiterator *di)
1649 if (di->state == di_nextsolvableattr)
1650 di->state = di_nextsolvablekey;
1652 di->state = di_nextkey;
1656 dataiterator_skip_solvable(Dataiterator *di)
1661 di->keyname = di->keynames[0];
1662 di->state = di_nextsolvable;
1666 dataiterator_skip_repo(Dataiterator *di)
1671 di->keyname = di->keynames[0];
1672 di->state = di_nextrepo;
1676 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1681 di->keyname = di->keynames[0];
1682 if (solvid == SOLVID_POS)
1684 di->repo = di->pool->pos.repo;
1691 di->data = di->repo->repodata + di->pool->pos.repodataid;
1693 di->solvid = solvid;
1694 di->state = di_enterrepo;
1695 di->flags |= SEARCH_THISSOLVID;
1700 di->repo = di->pool->solvables[solvid].repo;
1703 else if (di->repoid > 0)
1705 if (!di->pool->urepos)
1711 di->repo = di->pool->repos[di->repoid];
1714 di->solvid = solvid;
1716 di->flags |= SEARCH_THISSOLVID;
1717 di->state = di_enterrepo;
1721 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1727 di->repoid = 0; /* 0 means stay at repo */
1730 di->flags &= ~SEARCH_THISSOLVID;
1731 di->state = di_enterrepo;
1735 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1737 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1741 return datamatcher_match(ma, di->kv.str);
1744 /************************************************************************
1745 * data modify functions
1748 /* extend repodata so that it includes solvables p */
1750 repodata_extend(Repodata *data, Id p)
1752 if (data->start == data->end)
1753 data->start = data->end = p;
1756 int old = data->end - data->start;
1757 int new = p - data->end + 1;
1760 data->attrs = solv_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1761 memset(data->attrs + old, 0, new * sizeof(Id *));
1763 data->incoreoffset = solv_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1764 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1767 if (p < data->start)
1769 int old = data->end - data->start;
1770 int new = data->start - p;
1773 data->attrs = solv_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1774 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1775 memset(data->attrs, 0, new * sizeof(Id *));
1777 data->incoreoffset = solv_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1778 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1779 memset(data->incoreoffset, 0, new * sizeof(Id));
1784 /* shrink end of repodata */
1786 repodata_shrink(Repodata *data, int end)
1790 if (data->end <= end)
1792 if (data->start >= end)
1796 for (i = 0; i < data->end - data->start; i++)
1797 solv_free(data->attrs[i]);
1798 data->attrs = solv_free(data->attrs);
1800 data->incoreoffset = solv_free(data->incoreoffset);
1801 data->start = data->end = 0;
1806 for (i = end; i < data->end; i++)
1807 solv_free(data->attrs[i - data->start]);
1808 data->attrs = solv_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
1810 if (data->incoreoffset)
1811 data->incoreoffset = solv_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
1815 /* extend repodata so that it includes solvables from start to start + num - 1 */
1817 repodata_extend_block(Repodata *data, Id start, Id num)
1821 if (!data->incoreoffset)
1823 data->incoreoffset = solv_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1824 data->start = start;
1825 data->end = start + num;
1828 repodata_extend(data, start);
1830 repodata_extend(data, start + num - 1);
1833 /**********************************************************************/
1836 #define REPODATA_ATTRS_BLOCK 31
1837 #define REPODATA_ATTRDATA_BLOCK 1023
1838 #define REPODATA_ATTRIDDATA_BLOCK 63
1842 repodata_new_handle(Repodata *data)
1846 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1847 data->nxattrs = 2; /* -1: SOLVID_META */
1849 data->xattrs = solv_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1850 data->xattrs[data->nxattrs] = 0;
1851 return -(data->nxattrs++);
1855 repodata_get_attrp(Repodata *data, Id handle)
1859 if (handle == SOLVID_META && !data->xattrs)
1861 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1864 return data->xattrs - handle;
1866 if (handle < data->start || handle >= data->end)
1867 repodata_extend(data, handle);
1869 data->attrs = solv_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1870 return data->attrs + (handle - data->start);
1874 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1880 app = repodata_get_attrp(data, handle);
1885 /* Determine equality based on the name only, allows us to change
1886 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1887 for (pp = ap; *pp; pp += 2)
1888 if (data->keys[*pp].name == data->keys[keyid].name)
1892 if (overwrite || data->keys[*pp].type == REPOKEY_TYPE_DELETED)
1901 ap = solv_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1911 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1915 keyid = repodata_key2id(data, key, 1);
1916 repodata_insert_keyid(data, solvid, keyid, val, 1);
1920 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1924 key.type = REPOKEY_TYPE_ID;
1926 key.storage = KEY_STORAGE_INCORE;
1927 repodata_set(data, solvid, &key, id);
1931 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1935 key.type = REPOKEY_TYPE_NUM;
1937 key.storage = KEY_STORAGE_INCORE;
1938 repodata_set(data, solvid, &key, (Id)num);
1942 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
1946 if (data->localpool)
1947 id = stringpool_str2id(&data->spool, str, 1);
1949 id = pool_str2id(data->repo->pool, str, 1);
1951 key.type = REPOKEY_TYPE_ID;
1953 key.storage = KEY_STORAGE_INCORE;
1954 repodata_set(data, solvid, &key, id);
1958 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
1962 key.type = REPOKEY_TYPE_CONSTANT;
1963 key.size = constant;
1964 key.storage = KEY_STORAGE_INCORE;
1965 repodata_set(data, solvid, &key, 0);
1969 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
1973 key.type = REPOKEY_TYPE_CONSTANTID;
1975 key.storage = KEY_STORAGE_INCORE;
1976 repodata_set(data, solvid, &key, 0);
1980 repodata_set_void(Repodata *data, Id solvid, Id keyname)
1984 key.type = REPOKEY_TYPE_VOID;
1986 key.storage = KEY_STORAGE_INCORE;
1987 repodata_set(data, solvid, &key, 0);
1991 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
1996 l = strlen(str) + 1;
1998 key.type = REPOKEY_TYPE_STR;
2000 key.storage = KEY_STORAGE_INCORE;
2001 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2002 memcpy(data->attrdata + data->attrdatalen, str, l);
2003 repodata_set(data, solvid, &key, data->attrdatalen);
2004 data->attrdatalen += l;
2008 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
2014 key.type = REPOKEY_TYPE_BINARY;
2016 key.storage = KEY_STORAGE_INCORE;
2017 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
2018 dp = data->attrdata + data->attrdatalen;
2019 if (len >= (1 << 14))
2021 if (len >= (1 << 28))
2022 *dp++ = (len >> 28) | 128;
2023 if (len >= (1 << 21))
2024 *dp++ = (len >> 21) | 128;
2025 *dp++ = (len >> 14) | 128;
2027 if (len >= (1 << 7))
2028 *dp++ = (len >> 7) | 128;
2031 memcpy(dp, buf, len);
2032 repodata_set(data, solvid, &key, data->attrdatalen);
2033 data->attrdatalen = dp + len - data->attrdata;
2036 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
2037 * so that the caller can append entrysize new elements plus the termination zero there */
2039 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
2042 Id *ida, *pp, **ppp;
2044 /* check if it is the same as last time, this speeds things up a lot */
2045 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
2047 /* great! just append the new data */
2048 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2049 data->attriddatalen--; /* overwrite terminating 0 */
2050 data->lastdatalen += entrysize;
2054 ppp = repodata_get_attrp(data, handle);
2058 for (; *pp; pp += 2)
2059 if (data->keys[*pp].name == keyname)
2062 if (!pp || !*pp || data->keys[*pp].type != keytype)
2064 /* not found. allocate new key */
2070 key.storage = KEY_STORAGE_INCORE;
2071 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2072 keyid = repodata_key2id(data, &key, 1);
2073 repodata_insert_keyid(data, handle, keyid, data->attriddatalen, 1);
2074 data->lasthandle = handle;
2075 data->lastkey = keyid;
2076 data->lastdatalen = data->attriddatalen + entrysize + 1;
2080 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
2081 oldsize += entrysize;
2082 if (ida + 1 == data->attriddata + data->attriddatalen)
2084 /* this was the last entry, just append it */
2085 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2086 data->attriddatalen--; /* overwrite terminating 0 */
2090 /* too bad. move to back. */
2091 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2092 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
2093 pp[1] = data->attriddatalen;
2094 data->attriddatalen += oldsize;
2096 data->lasthandle = handle;
2097 data->lastkey = *pp;
2098 data->lastdatalen = data->attriddatalen + entrysize + 1;
2102 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2103 const unsigned char *str)
2108 if (!(l = solv_chksum_len(type)))
2113 key.storage = KEY_STORAGE_INCORE;
2114 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2115 memcpy(data->attrdata + data->attrdatalen, str, l);
2116 repodata_set(data, solvid, &key, data->attrdatalen);
2117 data->attrdatalen += l;
2121 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2124 unsigned char buf[64];
2127 if (!(l = solv_chksum_len(type)))
2129 if (l > sizeof(buf) || solv_hex2bin(&str, buf, l) != l)
2131 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2135 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2139 if (!(l = solv_chksum_len(type)))
2141 return pool_bin2hex(data->repo->pool, buf, l);
2144 /* rpm filenames don't contain the epoch, so strip it */
2145 static inline const char *
2146 evrid2vrstr(Pool *pool, Id evrid)
2148 const char *p, *evr = pool_id2str(pool, evrid);
2151 for (p = evr; *p >= '0' && *p <= '9'; p++)
2153 return p != evr && *p == ':' ? p + 1 : evr;
2157 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2159 Pool *pool = data->repo->pool;
2161 const char *str, *fp;
2165 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2168 if ((dir = strrchr(file, '/')) != 0)
2179 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2184 if (l == 1 && dir[0] == '.')
2186 s = pool->solvables + solvid;
2189 str = pool_id2str(pool, s->arch);
2190 if (!strncmp(dir, str, l) && !str[l])
2191 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2193 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2196 char *dir2 = solv_strdup(dir);
2198 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2203 str = pool_id2str(pool, s->name);
2205 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2208 str = evrid2vrstr(pool, s->evr);
2210 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2213 str = pool_id2str(pool, s->arch);
2215 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2217 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2222 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2226 repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
2232 key.type = REPOKEY_TYPE_IDARRAY;
2234 key.storage = KEY_STORAGE_INCORE;
2235 repodata_set(data, solvid, &key, data->attriddatalen);
2236 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, q->count + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2237 for (i = 0; i < q->count; i++)
2238 data->attriddata[data->attriddatalen++] = q->elements[i];
2239 data->attriddata[data->attriddatalen++] = 0;
2243 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2247 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2249 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2250 data->attriddata[data->attriddatalen++] = dir;
2251 data->attriddata[data->attriddatalen++] = num;
2252 data->attriddata[data->attriddatalen++] = num2;
2253 data->attriddata[data->attriddatalen++] = 0;
2257 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2263 l = strlen(str) + 1;
2264 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2265 memcpy(data->attrdata + data->attrdatalen, str, l);
2266 stroff = data->attrdatalen;
2267 data->attrdatalen += l;
2270 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2272 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2273 data->attriddata[data->attriddatalen++] = dir;
2274 data->attriddata[data->attriddatalen++] = stroff;
2275 data->attriddata[data->attriddatalen++] = 0;
2279 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2282 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2284 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2285 data->attriddata[data->attriddatalen++] = id;
2286 data->attriddata[data->attriddatalen++] = 0;
2290 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2294 if (data->localpool)
2295 id = stringpool_str2id(&data->spool, str, 1);
2297 id = pool_str2id(data->repo->pool, str, 1);
2298 repodata_add_idarray(data, solvid, keyname, id);
2302 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2304 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2305 data->attriddata[data->attriddatalen++] = ghandle;
2306 data->attriddata[data->attriddatalen++] = 0;
2310 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2312 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2313 data->attriddata[data->attriddatalen++] = ghandle;
2314 data->attriddata[data->attriddatalen++] = 0;
2318 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2321 app = repodata_get_attrp(data, solvid);
2325 for (; *ap; ap += 2)
2326 if (data->keys[*ap].name == keyname)
2332 for (; *ap; ap += 2)
2334 if (data->keys[*ap].name == keyname)
2342 /* XXX: does not work correctly, needs fix in iterators! */
2344 repodata_delete(Repodata *data, Id solvid, Id keyname)
2348 key.type = REPOKEY_TYPE_DELETED;
2350 key.storage = KEY_STORAGE_INCORE;
2351 repodata_set(data, solvid, &key, 0);
2354 /* add all (uninternalized) attrs from src to dest */
2356 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2359 if (dest == src || !(keyp = data->attrs[src - data->start]))
2361 for (; *keyp; keyp += 2)
2362 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2365 /* add some (uninternalized) attrs from src to dest */
2367 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2370 if (dest == src || !(keyp = data->attrs[src - data->start]))
2372 for (; *keyp; keyp += 2)
2373 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2374 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2379 /**********************************************************************/
2381 /* TODO: unify with repo_write and repo_solv! */
2383 #define EXTDATA_BLOCK 1023
2391 data_addid(struct extdata *xd, Id x)
2395 xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2396 dp = xd->buf + xd->len;
2401 *dp++ = (x >> 28) | 128;
2403 *dp++ = (x >> 21) | 128;
2404 *dp++ = (x >> 14) | 128;
2407 *dp++ = (x >> 7) | 128;
2409 xd->len = dp - xd->buf;
2413 data_addideof(struct extdata *xd, Id x, int eof)
2416 x = (x & 63) | ((x & ~63) << 1);
2417 data_addid(xd, (eof ? x : x | 64));
2421 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2423 xd->buf = solv_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2424 memcpy(xd->buf + xd->len, blob, len);
2428 /*********************************/
2430 /* internalalize some key into incore/vincore data */
2433 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2434 struct extdata *newvincore,
2436 Repokey *key, Id val)
2440 unsigned int oldvincorelen = 0;
2444 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2447 oldvincorelen = xd->len;
2451 case REPOKEY_TYPE_VOID:
2452 case REPOKEY_TYPE_CONSTANT:
2453 case REPOKEY_TYPE_CONSTANTID:
2455 case REPOKEY_TYPE_STR:
2456 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2458 case REPOKEY_TYPE_MD5:
2459 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2461 case REPOKEY_TYPE_SHA1:
2462 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2464 case REPOKEY_TYPE_SHA256:
2465 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2467 case REPOKEY_TYPE_ID:
2468 case REPOKEY_TYPE_NUM:
2469 case REPOKEY_TYPE_DIR:
2470 data_addid(xd, val);
2472 case REPOKEY_TYPE_BINARY:
2475 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2477 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2480 case REPOKEY_TYPE_IDARRAY:
2481 for (ida = data->attriddata + val; *ida; ida++)
2482 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2484 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2485 for (ida = data->attriddata + val; *ida; ida += 3)
2487 data_addid(xd, ida[0]);
2488 data_addid(xd, ida[1]);
2489 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2492 case REPOKEY_TYPE_DIRSTRARRAY:
2493 for (ida = data->attriddata + val; *ida; ida += 2)
2495 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2496 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2499 case REPOKEY_TYPE_FIXARRAY:
2503 for (ida = data->attriddata + val; *ida; ida++)
2506 Id *kp = data->xattrs[-*ida];
2514 schemaid = repodata_schema2id(data, schema, 1);
2515 else if (schemaid != repodata_schema2id(data, schema, 0))
2517 pool_debug(data->repo->pool, SOLV_FATAL, "fixarray substructs with different schemas\n");
2523 data_addid(xd, num);
2524 data_addid(xd, schemaid);
2525 for (ida = data->attriddata + val; *ida; ida++)
2527 Id *kp = data->xattrs[-*ida];
2531 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2535 case REPOKEY_TYPE_FLEXARRAY:
2538 for (ida = data->attriddata + val; *ida; ida++)
2540 data_addid(xd, num);
2541 for (ida = data->attriddata + val; *ida; ida++)
2543 Id *kp = data->xattrs[-*ida];
2546 data_addid(xd, 0); /* XXX */
2553 schemaid = repodata_schema2id(data, schema, 1);
2554 data_addid(xd, schemaid);
2555 kp = data->xattrs[-*ida];
2557 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2562 pool_debug(data->repo->pool, SOLV_FATAL, "don't know how to handle type %d\n", key->type);
2565 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2567 /* put offset/len in incore */
2568 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2569 oldvincorelen = xd->len - oldvincorelen;
2570 data_addid(newincore, oldvincorelen);
2575 repodata_internalize(Repodata *data)
2577 Repokey *key, solvkey;
2579 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2580 unsigned char *dp, *ndp;
2581 int newschema, oldcount;
2582 struct extdata newincore;
2583 struct extdata newvincore;
2586 if (!data->attrs && !data->xattrs)
2589 newvincore.buf = data->vincore;
2590 newvincore.len = data->vincorelen;
2592 /* find the solvables key, create if needed */
2593 memset(&solvkey, 0, sizeof(solvkey));
2594 solvkey.name = REPOSITORY_SOLVABLES;
2595 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2597 solvkey.storage = KEY_STORAGE_INCORE;
2598 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2600 schema = solv_malloc2(data->nkeys, sizeof(Id));
2601 seen = solv_malloc2(data->nkeys, sizeof(Id));
2603 /* Merge the data already existing (in data->schemata, ->incoredata and
2604 friends) with the new attributes in data->attrs[]. */
2605 nentry = data->end - data->start;
2606 memset(&newincore, 0, sizeof(newincore));
2607 data_addid(&newincore, 0); /* start data at offset 1 */
2609 data->mainschema = 0;
2610 data->mainschemaoffsets = solv_free(data->mainschemaoffsets);
2612 /* join entry data */
2613 /* we start with the meta data, entry -1 */
2614 for (entry = -1; entry < nentry; entry++)
2616 memset(seen, 0, data->nkeys * sizeof(Id));
2618 dp = data->incoredata;
2621 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2622 dp = data_read_id(dp, &oldschema);
2625 fprintf(stderr, "oldschema %d\n", oldschema);
2626 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2627 fprintf(stderr, "schemadata %p\n", data->schemadata);
2629 /* seen: -1: old data 0: skipped >0: id + 1 */
2633 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2637 pool_debug(data->repo->pool, SOLV_FATAL, "Inconsistent old data (key occured twice).\n");
2645 keyp = data->attrs ? data->attrs[entry] : 0;
2648 /* strip solvables key */
2650 for (sp = keyp = schema; *sp; sp++)
2651 if (*sp != solvkeyid)
2656 seen[solvkeyid] = 0;
2657 keyp = data->xattrs ? data->xattrs[1] : 0;
2660 for (; *keyp; keyp += 2)
2667 seen[*keyp] = keyp[1] + 1;
2669 if (entry < 0 && data->end != data->start)
2676 /* Ideally we'd like to sort the new schema here, to ensure
2677 schema equality independend of the ordering. We can't do that
2678 yet. For once see below (old ids need to come before new ids).
2679 An additional difficulty is that we also need to move
2680 the values with the keys. */
2681 schemaid = repodata_schema2id(data, schema, 1);
2683 schemaid = oldschema;
2686 /* Now create data blob. We walk through the (possibly new) schema
2687 and either copy over old data, or insert the new. */
2688 /* XXX Here we rely on the fact that the (new) schema has the form
2689 o1 o2 o3 o4 ... | n1 n2 n3 ...
2690 (oX being the old keyids (possibly overwritten), and nX being
2691 the new keyids). This rules out sorting the keyids in order
2692 to ensure a small schema count. */
2694 data->incoreoffset[entry] = newincore.len;
2695 data_addid(&newincore, schemaid);
2698 data->mainschema = schemaid;
2699 data->mainschemaoffsets = solv_calloc(sp - schema, sizeof(Id));
2701 keypstart = data->schemadata + data->schemata[schemaid];
2702 for (keyp = keypstart; *keyp; keyp++)
2705 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2706 if (*keyp == solvkeyid)
2708 /* add flexarray entry count */
2709 data_addid(&newincore, data->end - data->start);
2712 key = data->keys + *keyp;
2714 fprintf(stderr, "internalize %d(%d):%s:%s\n", entry, entry + data->start, pool_id2str(data->repo->pool, key->name), pool_id2str(data->repo->pool, key->type));
2719 /* Skip the data associated with this old key. */
2720 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2722 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2723 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2725 else if (key->storage == KEY_STORAGE_INCORE)
2726 ndp = data_skip_key(data, dp, key);
2729 if (seen[*keyp] == -1)
2731 /* If this key was an old one _and_ was not overwritten with
2732 a different value copy over the old value (we skipped it
2735 data_addblob(&newincore, dp, ndp - dp);
2738 else if (seen[*keyp])
2740 /* Otherwise we have a new value. Parse it into the internal
2742 repodata_serialize_key(data, &newincore, &newvincore,
2743 schema, key, seen[*keyp] - 1);
2747 if (entry >= 0 && data->attrs && data->attrs[entry])
2748 data->attrs[entry] = solv_free(data->attrs[entry]);
2750 /* free all xattrs */
2751 for (entry = 0; entry < data->nxattrs; entry++)
2752 if (data->xattrs[entry])
2753 solv_free(data->xattrs[entry]);
2754 data->xattrs = solv_free(data->xattrs);
2757 data->lasthandle = 0;
2759 data->lastdatalen = 0;
2762 repodata_free_schemahash(data);
2764 solv_free(data->incoredata);
2765 data->incoredata = newincore.buf;
2766 data->incoredatalen = newincore.len;
2767 data->incoredatafree = 0;
2769 solv_free(data->vincore);
2770 data->vincore = newvincore.buf;
2771 data->vincorelen = newvincore.len;
2773 data->attrs = solv_free(data->attrs);
2774 data->attrdata = solv_free(data->attrdata);
2775 data->attriddata = solv_free(data->attriddata);
2776 data->attrdatalen = 0;
2777 data->attriddatalen = 0;
2781 repodata_disable_paging(Repodata *data)
2783 if (maybe_load_repodata(data, 0))
2784 repopagestore_disable_paging(&data->store);
2788 repodata_load_stub(Repodata *data)
2790 Repo *repo = data->repo;
2791 Pool *pool = repo->pool;
2793 struct _Pool_tmpspace oldtmpspace;
2795 if (!pool->loadcallback)
2797 data->state = REPODATA_ERROR;
2800 data->state = REPODATA_LOADING;
2802 /* save tmp space */
2803 oldtmpspace = pool->tmpspace;
2804 memset(&pool->tmpspace, 0, sizeof(pool->tmpspace));
2806 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2808 /* restore tmp space */
2809 for (i = 0; i < POOL_TMPSPACEBUF; i++)
2810 solv_free(pool->tmpspace.buf[i]);
2811 pool->tmpspace = oldtmpspace;
2813 data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
2817 repodata_create_stubs(Repodata *data)
2819 Repo *repo = data->repo;
2820 Pool *pool = repo->pool;
2827 int datastart, dataend;
2829 repodataid = data - repo->repodata;
2830 datastart = data->start;
2831 dataend = data->end;
2832 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2833 while (dataiterator_step(&di))
2835 if (di.data - repo->repodata != repodataid)
2839 dataiterator_free(&di);
2842 stubdataids = solv_calloc(cnt, sizeof(*stubdataids));
2843 for (i = 0; i < cnt; i++)
2845 sdata = repo_add_repodata(repo, 0);
2846 if (dataend > datastart)
2847 repodata_extend_block(sdata, datastart, dataend - datastart);
2848 stubdataids[i] = sdata - repo->repodata;
2849 sdata->state = REPODATA_STUB;
2850 sdata->loadcallback = repodata_load_stub;
2853 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2855 while (dataiterator_step(&di))
2857 if (di.data - repo->repodata != repodataid)
2859 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
2861 dataiterator_entersub(&di);
2862 sdata = repo->repodata + stubdataids[i++];
2866 switch (di.key->type)
2868 case REPOKEY_TYPE_ID:
2869 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
2871 case REPOKEY_TYPE_CONSTANTID:
2872 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
2874 case REPOKEY_TYPE_STR:
2875 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
2877 case REPOKEY_TYPE_VOID:
2878 repodata_set_void(sdata, SOLVID_META, di.key->name);
2880 case REPOKEY_TYPE_NUM:
2881 repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num);
2883 case REPOKEY_TYPE_MD5:
2884 case REPOKEY_TYPE_SHA1:
2885 case REPOKEY_TYPE_SHA256:
2886 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
2888 case REPOKEY_TYPE_IDARRAY:
2889 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
2890 if (di.key->name == REPOSITORY_KEYS)
2897 xkeyname = di.kv.id;
2900 xkey.name = xkeyname;
2901 xkey.type = di.kv.id;
2902 xkey.storage = KEY_STORAGE_INCORE;
2904 repodata_key2id(sdata, &xkey, 1);
2911 dataiterator_free(&di);
2912 for (i = 0; i < cnt; i++)
2913 repodata_internalize(repo->repodata + stubdataids[i]);
2914 solv_free(stubdataids);
2918 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: