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)
101 repo->repodata = solv_realloc2(repo->repodata, repo->nrepodata, sizeof(*data));
102 data = repo->repodata + repo->nrepodata - 1;
103 repodata_initdata(data, repo, localpool);
108 repodata_free(Repodata *data)
110 Repo *repo = data->repo;
111 int i = data - repo->repodata;
112 repodata_freedata(data);
113 if (i < repo->nrepodata - 1)
114 memmove(repo->repodata + i, repo->repodata + i + 1, (repo->nrepodata - 1 - i) * sizeof(Repodata));
119 repodata_empty(Repodata *data, int localpool)
121 void (*loadcallback)(Repodata *) = data->loadcallback;
122 int state = data->state;
123 repodata_freedata(data);
124 repodata_initdata(data, data->repo, localpool);
126 data->loadcallback = loadcallback;
130 /***************************************************************
131 * key pool management
134 /* this is not so time critical that we need a hash, so we do a simple
137 repodata_key2id(Repodata *data, Repokey *key, int create)
141 for (keyid = 1; keyid < data->nkeys; keyid++)
142 if (data->keys[keyid].name == key->name && data->keys[keyid].type == key->type)
144 if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != data->keys[keyid].size)
148 if (keyid == data->nkeys)
152 /* allocate new key */
153 data->keys = solv_realloc2(data->keys, data->nkeys + 1, sizeof(Repokey));
154 data->keys[data->nkeys++] = *key;
155 if (data->verticaloffset)
157 data->verticaloffset = solv_realloc2(data->verticaloffset, data->nkeys, sizeof(Id));
158 data->verticaloffset[data->nkeys - 1] = 0;
160 data->keybits[(key->name >> 3) & (sizeof(data->keybits) - 1)] |= 1 << (key->name & 7);
166 /***************************************************************
167 * schema pool management
170 #define SCHEMATA_BLOCK 31
171 #define SCHEMATADATA_BLOCK 255
174 repodata_schema2id(Repodata *data, Id *schema, int create)
181 return 0; /* XXX: allow empty schema? */
182 if ((schematahash = data->schematahash) == 0)
184 data->schematahash = schematahash = solv_calloc(256, sizeof(Id));
185 for (i = 1; i < data->nschemata; i++)
187 for (sp = data->schemadata + data->schemata[i], h = 0; *sp; len++)
192 data->schemadata = solv_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
193 data->schemata = solv_extend_resize(data->schemata, data->nschemata, sizeof(Id), SCHEMATA_BLOCK);
196 for (sp = schema, len = 0, h = 0; *sp; len++)
201 cid = schematahash[h];
204 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
206 /* cache conflict, do a slow search */
207 for (cid = 1; cid < data->nschemata; cid++)
208 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
214 data->schemadata = solv_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
215 data->schemata = solv_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
217 memcpy(data->schemadata + data->schemadatalen, schema, len * sizeof(Id));
218 data->schemata[data->nschemata] = data->schemadatalen;
219 data->schemadatalen += len;
220 schematahash[h] = data->nschemata;
222 fprintf(stderr, "schema2id: new schema\n");
224 return data->nschemata++;
228 repodata_free_schemahash(Repodata *data)
230 data->schematahash = solv_free(data->schematahash);
232 data->schemata = solv_realloc2(data->schemata, data->nschemata, sizeof(Id));
233 data->schemadata = solv_realloc2(data->schemadata, data->schemadatalen, sizeof(Id));
237 /***************************************************************
238 * dir pool management
241 #ifndef HAVE_STRCHRNUL
242 static inline const char *strchrnul(const char *str, char x)
244 const char *p = strchr(str, x);
245 return p ? p : str + strlen(str);
250 repodata_str2dir(Repodata *data, const char *dir, int create)
256 while (*dir == '/' && dir[1] == '/')
258 if (*dir == '/' && !dir[1])
260 if (data->dirpool.ndirs)
262 return dirpool_add_dir(&data->dirpool, 0, 1, create);
266 dire = strchrnul(dir, '/');
268 id = stringpool_strn2id(&data->spool, dir, dire - dir, create);
270 id = pool_strn2id(data->repo->pool, dir, dire - dir, create);
273 parent = dirpool_add_dir(&data->dirpool, parent, id, create);
286 repodata_dir2str(Repodata *data, Id did, const char *suf)
288 Pool *pool = data->repo->pool;
295 return suf ? suf : "";
299 comp = dirpool_compid(&data->dirpool, parent);
300 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
302 parent = dirpool_parent(&data->dirpool, parent);
307 l += strlen(suf) + 1;
308 p = pool_alloctmpspace(pool, l + 1) + l;
319 comp = dirpool_compid(&data->dirpool, parent);
320 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
323 strncpy(p, comps, l);
324 parent = dirpool_parent(&data->dirpool, parent);
332 /***************************************************************
336 static inline unsigned char *
337 data_skip_schema(Repodata *data, unsigned char *dp, Id schema)
339 Id *keyp = data->schemadata + data->schemata[schema];
340 for (; *keyp; keyp++)
341 dp = data_skip_key(data, dp, data->keys + *keyp);
345 static unsigned char *
346 data_skip_key(Repodata *data, unsigned char *dp, Repokey *key)
348 int nentries, schema;
351 case REPOKEY_TYPE_FIXARRAY:
352 dp = data_read_id(dp, &nentries);
355 dp = data_read_id(dp, &schema);
357 dp = data_skip_schema(data, dp, schema);
359 case REPOKEY_TYPE_FLEXARRAY:
360 dp = data_read_id(dp, &nentries);
363 dp = data_read_id(dp, &schema);
364 dp = data_skip_schema(data, dp, schema);
368 if (key->storage == KEY_STORAGE_INCORE)
369 dp = data_skip(dp, key->type);
370 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
372 dp = data_skip(dp, REPOKEY_TYPE_ID);
373 dp = data_skip(dp, REPOKEY_TYPE_ID);
379 static unsigned char *
380 forward_to_key(Repodata *data, Id keyid, Id *keyp, unsigned char *dp)
386 if (data->mainschemaoffsets && dp == data->incoredata + data->mainschemaoffsets[0] && keyp == data->schemadata + data->schemata[data->mainschema])
389 for (i = 0; (k = *keyp++) != 0; i++)
391 return data->incoredata + data->mainschemaoffsets[i];
394 while ((k = *keyp++) != 0)
398 if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
400 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip offset */
401 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip length */
404 if (data->keys[k].storage != KEY_STORAGE_INCORE)
406 dp = data_skip_key(data, dp, data->keys + k);
411 static unsigned char *
412 get_vertical_data(Repodata *data, Repokey *key, Id off, Id len)
417 if (off >= data->lastverticaloffset)
419 off -= data->lastverticaloffset;
420 if (off + len > data->vincorelen)
422 return data->vincore + off;
424 if (off + len > key->size)
426 /* we now have the offset, go into vertical */
427 off += data->verticaloffset[key - data->keys];
428 /* fprintf(stderr, "key %d page %d\n", key->name, off / REPOPAGE_BLOBSIZE); */
429 dp = repopagestore_load_page_range(&data->store, off / REPOPAGE_BLOBSIZE, (off + len - 1) / REPOPAGE_BLOBSIZE);
431 dp += off % REPOPAGE_BLOBSIZE;
435 static inline unsigned char *
436 get_data(Repodata *data, Repokey *key, unsigned char **dpp, int advance)
438 unsigned char *dp = *dpp;
442 if (key->storage == KEY_STORAGE_INCORE)
445 *dpp = data_skip_key(data, dp, key);
448 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
451 dp = data_read_id(dp, &off);
452 dp = data_read_id(dp, &len);
455 return get_vertical_data(data, key, off, len);
461 load_repodata(Repodata *data)
463 if (data->loadcallback)
465 data->loadcallback(data);
466 if (data->state == REPODATA_AVAILABLE)
469 data->state = REPODATA_ERROR;
474 maybe_load_repodata(Repodata *data, Id keyname)
476 if (keyname && !repodata_precheck_keyname(data, keyname))
477 return 0; /* do not bother... */
484 for (i = 0; i < data->nkeys; i++)
485 if (keyname == data->keys[i].name)
487 if (i == data->nkeys)
490 return load_repodata(data);
493 case REPODATA_AVAILABLE:
494 case REPODATA_LOADING:
497 data->state = REPODATA_ERROR;
502 static inline unsigned char *
503 solvid2data(Repodata *data, Id solvid, Id *schemap)
505 unsigned char *dp = data->incoredata;
508 if (solvid == SOLVID_META) /* META */
510 else if (solvid == SOLVID_POS) /* META */
512 Pool *pool = data->repo->pool;
513 if (data->repo != pool->pos.repo)
515 if (data != data->repo->repodata + pool->pos.repodataid)
517 *schemap = pool->pos.schema;
518 return data->incoredata + pool->pos.dp;
522 if (solvid < data->start || solvid >= data->end)
524 dp += data->incoreoffset[solvid - data->start];
526 return data_read_id(dp, schemap);
529 /************************************************************************
533 static inline unsigned char *
534 find_key_data(Repodata *data, Id solvid, Id keyname, Repokey **keypp)
537 Id schema, *keyp, *kp;
540 if (!maybe_load_repodata(data, keyname))
542 dp = solvid2data(data, solvid, &schema);
545 keyp = data->schemadata + data->schemata[schema];
546 for (kp = keyp; *kp; kp++)
547 if (data->keys[*kp].name == keyname)
551 *keypp = key = data->keys + *kp;
552 if (key->type == REPOKEY_TYPE_DELETED)
554 if (key->type == REPOKEY_TYPE_VOID || key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID)
555 return dp; /* no need to forward... */
556 dp = forward_to_key(data, *kp, keyp, dp);
559 return get_data(data, key, &dp, 0);
563 repodata_lookup_type(Repodata *data, Id solvid, Id keyname)
565 Id schema, *keyp, *kp;
566 if (!maybe_load_repodata(data, keyname))
568 if (!solvid2data(data, solvid, &schema))
570 keyp = data->schemadata + data->schemata[schema];
571 for (kp = keyp; *kp; kp++)
572 if (data->keys[*kp].name == keyname)
573 return data->keys[*kp].type;
578 repodata_lookup_id(Repodata *data, Id solvid, Id keyname)
584 dp = find_key_data(data, solvid, keyname, &key);
587 if (key->type == REPOKEY_TYPE_CONSTANTID)
589 if (key->type != REPOKEY_TYPE_ID)
591 dp = data_read_id(dp, &id);
596 repodata_lookup_str(Repodata *data, Id solvid, Id keyname)
602 dp = find_key_data(data, solvid, keyname, &key);
605 if (key->type == REPOKEY_TYPE_STR)
606 return (const char *)dp;
607 if (key->type == REPOKEY_TYPE_CONSTANTID)
609 else if (key->type == REPOKEY_TYPE_ID)
610 dp = data_read_id(dp, &id);
614 return stringpool_id2str(&data->spool, id);
615 return pool_id2str(data->repo->pool, id);
619 repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned int *value)
626 dp = find_key_data(data, solvid, keyname, &key);
629 if (key->type == REPOKEY_TYPE_NUM
630 || key->type == REPOKEY_TYPE_U32
631 || key->type == REPOKEY_TYPE_CONSTANT)
634 dp = data_fetch(dp, &kv, key);
642 repodata_lookup_void(Repodata *data, Id solvid, Id keyname)
648 if (!maybe_load_repodata(data, keyname))
650 dp = solvid2data(data, solvid, &schema);
653 /* can't use find_key_data as we need to test the type */
654 for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++)
655 if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID)
660 const unsigned char *
661 repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep)
666 dp = find_key_data(data, solvid, keyname, &key);
674 repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
682 dp = find_key_data(data, solvid, keyname, &key);
685 if (key->type != REPOKEY_TYPE_IDARRAY && key->type != REPOKEY_TYPE_REL_IDARRAY)
689 dp = data_read_ideof(dp, &id, &eof);
698 repodata_globalize_id(Repodata *data, Id id, int create)
700 if (!id || !data || !data->localpool)
702 return pool_str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
706 repodata_localize_id(Repodata *data, Id id, int create)
708 if (!id || !data || !data->localpool)
710 return stringpool_str2id(&data->spool, pool_id2str(data->repo->pool, id), create);
714 /************************************************************************
720 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
724 case REPOKEY_TYPE_ID:
725 case REPOKEY_TYPE_CONSTANTID:
726 case REPOKEY_TYPE_IDARRAY:
727 if (data && data->localpool)
728 kv->str = stringpool_id2str(&data->spool, kv->id);
730 kv->str = pool_id2str(pool, kv->id);
731 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
734 for (s = kv->str; *s >= 'a' && *s <= 'z'; s++)
736 if (*s == ':' && s > kv->str)
740 case REPOKEY_TYPE_STR:
742 case REPOKEY_TYPE_DIRSTRARRAY:
743 if (!(flags & SEARCH_FILES))
744 return 1; /* match just the basename */
745 /* Put the full filename into kv->str. */
746 kv->str = repodata_dir2str(data, kv->id, kv->str);
747 /* And to compensate for that put the "empty" directory into
748 kv->id, so that later calls to repodata_dir2str on this data
749 come up with the same filename again. */
752 case REPOKEY_TYPE_MD5:
753 case REPOKEY_TYPE_SHA1:
754 case REPOKEY_TYPE_SHA256:
755 if (!(flags & SEARCH_CHECKSUMS))
756 return 0; /* skip em */
757 kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str);
765 struct subschema_data {
771 /* search a specific repodata */
773 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
777 Id keyid, *kp, *keyp;
778 unsigned char *dp, *ddp;
784 if (!maybe_load_repodata(data, keyname))
786 if (solvid == SOLVID_SUBSCHEMA)
788 struct subschema_data *subd = cbdata;
789 cbdata = subd->cbdata;
791 schema = subd->parent->id;
792 dp = (unsigned char *)subd->parent->str;
793 kv.parent = subd->parent;
798 dp = solvid2data(data, solvid, &schema);
801 s = data->repo->pool->solvables + solvid;
804 keyp = data->schemadata + data->schemata[schema];
807 /* search for a specific key */
808 for (kp = keyp; *kp; kp++)
809 if (data->keys[*kp].name == keyname)
813 dp = forward_to_key(data, *kp, keyp, dp);
819 while ((keyid = *keyp++) != 0)
822 key = data->keys + keyid;
823 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
825 if (key->type == REPOKEY_TYPE_DELETED)
827 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
829 struct subschema_data subd;
833 subd.cbdata = cbdata;
836 ddp = data_read_id(ddp, &nentries);
840 while (ddp && nentries > 0)
844 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
845 ddp = data_read_id(ddp, &schema);
847 kv.str = (char *)ddp;
848 stop = callback(cbdata, s, data, key, &kv);
849 if (stop > SEARCH_NEXT_KEY)
851 if (stop && stop != SEARCH_ENTERSUB)
853 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
854 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
855 ddp = data_skip_schema(data, ddp, schema);
858 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
862 kv.str = (char *)ddp;
863 stop = callback(cbdata, s, data, key, &kv);
864 if (stop > SEARCH_NEXT_KEY)
874 ddp = data_fetch(ddp, &kv, key);
877 stop = callback(cbdata, s, data, key, &kv);
880 while (!kv.eof && !stop);
881 if (onekey || stop > SEARCH_NEXT_KEY)
887 repodata_setpos_kv(Repodata *data, KeyValue *kv)
889 Pool *pool = data->repo->pool;
891 pool_clear_pos(pool);
894 pool->pos.repo = data->repo;
895 pool->pos.repodataid = data - data->repo->repodata;
896 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
897 pool->pos.schema = kv->id;
901 /************************************************************************
902 * data iterator functions
905 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
906 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
907 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
908 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
909 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
910 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
911 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
912 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
913 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
914 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
915 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
916 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
917 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
918 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
922 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
936 case SOLVABLE_VENDOR:
939 case SOLVABLE_PROVIDES:
941 return s->provides ? s->repo->idarraydata + s->provides : 0;
942 case SOLVABLE_OBSOLETES:
944 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
945 case SOLVABLE_CONFLICTS:
947 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
948 case SOLVABLE_REQUIRES:
950 return s->requires ? s->repo->idarraydata + s->requires : 0;
951 case SOLVABLE_RECOMMENDS:
953 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
954 case SOLVABLE_SUPPLEMENTS:
956 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
957 case SOLVABLE_SUGGESTS:
959 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
960 case SOLVABLE_ENHANCES:
962 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
965 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
972 datamatcher_init(Datamatcher *ma, const char *match, int flags)
978 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
980 ma->matchdata = solv_calloc(1, sizeof(regex_t));
981 ma->error = regcomp((regex_t *)ma->matchdata, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
984 solv_free(ma->matchdata);
985 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
992 datamatcher_free(Datamatcher *ma)
994 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
996 regfree(ma->matchdata);
997 ma->matchdata = solv_free(ma->matchdata);
1002 datamatcher_match(Datamatcher *ma, const char *str)
1005 switch ((ma->flags & SEARCH_STRINGMASK))
1007 case SEARCH_SUBSTRING:
1008 if (ma->flags & SEARCH_NOCASE)
1010 if (!strcasestr(str, ma->match))
1015 if (!strstr(str, ma->match))
1020 if (ma->flags & SEARCH_NOCASE)
1022 if (strcasecmp(ma->match, str))
1027 if (strcmp(ma->match, str))
1031 case SEARCH_STRINGSTART:
1032 if (ma->flags & SEARCH_NOCASE)
1034 if (strncasecmp(ma->match, str, strlen(ma->match)))
1039 if (strncmp(ma->match, str, strlen(ma->match)))
1043 case SEARCH_STRINGEND:
1044 l = strlen(str) - strlen(ma->match);
1047 if (ma->flags & SEARCH_NOCASE)
1049 if (strcasecmp(ma->match, str + l))
1054 if (strcmp(ma->match, str + l))
1059 if (fnmatch(ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
1063 if (regexec((const regex_t *)ma->matchdata, str, 0, NULL, 0))
1073 repodata_filelistfilter_matches(Repodata *data, const char *str)
1075 /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */
1076 /* for now hardcoded */
1077 if (strstr(str, "bin/"))
1079 if (!strncmp(str, "/etc/", 5))
1081 if (!strcmp(str, "/usr/lib/sendmail"))
1103 di_nextarrayelement,
1108 di_nextsolvableattr,
1113 /* see repo.h for documentation */
1115 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
1117 memset(di, 0, sizeof(*di));
1119 di->flags = flags & ~SEARCH_THISSOLVID;
1120 if (!pool || (repo && repo->pool != pool))
1128 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1134 di->keyname = keyname;
1135 di->keynames[0] = keyname;
1136 dataiterator_set_search(di, repo, p);
1141 dataiterator_init_clone(Dataiterator *di, Dataiterator *from)
1144 memset(&di->matcher, 0, sizeof(di->matcher));
1145 if (from->matcher.match)
1146 datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags);
1151 for (i = 1; i < di->nparents; i++)
1152 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1153 di->kv.parent = &di->parents[di->nparents - 1].kv;
1158 dataiterator_set_match(Dataiterator *di, const char *match, int flags)
1160 di->flags = (flags & ~SEARCH_THISSOLVID) | (di->flags & SEARCH_THISSOLVID);
1161 datamatcher_free(&di->matcher);
1162 memset(&di->matcher, 0, sizeof(di->matcher));
1166 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1176 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
1180 di->flags &= ~SEARCH_THISSOLVID;
1184 if (!di->pool->urepos)
1192 di->repo = di->pool->repos[di->repoid];
1194 di->state = di_enterrepo;
1196 dataiterator_jump_to_solvid(di, p);
1200 dataiterator_set_keyname(Dataiterator *di, Id keyname)
1203 di->keyname = keyname;
1204 di->keynames[0] = keyname;
1208 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1212 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1214 di->state = di_bye; /* sorry */
1217 for (i = di->nkeynames + 1; i > 0; i--)
1218 di->keynames[i] = di->keynames[i - 1];
1219 di->keynames[0] = di->keyname = keyname;
1224 dataiterator_free(Dataiterator *di)
1226 if (di->matcher.match)
1227 datamatcher_free(&di->matcher);
1230 static inline unsigned char *
1231 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1233 Id *keyp = di->keyp;
1234 Repokey *keys = di->data->keys;
1237 for (keyp = di->keyp; *keyp; keyp++)
1238 if (keys[*keyp].name == keyname)
1242 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1250 dataiterator_filelistcheck(Dataiterator *di)
1253 int needcomplete = 0;
1254 Repodata *data = di->data;
1256 if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
1257 if (!di->matcher.match
1258 || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
1259 && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)
1260 || !repodata_filelistfilter_matches(di->data, di->matcher.match))
1262 if (data->state != REPODATA_AVAILABLE)
1263 return needcomplete ? 1 : 0;
1264 for (j = 1; j < data->nkeys; j++)
1265 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
1267 return j == data->nkeys && !needcomplete ? 0 : 1;
1271 dataiterator_step(Dataiterator *di)
1279 case di_enterrepo: di_enterrepo:
1280 if (!di->repo || (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS)))
1282 if (!(di->flags & SEARCH_THISSOLVID))
1284 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1285 goto di_nextsolvable;
1289 case di_entersolvable: di_entersolvable:
1290 if (di->repodataid >= 0)
1292 di->repodataid = 0; /* reset repodata iterator */
1293 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)
1295 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1297 goto di_entersolvablekey;
1302 case di_enterrepodata: di_enterrepodata:
1303 if (di->repodataid >= 0)
1305 if (di->repodataid >= di->repo->nrepodata)
1306 goto di_nextsolvable;
1307 di->data = di->repo->repodata + di->repodataid;
1309 if (di->repodataid >= 0 && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
1310 goto di_nextrepodata;
1311 if (!maybe_load_repodata(di->data, di->keyname))
1312 goto di_nextrepodata;
1313 di->dp = solvid2data(di->data, di->solvid, &schema);
1315 goto di_nextrepodata;
1316 if (di->solvid == SOLVID_POS)
1317 di->solvid = di->pool->pos.solvid;
1318 /* reset key iterator */
1319 di->keyp = di->data->schemadata + di->data->schemata[schema];
1322 case di_enterschema: di_enterschema:
1324 di->dp = dataiterator_find_keyname(di, di->keyname);
1325 if (!di->dp || !*di->keyp)
1329 goto di_nextrepodata;
1333 case di_enterkey: di_enterkey:
1335 di->key = di->data->keys + *di->keyp;
1336 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1339 if (di->key->type == REPOKEY_TYPE_DELETED)
1341 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1343 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1349 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1351 di->state = di_nextkey;
1353 di->state = di_nextattr;
1356 case di_nextkey: di_nextkey:
1357 if (!di->keyname && *++di->keyp)
1363 case di_nextrepodata: di_nextrepodata:
1364 if (di->repodataid >= 0 && ++di->repodataid < di->repo->nrepodata)
1365 goto di_enterrepodata;
1368 case di_nextsolvable: di_nextsolvable:
1369 if (!(di->flags & SEARCH_THISSOLVID))
1372 di->solvid = di->repo->start;
1375 for (; di->solvid < di->repo->end; di->solvid++)
1377 if (di->pool->solvables[di->solvid].repo == di->repo)
1378 goto di_entersolvable;
1383 case di_nextrepo: di_nextrepo:
1388 if (di->repoid < di->pool->nrepos)
1390 di->repo = di->pool->repos[di->repoid];
1396 case di_bye: di_bye:
1400 case di_enterarray: di_enterarray:
1401 if (di->key->name == REPOSITORY_SOLVABLES)
1403 di->ddp = data_read_id(di->ddp, &di->kv.num);
1408 case di_nextarrayelement: di_nextarrayelement:
1411 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1412 if (di->kv.entry == di->kv.num)
1414 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1416 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1418 di->kv.str = (char *)di->ddp;
1420 di->state = di_nextkey;
1423 if (di->kv.entry == di->kv.num - 1)
1425 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1426 di->ddp = data_read_id(di->ddp, &di->kv.id);
1427 di->kv.str = (char *)di->ddp;
1428 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1430 if ((di->flags & SEARCH_SUB) != 0)
1431 di->state = di_entersub;
1433 di->state = di_nextarrayelement;
1436 case di_entersub: di_entersub:
1437 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1438 goto di_nextarrayelement; /* sorry, full */
1439 di->parents[di->nparents].kv = di->kv;
1440 di->parents[di->nparents].dp = di->dp;
1441 di->parents[di->nparents].keyp = di->keyp;
1442 di->dp = (unsigned char *)di->kv.str;
1443 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1444 memset(&di->kv, 0, sizeof(di->kv));
1445 di->kv.parent = &di->parents[di->nparents].kv;
1447 di->keyname = di->keynames[di->nparents - di->rootlevel];
1448 goto di_enterschema;
1450 case di_leavesub: di_leavesub:
1451 if (di->nparents - 1 < di->rootlevel)
1454 di->dp = di->parents[di->nparents].dp;
1455 di->kv = di->parents[di->nparents].kv;
1456 di->keyp = di->parents[di->nparents].keyp;
1457 di->key = di->data->keys + *di->keyp;
1458 di->ddp = (unsigned char *)di->kv.str;
1459 di->keyname = di->keynames[di->nparents - di->rootlevel];
1460 goto di_nextarrayelement;
1462 /* special solvable attr handling follows */
1464 case di_nextsolvableattr:
1465 di->kv.id = *di->idp++;
1470 di->state = di_nextsolvablekey;
1474 case di_nextsolvablekey: di_nextsolvablekey:
1475 if (di->keyname || di->key->name == RPM_RPMDBID)
1476 goto di_enterrepodata;
1480 case di_entersolvablekey: di_entersolvablekey:
1481 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1482 if (!di->idp || !di->idp[0])
1483 goto di_nextsolvablekey;
1484 di->kv.id = di->idp[0];
1485 di->kv.num = di->idp[0];
1487 if (!di->kv.eof && !di->idp[0])
1491 di->state = di_nextsolvablekey;
1493 di->state = di_nextsolvableattr;
1497 if (di->matcher.match)
1499 /* simple pre-check so that we don't need to stringify */
1500 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))
1502 int l = strlen(di->matcher.match) - strlen(di->kv.str);
1503 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
1506 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1508 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1512 if (!datamatcher_match(&di->matcher, di->kv.str))
1515 /* found something! */
1521 dataiterator_entersub(Dataiterator *di)
1523 if (di->state == di_nextarrayelement)
1524 di->state = di_entersub;
1528 dataiterator_setpos(Dataiterator *di)
1530 if (di->kv.eof == 2)
1532 pool_clear_pos(di->pool);
1535 di->pool->pos.solvid = di->solvid;
1536 di->pool->pos.repo = di->repo;
1537 di->pool->pos.repodataid = di->data - di->repo->repodata;
1538 di->pool->pos.schema = di->kv.id;
1539 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1543 dataiterator_setpos_parent(Dataiterator *di)
1545 if (!di->kv.parent || di->kv.parent->eof == 2)
1547 pool_clear_pos(di->pool);
1550 di->pool->pos.solvid = di->solvid;
1551 di->pool->pos.repo = di->repo;
1552 di->pool->pos.repodataid = di->data - di->repo->repodata;
1553 di->pool->pos.schema = di->kv.parent->id;
1554 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1557 /* clones just the position, not the search keys/matcher */
1559 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
1561 di->state = from->state;
1562 di->flags &= ~SEARCH_THISSOLVID;
1563 di->flags |= (from->flags & SEARCH_THISSOLVID);
1564 di->repo = from->repo;
1565 di->data = from->data;
1567 di->ddp = from->ddp;
1568 di->idp = from->idp;
1569 di->keyp = from->keyp;
1570 di->key = from->key;
1572 di->repodataid = from->repodataid;
1573 di->solvid = from->solvid;
1574 di->repoid = from->repoid;
1575 di->rootlevel = from->rootlevel;
1576 memcpy(di->parents, from->parents, sizeof(from->parents));
1577 di->nparents = from->nparents;
1581 for (i = 1; i < di->nparents; i++)
1582 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1583 di->kv.parent = &di->parents[di->nparents - 1].kv;
1588 dataiterator_seek(Dataiterator *di, int whence)
1590 if ((whence & DI_SEEK_STAY) != 0)
1591 di->rootlevel = di->nparents;
1592 switch (whence & ~DI_SEEK_STAY)
1595 if (di->state != di_nextarrayelement)
1597 if ((whence & DI_SEEK_STAY) != 0)
1598 di->rootlevel = di->nparents + 1; /* XXX: dangerous! */
1599 di->state = di_entersub;
1601 case DI_SEEK_PARENT:
1608 if (di->rootlevel > di->nparents)
1609 di->rootlevel = di->nparents;
1610 di->dp = di->parents[di->nparents].dp;
1611 di->kv = di->parents[di->nparents].kv;
1612 di->keyp = di->parents[di->nparents].keyp;
1613 di->key = di->data->keys + *di->keyp;
1614 di->ddp = (unsigned char *)di->kv.str;
1615 di->keyname = di->keynames[di->nparents - di->rootlevel];
1616 di->state = di_nextarrayelement;
1618 case DI_SEEK_REWIND:
1624 di->dp = (unsigned char *)di->kv.parent->str;
1625 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
1626 di->state = di_enterschema;
1634 dataiterator_skip_attribute(Dataiterator *di)
1636 if (di->state == di_nextsolvableattr)
1637 di->state = di_nextsolvablekey;
1639 di->state = di_nextkey;
1643 dataiterator_skip_solvable(Dataiterator *di)
1648 di->keyname = di->keynames[0];
1649 di->state = di_nextsolvable;
1653 dataiterator_skip_repo(Dataiterator *di)
1658 di->keyname = di->keynames[0];
1659 di->state = di_nextrepo;
1663 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1668 di->keyname = di->keynames[0];
1669 if (solvid == SOLVID_POS)
1671 di->repo = di->pool->pos.repo;
1678 di->data = di->repo->repodata + di->pool->pos.repodataid;
1679 di->repodataid = -1;
1680 di->solvid = solvid;
1681 di->state = di_enterrepo;
1682 di->flags |= SEARCH_THISSOLVID;
1687 di->repo = di->pool->solvables[solvid].repo;
1690 else if (di->repoid > 0)
1692 if (!di->pool->urepos)
1698 di->repo = di->pool->repos[di->repoid];
1701 di->solvid = solvid;
1703 di->flags |= SEARCH_THISSOLVID;
1704 di->state = di_enterrepo;
1708 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1714 di->repoid = 0; /* 0 means stay at repo */
1717 di->flags &= ~SEARCH_THISSOLVID;
1718 di->state = di_enterrepo;
1722 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1724 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1728 return datamatcher_match(ma, di->kv.str);
1731 /************************************************************************
1732 * data modify functions
1735 /* extend repodata so that it includes solvables p */
1737 repodata_extend(Repodata *data, Id p)
1739 if (data->start == data->end)
1740 data->start = data->end = p;
1743 int old = data->end - data->start;
1744 int new = p - data->end + 1;
1747 data->attrs = solv_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1748 memset(data->attrs + old, 0, new * sizeof(Id *));
1750 data->incoreoffset = solv_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1751 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1754 if (p < data->start)
1756 int old = data->end - data->start;
1757 int new = data->start - p;
1760 data->attrs = solv_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1761 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1762 memset(data->attrs, 0, new * sizeof(Id *));
1764 data->incoreoffset = solv_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1765 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1766 memset(data->incoreoffset, 0, new * sizeof(Id));
1771 /* shrink end of repodata */
1773 repodata_shrink(Repodata *data, int end)
1777 if (data->end <= end)
1779 if (data->start >= end)
1783 for (i = 0; i < data->end - data->start; i++)
1784 solv_free(data->attrs[i]);
1785 data->attrs = solv_free(data->attrs);
1787 data->incoreoffset = solv_free(data->incoreoffset);
1788 data->start = data->end = 0;
1793 for (i = end; i < data->end; i++)
1794 solv_free(data->attrs[i - data->start]);
1795 data->attrs = solv_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
1797 if (data->incoreoffset)
1798 data->incoreoffset = solv_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
1802 /* extend repodata so that it includes solvables from start to start + num - 1 */
1804 repodata_extend_block(Repodata *data, Id start, Id num)
1808 if (!data->incoreoffset)
1810 data->incoreoffset = solv_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1811 data->start = start;
1812 data->end = start + num;
1815 repodata_extend(data, start);
1817 repodata_extend(data, start + num - 1);
1820 /**********************************************************************/
1823 #define REPODATA_ATTRS_BLOCK 31
1824 #define REPODATA_ATTRDATA_BLOCK 1023
1825 #define REPODATA_ATTRIDDATA_BLOCK 63
1829 repodata_new_handle(Repodata *data)
1833 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1834 data->nxattrs = 2; /* -1: SOLVID_META */
1836 data->xattrs = solv_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1837 data->xattrs[data->nxattrs] = 0;
1838 return -(data->nxattrs++);
1842 repodata_get_attrp(Repodata *data, Id handle)
1846 if (handle == SOLVID_META && !data->xattrs)
1848 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1851 return data->xattrs - handle;
1853 if (handle < data->start || handle >= data->end)
1854 repodata_extend(data, handle);
1856 data->attrs = solv_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1857 return data->attrs + (handle - data->start);
1861 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1867 app = repodata_get_attrp(data, handle);
1872 /* Determine equality based on the name only, allows us to change
1873 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1874 for (pp = ap; *pp; pp += 2)
1875 if (data->keys[*pp].name == data->keys[keyid].name)
1879 if (overwrite || data->keys[*pp].type == REPOKEY_TYPE_DELETED)
1888 ap = solv_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1898 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1902 keyid = repodata_key2id(data, key, 1);
1903 repodata_insert_keyid(data, solvid, keyid, val, 1);
1907 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1911 key.type = REPOKEY_TYPE_ID;
1913 key.storage = KEY_STORAGE_INCORE;
1914 repodata_set(data, solvid, &key, id);
1918 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1922 key.type = REPOKEY_TYPE_NUM;
1924 key.storage = KEY_STORAGE_INCORE;
1925 repodata_set(data, solvid, &key, (Id)num);
1929 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
1933 if (data->localpool)
1934 id = stringpool_str2id(&data->spool, str, 1);
1936 id = pool_str2id(data->repo->pool, str, 1);
1938 key.type = REPOKEY_TYPE_ID;
1940 key.storage = KEY_STORAGE_INCORE;
1941 repodata_set(data, solvid, &key, id);
1945 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
1949 key.type = REPOKEY_TYPE_CONSTANT;
1950 key.size = constant;
1951 key.storage = KEY_STORAGE_INCORE;
1952 repodata_set(data, solvid, &key, 0);
1956 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
1960 key.type = REPOKEY_TYPE_CONSTANTID;
1962 key.storage = KEY_STORAGE_INCORE;
1963 repodata_set(data, solvid, &key, 0);
1967 repodata_set_void(Repodata *data, Id solvid, Id keyname)
1971 key.type = REPOKEY_TYPE_VOID;
1973 key.storage = KEY_STORAGE_INCORE;
1974 repodata_set(data, solvid, &key, 0);
1978 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
1983 l = strlen(str) + 1;
1985 key.type = REPOKEY_TYPE_STR;
1987 key.storage = KEY_STORAGE_INCORE;
1988 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1989 memcpy(data->attrdata + data->attrdatalen, str, l);
1990 repodata_set(data, solvid, &key, data->attrdatalen);
1991 data->attrdatalen += l;
1995 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
2001 key.type = REPOKEY_TYPE_BINARY;
2003 key.storage = KEY_STORAGE_INCORE;
2004 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
2005 dp = data->attrdata + data->attrdatalen;
2006 if (len >= (1 << 14))
2008 if (len >= (1 << 28))
2009 *dp++ = (len >> 28) | 128;
2010 if (len >= (1 << 21))
2011 *dp++ = (len >> 21) | 128;
2012 *dp++ = (len >> 14) | 128;
2014 if (len >= (1 << 7))
2015 *dp++ = (len >> 7) | 128;
2018 memcpy(dp, buf, len);
2019 repodata_set(data, solvid, &key, data->attrdatalen);
2020 data->attrdatalen = dp + len - data->attrdata;
2023 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
2024 * so that the caller can append entrysize new elements plus the termination zero there */
2026 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
2029 Id *ida, *pp, **ppp;
2031 /* check if it is the same as last time, this speeds things up a lot */
2032 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
2034 /* great! just append the new data */
2035 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2036 data->attriddatalen--; /* overwrite terminating 0 */
2037 data->lastdatalen += entrysize;
2041 ppp = repodata_get_attrp(data, handle);
2045 for (; *pp; pp += 2)
2046 if (data->keys[*pp].name == keyname)
2049 if (!pp || !*pp || data->keys[*pp].type != keytype)
2051 /* not found. allocate new key */
2057 key.storage = KEY_STORAGE_INCORE;
2058 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2059 keyid = repodata_key2id(data, &key, 1);
2060 repodata_insert_keyid(data, handle, keyid, data->attriddatalen, 1);
2061 data->lasthandle = handle;
2062 data->lastkey = keyid;
2063 data->lastdatalen = data->attriddatalen + entrysize + 1;
2067 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
2068 oldsize += entrysize;
2069 if (ida + 1 == data->attriddata + data->attriddatalen)
2071 /* this was the last entry, just append it */
2072 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2073 data->attriddatalen--; /* overwrite terminating 0 */
2077 /* too bad. move to back. */
2078 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2079 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
2080 pp[1] = data->attriddatalen;
2081 data->attriddatalen += oldsize;
2083 data->lasthandle = handle;
2084 data->lastkey = *pp;
2085 data->lastdatalen = data->attriddatalen + entrysize + 1;
2089 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2090 const unsigned char *str)
2095 if (!(l = solv_chksum_len(type)))
2100 key.storage = KEY_STORAGE_INCORE;
2101 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2102 memcpy(data->attrdata + data->attrdatalen, str, l);
2103 repodata_set(data, solvid, &key, data->attrdatalen);
2104 data->attrdatalen += l;
2108 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2111 unsigned char buf[64];
2114 if (!(l = solv_chksum_len(type)))
2116 if (l > sizeof(buf) || solv_hex2bin(&str, buf, l) != l)
2118 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2122 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2126 if (!(l = solv_chksum_len(type)))
2128 return pool_bin2hex(data->repo->pool, buf, l);
2131 /* rpm filenames don't contain the epoch, so strip it */
2132 static inline const char *
2133 evrid2vrstr(Pool *pool, Id evrid)
2135 const char *p, *evr = pool_id2str(pool, evrid);
2138 for (p = evr; *p >= '0' && *p <= '9'; p++)
2140 return p != evr && *p == ':' ? p + 1 : evr;
2144 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2146 Pool *pool = data->repo->pool;
2148 const char *str, *fp;
2152 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2155 if ((dir = strrchr(file, '/')) != 0)
2166 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2171 if (l == 1 && dir[0] == '.')
2173 s = pool->solvables + solvid;
2176 str = pool_id2str(pool, s->arch);
2177 if (!strncmp(dir, str, l) && !str[l])
2178 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2180 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2183 char *dir2 = solv_strdup(dir);
2185 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2190 str = pool_id2str(pool, s->name);
2192 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2195 str = evrid2vrstr(pool, s->evr);
2197 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2200 str = pool_id2str(pool, s->arch);
2202 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2204 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2209 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2213 repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
2219 key.type = REPOKEY_TYPE_IDARRAY;
2221 key.storage = KEY_STORAGE_INCORE;
2222 repodata_set(data, solvid, &key, data->attriddatalen);
2223 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, q->count + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2224 for (i = 0; i < q->count; i++)
2225 data->attriddata[data->attriddatalen++] = q->elements[i];
2226 data->attriddata[data->attriddatalen++] = 0;
2230 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2234 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2236 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2237 data->attriddata[data->attriddatalen++] = dir;
2238 data->attriddata[data->attriddatalen++] = num;
2239 data->attriddata[data->attriddatalen++] = num2;
2240 data->attriddata[data->attriddatalen++] = 0;
2244 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2250 l = strlen(str) + 1;
2251 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2252 memcpy(data->attrdata + data->attrdatalen, str, l);
2253 stroff = data->attrdatalen;
2254 data->attrdatalen += l;
2257 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2259 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2260 data->attriddata[data->attriddatalen++] = dir;
2261 data->attriddata[data->attriddatalen++] = stroff;
2262 data->attriddata[data->attriddatalen++] = 0;
2266 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2269 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2271 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2272 data->attriddata[data->attriddatalen++] = id;
2273 data->attriddata[data->attriddatalen++] = 0;
2277 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2281 if (data->localpool)
2282 id = stringpool_str2id(&data->spool, str, 1);
2284 id = pool_str2id(data->repo->pool, str, 1);
2285 repodata_add_idarray(data, solvid, keyname, id);
2289 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2291 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2292 data->attriddata[data->attriddatalen++] = ghandle;
2293 data->attriddata[data->attriddatalen++] = 0;
2297 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2299 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2300 data->attriddata[data->attriddatalen++] = ghandle;
2301 data->attriddata[data->attriddatalen++] = 0;
2305 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2308 app = repodata_get_attrp(data, solvid);
2312 for (; *ap; ap += 2)
2313 if (data->keys[*ap].name == keyname)
2319 for (; *ap; ap += 2)
2321 if (data->keys[*ap].name == keyname)
2329 /* XXX: does not work correctly, needs fix in iterators! */
2331 repodata_delete(Repodata *data, Id solvid, Id keyname)
2335 key.type = REPOKEY_TYPE_DELETED;
2337 key.storage = KEY_STORAGE_INCORE;
2338 repodata_set(data, solvid, &key, 0);
2341 /* add all (uninternalized) attrs from src to dest */
2343 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2346 if (dest == src || !(keyp = data->attrs[src - data->start]))
2348 for (; *keyp; keyp += 2)
2349 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2352 /* add some (uninternalized) attrs from src to dest */
2354 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2357 if (dest == src || !(keyp = data->attrs[src - data->start]))
2359 for (; *keyp; keyp += 2)
2360 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2361 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2366 /**********************************************************************/
2368 /* TODO: unify with repo_write and repo_solv! */
2370 #define EXTDATA_BLOCK 1023
2378 data_addid(struct extdata *xd, Id x)
2382 xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2383 dp = xd->buf + xd->len;
2388 *dp++ = (x >> 28) | 128;
2390 *dp++ = (x >> 21) | 128;
2391 *dp++ = (x >> 14) | 128;
2394 *dp++ = (x >> 7) | 128;
2396 xd->len = dp - xd->buf;
2400 data_addideof(struct extdata *xd, Id x, int eof)
2403 x = (x & 63) | ((x & ~63) << 1);
2404 data_addid(xd, (eof ? x : x | 64));
2408 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2410 xd->buf = solv_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2411 memcpy(xd->buf + xd->len, blob, len);
2415 /*********************************/
2417 /* internalalize some key into incore/vincore data */
2420 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2421 struct extdata *newvincore,
2423 Repokey *key, Id val)
2427 unsigned int oldvincorelen = 0;
2431 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2434 oldvincorelen = xd->len;
2438 case REPOKEY_TYPE_VOID:
2439 case REPOKEY_TYPE_CONSTANT:
2440 case REPOKEY_TYPE_CONSTANTID:
2442 case REPOKEY_TYPE_STR:
2443 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2445 case REPOKEY_TYPE_MD5:
2446 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2448 case REPOKEY_TYPE_SHA1:
2449 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2451 case REPOKEY_TYPE_SHA256:
2452 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2454 case REPOKEY_TYPE_ID:
2455 case REPOKEY_TYPE_NUM:
2456 case REPOKEY_TYPE_DIR:
2457 data_addid(xd, val);
2459 case REPOKEY_TYPE_BINARY:
2462 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2464 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2467 case REPOKEY_TYPE_IDARRAY:
2468 for (ida = data->attriddata + val; *ida; ida++)
2469 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2471 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2472 for (ida = data->attriddata + val; *ida; ida += 3)
2474 data_addid(xd, ida[0]);
2475 data_addid(xd, ida[1]);
2476 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2479 case REPOKEY_TYPE_DIRSTRARRAY:
2480 for (ida = data->attriddata + val; *ida; ida += 2)
2482 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2483 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2486 case REPOKEY_TYPE_FIXARRAY:
2490 for (ida = data->attriddata + val; *ida; ida++)
2493 Id *kp = data->xattrs[-*ida];
2501 schemaid = repodata_schema2id(data, schema, 1);
2502 else if (schemaid != repodata_schema2id(data, schema, 0))
2504 pool_debug(data->repo->pool, SOLV_FATAL, "fixarray substructs with different schemas\n");
2510 data_addid(xd, num);
2511 data_addid(xd, schemaid);
2512 for (ida = data->attriddata + val; *ida; ida++)
2514 Id *kp = data->xattrs[-*ida];
2518 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2522 case REPOKEY_TYPE_FLEXARRAY:
2525 for (ida = data->attriddata + val; *ida; ida++)
2527 data_addid(xd, num);
2528 for (ida = data->attriddata + val; *ida; ida++)
2530 Id *kp = data->xattrs[-*ida];
2533 data_addid(xd, 0); /* XXX */
2540 schemaid = repodata_schema2id(data, schema, 1);
2541 data_addid(xd, schemaid);
2542 kp = data->xattrs[-*ida];
2544 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2549 pool_debug(data->repo->pool, SOLV_FATAL, "don't know how to handle type %d\n", key->type);
2552 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2554 /* put offset/len in incore */
2555 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2556 oldvincorelen = xd->len - oldvincorelen;
2557 data_addid(newincore, oldvincorelen);
2562 repodata_internalize(Repodata *data)
2564 Repokey *key, solvkey;
2566 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2567 unsigned char *dp, *ndp;
2568 int newschema, oldcount;
2569 struct extdata newincore;
2570 struct extdata newvincore;
2573 if (!data->attrs && !data->xattrs)
2576 newvincore.buf = data->vincore;
2577 newvincore.len = data->vincorelen;
2579 /* find the solvables key, create if needed */
2580 memset(&solvkey, 0, sizeof(solvkey));
2581 solvkey.name = REPOSITORY_SOLVABLES;
2582 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2584 solvkey.storage = KEY_STORAGE_INCORE;
2585 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2587 schema = solv_malloc2(data->nkeys, sizeof(Id));
2588 seen = solv_malloc2(data->nkeys, sizeof(Id));
2590 /* Merge the data already existing (in data->schemata, ->incoredata and
2591 friends) with the new attributes in data->attrs[]. */
2592 nentry = data->end - data->start;
2593 memset(&newincore, 0, sizeof(newincore));
2594 data_addid(&newincore, 0); /* start data at offset 1 */
2596 data->mainschema = 0;
2597 data->mainschemaoffsets = solv_free(data->mainschemaoffsets);
2599 /* join entry data */
2600 /* we start with the meta data, entry -1 */
2601 for (entry = -1; entry < nentry; entry++)
2603 memset(seen, 0, data->nkeys * sizeof(Id));
2605 dp = data->incoredata;
2608 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2609 dp = data_read_id(dp, &oldschema);
2612 fprintf(stderr, "oldschema %d\n", oldschema);
2613 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2614 fprintf(stderr, "schemadata %p\n", data->schemadata);
2616 /* seen: -1: old data 0: skipped >0: id + 1 */
2620 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2624 pool_debug(data->repo->pool, SOLV_FATAL, "Inconsistent old data (key occured twice).\n");
2632 keyp = data->attrs ? data->attrs[entry] : 0;
2635 /* strip solvables key */
2637 for (sp = keyp = schema; *sp; sp++)
2638 if (*sp != solvkeyid)
2643 seen[solvkeyid] = 0;
2644 keyp = data->xattrs ? data->xattrs[1] : 0;
2647 for (; *keyp; keyp += 2)
2654 seen[*keyp] = keyp[1] + 1;
2656 if (entry < 0 && data->end != data->start)
2663 /* Ideally we'd like to sort the new schema here, to ensure
2664 schema equality independend of the ordering. We can't do that
2665 yet. For once see below (old ids need to come before new ids).
2666 An additional difficulty is that we also need to move
2667 the values with the keys. */
2668 schemaid = repodata_schema2id(data, schema, 1);
2670 schemaid = oldschema;
2673 /* Now create data blob. We walk through the (possibly new) schema
2674 and either copy over old data, or insert the new. */
2675 /* XXX Here we rely on the fact that the (new) schema has the form
2676 o1 o2 o3 o4 ... | n1 n2 n3 ...
2677 (oX being the old keyids (possibly overwritten), and nX being
2678 the new keyids). This rules out sorting the keyids in order
2679 to ensure a small schema count. */
2681 data->incoreoffset[entry] = newincore.len;
2682 data_addid(&newincore, schemaid);
2685 data->mainschema = schemaid;
2686 data->mainschemaoffsets = solv_calloc(sp - schema, sizeof(Id));
2688 keypstart = data->schemadata + data->schemata[schemaid];
2689 for (keyp = keypstart; *keyp; keyp++)
2692 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2693 if (*keyp == solvkeyid)
2695 /* add flexarray entry count */
2696 data_addid(&newincore, data->end - data->start);
2699 key = data->keys + *keyp;
2701 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));
2706 /* Skip the data associated with this old key. */
2707 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2709 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2710 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2712 else if (key->storage == KEY_STORAGE_INCORE)
2713 ndp = data_skip_key(data, dp, key);
2716 if (seen[*keyp] == -1)
2718 /* If this key was an old one _and_ was not overwritten with
2719 a different value copy over the old value (we skipped it
2722 data_addblob(&newincore, dp, ndp - dp);
2725 else if (seen[*keyp])
2727 /* Otherwise we have a new value. Parse it into the internal
2729 repodata_serialize_key(data, &newincore, &newvincore,
2730 schema, key, seen[*keyp] - 1);
2734 if (entry >= 0 && data->attrs && data->attrs[entry])
2735 data->attrs[entry] = solv_free(data->attrs[entry]);
2737 /* free all xattrs */
2738 for (entry = 0; entry < data->nxattrs; entry++)
2739 if (data->xattrs[entry])
2740 solv_free(data->xattrs[entry]);
2741 data->xattrs = solv_free(data->xattrs);
2744 data->lasthandle = 0;
2746 data->lastdatalen = 0;
2749 repodata_free_schemahash(data);
2751 solv_free(data->incoredata);
2752 data->incoredata = newincore.buf;
2753 data->incoredatalen = newincore.len;
2754 data->incoredatafree = 0;
2756 solv_free(data->vincore);
2757 data->vincore = newvincore.buf;
2758 data->vincorelen = newvincore.len;
2760 data->attrs = solv_free(data->attrs);
2761 data->attrdata = solv_free(data->attrdata);
2762 data->attriddata = solv_free(data->attriddata);
2763 data->attrdatalen = 0;
2764 data->attriddatalen = 0;
2768 repodata_disable_paging(Repodata *data)
2770 if (maybe_load_repodata(data, 0))
2771 repopagestore_disable_paging(&data->store);
2775 repodata_load_stub(Repodata *data)
2777 Repo *repo = data->repo;
2778 Pool *pool = repo->pool;
2780 struct _Pool_tmpspace oldtmpspace;
2782 if (!pool->loadcallback)
2784 data->state = REPODATA_ERROR;
2787 data->state = REPODATA_LOADING;
2789 /* save tmp space */
2790 oldtmpspace = pool->tmpspace;
2791 memset(&pool->tmpspace, 0, sizeof(pool->tmpspace));
2793 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2795 /* restore tmp space */
2796 for (i = 0; i < POOL_TMPSPACEBUF; i++)
2797 solv_free(pool->tmpspace.buf[i]);
2798 pool->tmpspace = oldtmpspace;
2800 data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
2804 repodata_create_stubs(Repodata *data)
2806 Repo *repo = data->repo;
2807 Pool *pool = repo->pool;
2814 int datastart, dataend;
2816 repodataid = data - repo->repodata;
2817 datastart = data->start;
2818 dataend = data->end;
2819 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2820 while (dataiterator_step(&di))
2822 if (di.data - repo->repodata != repodataid)
2826 dataiterator_free(&di);
2829 stubdataids = solv_calloc(cnt, sizeof(*stubdataids));
2830 for (i = 0; i < cnt; i++)
2832 sdata = repo_add_repodata(repo, 0);
2833 if (dataend > datastart)
2834 repodata_extend_block(sdata, datastart, dataend - datastart);
2835 stubdataids[i] = sdata - repo->repodata;
2836 sdata->state = REPODATA_STUB;
2837 sdata->loadcallback = repodata_load_stub;
2840 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2842 while (dataiterator_step(&di))
2844 if (di.data - repo->repodata != repodataid)
2846 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
2848 dataiterator_entersub(&di);
2849 sdata = repo->repodata + stubdataids[i++];
2853 switch (di.key->type)
2855 case REPOKEY_TYPE_ID:
2856 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
2858 case REPOKEY_TYPE_CONSTANTID:
2859 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
2861 case REPOKEY_TYPE_STR:
2862 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
2864 case REPOKEY_TYPE_VOID:
2865 repodata_set_void(sdata, SOLVID_META, di.key->name);
2867 case REPOKEY_TYPE_NUM:
2868 repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num);
2870 case REPOKEY_TYPE_MD5:
2871 case REPOKEY_TYPE_SHA1:
2872 case REPOKEY_TYPE_SHA256:
2873 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
2875 case REPOKEY_TYPE_IDARRAY:
2876 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
2877 if (di.key->name == REPOSITORY_KEYS)
2884 xkeyname = di.kv.id;
2887 xkey.name = xkeyname;
2888 xkey.type = di.kv.id;
2889 xkey.storage = KEY_STORAGE_INCORE;
2891 repodata_key2id(sdata, &xkey, 1);
2898 dataiterator_free(&di);
2899 for (i = 0; i < cnt; i++)
2900 repodata_internalize(repo->repodata + stubdataids[i]);
2901 solv_free(stubdataids);
2905 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: