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 = sat_calloc(1, sizeof(Repokey));
52 data->schemata = sat_calloc(1, sizeof(Id));
53 data->schemadata = sat_calloc(1, sizeof(Id));
55 data->schemadatalen = 1;
56 repopagestore_init(&data->store);
60 repodata_freedata(Repodata *data)
66 sat_free(data->schemata);
67 sat_free(data->schemadata);
68 sat_free(data->schematahash);
70 stringpool_free(&data->spool);
71 dirpool_free(&data->dirpool);
73 sat_free(data->mainschemaoffsets);
74 sat_free(data->incoredata);
75 sat_free(data->incoreoffset);
76 sat_free(data->verticaloffset);
78 repopagestore_free(&data->store);
80 sat_free(data->vincore);
83 for (i = 0; i < data->end - data->start; i++)
84 sat_free(data->attrs[i]);
85 sat_free(data->attrs);
87 for (i = 0; i < data->nxattrs; i++)
88 sat_free(data->xattrs[i]);
89 sat_free(data->xattrs);
91 sat_free(data->attrdata);
92 sat_free(data->attriddata);
96 repodata_create(Repo *repo, int localpool)
101 repo->repodata = sat_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 = sat_realloc2(data->keys, data->nkeys + 1, sizeof(Repokey));
154 data->keys[data->nkeys++] = *key;
155 if (data->verticaloffset)
157 data->verticaloffset = sat_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 = sat_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 = sat_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
193 data->schemata = sat_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 = sat_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
215 data->schemata = sat_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 = sat_free(data->schematahash);
232 data->schemata = sat_realloc2(data->schemata, data->nschemata, sizeof(Id));
233 data->schemadata = sat_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 = 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 / BLOB_PAGESIZE); */
429 dp = repopagestore_load_page_range(&data->store, off / BLOB_PAGESIZE, (off + len - 1) / BLOB_PAGESIZE);
431 dp += off % BLOB_PAGESIZE;
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 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)
633 dp = data_fetch(dp, &kv, key);
641 repodata_lookup_void(Repodata *data, Id solvid, Id keyname)
647 if (!maybe_load_repodata(data, keyname))
649 dp = solvid2data(data, solvid, &schema);
652 /* can't use find_key_data as we need to test the type */
653 for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++)
654 if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID)
659 const unsigned char *
660 repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep)
665 dp = find_key_data(data, solvid, keyname, &key);
673 repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
681 dp = find_key_data(data, solvid, keyname, &key);
684 if (key->type != REPOKEY_TYPE_IDARRAY && key->type != REPOKEY_TYPE_REL_IDARRAY)
688 dp = data_read_ideof(dp, &id, &eof);
697 repodata_globalize_id(Repodata *data, Id id, int create)
699 if (!id || !data || !data->localpool)
701 return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
705 repodata_localize_id(Repodata *data, Id id, int create)
707 if (!id || !data || !data->localpool)
709 return stringpool_str2id(&data->spool, id2str(data->repo->pool, id), create);
713 /************************************************************************
719 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
723 case REPOKEY_TYPE_ID:
724 case REPOKEY_TYPE_CONSTANTID:
725 case REPOKEY_TYPE_IDARRAY:
726 if (data && data->localpool)
727 kv->str = stringpool_id2str(&data->spool, kv->id);
729 kv->str = id2str(pool, kv->id);
730 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
733 for (s = kv->str; *s >= 'a' && *s <= 'z'; s++)
735 if (*s == ':' && s > kv->str)
739 case REPOKEY_TYPE_STR:
741 case REPOKEY_TYPE_DIRSTRARRAY:
742 if (!(flags & SEARCH_FILES))
743 return 1; /* match just the basename */
744 /* Put the full filename into kv->str. */
745 kv->str = repodata_dir2str(data, kv->id, kv->str);
746 /* And to compensate for that put the "empty" directory into
747 kv->id, so that later calls to repodata_dir2str on this data
748 come up with the same filename again. */
751 case REPOKEY_TYPE_MD5:
752 case REPOKEY_TYPE_SHA1:
753 case REPOKEY_TYPE_SHA256:
754 if (!(flags & SEARCH_CHECKSUMS))
755 return 0; /* skip em */
756 kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str);
764 struct subschema_data {
770 /* search a specific repodata */
772 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
776 Id keyid, *kp, *keyp;
777 unsigned char *dp, *ddp;
783 if (!maybe_load_repodata(data, keyname))
785 if (solvid == SOLVID_SUBSCHEMA)
787 struct subschema_data *subd = cbdata;
788 cbdata = subd->cbdata;
790 schema = subd->parent->id;
791 dp = (unsigned char *)subd->parent->str;
792 kv.parent = subd->parent;
797 dp = solvid2data(data, solvid, &schema);
800 s = data->repo->pool->solvables + solvid;
803 keyp = data->schemadata + data->schemata[schema];
806 /* search for a specific key */
807 for (kp = keyp; *kp; kp++)
808 if (data->keys[*kp].name == keyname)
812 dp = forward_to_key(data, *kp, keyp, dp);
818 while ((keyid = *keyp++) != 0)
821 key = data->keys + keyid;
822 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
824 if (key->type == REPOKEY_TYPE_DELETED)
826 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
828 struct subschema_data subd;
832 subd.cbdata = cbdata;
835 ddp = data_read_id(ddp, &nentries);
839 while (ddp && nentries > 0)
843 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
844 ddp = data_read_id(ddp, &schema);
846 kv.str = (char *)ddp;
847 stop = callback(cbdata, s, data, key, &kv);
848 if (stop > SEARCH_NEXT_KEY)
850 if (stop && stop != SEARCH_ENTERSUB)
852 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
853 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
854 ddp = data_skip_schema(data, ddp, schema);
857 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
861 kv.str = (char *)ddp;
862 stop = callback(cbdata, s, data, key, &kv);
863 if (stop > SEARCH_NEXT_KEY)
873 ddp = data_fetch(ddp, &kv, key);
876 stop = callback(cbdata, s, data, key, &kv);
879 while (!kv.eof && !stop);
880 if (onekey || stop > SEARCH_NEXT_KEY)
886 repodata_setpos_kv(Repodata *data, KeyValue *kv)
888 Pool *pool = data->repo->pool;
890 pool_clear_pos(pool);
893 pool->pos.repo = data->repo;
894 pool->pos.repodataid = data - data->repo->repodata;
895 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
896 pool->pos.schema = kv->id;
900 /************************************************************************
901 * data iterator functions
904 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
905 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
906 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
907 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
908 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
909 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
910 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
911 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
912 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
913 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
914 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
915 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
916 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
917 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
921 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
935 case SOLVABLE_VENDOR:
938 case SOLVABLE_PROVIDES:
940 return s->provides ? s->repo->idarraydata + s->provides : 0;
941 case SOLVABLE_OBSOLETES:
943 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
944 case SOLVABLE_CONFLICTS:
946 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
947 case SOLVABLE_REQUIRES:
949 return s->requires ? s->repo->idarraydata + s->requires : 0;
950 case SOLVABLE_RECOMMENDS:
952 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
953 case SOLVABLE_SUPPLEMENTS:
955 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
956 case SOLVABLE_SUGGESTS:
958 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
959 case SOLVABLE_ENHANCES:
961 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
964 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
971 datamatcher_init(Datamatcher *ma, const char *match, int flags)
977 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
979 ma->matchdata = sat_calloc(1, sizeof(regex_t));
980 ma->error = regcomp((regex_t *)ma->matchdata, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
983 sat_free(ma->matchdata);
984 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
991 datamatcher_free(Datamatcher *ma)
993 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
995 regfree(ma->matchdata);
996 ma->matchdata = sat_free(ma->matchdata);
1001 datamatcher_match(Datamatcher *ma, const char *str)
1004 switch ((ma->flags & SEARCH_STRINGMASK))
1006 case SEARCH_SUBSTRING:
1007 if (ma->flags & SEARCH_NOCASE)
1009 if (!strcasestr(str, ma->match))
1014 if (!strstr(str, ma->match))
1019 if (ma->flags & SEARCH_NOCASE)
1021 if (strcasecmp(ma->match, str))
1026 if (strcmp(ma->match, str))
1030 case SEARCH_STRINGSTART:
1031 if (ma->flags & SEARCH_NOCASE)
1033 if (strncasecmp(ma->match, str, strlen(ma->match)))
1038 if (strncmp(ma->match, str, strlen(ma->match)))
1042 case SEARCH_STRINGEND:
1043 l = strlen(str) - strlen(ma->match);
1046 if (ma->flags & SEARCH_NOCASE)
1048 if (strcasecmp(ma->match, str + l))
1053 if (strcmp(ma->match, str + l))
1058 if (fnmatch(ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
1062 if (regexec((const regex_t *)ma->matchdata, str, 0, NULL, 0))
1072 repodata_filelistfilter_matches(Repodata *data, const char *str)
1074 /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */
1075 /* for now hardcoded */
1076 if (strstr(str, "bin/"))
1078 if (!strncmp(str, "/etc/", 5))
1080 if (!strcmp(str, "/usr/lib/sendmail"))
1102 di_nextarrayelement,
1107 di_nextsolvableattr,
1112 /* see repo.h for documentation */
1114 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
1116 memset(di, 0, sizeof(*di));
1118 di->flags = flags & ~SEARCH_THISSOLVID;
1119 if (!pool || (repo && repo->pool != pool))
1127 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1133 di->keyname = keyname;
1134 di->keynames[0] = keyname;
1135 dataiterator_set_search(di, repo, p);
1140 dataiterator_init_clone(Dataiterator *di, Dataiterator *from)
1143 memset(&di->matcher, 0, sizeof(di->matcher));
1144 if (from->matcher.match)
1145 datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags);
1150 for (i = 1; i < di->nparents; i++)
1151 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1152 di->kv.parent = &di->parents[di->nparents - 1].kv;
1157 dataiterator_set_match(Dataiterator *di, const char *match, int flags)
1159 di->flags = (flags & ~SEARCH_THISSOLVID) | (di->flags & SEARCH_THISSOLVID);
1160 datamatcher_free(&di->matcher);
1161 memset(&di->matcher, 0, sizeof(di->matcher));
1165 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1175 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
1179 di->flags &= ~SEARCH_THISSOLVID;
1183 if (!di->pool->nrepos)
1191 di->repo = di->pool->repos[0];
1193 di->state = di_enterrepo;
1195 dataiterator_jump_to_solvid(di, p);
1199 dataiterator_set_keyname(Dataiterator *di, Id keyname)
1202 di->keyname = keyname;
1203 di->keynames[0] = keyname;
1207 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1211 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1213 di->state = di_bye; /* sorry */
1216 for (i = di->nkeynames + 1; i > 0; i--)
1217 di->keynames[i] = di->keynames[i - 1];
1218 di->keynames[0] = di->keyname = keyname;
1223 dataiterator_free(Dataiterator *di)
1225 if (di->matcher.match)
1226 datamatcher_free(&di->matcher);
1229 static inline unsigned char *
1230 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1232 Id *keyp = di->keyp;
1233 Repokey *keys = di->data->keys;
1236 for (keyp = di->keyp; *keyp; keyp++)
1237 if (keys[*keyp].name == keyname)
1241 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1249 dataiterator_filelistcheck(Dataiterator *di)
1252 int needcomplete = 0;
1253 Repodata *data = di->data;
1255 if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
1256 if (!di->matcher.match
1257 || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
1258 && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)
1259 || !repodata_filelistfilter_matches(di->data, di->matcher.match))
1261 if (data->state != REPODATA_AVAILABLE)
1262 return needcomplete ? 1 : 0;
1263 for (j = 1; j < data->nkeys; j++)
1264 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
1266 return j == data->nkeys && !needcomplete ? 0 : 1;
1270 dataiterator_step(Dataiterator *di)
1278 case di_enterrepo: di_enterrepo:
1281 if (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS))
1283 if (!(di->flags & SEARCH_THISSOLVID))
1285 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1286 goto di_nextsolvable;
1290 case di_entersolvable: di_entersolvable:
1291 if (di->repodataid >= 0)
1293 di->repodataid = 0; /* reset repodata iterator */
1294 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)
1296 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1298 goto di_entersolvablekey;
1303 case di_enterrepodata: di_enterrepodata:
1304 if (di->repodataid >= 0)
1306 if (di->repodataid >= di->repo->nrepodata)
1307 goto di_nextsolvable;
1308 di->data = di->repo->repodata + di->repodataid;
1310 if (di->repodataid >= 0 && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
1311 goto di_nextrepodata;
1312 if (!maybe_load_repodata(di->data, di->keyname))
1313 goto di_nextrepodata;
1314 di->dp = solvid2data(di->data, di->solvid, &schema);
1316 goto di_nextrepodata;
1317 if (di->solvid == SOLVID_POS)
1318 di->solvid = di->pool->pos.solvid;
1319 /* reset key iterator */
1320 di->keyp = di->data->schemadata + di->data->schemata[schema];
1323 case di_enterschema: di_enterschema:
1325 di->dp = dataiterator_find_keyname(di, di->keyname);
1326 if (!di->dp || !*di->keyp)
1330 goto di_nextrepodata;
1334 case di_enterkey: di_enterkey:
1336 di->key = di->data->keys + *di->keyp;
1337 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1340 if (di->key->type == REPOKEY_TYPE_DELETED)
1342 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1344 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1350 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1352 di->state = di_nextkey;
1354 di->state = di_nextattr;
1357 case di_nextkey: di_nextkey:
1358 if (!di->keyname && *++di->keyp)
1364 case di_nextrepodata: di_nextrepodata:
1365 if (di->repodataid >= 0 && ++di->repodataid < di->repo->nrepodata)
1366 goto di_enterrepodata;
1369 case di_nextsolvable: di_nextsolvable:
1370 if (!(di->flags & SEARCH_THISSOLVID))
1373 di->solvid = di->repo->start;
1376 for (; di->solvid < di->repo->end; di->solvid++)
1378 if (di->pool->solvables[di->solvid].repo == di->repo)
1379 goto di_entersolvable;
1384 case di_nextrepo: di_nextrepo:
1385 if (di->repoid >= 0)
1389 if (di->repoid < di->pool->nrepos)
1391 di->repo = di->pool->repos[di->repoid];
1397 case di_bye: di_bye:
1401 case di_enterarray: di_enterarray:
1402 if (di->key->name == REPOSITORY_SOLVABLES)
1404 di->ddp = data_read_id(di->ddp, &di->kv.num);
1409 case di_nextarrayelement: di_nextarrayelement:
1412 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1413 if (di->kv.entry == di->kv.num)
1415 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1417 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1419 di->kv.str = (char *)di->ddp;
1421 di->state = di_nextkey;
1424 if (di->kv.entry == di->kv.num - 1)
1426 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1427 di->ddp = data_read_id(di->ddp, &di->kv.id);
1428 di->kv.str = (char *)di->ddp;
1429 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1431 if ((di->flags & SEARCH_SUB) != 0)
1432 di->state = di_entersub;
1434 di->state = di_nextarrayelement;
1437 case di_entersub: di_entersub:
1438 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1439 goto di_nextarrayelement; /* sorry, full */
1440 di->parents[di->nparents].kv = di->kv;
1441 di->parents[di->nparents].dp = di->dp;
1442 di->parents[di->nparents].keyp = di->keyp;
1443 di->dp = (unsigned char *)di->kv.str;
1444 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1445 memset(&di->kv, 0, sizeof(di->kv));
1446 di->kv.parent = &di->parents[di->nparents].kv;
1448 di->keyname = di->keynames[di->nparents - di->rootlevel];
1449 goto di_enterschema;
1451 case di_leavesub: di_leavesub:
1452 if (di->nparents - 1 < di->rootlevel)
1455 di->dp = di->parents[di->nparents].dp;
1456 di->kv = di->parents[di->nparents].kv;
1457 di->keyp = di->parents[di->nparents].keyp;
1458 di->key = di->data->keys + *di->keyp;
1459 di->ddp = (unsigned char *)di->kv.str;
1460 di->keyname = di->keynames[di->nparents - di->rootlevel];
1461 goto di_nextarrayelement;
1463 /* special solvable attr handling follows */
1465 case di_nextsolvableattr:
1466 di->kv.id = *di->idp++;
1471 di->state = di_nextsolvablekey;
1475 case di_nextsolvablekey: di_nextsolvablekey:
1476 if (di->keyname || di->key->name == RPM_RPMDBID)
1477 goto di_enterrepodata;
1481 case di_entersolvablekey: di_entersolvablekey:
1482 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1483 if (!di->idp || !di->idp[0])
1484 goto di_nextsolvablekey;
1485 di->kv.id = di->idp[0];
1486 di->kv.num = di->idp[0];
1488 if (!di->kv.eof && !di->idp[0])
1492 di->state = di_nextsolvablekey;
1494 di->state = di_nextsolvableattr;
1498 if (di->matcher.match)
1500 /* simple pre-check so that we don't need to stringify */
1501 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))
1503 int l = strlen(di->matcher.match) - strlen(di->kv.str);
1504 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
1507 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1509 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1513 if (!datamatcher_match(&di->matcher, di->kv.str))
1516 /* found something! */
1522 dataiterator_entersub(Dataiterator *di)
1524 if (di->state == di_nextarrayelement)
1525 di->state = di_entersub;
1529 dataiterator_setpos(Dataiterator *di)
1531 if (di->kv.eof == 2)
1533 pool_clear_pos(di->pool);
1536 di->pool->pos.solvid = di->solvid;
1537 di->pool->pos.repo = di->repo;
1538 di->pool->pos.repodataid = di->data - di->repo->repodata;
1539 di->pool->pos.schema = di->kv.id;
1540 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1544 dataiterator_setpos_parent(Dataiterator *di)
1546 if (!di->kv.parent || di->kv.parent->eof == 2)
1548 pool_clear_pos(di->pool);
1551 di->pool->pos.solvid = di->solvid;
1552 di->pool->pos.repo = di->repo;
1553 di->pool->pos.repodataid = di->data - di->repo->repodata;
1554 di->pool->pos.schema = di->kv.parent->id;
1555 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1558 /* clones just the position, not the search keys/matcher */
1560 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
1562 di->state = from->state;
1563 di->flags &= ~SEARCH_THISSOLVID;
1564 di->flags |= (from->flags & SEARCH_THISSOLVID);
1565 di->repo = from->repo;
1566 di->data = from->data;
1568 di->ddp = from->ddp;
1569 di->idp = from->idp;
1570 di->keyp = from->keyp;
1571 di->key = from->key;
1573 di->repodataid = from->repodataid;
1574 di->solvid = from->solvid;
1575 di->repoid = from->repoid;
1576 di->rootlevel = from->rootlevel;
1577 memcpy(di->parents, from->parents, sizeof(from->parents));
1578 di->nparents = from->nparents;
1582 for (i = 1; i < di->nparents; i++)
1583 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1584 di->kv.parent = &di->parents[di->nparents - 1].kv;
1589 dataiterator_seek(Dataiterator *di, int whence)
1591 if ((whence & DI_SEEK_STAY) != 0)
1592 di->rootlevel = di->nparents;
1593 switch (whence & ~DI_SEEK_STAY)
1596 if (di->state != di_nextarrayelement)
1598 if ((whence & DI_SEEK_STAY) != 0)
1599 di->rootlevel = di->nparents + 1; /* XXX: dangerous! */
1600 di->state = di_entersub;
1602 case DI_SEEK_PARENT:
1609 if (di->rootlevel > di->nparents)
1610 di->rootlevel = di->nparents;
1611 di->dp = di->parents[di->nparents].dp;
1612 di->kv = di->parents[di->nparents].kv;
1613 di->keyp = di->parents[di->nparents].keyp;
1614 di->key = di->data->keys + *di->keyp;
1615 di->ddp = (unsigned char *)di->kv.str;
1616 di->keyname = di->keynames[di->nparents - di->rootlevel];
1617 di->state = di_nextarrayelement;
1619 case DI_SEEK_REWIND:
1625 di->dp = (unsigned char *)di->kv.parent->str;
1626 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
1627 di->state = di_enterschema;
1635 dataiterator_skip_attribute(Dataiterator *di)
1637 if (di->state == di_nextsolvableattr)
1638 di->state = di_nextsolvablekey;
1640 di->state = di_nextkey;
1644 dataiterator_skip_solvable(Dataiterator *di)
1649 di->keyname = di->keynames[0];
1650 di->state = di_nextsolvable;
1654 dataiterator_skip_repo(Dataiterator *di)
1659 di->keyname = di->keynames[0];
1660 di->state = di_nextrepo;
1664 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1669 di->keyname = di->keynames[0];
1670 if (solvid == SOLVID_POS)
1672 di->repo = di->pool->pos.repo;
1679 di->data = di->repo->repodata + di->pool->pos.repodataid;
1680 di->repodataid = -1;
1681 di->solvid = solvid;
1682 di->state = di_enterrepo;
1683 di->flags |= SEARCH_THISSOLVID;
1688 di->repo = di->pool->solvables[solvid].repo;
1691 else if (di->repoid >= 0)
1693 if (!di->pool->nrepos)
1698 di->repo = di->pool->repos[0];
1702 di->solvid = solvid;
1704 di->flags |= SEARCH_THISSOLVID;
1705 di->state = di_enterrepo;
1709 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1718 di->flags &= ~SEARCH_THISSOLVID;
1719 di->state = di_enterrepo;
1723 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1725 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1729 return datamatcher_match(ma, di->kv.str);
1732 /************************************************************************
1733 * data modify functions
1736 /* extend repodata so that it includes solvables p */
1738 repodata_extend(Repodata *data, Id p)
1740 if (data->start == data->end)
1741 data->start = data->end = p;
1744 int old = data->end - data->start;
1745 int new = p - data->end + 1;
1748 data->attrs = sat_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1749 memset(data->attrs + old, 0, new * sizeof(Id *));
1751 data->incoreoffset = sat_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1752 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1755 if (p < data->start)
1757 int old = data->end - data->start;
1758 int new = data->start - p;
1761 data->attrs = sat_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1762 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1763 memset(data->attrs, 0, new * sizeof(Id *));
1765 data->incoreoffset = sat_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1766 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1767 memset(data->incoreoffset, 0, new * sizeof(Id));
1772 /* shrink end of repodata */
1774 repodata_shrink(Repodata *data, int end)
1778 if (data->end <= end)
1780 if (data->start >= end)
1784 for (i = 0; i < data->end - data->start; i++)
1785 sat_free(data->attrs[i]);
1786 data->attrs = sat_free(data->attrs);
1788 data->incoreoffset = sat_free(data->incoreoffset);
1789 data->start = data->end = 0;
1794 for (i = end; i < data->end; i++)
1795 sat_free(data->attrs[i - data->start]);
1796 data->attrs = sat_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
1798 if (data->incoreoffset)
1799 data->incoreoffset = sat_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
1803 /* extend repodata so that it includes solvables from start to start + num - 1 */
1805 repodata_extend_block(Repodata *data, Id start, Id num)
1809 if (!data->incoreoffset)
1811 data->incoreoffset = sat_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1812 data->start = start;
1813 data->end = start + num;
1816 repodata_extend(data, start);
1818 repodata_extend(data, start + num - 1);
1821 /**********************************************************************/
1824 #define REPODATA_ATTRS_BLOCK 31
1825 #define REPODATA_ATTRDATA_BLOCK 1023
1826 #define REPODATA_ATTRIDDATA_BLOCK 63
1830 repodata_new_handle(Repodata *data)
1834 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1835 data->nxattrs = 2; /* -1: SOLVID_META */
1837 data->xattrs = sat_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1838 data->xattrs[data->nxattrs] = 0;
1839 return -(data->nxattrs++);
1843 repodata_get_attrp(Repodata *data, Id handle)
1847 if (handle == SOLVID_META && !data->xattrs)
1849 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1852 return data->xattrs - handle;
1854 if (handle < data->start || handle >= data->end)
1855 repodata_extend(data, handle);
1857 data->attrs = sat_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1858 return data->attrs + (handle - data->start);
1862 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1868 app = repodata_get_attrp(data, handle);
1873 /* Determine equality based on the name only, allows us to change
1874 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1875 for (pp = ap; *pp; pp += 2)
1876 if (data->keys[*pp].name == data->keys[keyid].name)
1880 if (overwrite || data->keys[*pp].type == REPOKEY_TYPE_DELETED)
1889 ap = sat_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1899 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1903 keyid = repodata_key2id(data, key, 1);
1904 repodata_insert_keyid(data, solvid, keyid, val, 1);
1908 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1912 key.type = REPOKEY_TYPE_ID;
1914 key.storage = KEY_STORAGE_INCORE;
1915 repodata_set(data, solvid, &key, id);
1919 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1923 key.type = REPOKEY_TYPE_NUM;
1925 key.storage = KEY_STORAGE_INCORE;
1926 repodata_set(data, solvid, &key, (Id)num);
1930 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
1934 if (data->localpool)
1935 id = stringpool_str2id(&data->spool, str, 1);
1937 id = str2id(data->repo->pool, str, 1);
1939 key.type = REPOKEY_TYPE_ID;
1941 key.storage = KEY_STORAGE_INCORE;
1942 repodata_set(data, solvid, &key, id);
1946 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
1950 key.type = REPOKEY_TYPE_CONSTANT;
1951 key.size = constant;
1952 key.storage = KEY_STORAGE_INCORE;
1953 repodata_set(data, solvid, &key, 0);
1957 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
1961 key.type = REPOKEY_TYPE_CONSTANTID;
1963 key.storage = KEY_STORAGE_INCORE;
1964 repodata_set(data, solvid, &key, 0);
1968 repodata_set_void(Repodata *data, Id solvid, Id keyname)
1972 key.type = REPOKEY_TYPE_VOID;
1974 key.storage = KEY_STORAGE_INCORE;
1975 repodata_set(data, solvid, &key, 0);
1979 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
1984 l = strlen(str) + 1;
1986 key.type = REPOKEY_TYPE_STR;
1988 key.storage = KEY_STORAGE_INCORE;
1989 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1990 memcpy(data->attrdata + data->attrdatalen, str, l);
1991 repodata_set(data, solvid, &key, data->attrdatalen);
1992 data->attrdatalen += l;
1996 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
2002 key.type = REPOKEY_TYPE_BINARY;
2004 key.storage = KEY_STORAGE_INCORE;
2005 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
2006 dp = data->attrdata + data->attrdatalen;
2007 if (len >= (1 << 14))
2009 if (len >= (1 << 28))
2010 *dp++ = (len >> 28) | 128;
2011 if (len >= (1 << 21))
2012 *dp++ = (len >> 21) | 128;
2013 *dp++ = (len >> 14) | 128;
2015 if (len >= (1 << 7))
2016 *dp++ = (len >> 7) | 128;
2019 memcpy(dp, buf, len);
2020 repodata_set(data, solvid, &key, data->attrdatalen);
2021 data->attrdatalen = dp + len - data->attrdata;
2024 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
2025 * so that the caller can append entrysize new elements plus the termination zero there */
2027 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
2030 Id *ida, *pp, **ppp;
2032 /* check if it is the same as last time, this speeds things up a lot */
2033 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
2035 /* great! just append the new data */
2036 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2037 data->attriddatalen--; /* overwrite terminating 0 */
2038 data->lastdatalen += entrysize;
2042 ppp = repodata_get_attrp(data, handle);
2046 for (; *pp; pp += 2)
2047 if (data->keys[*pp].name == keyname)
2050 if (!pp || !*pp || data->keys[*pp].type != keytype)
2052 /* not found. allocate new key */
2058 key.storage = KEY_STORAGE_INCORE;
2059 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2060 keyid = repodata_key2id(data, &key, 1);
2061 repodata_insert_keyid(data, handle, keyid, data->attriddatalen, 1);
2062 data->lasthandle = handle;
2063 data->lastkey = keyid;
2064 data->lastdatalen = data->attriddatalen + entrysize + 1;
2068 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
2069 oldsize += entrysize;
2070 if (ida + 1 == data->attriddata + data->attriddatalen)
2072 /* this was the last entry, just append it */
2073 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2074 data->attriddatalen--; /* overwrite terminating 0 */
2078 /* too bad. move to back. */
2079 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2080 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
2081 pp[1] = data->attriddatalen;
2082 data->attriddatalen += oldsize;
2084 data->lasthandle = handle;
2085 data->lastkey = *pp;
2086 data->lastdatalen = data->attriddatalen + entrysize + 1;
2090 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2091 const unsigned char *str)
2096 if (!(l = sat_chksum_len(type)))
2101 key.storage = KEY_STORAGE_INCORE;
2102 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2103 memcpy(data->attrdata + data->attrdatalen, str, l);
2104 repodata_set(data, solvid, &key, data->attrdatalen);
2105 data->attrdatalen += l;
2109 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2112 unsigned char buf[64];
2115 if (!(l = sat_chksum_len(type)))
2117 if (l > sizeof(buf) || sat_hex2bin(&str, buf, l) != l)
2119 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2123 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2127 if (!(l = sat_chksum_len(type)))
2129 return pool_bin2hex(data->repo->pool, buf, l);
2132 /* rpm filenames don't contain the epoch, so strip it */
2133 static inline const char *
2134 evrid2vrstr(Pool *pool, Id evrid)
2136 const char *p, *evr = id2str(pool, evrid);
2139 for (p = evr; *p >= '0' && *p <= '9'; p++)
2141 return p != evr && *p == ':' ? p + 1 : evr;
2145 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2147 Pool *pool = data->repo->pool;
2149 const char *str, *fp;
2153 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2156 if ((dir = strrchr(file, '/')) != 0)
2167 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2172 if (l == 1 && dir[0] == '.')
2174 s = pool->solvables + solvid;
2177 str = id2str(pool, s->arch);
2178 if (!strncmp(dir, str, l) && !str[l])
2179 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2181 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2184 char *dir2 = strdup(dir);
2186 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2191 str = id2str(pool, s->name);
2193 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2196 str = evrid2vrstr(pool, s->evr);
2198 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2201 str = id2str(pool, s->arch);
2203 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2205 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2210 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2214 repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
2220 key.type = REPOKEY_TYPE_IDARRAY;
2222 key.storage = KEY_STORAGE_INCORE;
2223 repodata_set(data, solvid, &key, data->attriddatalen);
2224 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, q->count + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2225 for (i = 0; i < q->count; i++)
2226 data->attriddata[data->attriddatalen++] = q->elements[i];
2227 data->attriddata[data->attriddatalen++] = 0;
2231 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2235 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2237 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2238 data->attriddata[data->attriddatalen++] = dir;
2239 data->attriddata[data->attriddatalen++] = num;
2240 data->attriddata[data->attriddatalen++] = num2;
2241 data->attriddata[data->attriddatalen++] = 0;
2245 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2251 l = strlen(str) + 1;
2252 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2253 memcpy(data->attrdata + data->attrdatalen, str, l);
2254 stroff = data->attrdatalen;
2255 data->attrdatalen += l;
2258 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2260 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2261 data->attriddata[data->attriddatalen++] = dir;
2262 data->attriddata[data->attriddatalen++] = stroff;
2263 data->attriddata[data->attriddatalen++] = 0;
2267 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2270 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2272 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2273 data->attriddata[data->attriddatalen++] = id;
2274 data->attriddata[data->attriddatalen++] = 0;
2278 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2282 if (data->localpool)
2283 id = stringpool_str2id(&data->spool, str, 1);
2285 id = str2id(data->repo->pool, str, 1);
2286 repodata_add_idarray(data, solvid, keyname, id);
2290 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2292 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2293 data->attriddata[data->attriddatalen++] = ghandle;
2294 data->attriddata[data->attriddatalen++] = 0;
2298 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2300 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2301 data->attriddata[data->attriddatalen++] = ghandle;
2302 data->attriddata[data->attriddatalen++] = 0;
2306 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2309 app = repodata_get_attrp(data, solvid);
2313 for (; *ap; ap += 2)
2314 if (data->keys[*ap].name == keyname)
2320 for (; *ap; ap += 2)
2322 if (data->keys[*ap].name == keyname)
2330 /* XXX: does not work correctly, needs fix in iterators! */
2332 repodata_delete(Repodata *data, Id solvid, Id keyname)
2336 key.type = REPOKEY_TYPE_DELETED;
2338 key.storage = KEY_STORAGE_INCORE;
2339 repodata_set(data, solvid, &key, 0);
2342 /* add all (uninternalized) attrs from src to dest */
2344 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2347 if (dest == src || !(keyp = data->attrs[src - data->start]))
2349 for (; *keyp; keyp += 2)
2350 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2353 /* add some (uninternalized) attrs from src to dest */
2355 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2358 if (dest == src || !(keyp = data->attrs[src - data->start]))
2360 for (; *keyp; keyp += 2)
2361 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2362 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2367 /**********************************************************************/
2369 /* TODO: unify with repo_write and repo_solv! */
2371 #define EXTDATA_BLOCK 1023
2379 data_addid(struct extdata *xd, Id x)
2383 xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2384 dp = xd->buf + xd->len;
2389 *dp++ = (x >> 28) | 128;
2391 *dp++ = (x >> 21) | 128;
2392 *dp++ = (x >> 14) | 128;
2395 *dp++ = (x >> 7) | 128;
2397 xd->len = dp - xd->buf;
2401 data_addideof(struct extdata *xd, Id x, int eof)
2404 x = (x & 63) | ((x & ~63) << 1);
2405 data_addid(xd, (eof ? x : x | 64));
2409 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2411 xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2412 memcpy(xd->buf + xd->len, blob, len);
2416 /*********************************/
2418 /* internalalize some key into incore/vincore data */
2421 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2422 struct extdata *newvincore,
2424 Repokey *key, Id val)
2428 unsigned int oldvincorelen = 0;
2432 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2435 oldvincorelen = xd->len;
2439 case REPOKEY_TYPE_VOID:
2440 case REPOKEY_TYPE_CONSTANT:
2441 case REPOKEY_TYPE_CONSTANTID:
2443 case REPOKEY_TYPE_STR:
2444 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2446 case REPOKEY_TYPE_MD5:
2447 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2449 case REPOKEY_TYPE_SHA1:
2450 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2452 case REPOKEY_TYPE_SHA256:
2453 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2455 case REPOKEY_TYPE_ID:
2456 case REPOKEY_TYPE_NUM:
2457 case REPOKEY_TYPE_DIR:
2458 data_addid(xd, val);
2460 case REPOKEY_TYPE_BINARY:
2463 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2465 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2468 case REPOKEY_TYPE_IDARRAY:
2469 for (ida = data->attriddata + val; *ida; ida++)
2470 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2472 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2473 for (ida = data->attriddata + val; *ida; ida += 3)
2475 data_addid(xd, ida[0]);
2476 data_addid(xd, ida[1]);
2477 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2480 case REPOKEY_TYPE_DIRSTRARRAY:
2481 for (ida = data->attriddata + val; *ida; ida += 2)
2483 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2484 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2487 case REPOKEY_TYPE_FIXARRAY:
2491 for (ida = data->attriddata + val; *ida; ida++)
2494 Id *kp = data->xattrs[-*ida];
2502 schemaid = repodata_schema2id(data, schema, 1);
2503 else if (schemaid != repodata_schema2id(data, schema, 0))
2505 pool_debug(data->repo->pool, SAT_FATAL, "fixarray substructs with different schemas\n");
2511 data_addid(xd, num);
2512 data_addid(xd, schemaid);
2513 for (ida = data->attriddata + val; *ida; ida++)
2515 Id *kp = data->xattrs[-*ida];
2519 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2523 case REPOKEY_TYPE_FLEXARRAY:
2526 for (ida = data->attriddata + val; *ida; ida++)
2528 data_addid(xd, num);
2529 for (ida = data->attriddata + val; *ida; ida++)
2531 Id *kp = data->xattrs[-*ida];
2534 data_addid(xd, 0); /* XXX */
2541 schemaid = repodata_schema2id(data, schema, 1);
2542 data_addid(xd, schemaid);
2543 kp = data->xattrs[-*ida];
2545 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2550 pool_debug(data->repo->pool, SAT_FATAL, "don't know how to handle type %d\n", key->type);
2553 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2555 /* put offset/len in incore */
2556 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2557 oldvincorelen = xd->len - oldvincorelen;
2558 data_addid(newincore, oldvincorelen);
2563 repodata_internalize(Repodata *data)
2565 Repokey *key, solvkey;
2567 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2568 unsigned char *dp, *ndp;
2569 int newschema, oldcount;
2570 struct extdata newincore;
2571 struct extdata newvincore;
2574 if (!data->attrs && !data->xattrs)
2577 newvincore.buf = data->vincore;
2578 newvincore.len = data->vincorelen;
2580 /* find the solvables key, create if needed */
2581 memset(&solvkey, 0, sizeof(solvkey));
2582 solvkey.name = REPOSITORY_SOLVABLES;
2583 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2585 solvkey.storage = KEY_STORAGE_INCORE;
2586 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2588 schema = sat_malloc2(data->nkeys, sizeof(Id));
2589 seen = sat_malloc2(data->nkeys, sizeof(Id));
2591 /* Merge the data already existing (in data->schemata, ->incoredata and
2592 friends) with the new attributes in data->attrs[]. */
2593 nentry = data->end - data->start;
2594 memset(&newincore, 0, sizeof(newincore));
2595 data_addid(&newincore, 0); /* start data at offset 1 */
2597 data->mainschema = 0;
2598 data->mainschemaoffsets = sat_free(data->mainschemaoffsets);
2600 /* join entry data */
2601 /* we start with the meta data, entry -1 */
2602 for (entry = -1; entry < nentry; entry++)
2604 memset(seen, 0, data->nkeys * sizeof(Id));
2606 dp = data->incoredata;
2609 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2610 dp = data_read_id(dp, &oldschema);
2613 fprintf(stderr, "oldschema %d\n", oldschema);
2614 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2615 fprintf(stderr, "schemadata %p\n", data->schemadata);
2617 /* seen: -1: old data 0: skipped >0: id + 1 */
2621 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2625 pool_debug(data->repo->pool, SAT_FATAL, "Inconsistent old data (key occured twice).\n");
2633 keyp = data->attrs ? data->attrs[entry] : 0;
2636 /* strip solvables key */
2638 for (sp = keyp = schema; *sp; sp++)
2639 if (*sp != solvkeyid)
2644 seen[solvkeyid] = 0;
2645 keyp = data->xattrs ? data->xattrs[1] : 0;
2648 for (; *keyp; keyp += 2)
2655 seen[*keyp] = keyp[1] + 1;
2657 if (entry < 0 && data->end != data->start)
2664 /* Ideally we'd like to sort the new schema here, to ensure
2665 schema equality independend of the ordering. We can't do that
2666 yet. For once see below (old ids need to come before new ids).
2667 An additional difficulty is that we also need to move
2668 the values with the keys. */
2669 schemaid = repodata_schema2id(data, schema, 1);
2671 schemaid = oldschema;
2674 /* Now create data blob. We walk through the (possibly new) schema
2675 and either copy over old data, or insert the new. */
2676 /* XXX Here we rely on the fact that the (new) schema has the form
2677 o1 o2 o3 o4 ... | n1 n2 n3 ...
2678 (oX being the old keyids (possibly overwritten), and nX being
2679 the new keyids). This rules out sorting the keyids in order
2680 to ensure a small schema count. */
2682 data->incoreoffset[entry] = newincore.len;
2683 data_addid(&newincore, schemaid);
2686 data->mainschema = schemaid;
2687 data->mainschemaoffsets = sat_calloc(sp - schema, sizeof(Id));
2689 keypstart = data->schemadata + data->schemata[schemaid];
2690 for (keyp = keypstart; *keyp; keyp++)
2693 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2694 if (*keyp == solvkeyid)
2696 /* add flexarray entry count */
2697 data_addid(&newincore, data->end - data->start);
2700 key = data->keys + *keyp;
2702 fprintf(stderr, "internalize %d(%d):%s:%s\n", entry, entry + data->start, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
2707 /* Skip the data associated with this old key. */
2708 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2710 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2711 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2713 else if (key->storage == KEY_STORAGE_INCORE)
2714 ndp = data_skip_key(data, dp, key);
2717 if (seen[*keyp] == -1)
2719 /* If this key was an old one _and_ was not overwritten with
2720 a different value copy over the old value (we skipped it
2723 data_addblob(&newincore, dp, ndp - dp);
2726 else if (seen[*keyp])
2728 /* Otherwise we have a new value. Parse it into the internal
2730 repodata_serialize_key(data, &newincore, &newvincore,
2731 schema, key, seen[*keyp] - 1);
2735 if (entry >= 0 && data->attrs && data->attrs[entry])
2736 data->attrs[entry] = sat_free(data->attrs[entry]);
2738 /* free all xattrs */
2739 for (entry = 0; entry < data->nxattrs; entry++)
2740 if (data->xattrs[entry])
2741 sat_free(data->xattrs[entry]);
2742 data->xattrs = sat_free(data->xattrs);
2745 data->lasthandle = 0;
2747 data->lastdatalen = 0;
2750 repodata_free_schemahash(data);
2752 sat_free(data->incoredata);
2753 data->incoredata = newincore.buf;
2754 data->incoredatalen = newincore.len;
2755 data->incoredatafree = 0;
2757 sat_free(data->vincore);
2758 data->vincore = newvincore.buf;
2759 data->vincorelen = newvincore.len;
2761 data->attrs = sat_free(data->attrs);
2762 data->attrdata = sat_free(data->attrdata);
2763 data->attriddata = sat_free(data->attriddata);
2764 data->attrdatalen = 0;
2765 data->attriddatalen = 0;
2769 repodata_disable_paging(Repodata *data)
2771 if (maybe_load_repodata(data, 0))
2772 repopagestore_disable_paging(&data->store);
2776 repodata_load_stub(Repodata *data)
2778 Repo *repo = data->repo;
2779 Pool *pool = repo->pool;
2781 struct _Pool_tmpspace oldtmpspace;
2783 if (!pool->loadcallback)
2785 data->state = REPODATA_ERROR;
2788 data->state = REPODATA_LOADING;
2790 /* save tmp space */
2791 oldtmpspace = pool->tmpspace;
2792 memset(&pool->tmpspace, 0, sizeof(pool->tmpspace));
2794 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2796 /* restore tmp space */
2797 for (i = 0; i < POOL_TMPSPACEBUF; i++)
2798 sat_free(pool->tmpspace.buf[i]);
2799 pool->tmpspace = oldtmpspace;
2801 data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
2805 repodata_create_stubs(Repodata *data)
2807 Repo *repo = data->repo;
2808 Pool *pool = repo->pool;
2815 int datastart, dataend;
2817 repodataid = data - repo->repodata;
2818 datastart = data->start;
2819 dataend = data->end;
2820 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2821 while (dataiterator_step(&di))
2823 if (di.data - repo->repodata != repodataid)
2827 dataiterator_free(&di);
2830 stubdataids = sat_calloc(cnt, sizeof(*stubdataids));
2831 for (i = 0; i < cnt; i++)
2833 sdata = repo_add_repodata(repo, 0);
2834 if (dataend > datastart)
2835 repodata_extend_block(sdata, datastart, dataend - datastart);
2836 stubdataids[i] = sdata - repo->repodata;
2837 sdata->state = REPODATA_STUB;
2838 sdata->loadcallback = repodata_load_stub;
2841 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2843 while (dataiterator_step(&di))
2845 if (di.data - repo->repodata != repodataid)
2847 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
2849 dataiterator_entersub(&di);
2850 sdata = repo->repodata + stubdataids[i++];
2854 switch (di.key->type)
2856 case REPOKEY_TYPE_ID:
2857 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
2859 case REPOKEY_TYPE_CONSTANTID:
2860 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
2862 case REPOKEY_TYPE_STR:
2863 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
2865 case REPOKEY_TYPE_VOID:
2866 repodata_set_void(sdata, SOLVID_META, di.key->name);
2868 case REPOKEY_TYPE_NUM:
2869 repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num);
2871 case REPOKEY_TYPE_MD5:
2872 case REPOKEY_TYPE_SHA1:
2873 case REPOKEY_TYPE_SHA256:
2874 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
2876 case REPOKEY_TYPE_IDARRAY:
2877 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
2878 if (di.key->name == REPOSITORY_KEYS)
2885 xkeyname = di.kv.id;
2888 xkey.name = xkeyname;
2889 xkey.type = di.kv.id;
2890 xkey.storage = KEY_STORAGE_INCORE;
2892 repodata_key2id(sdata, &xkey, 1);
2899 dataiterator_free(&di);
2900 for (i = 0; i < cnt; i++)
2901 repodata_internalize(repo->repodata + stubdataids[i]);
2902 sat_free(stubdataids);
2906 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: