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->nrepos)
1192 di->repo = di->pool->repos[0];
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:
1282 if (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS))
1284 if (!(di->flags & SEARCH_THISSOLVID))
1286 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1287 goto di_nextsolvable;
1291 case di_entersolvable: di_entersolvable:
1292 if (di->repodataid >= 0)
1294 di->repodataid = 0; /* reset repodata iterator */
1295 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)
1297 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1299 goto di_entersolvablekey;
1304 case di_enterrepodata: di_enterrepodata:
1305 if (di->repodataid >= 0)
1307 if (di->repodataid >= di->repo->nrepodata)
1308 goto di_nextsolvable;
1309 di->data = di->repo->repodata + di->repodataid;
1311 if (di->repodataid >= 0 && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
1312 goto di_nextrepodata;
1313 if (!maybe_load_repodata(di->data, di->keyname))
1314 goto di_nextrepodata;
1315 di->dp = solvid2data(di->data, di->solvid, &schema);
1317 goto di_nextrepodata;
1318 if (di->solvid == SOLVID_POS)
1319 di->solvid = di->pool->pos.solvid;
1320 /* reset key iterator */
1321 di->keyp = di->data->schemadata + di->data->schemata[schema];
1324 case di_enterschema: di_enterschema:
1326 di->dp = dataiterator_find_keyname(di, di->keyname);
1327 if (!di->dp || !*di->keyp)
1331 goto di_nextrepodata;
1335 case di_enterkey: di_enterkey:
1337 di->key = di->data->keys + *di->keyp;
1338 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1341 if (di->key->type == REPOKEY_TYPE_DELETED)
1343 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1345 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1351 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1353 di->state = di_nextkey;
1355 di->state = di_nextattr;
1358 case di_nextkey: di_nextkey:
1359 if (!di->keyname && *++di->keyp)
1365 case di_nextrepodata: di_nextrepodata:
1366 if (di->repodataid >= 0 && ++di->repodataid < di->repo->nrepodata)
1367 goto di_enterrepodata;
1370 case di_nextsolvable: di_nextsolvable:
1371 if (!(di->flags & SEARCH_THISSOLVID))
1374 di->solvid = di->repo->start;
1377 for (; di->solvid < di->repo->end; di->solvid++)
1379 if (di->pool->solvables[di->solvid].repo == di->repo)
1380 goto di_entersolvable;
1385 case di_nextrepo: di_nextrepo:
1390 if (di->repoid - 1 < di->pool->nrepos)
1392 di->repo = di->pool->repos[di->repoid - 1];
1398 case di_bye: di_bye:
1402 case di_enterarray: di_enterarray:
1403 if (di->key->name == REPOSITORY_SOLVABLES)
1405 di->ddp = data_read_id(di->ddp, &di->kv.num);
1410 case di_nextarrayelement: di_nextarrayelement:
1413 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1414 if (di->kv.entry == di->kv.num)
1416 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1418 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1420 di->kv.str = (char *)di->ddp;
1422 di->state = di_nextkey;
1425 if (di->kv.entry == di->kv.num - 1)
1427 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1428 di->ddp = data_read_id(di->ddp, &di->kv.id);
1429 di->kv.str = (char *)di->ddp;
1430 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1432 if ((di->flags & SEARCH_SUB) != 0)
1433 di->state = di_entersub;
1435 di->state = di_nextarrayelement;
1438 case di_entersub: di_entersub:
1439 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1440 goto di_nextarrayelement; /* sorry, full */
1441 di->parents[di->nparents].kv = di->kv;
1442 di->parents[di->nparents].dp = di->dp;
1443 di->parents[di->nparents].keyp = di->keyp;
1444 di->dp = (unsigned char *)di->kv.str;
1445 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1446 memset(&di->kv, 0, sizeof(di->kv));
1447 di->kv.parent = &di->parents[di->nparents].kv;
1449 di->keyname = di->keynames[di->nparents - di->rootlevel];
1450 goto di_enterschema;
1452 case di_leavesub: di_leavesub:
1453 if (di->nparents - 1 < di->rootlevel)
1456 di->dp = di->parents[di->nparents].dp;
1457 di->kv = di->parents[di->nparents].kv;
1458 di->keyp = di->parents[di->nparents].keyp;
1459 di->key = di->data->keys + *di->keyp;
1460 di->ddp = (unsigned char *)di->kv.str;
1461 di->keyname = di->keynames[di->nparents - di->rootlevel];
1462 goto di_nextarrayelement;
1464 /* special solvable attr handling follows */
1466 case di_nextsolvableattr:
1467 di->kv.id = *di->idp++;
1472 di->state = di_nextsolvablekey;
1476 case di_nextsolvablekey: di_nextsolvablekey:
1477 if (di->keyname || di->key->name == RPM_RPMDBID)
1478 goto di_enterrepodata;
1482 case di_entersolvablekey: di_entersolvablekey:
1483 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1484 if (!di->idp || !di->idp[0])
1485 goto di_nextsolvablekey;
1486 di->kv.id = di->idp[0];
1487 di->kv.num = di->idp[0];
1489 if (!di->kv.eof && !di->idp[0])
1493 di->state = di_nextsolvablekey;
1495 di->state = di_nextsolvableattr;
1499 if (di->matcher.match)
1501 /* simple pre-check so that we don't need to stringify */
1502 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))
1504 int l = strlen(di->matcher.match) - strlen(di->kv.str);
1505 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
1508 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1510 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1514 if (!datamatcher_match(&di->matcher, di->kv.str))
1517 /* found something! */
1523 dataiterator_entersub(Dataiterator *di)
1525 if (di->state == di_nextarrayelement)
1526 di->state = di_entersub;
1530 dataiterator_setpos(Dataiterator *di)
1532 if (di->kv.eof == 2)
1534 pool_clear_pos(di->pool);
1537 di->pool->pos.solvid = di->solvid;
1538 di->pool->pos.repo = di->repo;
1539 di->pool->pos.repodataid = di->data - di->repo->repodata;
1540 di->pool->pos.schema = di->kv.id;
1541 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1545 dataiterator_setpos_parent(Dataiterator *di)
1547 if (!di->kv.parent || di->kv.parent->eof == 2)
1549 pool_clear_pos(di->pool);
1552 di->pool->pos.solvid = di->solvid;
1553 di->pool->pos.repo = di->repo;
1554 di->pool->pos.repodataid = di->data - di->repo->repodata;
1555 di->pool->pos.schema = di->kv.parent->id;
1556 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1559 /* clones just the position, not the search keys/matcher */
1561 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
1563 di->state = from->state;
1564 di->flags &= ~SEARCH_THISSOLVID;
1565 di->flags |= (from->flags & SEARCH_THISSOLVID);
1566 di->repo = from->repo;
1567 di->data = from->data;
1569 di->ddp = from->ddp;
1570 di->idp = from->idp;
1571 di->keyp = from->keyp;
1572 di->key = from->key;
1574 di->repodataid = from->repodataid;
1575 di->solvid = from->solvid;
1576 di->repoid = from->repoid;
1577 di->rootlevel = from->rootlevel;
1578 memcpy(di->parents, from->parents, sizeof(from->parents));
1579 di->nparents = from->nparents;
1583 for (i = 1; i < di->nparents; i++)
1584 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1585 di->kv.parent = &di->parents[di->nparents - 1].kv;
1590 dataiterator_seek(Dataiterator *di, int whence)
1592 if ((whence & DI_SEEK_STAY) != 0)
1593 di->rootlevel = di->nparents;
1594 switch (whence & ~DI_SEEK_STAY)
1597 if (di->state != di_nextarrayelement)
1599 if ((whence & DI_SEEK_STAY) != 0)
1600 di->rootlevel = di->nparents + 1; /* XXX: dangerous! */
1601 di->state = di_entersub;
1603 case DI_SEEK_PARENT:
1610 if (di->rootlevel > di->nparents)
1611 di->rootlevel = di->nparents;
1612 di->dp = di->parents[di->nparents].dp;
1613 di->kv = di->parents[di->nparents].kv;
1614 di->keyp = di->parents[di->nparents].keyp;
1615 di->key = di->data->keys + *di->keyp;
1616 di->ddp = (unsigned char *)di->kv.str;
1617 di->keyname = di->keynames[di->nparents - di->rootlevel];
1618 di->state = di_nextarrayelement;
1620 case DI_SEEK_REWIND:
1626 di->dp = (unsigned char *)di->kv.parent->str;
1627 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
1628 di->state = di_enterschema;
1636 dataiterator_skip_attribute(Dataiterator *di)
1638 if (di->state == di_nextsolvableattr)
1639 di->state = di_nextsolvablekey;
1641 di->state = di_nextkey;
1645 dataiterator_skip_solvable(Dataiterator *di)
1650 di->keyname = di->keynames[0];
1651 di->state = di_nextsolvable;
1655 dataiterator_skip_repo(Dataiterator *di)
1660 di->keyname = di->keynames[0];
1661 di->state = di_nextrepo;
1665 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1670 di->keyname = di->keynames[0];
1671 if (solvid == SOLVID_POS)
1673 di->repo = di->pool->pos.repo;
1680 di->data = di->repo->repodata + di->pool->pos.repodataid;
1681 di->repodataid = -1;
1682 di->solvid = solvid;
1683 di->state = di_enterrepo;
1684 di->flags |= SEARCH_THISSOLVID;
1689 di->repo = di->pool->solvables[solvid].repo;
1692 else if (di->repoid > 0)
1694 if (!di->pool->nrepos)
1700 di->repo = di->pool->repos[0];
1703 di->solvid = solvid;
1705 di->flags |= SEARCH_THISSOLVID;
1706 di->state = di_enterrepo;
1710 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1716 di->repoid = 0; /* 0 means stay at repo */
1719 di->flags &= ~SEARCH_THISSOLVID;
1720 di->state = di_enterrepo;
1724 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1726 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1730 return datamatcher_match(ma, di->kv.str);
1733 /************************************************************************
1734 * data modify functions
1737 /* extend repodata so that it includes solvables p */
1739 repodata_extend(Repodata *data, Id p)
1741 if (data->start == data->end)
1742 data->start = data->end = p;
1745 int old = data->end - data->start;
1746 int new = p - data->end + 1;
1749 data->attrs = solv_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1750 memset(data->attrs + old, 0, new * sizeof(Id *));
1752 data->incoreoffset = solv_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1753 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1756 if (p < data->start)
1758 int old = data->end - data->start;
1759 int new = data->start - p;
1762 data->attrs = solv_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1763 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1764 memset(data->attrs, 0, new * sizeof(Id *));
1766 data->incoreoffset = solv_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1767 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1768 memset(data->incoreoffset, 0, new * sizeof(Id));
1773 /* shrink end of repodata */
1775 repodata_shrink(Repodata *data, int end)
1779 if (data->end <= end)
1781 if (data->start >= end)
1785 for (i = 0; i < data->end - data->start; i++)
1786 solv_free(data->attrs[i]);
1787 data->attrs = solv_free(data->attrs);
1789 data->incoreoffset = solv_free(data->incoreoffset);
1790 data->start = data->end = 0;
1795 for (i = end; i < data->end; i++)
1796 solv_free(data->attrs[i - data->start]);
1797 data->attrs = solv_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
1799 if (data->incoreoffset)
1800 data->incoreoffset = solv_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
1804 /* extend repodata so that it includes solvables from start to start + num - 1 */
1806 repodata_extend_block(Repodata *data, Id start, Id num)
1810 if (!data->incoreoffset)
1812 data->incoreoffset = solv_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1813 data->start = start;
1814 data->end = start + num;
1817 repodata_extend(data, start);
1819 repodata_extend(data, start + num - 1);
1822 /**********************************************************************/
1825 #define REPODATA_ATTRS_BLOCK 31
1826 #define REPODATA_ATTRDATA_BLOCK 1023
1827 #define REPODATA_ATTRIDDATA_BLOCK 63
1831 repodata_new_handle(Repodata *data)
1835 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1836 data->nxattrs = 2; /* -1: SOLVID_META */
1838 data->xattrs = solv_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1839 data->xattrs[data->nxattrs] = 0;
1840 return -(data->nxattrs++);
1844 repodata_get_attrp(Repodata *data, Id handle)
1848 if (handle == SOLVID_META && !data->xattrs)
1850 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1853 return data->xattrs - handle;
1855 if (handle < data->start || handle >= data->end)
1856 repodata_extend(data, handle);
1858 data->attrs = solv_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1859 return data->attrs + (handle - data->start);
1863 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1869 app = repodata_get_attrp(data, handle);
1874 /* Determine equality based on the name only, allows us to change
1875 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1876 for (pp = ap; *pp; pp += 2)
1877 if (data->keys[*pp].name == data->keys[keyid].name)
1881 if (overwrite || data->keys[*pp].type == REPOKEY_TYPE_DELETED)
1890 ap = solv_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1900 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1904 keyid = repodata_key2id(data, key, 1);
1905 repodata_insert_keyid(data, solvid, keyid, val, 1);
1909 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1913 key.type = REPOKEY_TYPE_ID;
1915 key.storage = KEY_STORAGE_INCORE;
1916 repodata_set(data, solvid, &key, id);
1920 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1924 key.type = REPOKEY_TYPE_NUM;
1926 key.storage = KEY_STORAGE_INCORE;
1927 repodata_set(data, solvid, &key, (Id)num);
1931 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
1935 if (data->localpool)
1936 id = stringpool_str2id(&data->spool, str, 1);
1938 id = pool_str2id(data->repo->pool, str, 1);
1940 key.type = REPOKEY_TYPE_ID;
1942 key.storage = KEY_STORAGE_INCORE;
1943 repodata_set(data, solvid, &key, id);
1947 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
1951 key.type = REPOKEY_TYPE_CONSTANT;
1952 key.size = constant;
1953 key.storage = KEY_STORAGE_INCORE;
1954 repodata_set(data, solvid, &key, 0);
1958 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
1962 key.type = REPOKEY_TYPE_CONSTANTID;
1964 key.storage = KEY_STORAGE_INCORE;
1965 repodata_set(data, solvid, &key, 0);
1969 repodata_set_void(Repodata *data, Id solvid, Id keyname)
1973 key.type = REPOKEY_TYPE_VOID;
1975 key.storage = KEY_STORAGE_INCORE;
1976 repodata_set(data, solvid, &key, 0);
1980 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
1985 l = strlen(str) + 1;
1987 key.type = REPOKEY_TYPE_STR;
1989 key.storage = KEY_STORAGE_INCORE;
1990 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1991 memcpy(data->attrdata + data->attrdatalen, str, l);
1992 repodata_set(data, solvid, &key, data->attrdatalen);
1993 data->attrdatalen += l;
1997 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
2003 key.type = REPOKEY_TYPE_BINARY;
2005 key.storage = KEY_STORAGE_INCORE;
2006 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
2007 dp = data->attrdata + data->attrdatalen;
2008 if (len >= (1 << 14))
2010 if (len >= (1 << 28))
2011 *dp++ = (len >> 28) | 128;
2012 if (len >= (1 << 21))
2013 *dp++ = (len >> 21) | 128;
2014 *dp++ = (len >> 14) | 128;
2016 if (len >= (1 << 7))
2017 *dp++ = (len >> 7) | 128;
2020 memcpy(dp, buf, len);
2021 repodata_set(data, solvid, &key, data->attrdatalen);
2022 data->attrdatalen = dp + len - data->attrdata;
2025 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
2026 * so that the caller can append entrysize new elements plus the termination zero there */
2028 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
2031 Id *ida, *pp, **ppp;
2033 /* check if it is the same as last time, this speeds things up a lot */
2034 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
2036 /* great! just append the new data */
2037 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2038 data->attriddatalen--; /* overwrite terminating 0 */
2039 data->lastdatalen += entrysize;
2043 ppp = repodata_get_attrp(data, handle);
2047 for (; *pp; pp += 2)
2048 if (data->keys[*pp].name == keyname)
2051 if (!pp || !*pp || data->keys[*pp].type != keytype)
2053 /* not found. allocate new key */
2059 key.storage = KEY_STORAGE_INCORE;
2060 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2061 keyid = repodata_key2id(data, &key, 1);
2062 repodata_insert_keyid(data, handle, keyid, data->attriddatalen, 1);
2063 data->lasthandle = handle;
2064 data->lastkey = keyid;
2065 data->lastdatalen = data->attriddatalen + entrysize + 1;
2069 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
2070 oldsize += entrysize;
2071 if (ida + 1 == data->attriddata + data->attriddatalen)
2073 /* this was the last entry, just append it */
2074 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2075 data->attriddatalen--; /* overwrite terminating 0 */
2079 /* too bad. move to back. */
2080 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2081 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
2082 pp[1] = data->attriddatalen;
2083 data->attriddatalen += oldsize;
2085 data->lasthandle = handle;
2086 data->lastkey = *pp;
2087 data->lastdatalen = data->attriddatalen + entrysize + 1;
2091 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2092 const unsigned char *str)
2097 if (!(l = solv_chksum_len(type)))
2102 key.storage = KEY_STORAGE_INCORE;
2103 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2104 memcpy(data->attrdata + data->attrdatalen, str, l);
2105 repodata_set(data, solvid, &key, data->attrdatalen);
2106 data->attrdatalen += l;
2110 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2113 unsigned char buf[64];
2116 if (!(l = solv_chksum_len(type)))
2118 if (l > sizeof(buf) || solv_hex2bin(&str, buf, l) != l)
2120 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2124 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2128 if (!(l = solv_chksum_len(type)))
2130 return pool_bin2hex(data->repo->pool, buf, l);
2133 /* rpm filenames don't contain the epoch, so strip it */
2134 static inline const char *
2135 evrid2vrstr(Pool *pool, Id evrid)
2137 const char *p, *evr = pool_id2str(pool, evrid);
2140 for (p = evr; *p >= '0' && *p <= '9'; p++)
2142 return p != evr && *p == ':' ? p + 1 : evr;
2146 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2148 Pool *pool = data->repo->pool;
2150 const char *str, *fp;
2154 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2157 if ((dir = strrchr(file, '/')) != 0)
2168 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2173 if (l == 1 && dir[0] == '.')
2175 s = pool->solvables + solvid;
2178 str = pool_id2str(pool, s->arch);
2179 if (!strncmp(dir, str, l) && !str[l])
2180 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2182 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2185 char *dir2 = strdup(dir);
2187 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2192 str = pool_id2str(pool, s->name);
2194 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2197 str = evrid2vrstr(pool, s->evr);
2199 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2202 str = pool_id2str(pool, s->arch);
2204 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2206 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2211 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2215 repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
2221 key.type = REPOKEY_TYPE_IDARRAY;
2223 key.storage = KEY_STORAGE_INCORE;
2224 repodata_set(data, solvid, &key, data->attriddatalen);
2225 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, q->count + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2226 for (i = 0; i < q->count; i++)
2227 data->attriddata[data->attriddatalen++] = q->elements[i];
2228 data->attriddata[data->attriddatalen++] = 0;
2232 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2236 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2238 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2239 data->attriddata[data->attriddatalen++] = dir;
2240 data->attriddata[data->attriddatalen++] = num;
2241 data->attriddata[data->attriddatalen++] = num2;
2242 data->attriddata[data->attriddatalen++] = 0;
2246 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2252 l = strlen(str) + 1;
2253 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2254 memcpy(data->attrdata + data->attrdatalen, str, l);
2255 stroff = data->attrdatalen;
2256 data->attrdatalen += l;
2259 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2261 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2262 data->attriddata[data->attriddatalen++] = dir;
2263 data->attriddata[data->attriddatalen++] = stroff;
2264 data->attriddata[data->attriddatalen++] = 0;
2268 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2271 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2273 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2274 data->attriddata[data->attriddatalen++] = id;
2275 data->attriddata[data->attriddatalen++] = 0;
2279 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2283 if (data->localpool)
2284 id = stringpool_str2id(&data->spool, str, 1);
2286 id = pool_str2id(data->repo->pool, str, 1);
2287 repodata_add_idarray(data, solvid, keyname, id);
2291 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2293 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2294 data->attriddata[data->attriddatalen++] = ghandle;
2295 data->attriddata[data->attriddatalen++] = 0;
2299 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2301 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2302 data->attriddata[data->attriddatalen++] = ghandle;
2303 data->attriddata[data->attriddatalen++] = 0;
2307 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2310 app = repodata_get_attrp(data, solvid);
2314 for (; *ap; ap += 2)
2315 if (data->keys[*ap].name == keyname)
2321 for (; *ap; ap += 2)
2323 if (data->keys[*ap].name == keyname)
2331 /* XXX: does not work correctly, needs fix in iterators! */
2333 repodata_delete(Repodata *data, Id solvid, Id keyname)
2337 key.type = REPOKEY_TYPE_DELETED;
2339 key.storage = KEY_STORAGE_INCORE;
2340 repodata_set(data, solvid, &key, 0);
2343 /* add all (uninternalized) attrs from src to dest */
2345 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2348 if (dest == src || !(keyp = data->attrs[src - data->start]))
2350 for (; *keyp; keyp += 2)
2351 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2354 /* add some (uninternalized) attrs from src to dest */
2356 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2359 if (dest == src || !(keyp = data->attrs[src - data->start]))
2361 for (; *keyp; keyp += 2)
2362 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2363 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2368 /**********************************************************************/
2370 /* TODO: unify with repo_write and repo_solv! */
2372 #define EXTDATA_BLOCK 1023
2380 data_addid(struct extdata *xd, Id x)
2384 xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2385 dp = xd->buf + xd->len;
2390 *dp++ = (x >> 28) | 128;
2392 *dp++ = (x >> 21) | 128;
2393 *dp++ = (x >> 14) | 128;
2396 *dp++ = (x >> 7) | 128;
2398 xd->len = dp - xd->buf;
2402 data_addideof(struct extdata *xd, Id x, int eof)
2405 x = (x & 63) | ((x & ~63) << 1);
2406 data_addid(xd, (eof ? x : x | 64));
2410 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2412 xd->buf = solv_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2413 memcpy(xd->buf + xd->len, blob, len);
2417 /*********************************/
2419 /* internalalize some key into incore/vincore data */
2422 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2423 struct extdata *newvincore,
2425 Repokey *key, Id val)
2429 unsigned int oldvincorelen = 0;
2433 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2436 oldvincorelen = xd->len;
2440 case REPOKEY_TYPE_VOID:
2441 case REPOKEY_TYPE_CONSTANT:
2442 case REPOKEY_TYPE_CONSTANTID:
2444 case REPOKEY_TYPE_STR:
2445 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2447 case REPOKEY_TYPE_MD5:
2448 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2450 case REPOKEY_TYPE_SHA1:
2451 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2453 case REPOKEY_TYPE_SHA256:
2454 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2456 case REPOKEY_TYPE_ID:
2457 case REPOKEY_TYPE_NUM:
2458 case REPOKEY_TYPE_DIR:
2459 data_addid(xd, val);
2461 case REPOKEY_TYPE_BINARY:
2464 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2466 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2469 case REPOKEY_TYPE_IDARRAY:
2470 for (ida = data->attriddata + val; *ida; ida++)
2471 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2473 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2474 for (ida = data->attriddata + val; *ida; ida += 3)
2476 data_addid(xd, ida[0]);
2477 data_addid(xd, ida[1]);
2478 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2481 case REPOKEY_TYPE_DIRSTRARRAY:
2482 for (ida = data->attriddata + val; *ida; ida += 2)
2484 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2485 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2488 case REPOKEY_TYPE_FIXARRAY:
2492 for (ida = data->attriddata + val; *ida; ida++)
2495 Id *kp = data->xattrs[-*ida];
2503 schemaid = repodata_schema2id(data, schema, 1);
2504 else if (schemaid != repodata_schema2id(data, schema, 0))
2506 pool_debug(data->repo->pool, SOLV_FATAL, "fixarray substructs with different schemas\n");
2512 data_addid(xd, num);
2513 data_addid(xd, schemaid);
2514 for (ida = data->attriddata + val; *ida; ida++)
2516 Id *kp = data->xattrs[-*ida];
2520 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2524 case REPOKEY_TYPE_FLEXARRAY:
2527 for (ida = data->attriddata + val; *ida; ida++)
2529 data_addid(xd, num);
2530 for (ida = data->attriddata + val; *ida; ida++)
2532 Id *kp = data->xattrs[-*ida];
2535 data_addid(xd, 0); /* XXX */
2542 schemaid = repodata_schema2id(data, schema, 1);
2543 data_addid(xd, schemaid);
2544 kp = data->xattrs[-*ida];
2546 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2551 pool_debug(data->repo->pool, SOLV_FATAL, "don't know how to handle type %d\n", key->type);
2554 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2556 /* put offset/len in incore */
2557 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2558 oldvincorelen = xd->len - oldvincorelen;
2559 data_addid(newincore, oldvincorelen);
2564 repodata_internalize(Repodata *data)
2566 Repokey *key, solvkey;
2568 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2569 unsigned char *dp, *ndp;
2570 int newschema, oldcount;
2571 struct extdata newincore;
2572 struct extdata newvincore;
2575 if (!data->attrs && !data->xattrs)
2578 newvincore.buf = data->vincore;
2579 newvincore.len = data->vincorelen;
2581 /* find the solvables key, create if needed */
2582 memset(&solvkey, 0, sizeof(solvkey));
2583 solvkey.name = REPOSITORY_SOLVABLES;
2584 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2586 solvkey.storage = KEY_STORAGE_INCORE;
2587 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2589 schema = solv_malloc2(data->nkeys, sizeof(Id));
2590 seen = solv_malloc2(data->nkeys, sizeof(Id));
2592 /* Merge the data already existing (in data->schemata, ->incoredata and
2593 friends) with the new attributes in data->attrs[]. */
2594 nentry = data->end - data->start;
2595 memset(&newincore, 0, sizeof(newincore));
2596 data_addid(&newincore, 0); /* start data at offset 1 */
2598 data->mainschema = 0;
2599 data->mainschemaoffsets = solv_free(data->mainschemaoffsets);
2601 /* join entry data */
2602 /* we start with the meta data, entry -1 */
2603 for (entry = -1; entry < nentry; entry++)
2605 memset(seen, 0, data->nkeys * sizeof(Id));
2607 dp = data->incoredata;
2610 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2611 dp = data_read_id(dp, &oldschema);
2614 fprintf(stderr, "oldschema %d\n", oldschema);
2615 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2616 fprintf(stderr, "schemadata %p\n", data->schemadata);
2618 /* seen: -1: old data 0: skipped >0: id + 1 */
2622 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2626 pool_debug(data->repo->pool, SOLV_FATAL, "Inconsistent old data (key occured twice).\n");
2634 keyp = data->attrs ? data->attrs[entry] : 0;
2637 /* strip solvables key */
2639 for (sp = keyp = schema; *sp; sp++)
2640 if (*sp != solvkeyid)
2645 seen[solvkeyid] = 0;
2646 keyp = data->xattrs ? data->xattrs[1] : 0;
2649 for (; *keyp; keyp += 2)
2656 seen[*keyp] = keyp[1] + 1;
2658 if (entry < 0 && data->end != data->start)
2665 /* Ideally we'd like to sort the new schema here, to ensure
2666 schema equality independend of the ordering. We can't do that
2667 yet. For once see below (old ids need to come before new ids).
2668 An additional difficulty is that we also need to move
2669 the values with the keys. */
2670 schemaid = repodata_schema2id(data, schema, 1);
2672 schemaid = oldschema;
2675 /* Now create data blob. We walk through the (possibly new) schema
2676 and either copy over old data, or insert the new. */
2677 /* XXX Here we rely on the fact that the (new) schema has the form
2678 o1 o2 o3 o4 ... | n1 n2 n3 ...
2679 (oX being the old keyids (possibly overwritten), and nX being
2680 the new keyids). This rules out sorting the keyids in order
2681 to ensure a small schema count. */
2683 data->incoreoffset[entry] = newincore.len;
2684 data_addid(&newincore, schemaid);
2687 data->mainschema = schemaid;
2688 data->mainschemaoffsets = solv_calloc(sp - schema, sizeof(Id));
2690 keypstart = data->schemadata + data->schemata[schemaid];
2691 for (keyp = keypstart; *keyp; keyp++)
2694 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2695 if (*keyp == solvkeyid)
2697 /* add flexarray entry count */
2698 data_addid(&newincore, data->end - data->start);
2701 key = data->keys + *keyp;
2703 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));
2708 /* Skip the data associated with this old key. */
2709 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2711 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2712 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2714 else if (key->storage == KEY_STORAGE_INCORE)
2715 ndp = data_skip_key(data, dp, key);
2718 if (seen[*keyp] == -1)
2720 /* If this key was an old one _and_ was not overwritten with
2721 a different value copy over the old value (we skipped it
2724 data_addblob(&newincore, dp, ndp - dp);
2727 else if (seen[*keyp])
2729 /* Otherwise we have a new value. Parse it into the internal
2731 repodata_serialize_key(data, &newincore, &newvincore,
2732 schema, key, seen[*keyp] - 1);
2736 if (entry >= 0 && data->attrs && data->attrs[entry])
2737 data->attrs[entry] = solv_free(data->attrs[entry]);
2739 /* free all xattrs */
2740 for (entry = 0; entry < data->nxattrs; entry++)
2741 if (data->xattrs[entry])
2742 solv_free(data->xattrs[entry]);
2743 data->xattrs = solv_free(data->xattrs);
2746 data->lasthandle = 0;
2748 data->lastdatalen = 0;
2751 repodata_free_schemahash(data);
2753 solv_free(data->incoredata);
2754 data->incoredata = newincore.buf;
2755 data->incoredatalen = newincore.len;
2756 data->incoredatafree = 0;
2758 solv_free(data->vincore);
2759 data->vincore = newvincore.buf;
2760 data->vincorelen = newvincore.len;
2762 data->attrs = solv_free(data->attrs);
2763 data->attrdata = solv_free(data->attrdata);
2764 data->attriddata = solv_free(data->attriddata);
2765 data->attrdatalen = 0;
2766 data->attriddatalen = 0;
2770 repodata_disable_paging(Repodata *data)
2772 if (maybe_load_repodata(data, 0))
2773 repopagestore_disable_paging(&data->store);
2777 repodata_load_stub(Repodata *data)
2779 Repo *repo = data->repo;
2780 Pool *pool = repo->pool;
2782 struct _Pool_tmpspace oldtmpspace;
2784 if (!pool->loadcallback)
2786 data->state = REPODATA_ERROR;
2789 data->state = REPODATA_LOADING;
2791 /* save tmp space */
2792 oldtmpspace = pool->tmpspace;
2793 memset(&pool->tmpspace, 0, sizeof(pool->tmpspace));
2795 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2797 /* restore tmp space */
2798 for (i = 0; i < POOL_TMPSPACEBUF; i++)
2799 solv_free(pool->tmpspace.buf[i]);
2800 pool->tmpspace = oldtmpspace;
2802 data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
2806 repodata_create_stubs(Repodata *data)
2808 Repo *repo = data->repo;
2809 Pool *pool = repo->pool;
2816 int datastart, dataend;
2818 repodataid = data - repo->repodata;
2819 datastart = data->start;
2820 dataend = data->end;
2821 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2822 while (dataiterator_step(&di))
2824 if (di.data - repo->repodata != repodataid)
2828 dataiterator_free(&di);
2831 stubdataids = solv_calloc(cnt, sizeof(*stubdataids));
2832 for (i = 0; i < cnt; i++)
2834 sdata = repo_add_repodata(repo, 0);
2835 if (dataend > datastart)
2836 repodata_extend_block(sdata, datastart, dataend - datastart);
2837 stubdataids[i] = sdata - repo->repodata;
2838 sdata->state = REPODATA_STUB;
2839 sdata->loadcallback = repodata_load_stub;
2842 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2844 while (dataiterator_step(&di))
2846 if (di.data - repo->repodata != repodataid)
2848 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
2850 dataiterator_entersub(&di);
2851 sdata = repo->repodata + stubdataids[i++];
2855 switch (di.key->type)
2857 case REPOKEY_TYPE_ID:
2858 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
2860 case REPOKEY_TYPE_CONSTANTID:
2861 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
2863 case REPOKEY_TYPE_STR:
2864 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
2866 case REPOKEY_TYPE_VOID:
2867 repodata_set_void(sdata, SOLVID_META, di.key->name);
2869 case REPOKEY_TYPE_NUM:
2870 repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num);
2872 case REPOKEY_TYPE_MD5:
2873 case REPOKEY_TYPE_SHA1:
2874 case REPOKEY_TYPE_SHA256:
2875 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
2877 case REPOKEY_TYPE_IDARRAY:
2878 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
2879 if (di.key->name == REPOSITORY_KEYS)
2886 xkeyname = di.kv.id;
2889 xkey.name = xkeyname;
2890 xkey.type = di.kv.id;
2891 xkey.storage = KEY_STORAGE_INCORE;
2893 repodata_key2id(sdata, &xkey, 1);
2900 dataiterator_free(&di);
2901 for (i = 0; i < cnt; i++)
2902 repodata_internalize(repo->repodata + stubdataids[i]);
2903 solv_free(stubdataids);
2907 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: