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 extern unsigned int compress_buf (const unsigned char *in, unsigned int in_len,
38 unsigned char *out, unsigned int out_len);
39 extern unsigned int unchecked_decompress_buf (const unsigned char *in,
42 unsigned int out_len);
44 #define REPODATA_BLOCK 255
48 repodata_initdata(Repodata *data, Repo *repo, int localpool)
50 memset(data, 0, sizeof (*data));
52 data->localpool = localpool;
54 stringpool_init_empty(&data->spool);
55 data->keys = sat_calloc(1, sizeof(Repokey));
57 data->schemata = sat_calloc(1, sizeof(Id));
58 data->schemadata = sat_calloc(1, sizeof(Id));
60 data->schemadatalen = 1;
61 repopagestore_init(&data->store);
65 repodata_freedata(Repodata *data)
71 sat_free(data->schemata);
72 sat_free(data->schemadata);
73 sat_free(data->schematahash);
75 stringpool_free(&data->spool);
76 dirpool_free(&data->dirpool);
78 sat_free(data->mainschemaoffsets);
79 sat_free(data->incoredata);
80 sat_free(data->incoreoffset);
81 sat_free(data->verticaloffset);
83 repopagestore_free(&data->store);
85 sat_free(data->vincore);
88 for (i = 0; i < data->end - data->start; i++)
89 sat_free(data->attrs[i]);
90 sat_free(data->attrs);
92 for (i = 0; i < data->nxattrs; i++)
93 sat_free(data->xattrs[i]);
94 sat_free(data->xattrs);
96 sat_free(data->attrdata);
97 sat_free(data->attriddata);
101 repodata_create(Repo *repo, int localpool)
106 repo->repodata = sat_realloc2(repo->repodata, repo->nrepodata, sizeof(*data));
107 data = repo->repodata + repo->nrepodata - 1;
108 repodata_initdata(data, repo, localpool);
113 repodata_free(Repodata *data)
115 Repo *repo = data->repo;
116 int i = data - repo->repodata;
117 repodata_freedata(data);
118 if (i < repo->nrepodata - 1)
119 memmove(repo->repodata + i, repo->repodata + i + 1, (repo->nrepodata - 1 - i) * sizeof(Repodata));
124 repodata_empty(Repodata *data, int localpool)
126 void (*loadcallback)(Repodata *) = data->loadcallback;
127 int state = data->state;
128 repodata_freedata(data);
129 repodata_initdata(data, data->repo, localpool);
131 data->loadcallback = loadcallback;
135 /***************************************************************
136 * key pool management
139 /* this is not so time critical that we need a hash, so we do a simple
142 repodata_key2id(Repodata *data, Repokey *key, int create)
146 for (keyid = 1; keyid < data->nkeys; keyid++)
147 if (data->keys[keyid].name == key->name && data->keys[keyid].type == key->type)
149 if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != data->keys[keyid].size)
153 if (keyid == data->nkeys)
157 /* allocate new key */
158 data->keys = sat_realloc2(data->keys, data->nkeys + 1, sizeof(Repokey));
159 data->keys[data->nkeys++] = *key;
160 if (data->verticaloffset)
162 data->verticaloffset = sat_realloc2(data->verticaloffset, data->nkeys, sizeof(Id));
163 data->verticaloffset[data->nkeys - 1] = 0;
165 data->keybits[(key->name >> 3) & (sizeof(data->keybits) - 1)] |= 1 << (key->name & 7);
171 /***************************************************************
172 * schema pool management
175 #define SCHEMATA_BLOCK 31
176 #define SCHEMATADATA_BLOCK 255
179 repodata_schema2id(Repodata *data, Id *schema, int create)
185 if ((schematahash = data->schematahash) == 0)
187 data->schematahash = schematahash = sat_calloc(256, sizeof(Id));
188 for (i = 0; i < data->nschemata; i++)
190 for (sp = data->schemadata + data->schemata[i], h = 0; *sp; len++)
193 schematahash[h] = i + 1;
195 data->schemadata = sat_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
196 data->schemata = sat_extend_resize(data->schemata, data->nschemata, sizeof(Id), SCHEMATA_BLOCK);
199 for (sp = schema, len = 0, h = 0; *sp; len++)
204 cid = schematahash[h];
208 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
211 for (cid = 0; cid < data->nschemata; cid++)
212 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
218 data->schemadata = sat_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
219 data->schemata = sat_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
221 memcpy(data->schemadata + data->schemadatalen, schema, len * sizeof(Id));
222 data->schemata[data->nschemata] = data->schemadatalen;
223 data->schemadatalen += len;
224 schematahash[h] = data->nschemata + 1;
226 fprintf(stderr, "schema2id: new schema\n");
228 return data->nschemata++;
232 repodata_free_schemahash(Repodata *data)
234 data->schematahash = sat_free(data->schematahash);
236 data->schemata = sat_realloc2(data->schemata, data->nschemata, sizeof(Id));
237 data->schemadata = sat_realloc2(data->schemadata, data->schemadatalen, sizeof(Id));
241 /***************************************************************
242 * dir pool management
245 #ifndef HAVE_STRCHRNUL
246 static inline const char *strchrnul(const char *str, char x)
248 const char *p = strchr(str, x);
249 return p ? p : str + strlen(str);
254 repodata_str2dir(Repodata *data, const char *dir, int create)
260 while (*dir == '/' && dir[1] == '/')
262 if (*dir == '/' && !dir[1])
264 if (data->dirpool.ndirs)
266 return dirpool_add_dir(&data->dirpool, 0, 1, create);
270 dire = strchrnul(dir, '/');
272 id = stringpool_strn2id(&data->spool, dir, dire - dir, create);
274 id = strn2id(data->repo->pool, dir, dire - dir, create);
277 parent = dirpool_add_dir(&data->dirpool, parent, id, create);
290 repodata_dir2str(Repodata *data, Id did, const char *suf)
292 Pool *pool = data->repo->pool;
299 return suf ? suf : "";
303 comp = dirpool_compid(&data->dirpool, parent);
304 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
306 parent = dirpool_parent(&data->dirpool, parent);
311 l += strlen(suf) + 1;
312 p = pool_alloctmpspace(pool, l + 1) + l;
323 comp = dirpool_compid(&data->dirpool, parent);
324 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
327 strncpy(p, comps, l);
328 parent = dirpool_parent(&data->dirpool, parent);
336 /***************************************************************
340 static inline unsigned char *
341 data_skip_schema(Repodata *data, unsigned char *dp, Id schema)
343 Id *keyp = data->schemadata + data->schemata[schema];
344 for (; *keyp; keyp++)
345 dp = data_skip_key(data, dp, data->keys + *keyp);
350 data_skip_key(Repodata *data, unsigned char *dp, Repokey *key)
352 int nentries, schema;
355 case REPOKEY_TYPE_FIXARRAY:
356 dp = data_read_id(dp, &nentries);
359 dp = data_read_id(dp, &schema);
361 dp = data_skip_schema(data, dp, schema);
363 case REPOKEY_TYPE_FLEXARRAY:
364 dp = data_read_id(dp, &nentries);
367 dp = data_read_id(dp, &schema);
368 dp = data_skip_schema(data, dp, schema);
372 if (key->storage == KEY_STORAGE_INCORE)
373 dp = data_skip(dp, key->type);
374 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
376 dp = data_skip(dp, REPOKEY_TYPE_ID);
377 dp = data_skip(dp, REPOKEY_TYPE_ID);
383 static unsigned char *
384 forward_to_key(Repodata *data, Id keyid, Id *keyp, unsigned char *dp)
390 if (data->mainschemaoffsets && dp == data->incoredata + data->mainschemaoffsets[0] && keyp == data->schemadata + data->schemata[data->mainschema])
393 for (i = 0; (k = *keyp++) != 0; i++)
395 return data->incoredata + data->mainschemaoffsets[i];
398 while ((k = *keyp++) != 0)
402 if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
404 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip offset */
405 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip length */
408 if (data->keys[k].storage != KEY_STORAGE_INCORE)
410 dp = data_skip_key(data, dp, data->keys + k);
415 static unsigned char *
416 get_vertical_data(Repodata *data, Repokey *key, Id off, Id len)
421 if (off >= data->lastverticaloffset)
423 off -= data->lastverticaloffset;
424 if (off + len > data->vincorelen)
426 return data->vincore + off;
428 if (off + len > key->size)
430 /* we now have the offset, go into vertical */
431 off += data->verticaloffset[key - data->keys];
432 /* fprintf(stderr, "key %d page %d\n", key->name, off / BLOB_PAGESIZE); */
433 dp = repopagestore_load_page_range(&data->store, off / BLOB_PAGESIZE, (off + len - 1) / BLOB_PAGESIZE);
435 dp += off % BLOB_PAGESIZE;
439 static inline unsigned char *
440 get_data(Repodata *data, Repokey *key, unsigned char **dpp, int advance)
442 unsigned char *dp = *dpp;
446 if (key->storage == KEY_STORAGE_INCORE)
449 *dpp = data_skip_key(data, dp, key);
452 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
455 dp = data_read_id(dp, &off);
456 dp = data_read_id(dp, &len);
459 return get_vertical_data(data, key, off, len);
465 load_repodata(Repodata *data)
467 if (data->loadcallback)
469 data->loadcallback(data);
470 if (data->state == REPODATA_AVAILABLE)
473 data->state = REPODATA_ERROR;
478 maybe_load_repodata(Repodata *data, Id keyname)
480 if (keyname && !repodata_precheck_keyname(data, keyname))
481 return 0; /* do not bother... */
488 for (i = 0; i < data->nkeys; i++)
489 if (keyname == data->keys[i].name)
491 if (i == data->nkeys)
494 return load_repodata(data);
497 case REPODATA_AVAILABLE:
498 case REPODATA_LOADING:
501 data->state = REPODATA_ERROR;
506 static inline unsigned char *
507 solvid2data(Repodata *data, Id solvid, Id *schemap)
509 unsigned char *dp = data->incoredata;
512 if (solvid == SOLVID_META) /* META */
514 else if (solvid == SOLVID_POS) /* META */
516 Pool *pool = data->repo->pool;
517 if (data->repo != pool->pos.repo)
519 if (data != data->repo->repodata + pool->pos.repodataid)
521 *schemap = pool->pos.schema;
522 return data->incoredata + pool->pos.dp;
526 if (solvid < data->start || solvid >= data->end)
528 dp += data->incoreoffset[solvid - data->start];
530 return data_read_id(dp, schemap);
533 /************************************************************************
537 static inline unsigned char *
538 find_key_data(Repodata *data, Id solvid, Id keyname, Repokey **keypp)
541 Id schema, *keyp, *kp;
544 if (!maybe_load_repodata(data, keyname))
546 dp = solvid2data(data, solvid, &schema);
549 keyp = data->schemadata + data->schemata[schema];
550 for (kp = keyp; *kp; kp++)
551 if (data->keys[*kp].name == keyname)
555 *keypp = key = data->keys + *kp;
556 if (key->type == REPOKEY_TYPE_DELETED)
558 if (key->type == REPOKEY_TYPE_VOID || key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID)
559 return dp; /* no need to forward... */
560 dp = forward_to_key(data, *kp, keyp, dp);
563 return get_data(data, key, &dp, 0);
567 repodata_lookup_type(Repodata *data, Id solvid, Id keyname)
569 Id schema, *keyp, *kp;
570 if (!maybe_load_repodata(data, keyname))
572 if (!solvid2data(data, solvid, &schema))
574 keyp = data->schemadata + data->schemata[schema];
575 for (kp = keyp; *kp; kp++)
576 if (data->keys[*kp].name == keyname)
577 return data->keys[*kp].type;
582 repodata_lookup_id(Repodata *data, Id solvid, Id keyname)
588 dp = find_key_data(data, solvid, keyname, &key);
591 if (key->type == REPOKEY_TYPE_CONSTANTID)
593 if (key->type != REPOKEY_TYPE_ID)
595 dp = data_read_id(dp, &id);
600 repodata_lookup_str(Repodata *data, Id solvid, Id keyname)
606 dp = find_key_data(data, solvid, keyname, &key);
609 if (key->type == REPOKEY_TYPE_STR)
610 return (const char *)dp;
611 if (key->type == REPOKEY_TYPE_CONSTANTID)
612 return id2str(data->repo->pool, key->size);
613 if (key->type == REPOKEY_TYPE_ID)
614 dp = data_read_id(dp, &id);
618 return data->spool.stringspace + data->spool.strings[id];
619 return id2str(data->repo->pool, id);
623 repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned int *value)
630 dp = find_key_data(data, solvid, keyname, &key);
633 if (key->type == REPOKEY_TYPE_NUM
634 || key->type == REPOKEY_TYPE_U32
635 || key->type == REPOKEY_TYPE_CONSTANT)
637 dp = data_fetch(dp, &kv, key);
645 repodata_lookup_void(Repodata *data, Id solvid, Id keyname)
651 if (!maybe_load_repodata(data, keyname))
653 dp = solvid2data(data, solvid, &schema);
656 /* can't use find_key_data as we need to test the type */
657 for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++)
658 if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID)
663 const unsigned char *
664 repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep)
669 dp = find_key_data(data, solvid, keyname, &key);
677 repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
685 dp = find_key_data(data, solvid, keyname, &key);
688 if (key->type != REPOKEY_TYPE_IDARRAY && key->type != REPOKEY_TYPE_REL_IDARRAY)
692 dp = data_read_ideof(dp, &id, &eof);
701 repodata_globalize_id(Repodata *data, Id id, int create)
703 if (!id || !data || !data->localpool)
705 return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
709 /************************************************************************
715 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
719 case REPOKEY_TYPE_ID:
720 case REPOKEY_TYPE_CONSTANTID:
721 case REPOKEY_TYPE_IDARRAY:
722 if (data && data->localpool)
723 kv->str = stringpool_id2str(&data->spool, kv->id);
725 kv->str = id2str(pool, kv->id);
726 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
729 for (s = kv->str; *s >= 'a' && *s <= 'z'; s++)
731 if (*s == ':' && s > kv->str)
735 case REPOKEY_TYPE_STR:
737 case REPOKEY_TYPE_DIRSTRARRAY:
738 if (!(flags & SEARCH_FILES))
739 return 1; /* match just the basename */
740 /* Put the full filename into kv->str. */
741 kv->str = repodata_dir2str(data, kv->id, kv->str);
742 /* And to compensate for that put the "empty" directory into
743 kv->id, so that later calls to repodata_dir2str on this data
744 come up with the same filename again. */
747 case REPOKEY_TYPE_MD5:
748 case REPOKEY_TYPE_SHA1:
749 case REPOKEY_TYPE_SHA256:
750 if (!(flags & SEARCH_CHECKSUMS))
751 return 0; /* skip em */
752 kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str);
760 struct subschema_data {
766 /* search a specific repodata */
768 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
772 Id keyid, *kp, *keyp;
773 unsigned char *dp, *ddp;
779 if (!maybe_load_repodata(data, keyname))
781 if (solvid == SOLVID_SUBSCHEMA)
783 struct subschema_data *subd = cbdata;
784 cbdata = subd->cbdata;
786 schema = subd->parent->id;
787 dp = (unsigned char *)subd->parent->str;
788 kv.parent = subd->parent;
793 dp = solvid2data(data, solvid, &schema);
796 s = data->repo->pool->solvables + solvid;
799 keyp = data->schemadata + data->schemata[schema];
802 /* search for a specific key */
803 for (kp = keyp; *kp; kp++)
804 if (data->keys[*kp].name == keyname)
808 dp = forward_to_key(data, *kp, keyp, dp);
814 while ((keyid = *keyp++) != 0)
817 key = data->keys + keyid;
818 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
820 if (key->type == REPOKEY_TYPE_DELETED)
822 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
824 struct subschema_data subd;
828 subd.cbdata = cbdata;
831 ddp = data_read_id(ddp, &nentries);
835 while (ddp && nentries > 0)
839 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
840 ddp = data_read_id(ddp, &schema);
842 kv.str = (char *)ddp;
843 stop = callback(cbdata, s, data, key, &kv);
844 if (stop > SEARCH_NEXT_KEY)
846 if (stop && stop != SEARCH_ENTERSUB)
848 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
849 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
850 ddp = data_skip_schema(data, ddp, schema);
853 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
857 kv.str = (char *)ddp;
858 stop = callback(cbdata, s, data, key, &kv);
859 if (stop > SEARCH_NEXT_KEY)
869 ddp = data_fetch(ddp, &kv, key);
872 stop = callback(cbdata, s, data, key, &kv);
875 while (!kv.eof && !stop);
876 if (onekey || stop > SEARCH_NEXT_KEY)
882 repodata_setpos_kv(Repodata *data, KeyValue *kv)
884 Pool *pool = data->repo->pool;
886 pool_clear_pos(pool);
889 pool->pos.repo = data->repo;
890 pool->pos.repodataid = data - data->repo->repodata;
891 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
892 pool->pos.schema = kv->id;
896 /************************************************************************
897 * data iterator functions
900 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
901 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
902 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
903 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
904 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
905 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
906 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
907 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
908 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
909 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
910 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
911 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
912 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
913 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
917 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
931 case SOLVABLE_VENDOR:
934 case SOLVABLE_PROVIDES:
936 return s->provides ? s->repo->idarraydata + s->provides : 0;
937 case SOLVABLE_OBSOLETES:
939 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
940 case SOLVABLE_CONFLICTS:
942 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
943 case SOLVABLE_REQUIRES:
945 return s->requires ? s->repo->idarraydata + s->requires : 0;
946 case SOLVABLE_RECOMMENDS:
948 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
949 case SOLVABLE_SUPPLEMENTS:
951 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
952 case SOLVABLE_SUGGESTS:
954 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
955 case SOLVABLE_ENHANCES:
957 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
960 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
967 datamatcher_init(Datamatcher *ma, const char *match, int flags)
973 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
975 ma->matchdata = sat_calloc(1, sizeof(regex_t));
976 ma->error = regcomp((regex_t *)ma->matchdata, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
979 sat_free(ma->matchdata);
980 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
987 datamatcher_free(Datamatcher *ma)
989 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
991 regfree(ma->matchdata);
992 ma->matchdata = sat_free(ma->matchdata);
997 datamatcher_match(Datamatcher *ma, const char *str)
1000 switch ((ma->flags & SEARCH_STRINGMASK))
1002 case SEARCH_SUBSTRING:
1003 if (ma->flags & SEARCH_NOCASE)
1005 if (!strcasestr(str, ma->match))
1010 if (!strstr(str, ma->match))
1015 if (ma->flags & SEARCH_NOCASE)
1017 if (strcasecmp(ma->match, str))
1022 if (strcmp(ma->match, str))
1026 case SEARCH_STRINGSTART:
1027 if (ma->flags & SEARCH_NOCASE)
1029 if (strncasecmp(ma->match, str, strlen(ma->match)))
1034 if (strncmp(ma->match, str, strlen(ma->match)))
1038 case SEARCH_STRINGEND:
1039 l = strlen(str) - strlen(ma->match);
1042 if (ma->flags & SEARCH_NOCASE)
1044 if (strcasecmp(ma->match, str + l))
1049 if (strcmp(ma->match, str + l))
1054 if (fnmatch(ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
1058 if (regexec((const regex_t *)ma->matchdata, str, 0, NULL, 0))
1068 repodata_filelistfilter_matches(Repodata *data, const char *str)
1070 /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */
1071 /* for now hardcoded */
1072 if (strstr(str, "bin/"))
1074 if (!strncmp(str, "/etc/", 5))
1076 if (!strcmp(str, "/usr/lib/sendmail"))
1098 di_nextarrayelement,
1103 di_nextsolvableattr,
1108 /* see repo.h for documentation */
1110 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
1112 memset(di, 0, sizeof(*di));
1114 di->flags = flags & ~SEARCH_THISSOLVID;
1115 if (!pool || (repo && repo->pool != pool))
1123 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1129 di->keyname = keyname;
1130 di->keynames[0] = keyname;
1131 dataiterator_set_search(di, repo, p);
1136 dataiterator_init_clone(Dataiterator *di, Dataiterator *from)
1139 memset(&di->matcher, 0, sizeof(di->matcher));
1140 if (from->matcher.match)
1141 datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags);
1146 for (i = 1; i < di->nparents; i++)
1147 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1148 di->kv.parent = &di->parents[di->nparents - 1].kv;
1153 dataiterator_set_match(Dataiterator *di, const char *match, int flags)
1155 di->flags = (flags & ~SEARCH_THISSOLVID) | (di->flags & SEARCH_THISSOLVID);
1156 datamatcher_free(&di->matcher);
1157 memset(&di->matcher, 0, sizeof(di->matcher));
1161 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1171 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
1175 di->flags &= ~SEARCH_THISSOLVID;
1179 if (!di->pool->nrepos)
1187 di->repo = di->pool->repos[0];
1189 di->state = di_enterrepo;
1191 dataiterator_jump_to_solvid(di, p);
1195 dataiterator_set_keyname(Dataiterator *di, Id keyname)
1198 di->keyname = keyname;
1199 di->keynames[0] = keyname;
1203 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1207 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1209 di->state = di_bye; /* sorry */
1212 for (i = di->nkeynames + 1; i > 0; i--)
1213 di->keynames[i] = di->keynames[i - 1];
1214 di->keynames[0] = di->keyname = keyname;
1219 dataiterator_free(Dataiterator *di)
1221 if (di->matcher.match)
1222 datamatcher_free(&di->matcher);
1225 static inline unsigned char *
1226 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1228 Id *keyp = di->keyp;
1229 Repokey *keys = di->data->keys;
1232 for (keyp = di->keyp; *keyp; keyp++)
1233 if (keys[*keyp].name == keyname)
1237 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1245 dataiterator_filelistcheck(Dataiterator *di)
1248 int needcomplete = 0;
1249 Repodata *data = di->data;
1251 if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
1252 if (!di->matcher.match
1253 || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
1254 && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)
1255 || !repodata_filelistfilter_matches(di->data, di->matcher.match))
1257 if (data->state != REPODATA_AVAILABLE)
1258 return needcomplete ? 1 : 0;
1259 for (j = 1; j < data->nkeys; j++)
1260 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
1262 return j == data->nkeys && !needcomplete ? 0 : 1;
1266 dataiterator_step(Dataiterator *di)
1274 case di_enterrepo: di_enterrepo:
1277 if (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS))
1279 if (!(di->flags & SEARCH_THISSOLVID))
1281 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1282 goto di_nextsolvable;
1286 case di_entersolvable: di_entersolvable:
1287 if (di->repodataid >= 0)
1289 di->repodataid = 0; /* reset repodata iterator */
1290 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)
1292 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1294 goto di_entersolvablekey;
1299 case di_enterrepodata: di_enterrepodata:
1300 if (di->repodataid >= 0)
1302 if (di->repodataid >= di->repo->nrepodata)
1303 goto di_nextsolvable;
1304 di->data = di->repo->repodata + di->repodataid;
1306 if (di->repodataid >= 0 && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
1307 goto di_nextrepodata;
1308 if (!maybe_load_repodata(di->data, di->keyname))
1309 goto di_nextrepodata;
1310 di->dp = solvid2data(di->data, di->solvid, &schema);
1312 goto di_nextrepodata;
1313 if (di->solvid == SOLVID_POS)
1314 di->solvid = di->pool->pos.solvid;
1315 /* reset key iterator */
1316 di->keyp = di->data->schemadata + di->data->schemata[schema];
1319 case di_enterschema: di_enterschema:
1321 di->dp = dataiterator_find_keyname(di, di->keyname);
1322 if (!di->dp || !*di->keyp)
1326 goto di_nextrepodata;
1330 case di_enterkey: di_enterkey:
1332 di->key = di->data->keys + *di->keyp;
1333 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1336 if (di->key->type == REPOKEY_TYPE_DELETED)
1338 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1340 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1346 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1348 di->state = di_nextkey;
1350 di->state = di_nextattr;
1353 case di_nextkey: di_nextkey:
1354 if (!di->keyname && *++di->keyp)
1360 case di_nextrepodata: di_nextrepodata:
1361 if (di->repodataid >= 0 && ++di->repodataid < di->repo->nrepodata)
1362 goto di_enterrepodata;
1365 case di_nextsolvable: di_nextsolvable:
1366 if (!(di->flags & SEARCH_THISSOLVID))
1369 di->solvid = di->repo->start;
1372 for (; di->solvid < di->repo->end; di->solvid++)
1374 if (di->pool->solvables[di->solvid].repo == di->repo)
1375 goto di_entersolvable;
1380 case di_nextrepo: di_nextrepo:
1381 if (di->repoid >= 0)
1385 if (di->repoid < di->pool->nrepos)
1387 di->repo = di->pool->repos[di->repoid];
1393 case di_bye: di_bye:
1397 case di_enterarray: di_enterarray:
1398 if (di->key->name == REPOSITORY_SOLVABLES)
1400 di->ddp = data_read_id(di->ddp, &di->kv.num);
1405 case di_nextarrayelement: di_nextarrayelement:
1408 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1409 if (di->kv.entry == di->kv.num)
1411 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1413 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1415 di->kv.str = (char *)di->ddp;
1417 di->state = di_nextkey;
1420 if (di->kv.entry == di->kv.num - 1)
1422 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1423 di->ddp = data_read_id(di->ddp, &di->kv.id);
1424 di->kv.str = (char *)di->ddp;
1425 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1427 if ((di->flags & SEARCH_SUB) != 0)
1428 di->state = di_entersub;
1430 di->state = di_nextarrayelement;
1433 case di_entersub: di_entersub:
1434 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1435 goto di_nextarrayelement; /* sorry, full */
1436 di->parents[di->nparents].kv = di->kv;
1437 di->parents[di->nparents].dp = di->dp;
1438 di->parents[di->nparents].keyp = di->keyp;
1439 di->dp = (unsigned char *)di->kv.str;
1440 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1441 memset(&di->kv, 0, sizeof(di->kv));
1442 di->kv.parent = &di->parents[di->nparents].kv;
1444 di->keyname = di->keynames[di->nparents - di->rootlevel];
1445 goto di_enterschema;
1447 case di_leavesub: di_leavesub:
1448 if (di->nparents - 1 < di->rootlevel)
1451 di->dp = di->parents[di->nparents].dp;
1452 di->kv = di->parents[di->nparents].kv;
1453 di->keyp = di->parents[di->nparents].keyp;
1454 di->key = di->data->keys + *di->keyp;
1455 di->ddp = (unsigned char *)di->kv.str;
1456 di->keyname = di->keynames[di->nparents - di->rootlevel];
1457 goto di_nextarrayelement;
1459 /* special solvable attr handling follows */
1461 case di_nextsolvableattr:
1462 di->kv.id = *di->idp++;
1467 di->state = di_nextsolvablekey;
1471 case di_nextsolvablekey: di_nextsolvablekey:
1472 if (di->keyname || di->key->name == RPM_RPMDBID)
1473 goto di_enterrepodata;
1477 case di_entersolvablekey: di_entersolvablekey:
1478 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1479 if (!di->idp || !di->idp[0])
1480 goto di_nextsolvablekey;
1481 di->kv.id = di->idp[0];
1482 di->kv.num = di->idp[0];
1484 if (!di->kv.eof && !di->idp[0])
1488 di->state = di_nextsolvablekey;
1490 di->state = di_nextsolvableattr;
1494 if (di->matcher.match)
1496 /* simple pre-check so that we don't need to stringify */
1497 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))
1499 int l = strlen(di->matcher.match) - strlen(di->kv.str);
1500 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
1503 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1505 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1509 if (!datamatcher_match(&di->matcher, di->kv.str))
1512 /* found something! */
1518 dataiterator_entersub(Dataiterator *di)
1520 if (di->state == di_nextarrayelement)
1521 di->state = di_entersub;
1525 dataiterator_setpos(Dataiterator *di)
1527 if (di->kv.eof == 2)
1529 pool_clear_pos(di->pool);
1532 di->pool->pos.solvid = di->solvid;
1533 di->pool->pos.repo = di->repo;
1534 di->pool->pos.repodataid = di->data - di->repo->repodata;
1535 di->pool->pos.schema = di->kv.id;
1536 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1540 dataiterator_setpos_parent(Dataiterator *di)
1542 if (!di->kv.parent || di->kv.parent->eof == 2)
1544 pool_clear_pos(di->pool);
1547 di->pool->pos.solvid = di->solvid;
1548 di->pool->pos.repo = di->repo;
1549 di->pool->pos.repodataid = di->data - di->repo->repodata;
1550 di->pool->pos.schema = di->kv.parent->id;
1551 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1554 /* clones just the position, not the search keys/matcher */
1556 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
1558 di->state = from->state;
1559 di->flags &= ~SEARCH_THISSOLVID;
1560 di->flags |= (from->flags & SEARCH_THISSOLVID);
1561 di->repo = from->repo;
1562 di->data = from->data;
1564 di->ddp = from->ddp;
1565 di->idp = from->idp;
1566 di->keyp = from->keyp;
1567 di->key = from->key;
1569 di->repodataid = from->repodataid;
1570 di->solvid = from->solvid;
1571 di->repoid = from->repoid;
1572 di->rootlevel = from->rootlevel;
1573 memcpy(di->parents, from->parents, sizeof(from->parents));
1574 di->nparents = from->nparents;
1578 for (i = 1; i < di->nparents; i++)
1579 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1580 di->kv.parent = &di->parents[di->nparents - 1].kv;
1585 dataiterator_seek(Dataiterator *di, int whence)
1587 if ((whence & DI_SEEK_STAY) != 0)
1588 di->rootlevel = di->nparents;
1589 switch (whence & ~DI_SEEK_STAY)
1592 if (di->state != di_nextarrayelement)
1594 if ((whence & DI_SEEK_STAY) != 0)
1595 di->rootlevel = di->nparents + 1; /* XXX: dangerous! */
1596 di->state = di_entersub;
1598 case DI_SEEK_PARENT:
1605 if (di->rootlevel > di->nparents)
1606 di->rootlevel = di->nparents;
1607 di->dp = di->parents[di->nparents].dp;
1608 di->kv = di->parents[di->nparents].kv;
1609 di->keyp = di->parents[di->nparents].keyp;
1610 di->key = di->data->keys + *di->keyp;
1611 di->ddp = (unsigned char *)di->kv.str;
1612 di->keyname = di->keynames[di->nparents - di->rootlevel];
1613 di->state = di_nextarrayelement;
1615 case DI_SEEK_REWIND:
1621 di->dp = (unsigned char *)di->kv.parent->str;
1622 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
1623 di->state = di_enterschema;
1631 dataiterator_skip_attribute(Dataiterator *di)
1633 if (di->state == di_nextsolvableattr)
1634 di->state = di_nextsolvablekey;
1636 di->state = di_nextkey;
1640 dataiterator_skip_solvable(Dataiterator *di)
1645 di->keyname = di->keynames[0];
1646 di->state = di_nextsolvable;
1650 dataiterator_skip_repo(Dataiterator *di)
1655 di->keyname = di->keynames[0];
1656 di->state = di_nextrepo;
1660 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1665 di->keyname = di->keynames[0];
1666 if (solvid == SOLVID_POS)
1668 di->repo = di->pool->pos.repo;
1675 di->data = di->repo->repodata + di->pool->pos.repodataid;
1676 di->repodataid = -1;
1677 di->solvid = solvid;
1678 di->state = di_enterrepo;
1679 di->flags |= SEARCH_THISSOLVID;
1684 di->repo = di->pool->solvables[solvid].repo;
1687 else if (di->repoid >= 0)
1689 if (!di->pool->nrepos)
1694 di->repo = di->pool->repos[0];
1698 di->solvid = solvid;
1700 di->flags |= SEARCH_THISSOLVID;
1701 di->state = di_enterrepo;
1705 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1714 di->flags &= ~SEARCH_THISSOLVID;
1715 di->state = di_enterrepo;
1719 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1721 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1725 return datamatcher_match(ma, di->kv.str);
1728 /************************************************************************
1729 * data modify functions
1732 /* extend repodata so that it includes solvables p */
1734 repodata_extend(Repodata *data, Id p)
1736 if (data->start == data->end)
1737 data->start = data->end = p;
1740 int old = data->end - data->start;
1741 int new = p - data->end + 1;
1744 data->attrs = sat_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1745 memset(data->attrs + old, 0, new * sizeof(Id *));
1747 data->incoreoffset = sat_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1748 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1751 if (p < data->start)
1753 int old = data->end - data->start;
1754 int new = data->start - p;
1757 data->attrs = sat_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1758 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1759 memset(data->attrs, 0, new * sizeof(Id *));
1761 data->incoreoffset = sat_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1762 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1763 memset(data->incoreoffset, 0, new * sizeof(Id));
1768 /* shrink end of repodata */
1770 repodata_shrink(Repodata *data, int end)
1774 if (data->end <= end)
1776 if (data->start >= end)
1780 for (i = 0; i < data->end - data->start; i++)
1781 sat_free(data->attrs[i]);
1782 data->attrs = sat_free(data->attrs);
1784 data->incoreoffset = sat_free(data->incoreoffset);
1785 data->start = data->end = 0;
1790 for (i = end; i < data->end; i++)
1791 sat_free(data->attrs[i - data->start]);
1792 data->attrs = sat_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
1794 if (data->incoreoffset)
1795 data->incoreoffset = sat_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
1799 /* extend repodata so that it includes solvables from start to start + num - 1 */
1801 repodata_extend_block(Repodata *data, Id start, Id num)
1805 if (!data->incoreoffset)
1807 data->incoreoffset = sat_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1808 data->start = start;
1809 data->end = start + num;
1812 repodata_extend(data, start);
1814 repodata_extend(data, start + num - 1);
1817 /**********************************************************************/
1820 #define REPODATA_ATTRS_BLOCK 31
1821 #define REPODATA_ATTRDATA_BLOCK 1023
1822 #define REPODATA_ATTRIDDATA_BLOCK 63
1826 repodata_new_handle(Repodata *data)
1830 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1833 data->xattrs = sat_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1834 data->xattrs[data->nxattrs] = 0;
1835 return -(data->nxattrs++);
1839 repodata_get_attrp(Repodata *data, Id handle)
1841 if (handle == SOLVID_META)
1845 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1850 return data->xattrs - handle;
1851 if (handle < data->start || handle >= data->end)
1852 repodata_extend(data, handle);
1854 data->attrs = sat_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1855 return data->attrs + (handle - data->start);
1859 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1865 app = repodata_get_attrp(data, handle);
1870 /* Determine equality based on the name only, allows us to change
1871 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1872 for (pp = ap; *pp; pp += 2)
1873 if (data->keys[*pp].name == data->keys[keyid].name)
1877 if (overwrite || data->keys[*pp].type == REPOKEY_TYPE_DELETED)
1886 ap = sat_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1896 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1900 keyid = repodata_key2id(data, key, 1);
1901 repodata_insert_keyid(data, solvid, keyid, val, 1);
1905 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1909 key.type = REPOKEY_TYPE_ID;
1911 key.storage = KEY_STORAGE_INCORE;
1912 repodata_set(data, solvid, &key, id);
1916 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1920 key.type = REPOKEY_TYPE_NUM;
1922 key.storage = KEY_STORAGE_INCORE;
1923 repodata_set(data, solvid, &key, (Id)num);
1927 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
1931 if (data->localpool)
1932 id = stringpool_str2id(&data->spool, str, 1);
1934 id = str2id(data->repo->pool, str, 1);
1936 key.type = REPOKEY_TYPE_ID;
1938 key.storage = KEY_STORAGE_INCORE;
1939 repodata_set(data, solvid, &key, id);
1943 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
1947 key.type = REPOKEY_TYPE_CONSTANT;
1948 key.size = constant;
1949 key.storage = KEY_STORAGE_INCORE;
1950 repodata_set(data, solvid, &key, 0);
1954 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
1958 key.type = REPOKEY_TYPE_CONSTANTID;
1960 key.storage = KEY_STORAGE_INCORE;
1961 repodata_set(data, solvid, &key, 0);
1965 repodata_set_void(Repodata *data, Id solvid, Id keyname)
1969 key.type = REPOKEY_TYPE_VOID;
1971 key.storage = KEY_STORAGE_INCORE;
1972 repodata_set(data, solvid, &key, 0);
1976 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
1981 l = strlen(str) + 1;
1983 key.type = REPOKEY_TYPE_STR;
1985 key.storage = KEY_STORAGE_INCORE;
1986 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1987 memcpy(data->attrdata + data->attrdatalen, str, l);
1988 repodata_set(data, solvid, &key, data->attrdatalen);
1989 data->attrdatalen += l;
1993 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
1999 key.type = REPOKEY_TYPE_BINARY;
2001 key.storage = KEY_STORAGE_INCORE;
2002 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
2003 dp = data->attrdata + data->attrdatalen;
2004 if (len >= (1 << 14))
2006 if (len >= (1 << 28))
2007 *dp++ = (len >> 28) | 128;
2008 if (len >= (1 << 21))
2009 *dp++ = (len >> 21) | 128;
2010 *dp++ = (len >> 14) | 128;
2012 if (len >= (1 << 7))
2013 *dp++ = (len >> 7) | 128;
2016 memcpy(dp, buf, len);
2017 repodata_set(data, solvid, &key, data->attrdatalen);
2018 data->attrdatalen = dp + len - data->attrdata;
2021 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
2022 * so that the caller can append entrysize new elements plus the termination zero there */
2024 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
2027 Id *ida, *pp, **ppp;
2029 /* check if it is the same as last time, this speeds things up a lot */
2030 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
2032 /* great! just append the new data */
2033 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2034 data->attriddatalen--; /* overwrite terminating 0 */
2035 data->lastdatalen += entrysize;
2039 ppp = repodata_get_attrp(data, handle);
2043 for (; *pp; pp += 2)
2044 if (data->keys[*pp].name == keyname)
2047 if (!pp || !*pp || data->keys[*pp].type != keytype)
2049 /* not found. allocate new key */
2055 key.storage = KEY_STORAGE_INCORE;
2056 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2057 keyid = repodata_key2id(data, &key, 1);
2058 repodata_insert_keyid(data, handle, keyid, data->attriddatalen, 1);
2059 data->lasthandle = handle;
2060 data->lastkey = keyid;
2061 data->lastdatalen = data->attriddatalen + entrysize + 1;
2065 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
2066 oldsize += entrysize;
2067 if (ida + 1 == data->attriddata + data->attriddatalen)
2069 /* this was the last entry, just append it */
2070 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2071 data->attriddatalen--; /* overwrite terminating 0 */
2075 /* too bad. move to back. */
2076 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2077 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
2078 pp[1] = data->attriddatalen;
2079 data->attriddatalen += oldsize;
2081 data->lasthandle = handle;
2082 data->lastkey = *pp;
2083 data->lastdatalen = data->attriddatalen + entrysize + 1;
2087 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2088 const unsigned char *str)
2093 if (!(l = sat_chksum_len(type)))
2098 key.storage = KEY_STORAGE_INCORE;
2099 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2100 memcpy(data->attrdata + data->attrdatalen, str, l);
2101 repodata_set(data, solvid, &key, data->attrdatalen);
2102 data->attrdatalen += l;
2106 hexstr2bytes(unsigned char *buf, const char *str, int buflen)
2109 for (i = 0; i < buflen; i++)
2111 #define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
2112 : ((c)>='a' && (c)<='f') ? ((c)-('a'-10)) \
2113 : ((c)>='A' && (c)<='F') ? ((c)-('A'-10)) \
2124 buf[i] = (buf[i] << 4) | v;
2131 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2134 unsigned char buf[64];
2137 if (!(l = sat_chksum_len(type)))
2139 if (hexstr2bytes(buf, str, l) != l)
2141 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2145 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2150 if (!(l = sat_chksum_len(type)))
2152 s = str = pool_alloctmpspace(data->repo->pool, 2 * l + 1);
2153 for (i = 0; i < l; i++)
2155 unsigned char v = buf[i];
2156 unsigned char w = v >> 4;
2157 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
2159 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
2165 /* rpm filenames don't contain the epoch, so strip it */
2166 static inline const char *
2167 evrid2vrstr(Pool *pool, Id evrid)
2169 const char *p, *evr = id2str(pool, evrid);
2172 for (p = evr; *p >= '0' && *p <= '9'; p++)
2174 return p != evr && *p == ':' ? p + 1 : evr;
2178 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2180 Pool *pool = data->repo->pool;
2182 const char *str, *fp;
2186 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2189 if ((dir = strrchr(file, '/')) != 0)
2200 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2205 if (l == 1 && dir[0] == '.')
2207 s = pool->solvables + solvid;
2210 str = id2str(pool, s->arch);
2211 if (!strncmp(dir, str, l) && !str[l])
2212 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2214 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2217 char *dir2 = strdup(dir);
2219 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2224 str = id2str(pool, s->name);
2226 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2229 str = evrid2vrstr(pool, s->evr);
2231 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2234 str = id2str(pool, s->arch);
2236 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2238 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2243 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2247 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2251 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2253 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2254 data->attriddata[data->attriddatalen++] = dir;
2255 data->attriddata[data->attriddatalen++] = num;
2256 data->attriddata[data->attriddatalen++] = num2;
2257 data->attriddata[data->attriddatalen++] = 0;
2261 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2267 l = strlen(str) + 1;
2268 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2269 memcpy(data->attrdata + data->attrdatalen, str, l);
2270 stroff = data->attrdatalen;
2271 data->attrdatalen += l;
2274 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2276 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2277 data->attriddata[data->attriddatalen++] = dir;
2278 data->attriddata[data->attriddatalen++] = stroff;
2279 data->attriddata[data->attriddatalen++] = 0;
2283 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2286 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2288 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2289 data->attriddata[data->attriddatalen++] = id;
2290 data->attriddata[data->attriddatalen++] = 0;
2294 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2298 if (data->localpool)
2299 id = stringpool_str2id(&data->spool, str, 1);
2301 id = str2id(data->repo->pool, str, 1);
2302 repodata_add_idarray(data, solvid, keyname, id);
2306 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2308 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2309 data->attriddata[data->attriddatalen++] = ghandle;
2310 data->attriddata[data->attriddatalen++] = 0;
2314 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2316 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2317 data->attriddata[data->attriddatalen++] = ghandle;
2318 data->attriddata[data->attriddatalen++] = 0;
2322 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2325 app = repodata_get_attrp(data, solvid);
2329 for (; *ap; ap += 2)
2330 if (data->keys[*ap].name == keyname)
2336 for (; *ap; ap += 2)
2338 if (data->keys[*ap].name == keyname)
2346 /* XXX: does not work correctly, needs fix in iterators! */
2348 repodata_delete(Repodata *data, Id solvid, Id keyname)
2352 key.type = REPOKEY_TYPE_DELETED;
2354 key.storage = KEY_STORAGE_INCORE;
2355 repodata_set(data, solvid, &key, 0);
2358 /* add all (uninternalized) attrs from src to dest */
2360 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2363 if (dest == src || !(keyp = data->attrs[src - data->start]))
2365 for (; *keyp; keyp += 2)
2366 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2369 /* add some (uninternalized) attrs from src to dest */
2371 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2374 if (dest == src || !(keyp = data->attrs[src - data->start]))
2376 for (; *keyp; keyp += 2)
2377 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2378 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2383 /**********************************************************************/
2385 /* TODO: unify with repo_write and repo_solv! */
2387 #define EXTDATA_BLOCK 1023
2395 data_addid(struct extdata *xd, Id x)
2399 xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2400 dp = xd->buf + xd->len;
2405 *dp++ = (x >> 28) | 128;
2407 *dp++ = (x >> 21) | 128;
2408 *dp++ = (x >> 14) | 128;
2411 *dp++ = (x >> 7) | 128;
2413 xd->len = dp - xd->buf;
2417 data_addideof(struct extdata *xd, Id x, int eof)
2420 x = (x & 63) | ((x & ~63) << 1);
2421 data_addid(xd, (eof ? x : x | 64));
2425 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2427 xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2428 memcpy(xd->buf + xd->len, blob, len);
2432 /*********************************/
2435 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2436 struct extdata *newvincore,
2438 Repokey *key, Id val)
2440 /* Otherwise we have a new value. Parse it into the internal
2444 unsigned int oldvincorelen = 0;
2448 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2451 oldvincorelen = xd->len;
2455 case REPOKEY_TYPE_VOID:
2456 case REPOKEY_TYPE_CONSTANT:
2457 case REPOKEY_TYPE_CONSTANTID:
2459 case REPOKEY_TYPE_STR:
2460 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2462 case REPOKEY_TYPE_MD5:
2463 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2465 case REPOKEY_TYPE_SHA1:
2466 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2468 case REPOKEY_TYPE_SHA256:
2469 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2471 case REPOKEY_TYPE_ID:
2472 case REPOKEY_TYPE_NUM:
2473 case REPOKEY_TYPE_DIR:
2474 data_addid(xd, val);
2476 case REPOKEY_TYPE_BINARY:
2479 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2481 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2484 case REPOKEY_TYPE_IDARRAY:
2485 for (ida = data->attriddata + val; *ida; ida++)
2486 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2488 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2489 for (ida = data->attriddata + val; *ida; ida += 3)
2491 data_addid(xd, ida[0]);
2492 data_addid(xd, ida[1]);
2493 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2496 case REPOKEY_TYPE_DIRSTRARRAY:
2497 for (ida = data->attriddata + val; *ida; ida += 2)
2499 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2500 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2503 case REPOKEY_TYPE_FIXARRAY:
2507 for (ida = data->attriddata + val; *ida; ida++)
2510 fprintf(stderr, "serialize struct %d\n", *ida);
2513 Id *kp = data->xattrs[-*ida];
2520 fprintf(stderr, " %s:%d\n", id2str(data->repo->pool, data->keys[*kp].name), kp[1]);
2526 schemaid = repodata_schema2id(data, schema, 1);
2527 else if (schemaid != repodata_schema2id(data, schema, 0))
2529 pool_debug(data->repo->pool, SAT_FATAL, "fixarray substructs with different schemas\n");
2533 fprintf(stderr, " schema %d\n", schemaid);
2538 data_addid(xd, num);
2539 data_addid(xd, schemaid);
2540 for (ida = data->attriddata + val; *ida; ida++)
2542 Id *kp = data->xattrs[-*ida];
2547 repodata_serialize_key(data, newincore, newvincore,
2548 schema, data->keys + *kp, kp[1]);
2553 case REPOKEY_TYPE_FLEXARRAY:
2556 for (ida = data->attriddata + val; *ida; ida++)
2558 data_addid(xd, num);
2559 for (ida = data->attriddata + val; *ida; ida++)
2561 Id *kp = data->xattrs[-*ida];
2564 data_addid(xd, 0); /* XXX */
2571 schemaid = repodata_schema2id(data, schema, 1);
2572 data_addid(xd, schemaid);
2573 kp = data->xattrs[-*ida];
2576 repodata_serialize_key(data, newincore, newvincore,
2577 schema, data->keys + *kp, kp[1]);
2583 pool_debug(data->repo->pool, SAT_FATAL, "don't know how to handle type %d\n", key->type);
2586 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2588 /* put offset/len in incore */
2589 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2590 oldvincorelen = xd->len - oldvincorelen;
2591 data_addid(newincore, oldvincorelen);
2596 repodata_internalize(Repodata *data)
2598 Repokey *key, solvkey;
2600 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2601 unsigned char *dp, *ndp;
2602 int newschema, oldcount;
2603 struct extdata newincore;
2604 struct extdata newvincore;
2607 if (!data->attrs && !data->xattrs)
2610 newvincore.buf = data->vincore;
2611 newvincore.len = data->vincorelen;
2613 /* find the solvables key, create if needed */
2614 memset(&solvkey, 0, sizeof(solvkey));
2615 solvkey.name = REPOSITORY_SOLVABLES;
2616 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2618 solvkey.storage = KEY_STORAGE_INCORE;
2619 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2621 schema = sat_malloc2(data->nkeys, sizeof(Id));
2622 seen = sat_malloc2(data->nkeys, sizeof(Id));
2624 /* Merge the data already existing (in data->schemata, ->incoredata and
2625 friends) with the new attributes in data->attrs[]. */
2626 nentry = data->end - data->start;
2627 memset(&newincore, 0, sizeof(newincore));
2628 data_addid(&newincore, 0); /* start data at offset 1 */
2630 data->mainschema = 0;
2631 data->mainschemaoffsets = sat_free(data->mainschemaoffsets);
2633 /* join entry data */
2634 /* we start with the meta data, entry -1 */
2635 for (entry = -1; entry < nentry; entry++)
2637 memset(seen, 0, data->nkeys * sizeof(Id));
2639 dp = data->incoredata;
2642 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2643 dp = data_read_id(dp, &oldschema);
2646 fprintf(stderr, "oldschema %d\n", oldschema);
2647 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2648 fprintf(stderr, "schemadata %p\n", data->schemadata);
2650 /* seen: -1: old data 0: skipped >0: id + 1 */
2654 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2658 pool_debug(data->repo->pool, SAT_FATAL, "Inconsistent old data (key occured twice).\n");
2666 keyp = data->attrs ? data->attrs[entry] : 0;
2669 /* strip solvables key */
2671 for (sp = keyp = schema; *sp; sp++)
2672 if (*sp != solvkeyid)
2677 seen[solvkeyid] = 0;
2678 keyp = data->xattrs ? data->xattrs[1] : 0;
2681 for (; *keyp; keyp += 2)
2688 seen[*keyp] = keyp[1] + 1;
2690 if (entry < 0 && data->end != data->start)
2697 /* Ideally we'd like to sort the new schema here, to ensure
2698 schema equality independend of the ordering. We can't do that
2699 yet. For once see below (old ids need to come before new ids).
2700 An additional difficulty is that we also need to move
2701 the values with the keys. */
2702 schemaid = repodata_schema2id(data, schema, 1);
2704 schemaid = oldschema;
2707 /* Now create data blob. We walk through the (possibly new) schema
2708 and either copy over old data, or insert the new. */
2709 /* XXX Here we rely on the fact that the (new) schema has the form
2710 o1 o2 o3 o4 ... | n1 n2 n3 ...
2711 (oX being the old keyids (possibly overwritten), and nX being
2712 the new keyids). This rules out sorting the keyids in order
2713 to ensure a small schema count. */
2715 data->incoreoffset[entry] = newincore.len;
2716 data_addid(&newincore, schemaid);
2719 data->mainschema = schemaid;
2720 data->mainschemaoffsets = sat_calloc(sp - schema, sizeof(Id));
2722 keypstart = data->schemadata + data->schemata[schemaid];
2723 for (keyp = keypstart; *keyp; keyp++)
2726 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2727 if (*keyp == solvkeyid)
2729 /* add flexarray entry count */
2730 data_addid(&newincore, data->end - data->start);
2733 key = data->keys + *keyp;
2735 fprintf(stderr, "internalize %d(%d):%s:%s\n", entry, entry + data->start, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
2740 /* Skip the data associated with this old key. */
2741 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2743 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2744 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2746 else if (key->storage == KEY_STORAGE_INCORE)
2747 ndp = data_skip_key(data, dp, key);
2750 if (seen[*keyp] == -1)
2752 /* If this key was an old one _and_ was not overwritten with
2753 a different value copy over the old value (we skipped it
2756 data_addblob(&newincore, dp, ndp - dp);
2759 else if (seen[*keyp])
2761 /* Otherwise we have a new value. Parse it into the internal
2763 repodata_serialize_key(data, &newincore, &newvincore,
2764 schema, key, seen[*keyp] - 1);
2768 if (entry >= 0 && data->attrs && data->attrs[entry])
2769 data->attrs[entry] = sat_free(data->attrs[entry]);
2771 /* free all xattrs */
2772 for (entry = 0; entry < data->nxattrs; entry++)
2773 if (data->xattrs[entry])
2774 sat_free(data->xattrs[entry]);
2775 data->xattrs = sat_free(data->xattrs);
2778 data->lasthandle = 0;
2780 data->lastdatalen = 0;
2783 repodata_free_schemahash(data);
2785 sat_free(data->incoredata);
2786 data->incoredata = newincore.buf;
2787 data->incoredatalen = newincore.len;
2788 data->incoredatafree = 0;
2790 sat_free(data->vincore);
2791 data->vincore = newvincore.buf;
2792 data->vincorelen = newvincore.len;
2794 data->attrs = sat_free(data->attrs);
2795 data->attrdata = sat_free(data->attrdata);
2796 data->attriddata = sat_free(data->attriddata);
2797 data->attrdatalen = 0;
2798 data->attriddatalen = 0;
2802 repodata_disable_paging(Repodata *data)
2804 if (maybe_load_repodata(data, 0))
2805 repopagestore_disable_paging(&data->store);
2809 repodata_load_stub(Repodata *data)
2811 Repo *repo = data->repo;
2812 Pool *pool = repo->pool;
2815 if (!pool->loadcallback)
2817 data->state = REPODATA_ERROR;
2820 data->state = REPODATA_LOADING;
2821 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2822 data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
2826 repodata_create_stubs(Repodata *data)
2828 Repo *repo = data->repo;
2829 Pool *pool = repo->pool;
2836 int datastart, dataend;
2838 repodataid = data - repo->repodata;
2839 datastart = data->start;
2840 dataend = data->end;
2841 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2842 while (dataiterator_step(&di))
2844 if (di.data - repo->repodata != repodataid)
2848 dataiterator_free(&di);
2851 stubdataids = sat_calloc(cnt, sizeof(*stubdataids));
2852 for (i = 0; i < cnt; i++)
2854 sdata = repo_add_repodata(repo, 0);
2855 if (dataend > datastart)
2856 repodata_extend_block(sdata, datastart, dataend - datastart);
2857 stubdataids[i] = sdata - repo->repodata;
2858 sdata->state = REPODATA_STUB;
2859 sdata->loadcallback = repodata_load_stub;
2862 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2864 while (dataiterator_step(&di))
2866 if (di.data - repo->repodata != repodataid)
2868 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
2870 dataiterator_entersub(&di);
2871 sdata = repo->repodata + stubdataids[i++];
2875 switch (di.key->type)
2877 case REPOKEY_TYPE_ID:
2878 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
2880 case REPOKEY_TYPE_CONSTANTID:
2881 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
2883 case REPOKEY_TYPE_STR:
2884 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
2886 case REPOKEY_TYPE_VOID:
2887 repodata_set_void(sdata, SOLVID_META, di.key->name);
2889 case REPOKEY_TYPE_NUM:
2890 repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num);
2892 case REPOKEY_TYPE_MD5:
2893 case REPOKEY_TYPE_SHA1:
2894 case REPOKEY_TYPE_SHA256:
2895 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
2897 case REPOKEY_TYPE_IDARRAY:
2898 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
2899 if (di.key->name == REPOSITORY_KEYS)
2906 xkeyname = di.kv.id;
2909 xkey.name = xkeyname;
2910 xkey.type = di.kv.id;
2911 xkey.storage = KEY_STORAGE_INCORE;
2913 repodata_key2id(sdata, &xkey, 1);
2920 dataiterator_free(&di);
2921 for (i = 0; i < cnt; i++)
2922 repodata_internalize(repo->repodata + stubdataids[i]);
2923 sat_free(stubdataids);
2927 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: