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 repodata_localize_id(Repodata *data, Id id, int create)
711 if (!id || !data || !data->localpool)
713 return stringpool_str2id(&data->spool, id2str(data->repo->pool, id), create);
717 /************************************************************************
723 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
727 case REPOKEY_TYPE_ID:
728 case REPOKEY_TYPE_CONSTANTID:
729 case REPOKEY_TYPE_IDARRAY:
730 if (data && data->localpool)
731 kv->str = stringpool_id2str(&data->spool, kv->id);
733 kv->str = id2str(pool, kv->id);
734 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
737 for (s = kv->str; *s >= 'a' && *s <= 'z'; s++)
739 if (*s == ':' && s > kv->str)
743 case REPOKEY_TYPE_STR:
745 case REPOKEY_TYPE_DIRSTRARRAY:
746 if (!(flags & SEARCH_FILES))
747 return 1; /* match just the basename */
748 /* Put the full filename into kv->str. */
749 kv->str = repodata_dir2str(data, kv->id, kv->str);
750 /* And to compensate for that put the "empty" directory into
751 kv->id, so that later calls to repodata_dir2str on this data
752 come up with the same filename again. */
755 case REPOKEY_TYPE_MD5:
756 case REPOKEY_TYPE_SHA1:
757 case REPOKEY_TYPE_SHA256:
758 if (!(flags & SEARCH_CHECKSUMS))
759 return 0; /* skip em */
760 kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str);
768 struct subschema_data {
774 /* search a specific repodata */
776 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
780 Id keyid, *kp, *keyp;
781 unsigned char *dp, *ddp;
787 if (!maybe_load_repodata(data, keyname))
789 if (solvid == SOLVID_SUBSCHEMA)
791 struct subschema_data *subd = cbdata;
792 cbdata = subd->cbdata;
794 schema = subd->parent->id;
795 dp = (unsigned char *)subd->parent->str;
796 kv.parent = subd->parent;
801 dp = solvid2data(data, solvid, &schema);
804 s = data->repo->pool->solvables + solvid;
807 keyp = data->schemadata + data->schemata[schema];
810 /* search for a specific key */
811 for (kp = keyp; *kp; kp++)
812 if (data->keys[*kp].name == keyname)
816 dp = forward_to_key(data, *kp, keyp, dp);
822 while ((keyid = *keyp++) != 0)
825 key = data->keys + keyid;
826 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
828 if (key->type == REPOKEY_TYPE_DELETED)
830 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
832 struct subschema_data subd;
836 subd.cbdata = cbdata;
839 ddp = data_read_id(ddp, &nentries);
843 while (ddp && nentries > 0)
847 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
848 ddp = data_read_id(ddp, &schema);
850 kv.str = (char *)ddp;
851 stop = callback(cbdata, s, data, key, &kv);
852 if (stop > SEARCH_NEXT_KEY)
854 if (stop && stop != SEARCH_ENTERSUB)
856 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
857 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
858 ddp = data_skip_schema(data, ddp, schema);
861 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
865 kv.str = (char *)ddp;
866 stop = callback(cbdata, s, data, key, &kv);
867 if (stop > SEARCH_NEXT_KEY)
877 ddp = data_fetch(ddp, &kv, key);
880 stop = callback(cbdata, s, data, key, &kv);
883 while (!kv.eof && !stop);
884 if (onekey || stop > SEARCH_NEXT_KEY)
890 repodata_setpos_kv(Repodata *data, KeyValue *kv)
892 Pool *pool = data->repo->pool;
894 pool_clear_pos(pool);
897 pool->pos.repo = data->repo;
898 pool->pos.repodataid = data - data->repo->repodata;
899 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
900 pool->pos.schema = kv->id;
904 /************************************************************************
905 * data iterator functions
908 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
909 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
910 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
911 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
912 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
913 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
914 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
915 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
916 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
917 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
918 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
919 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
920 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
921 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
925 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
939 case SOLVABLE_VENDOR:
942 case SOLVABLE_PROVIDES:
944 return s->provides ? s->repo->idarraydata + s->provides : 0;
945 case SOLVABLE_OBSOLETES:
947 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
948 case SOLVABLE_CONFLICTS:
950 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
951 case SOLVABLE_REQUIRES:
953 return s->requires ? s->repo->idarraydata + s->requires : 0;
954 case SOLVABLE_RECOMMENDS:
956 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
957 case SOLVABLE_SUPPLEMENTS:
959 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
960 case SOLVABLE_SUGGESTS:
962 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
963 case SOLVABLE_ENHANCES:
965 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
968 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
975 datamatcher_init(Datamatcher *ma, const char *match, int flags)
981 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
983 ma->matchdata = sat_calloc(1, sizeof(regex_t));
984 ma->error = regcomp((regex_t *)ma->matchdata, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
987 sat_free(ma->matchdata);
988 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
995 datamatcher_free(Datamatcher *ma)
997 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
999 regfree(ma->matchdata);
1000 ma->matchdata = sat_free(ma->matchdata);
1005 datamatcher_match(Datamatcher *ma, const char *str)
1008 switch ((ma->flags & SEARCH_STRINGMASK))
1010 case SEARCH_SUBSTRING:
1011 if (ma->flags & SEARCH_NOCASE)
1013 if (!strcasestr(str, ma->match))
1018 if (!strstr(str, ma->match))
1023 if (ma->flags & SEARCH_NOCASE)
1025 if (strcasecmp(ma->match, str))
1030 if (strcmp(ma->match, str))
1034 case SEARCH_STRINGSTART:
1035 if (ma->flags & SEARCH_NOCASE)
1037 if (strncasecmp(ma->match, str, strlen(ma->match)))
1042 if (strncmp(ma->match, str, strlen(ma->match)))
1046 case SEARCH_STRINGEND:
1047 l = strlen(str) - strlen(ma->match);
1050 if (ma->flags & SEARCH_NOCASE)
1052 if (strcasecmp(ma->match, str + l))
1057 if (strcmp(ma->match, str + l))
1062 if (fnmatch(ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
1066 if (regexec((const regex_t *)ma->matchdata, str, 0, NULL, 0))
1076 repodata_filelistfilter_matches(Repodata *data, const char *str)
1078 /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */
1079 /* for now hardcoded */
1080 if (strstr(str, "bin/"))
1082 if (!strncmp(str, "/etc/", 5))
1084 if (!strcmp(str, "/usr/lib/sendmail"))
1106 di_nextarrayelement,
1111 di_nextsolvableattr,
1116 /* see repo.h for documentation */
1118 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
1120 memset(di, 0, sizeof(*di));
1122 di->flags = flags & ~SEARCH_THISSOLVID;
1123 if (!pool || (repo && repo->pool != pool))
1131 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1137 di->keyname = keyname;
1138 di->keynames[0] = keyname;
1139 dataiterator_set_search(di, repo, p);
1144 dataiterator_init_clone(Dataiterator *di, Dataiterator *from)
1147 memset(&di->matcher, 0, sizeof(di->matcher));
1148 if (from->matcher.match)
1149 datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags);
1154 for (i = 1; i < di->nparents; i++)
1155 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1156 di->kv.parent = &di->parents[di->nparents - 1].kv;
1161 dataiterator_set_match(Dataiterator *di, const char *match, int flags)
1163 di->flags = (flags & ~SEARCH_THISSOLVID) | (di->flags & SEARCH_THISSOLVID);
1164 datamatcher_free(&di->matcher);
1165 memset(&di->matcher, 0, sizeof(di->matcher));
1169 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1179 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
1183 di->flags &= ~SEARCH_THISSOLVID;
1187 if (!di->pool->nrepos)
1195 di->repo = di->pool->repos[0];
1197 di->state = di_enterrepo;
1199 dataiterator_jump_to_solvid(di, p);
1203 dataiterator_set_keyname(Dataiterator *di, Id keyname)
1206 di->keyname = keyname;
1207 di->keynames[0] = keyname;
1211 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1215 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1217 di->state = di_bye; /* sorry */
1220 for (i = di->nkeynames + 1; i > 0; i--)
1221 di->keynames[i] = di->keynames[i - 1];
1222 di->keynames[0] = di->keyname = keyname;
1227 dataiterator_free(Dataiterator *di)
1229 if (di->matcher.match)
1230 datamatcher_free(&di->matcher);
1233 static inline unsigned char *
1234 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1236 Id *keyp = di->keyp;
1237 Repokey *keys = di->data->keys;
1240 for (keyp = di->keyp; *keyp; keyp++)
1241 if (keys[*keyp].name == keyname)
1245 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1253 dataiterator_filelistcheck(Dataiterator *di)
1256 int needcomplete = 0;
1257 Repodata *data = di->data;
1259 if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
1260 if (!di->matcher.match
1261 || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
1262 && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)
1263 || !repodata_filelistfilter_matches(di->data, di->matcher.match))
1265 if (data->state != REPODATA_AVAILABLE)
1266 return needcomplete ? 1 : 0;
1267 for (j = 1; j < data->nkeys; j++)
1268 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
1270 return j == data->nkeys && !needcomplete ? 0 : 1;
1274 dataiterator_step(Dataiterator *di)
1282 case di_enterrepo: di_enterrepo:
1285 if (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS))
1287 if (!(di->flags & SEARCH_THISSOLVID))
1289 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1290 goto di_nextsolvable;
1294 case di_entersolvable: di_entersolvable:
1295 if (di->repodataid >= 0)
1297 di->repodataid = 0; /* reset repodata iterator */
1298 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)
1300 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1302 goto di_entersolvablekey;
1307 case di_enterrepodata: di_enterrepodata:
1308 if (di->repodataid >= 0)
1310 if (di->repodataid >= di->repo->nrepodata)
1311 goto di_nextsolvable;
1312 di->data = di->repo->repodata + di->repodataid;
1314 if (di->repodataid >= 0 && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
1315 goto di_nextrepodata;
1316 if (!maybe_load_repodata(di->data, di->keyname))
1317 goto di_nextrepodata;
1318 di->dp = solvid2data(di->data, di->solvid, &schema);
1320 goto di_nextrepodata;
1321 if (di->solvid == SOLVID_POS)
1322 di->solvid = di->pool->pos.solvid;
1323 /* reset key iterator */
1324 di->keyp = di->data->schemadata + di->data->schemata[schema];
1327 case di_enterschema: di_enterschema:
1329 di->dp = dataiterator_find_keyname(di, di->keyname);
1330 if (!di->dp || !*di->keyp)
1334 goto di_nextrepodata;
1338 case di_enterkey: di_enterkey:
1340 di->key = di->data->keys + *di->keyp;
1341 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1344 if (di->key->type == REPOKEY_TYPE_DELETED)
1346 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1348 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1354 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1356 di->state = di_nextkey;
1358 di->state = di_nextattr;
1361 case di_nextkey: di_nextkey:
1362 if (!di->keyname && *++di->keyp)
1368 case di_nextrepodata: di_nextrepodata:
1369 if (di->repodataid >= 0 && ++di->repodataid < di->repo->nrepodata)
1370 goto di_enterrepodata;
1373 case di_nextsolvable: di_nextsolvable:
1374 if (!(di->flags & SEARCH_THISSOLVID))
1377 di->solvid = di->repo->start;
1380 for (; di->solvid < di->repo->end; di->solvid++)
1382 if (di->pool->solvables[di->solvid].repo == di->repo)
1383 goto di_entersolvable;
1388 case di_nextrepo: di_nextrepo:
1389 if (di->repoid >= 0)
1393 if (di->repoid < di->pool->nrepos)
1395 di->repo = di->pool->repos[di->repoid];
1401 case di_bye: di_bye:
1405 case di_enterarray: di_enterarray:
1406 if (di->key->name == REPOSITORY_SOLVABLES)
1408 di->ddp = data_read_id(di->ddp, &di->kv.num);
1413 case di_nextarrayelement: di_nextarrayelement:
1416 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1417 if (di->kv.entry == di->kv.num)
1419 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1421 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1423 di->kv.str = (char *)di->ddp;
1425 di->state = di_nextkey;
1428 if (di->kv.entry == di->kv.num - 1)
1430 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1431 di->ddp = data_read_id(di->ddp, &di->kv.id);
1432 di->kv.str = (char *)di->ddp;
1433 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1435 if ((di->flags & SEARCH_SUB) != 0)
1436 di->state = di_entersub;
1438 di->state = di_nextarrayelement;
1441 case di_entersub: di_entersub:
1442 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1443 goto di_nextarrayelement; /* sorry, full */
1444 di->parents[di->nparents].kv = di->kv;
1445 di->parents[di->nparents].dp = di->dp;
1446 di->parents[di->nparents].keyp = di->keyp;
1447 di->dp = (unsigned char *)di->kv.str;
1448 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1449 memset(&di->kv, 0, sizeof(di->kv));
1450 di->kv.parent = &di->parents[di->nparents].kv;
1452 di->keyname = di->keynames[di->nparents - di->rootlevel];
1453 goto di_enterschema;
1455 case di_leavesub: di_leavesub:
1456 if (di->nparents - 1 < di->rootlevel)
1459 di->dp = di->parents[di->nparents].dp;
1460 di->kv = di->parents[di->nparents].kv;
1461 di->keyp = di->parents[di->nparents].keyp;
1462 di->key = di->data->keys + *di->keyp;
1463 di->ddp = (unsigned char *)di->kv.str;
1464 di->keyname = di->keynames[di->nparents - di->rootlevel];
1465 goto di_nextarrayelement;
1467 /* special solvable attr handling follows */
1469 case di_nextsolvableattr:
1470 di->kv.id = *di->idp++;
1475 di->state = di_nextsolvablekey;
1479 case di_nextsolvablekey: di_nextsolvablekey:
1480 if (di->keyname || di->key->name == RPM_RPMDBID)
1481 goto di_enterrepodata;
1485 case di_entersolvablekey: di_entersolvablekey:
1486 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1487 if (!di->idp || !di->idp[0])
1488 goto di_nextsolvablekey;
1489 di->kv.id = di->idp[0];
1490 di->kv.num = di->idp[0];
1492 if (!di->kv.eof && !di->idp[0])
1496 di->state = di_nextsolvablekey;
1498 di->state = di_nextsolvableattr;
1502 if (di->matcher.match)
1504 /* simple pre-check so that we don't need to stringify */
1505 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))
1507 int l = strlen(di->matcher.match) - strlen(di->kv.str);
1508 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
1511 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1513 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1517 if (!datamatcher_match(&di->matcher, di->kv.str))
1520 /* found something! */
1526 dataiterator_entersub(Dataiterator *di)
1528 if (di->state == di_nextarrayelement)
1529 di->state = di_entersub;
1533 dataiterator_setpos(Dataiterator *di)
1535 if (di->kv.eof == 2)
1537 pool_clear_pos(di->pool);
1540 di->pool->pos.solvid = di->solvid;
1541 di->pool->pos.repo = di->repo;
1542 di->pool->pos.repodataid = di->data - di->repo->repodata;
1543 di->pool->pos.schema = di->kv.id;
1544 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1548 dataiterator_setpos_parent(Dataiterator *di)
1550 if (!di->kv.parent || di->kv.parent->eof == 2)
1552 pool_clear_pos(di->pool);
1555 di->pool->pos.solvid = di->solvid;
1556 di->pool->pos.repo = di->repo;
1557 di->pool->pos.repodataid = di->data - di->repo->repodata;
1558 di->pool->pos.schema = di->kv.parent->id;
1559 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1562 /* clones just the position, not the search keys/matcher */
1564 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
1566 di->state = from->state;
1567 di->flags &= ~SEARCH_THISSOLVID;
1568 di->flags |= (from->flags & SEARCH_THISSOLVID);
1569 di->repo = from->repo;
1570 di->data = from->data;
1572 di->ddp = from->ddp;
1573 di->idp = from->idp;
1574 di->keyp = from->keyp;
1575 di->key = from->key;
1577 di->repodataid = from->repodataid;
1578 di->solvid = from->solvid;
1579 di->repoid = from->repoid;
1580 di->rootlevel = from->rootlevel;
1581 memcpy(di->parents, from->parents, sizeof(from->parents));
1582 di->nparents = from->nparents;
1586 for (i = 1; i < di->nparents; i++)
1587 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1588 di->kv.parent = &di->parents[di->nparents - 1].kv;
1593 dataiterator_seek(Dataiterator *di, int whence)
1595 if ((whence & DI_SEEK_STAY) != 0)
1596 di->rootlevel = di->nparents;
1597 switch (whence & ~DI_SEEK_STAY)
1600 if (di->state != di_nextarrayelement)
1602 if ((whence & DI_SEEK_STAY) != 0)
1603 di->rootlevel = di->nparents + 1; /* XXX: dangerous! */
1604 di->state = di_entersub;
1606 case DI_SEEK_PARENT:
1613 if (di->rootlevel > di->nparents)
1614 di->rootlevel = di->nparents;
1615 di->dp = di->parents[di->nparents].dp;
1616 di->kv = di->parents[di->nparents].kv;
1617 di->keyp = di->parents[di->nparents].keyp;
1618 di->key = di->data->keys + *di->keyp;
1619 di->ddp = (unsigned char *)di->kv.str;
1620 di->keyname = di->keynames[di->nparents - di->rootlevel];
1621 di->state = di_nextarrayelement;
1623 case DI_SEEK_REWIND:
1629 di->dp = (unsigned char *)di->kv.parent->str;
1630 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
1631 di->state = di_enterschema;
1639 dataiterator_skip_attribute(Dataiterator *di)
1641 if (di->state == di_nextsolvableattr)
1642 di->state = di_nextsolvablekey;
1644 di->state = di_nextkey;
1648 dataiterator_skip_solvable(Dataiterator *di)
1653 di->keyname = di->keynames[0];
1654 di->state = di_nextsolvable;
1658 dataiterator_skip_repo(Dataiterator *di)
1663 di->keyname = di->keynames[0];
1664 di->state = di_nextrepo;
1668 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1673 di->keyname = di->keynames[0];
1674 if (solvid == SOLVID_POS)
1676 di->repo = di->pool->pos.repo;
1683 di->data = di->repo->repodata + di->pool->pos.repodataid;
1684 di->repodataid = -1;
1685 di->solvid = solvid;
1686 di->state = di_enterrepo;
1687 di->flags |= SEARCH_THISSOLVID;
1692 di->repo = di->pool->solvables[solvid].repo;
1695 else if (di->repoid >= 0)
1697 if (!di->pool->nrepos)
1702 di->repo = di->pool->repos[0];
1706 di->solvid = solvid;
1708 di->flags |= SEARCH_THISSOLVID;
1709 di->state = di_enterrepo;
1713 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1722 di->flags &= ~SEARCH_THISSOLVID;
1723 di->state = di_enterrepo;
1727 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1729 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1733 return datamatcher_match(ma, di->kv.str);
1736 /************************************************************************
1737 * data modify functions
1740 /* extend repodata so that it includes solvables p */
1742 repodata_extend(Repodata *data, Id p)
1744 if (data->start == data->end)
1745 data->start = data->end = p;
1748 int old = data->end - data->start;
1749 int new = p - data->end + 1;
1752 data->attrs = sat_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1753 memset(data->attrs + old, 0, new * sizeof(Id *));
1755 data->incoreoffset = sat_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1756 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1759 if (p < data->start)
1761 int old = data->end - data->start;
1762 int new = data->start - p;
1765 data->attrs = sat_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1766 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1767 memset(data->attrs, 0, new * sizeof(Id *));
1769 data->incoreoffset = sat_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1770 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1771 memset(data->incoreoffset, 0, new * sizeof(Id));
1776 /* shrink end of repodata */
1778 repodata_shrink(Repodata *data, int end)
1782 if (data->end <= end)
1784 if (data->start >= end)
1788 for (i = 0; i < data->end - data->start; i++)
1789 sat_free(data->attrs[i]);
1790 data->attrs = sat_free(data->attrs);
1792 data->incoreoffset = sat_free(data->incoreoffset);
1793 data->start = data->end = 0;
1798 for (i = end; i < data->end; i++)
1799 sat_free(data->attrs[i - data->start]);
1800 data->attrs = sat_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
1802 if (data->incoreoffset)
1803 data->incoreoffset = sat_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
1807 /* extend repodata so that it includes solvables from start to start + num - 1 */
1809 repodata_extend_block(Repodata *data, Id start, Id num)
1813 if (!data->incoreoffset)
1815 data->incoreoffset = sat_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1816 data->start = start;
1817 data->end = start + num;
1820 repodata_extend(data, start);
1822 repodata_extend(data, start + num - 1);
1825 /**********************************************************************/
1828 #define REPODATA_ATTRS_BLOCK 31
1829 #define REPODATA_ATTRDATA_BLOCK 1023
1830 #define REPODATA_ATTRIDDATA_BLOCK 63
1834 repodata_new_handle(Repodata *data)
1838 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1839 data->nxattrs = 2; /* -1: SOLVID_META */
1841 data->xattrs = sat_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1842 data->xattrs[data->nxattrs] = 0;
1843 return -(data->nxattrs++);
1847 repodata_get_attrp(Repodata *data, Id handle)
1851 if (handle == SOLVID_META && !data->xattrs)
1853 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1856 return data->xattrs - handle;
1858 if (handle < data->start || handle >= data->end)
1859 repodata_extend(data, handle);
1861 data->attrs = sat_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1862 return data->attrs + (handle - data->start);
1866 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1872 app = repodata_get_attrp(data, handle);
1877 /* Determine equality based on the name only, allows us to change
1878 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1879 for (pp = ap; *pp; pp += 2)
1880 if (data->keys[*pp].name == data->keys[keyid].name)
1884 if (overwrite || data->keys[*pp].type == REPOKEY_TYPE_DELETED)
1893 ap = sat_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1903 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1907 keyid = repodata_key2id(data, key, 1);
1908 repodata_insert_keyid(data, solvid, keyid, val, 1);
1912 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1916 key.type = REPOKEY_TYPE_ID;
1918 key.storage = KEY_STORAGE_INCORE;
1919 repodata_set(data, solvid, &key, id);
1923 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1927 key.type = REPOKEY_TYPE_NUM;
1929 key.storage = KEY_STORAGE_INCORE;
1930 repodata_set(data, solvid, &key, (Id)num);
1934 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
1938 if (data->localpool)
1939 id = stringpool_str2id(&data->spool, str, 1);
1941 id = str2id(data->repo->pool, str, 1);
1943 key.type = REPOKEY_TYPE_ID;
1945 key.storage = KEY_STORAGE_INCORE;
1946 repodata_set(data, solvid, &key, id);
1950 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
1954 key.type = REPOKEY_TYPE_CONSTANT;
1955 key.size = constant;
1956 key.storage = KEY_STORAGE_INCORE;
1957 repodata_set(data, solvid, &key, 0);
1961 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
1965 key.type = REPOKEY_TYPE_CONSTANTID;
1967 key.storage = KEY_STORAGE_INCORE;
1968 repodata_set(data, solvid, &key, 0);
1972 repodata_set_void(Repodata *data, Id solvid, Id keyname)
1976 key.type = REPOKEY_TYPE_VOID;
1978 key.storage = KEY_STORAGE_INCORE;
1979 repodata_set(data, solvid, &key, 0);
1983 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
1988 l = strlen(str) + 1;
1990 key.type = REPOKEY_TYPE_STR;
1992 key.storage = KEY_STORAGE_INCORE;
1993 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1994 memcpy(data->attrdata + data->attrdatalen, str, l);
1995 repodata_set(data, solvid, &key, data->attrdatalen);
1996 data->attrdatalen += l;
2000 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
2006 key.type = REPOKEY_TYPE_BINARY;
2008 key.storage = KEY_STORAGE_INCORE;
2009 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
2010 dp = data->attrdata + data->attrdatalen;
2011 if (len >= (1 << 14))
2013 if (len >= (1 << 28))
2014 *dp++ = (len >> 28) | 128;
2015 if (len >= (1 << 21))
2016 *dp++ = (len >> 21) | 128;
2017 *dp++ = (len >> 14) | 128;
2019 if (len >= (1 << 7))
2020 *dp++ = (len >> 7) | 128;
2023 memcpy(dp, buf, len);
2024 repodata_set(data, solvid, &key, data->attrdatalen);
2025 data->attrdatalen = dp + len - data->attrdata;
2028 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
2029 * so that the caller can append entrysize new elements plus the termination zero there */
2031 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
2034 Id *ida, *pp, **ppp;
2036 /* check if it is the same as last time, this speeds things up a lot */
2037 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
2039 /* great! just append the new data */
2040 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2041 data->attriddatalen--; /* overwrite terminating 0 */
2042 data->lastdatalen += entrysize;
2046 ppp = repodata_get_attrp(data, handle);
2050 for (; *pp; pp += 2)
2051 if (data->keys[*pp].name == keyname)
2054 if (!pp || !*pp || data->keys[*pp].type != keytype)
2056 /* not found. allocate new key */
2062 key.storage = KEY_STORAGE_INCORE;
2063 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2064 keyid = repodata_key2id(data, &key, 1);
2065 repodata_insert_keyid(data, handle, keyid, data->attriddatalen, 1);
2066 data->lasthandle = handle;
2067 data->lastkey = keyid;
2068 data->lastdatalen = data->attriddatalen + entrysize + 1;
2072 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
2073 oldsize += entrysize;
2074 if (ida + 1 == data->attriddata + data->attriddatalen)
2076 /* this was the last entry, just append it */
2077 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2078 data->attriddatalen--; /* overwrite terminating 0 */
2082 /* too bad. move to back. */
2083 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2084 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
2085 pp[1] = data->attriddatalen;
2086 data->attriddatalen += oldsize;
2088 data->lasthandle = handle;
2089 data->lastkey = *pp;
2090 data->lastdatalen = data->attriddatalen + entrysize + 1;
2094 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2095 const unsigned char *str)
2100 if (!(l = sat_chksum_len(type)))
2105 key.storage = KEY_STORAGE_INCORE;
2106 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2107 memcpy(data->attrdata + data->attrdatalen, str, l);
2108 repodata_set(data, solvid, &key, data->attrdatalen);
2109 data->attrdatalen += l;
2113 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2116 unsigned char buf[64];
2119 if (!(l = sat_chksum_len(type)))
2121 if (l > sizeof(buf) || sat_hex2bin(&str, buf, l) != l)
2123 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2127 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2131 if (!(l = sat_chksum_len(type)))
2133 return pool_bin2hex(data->repo->pool, buf, l);
2136 /* rpm filenames don't contain the epoch, so strip it */
2137 static inline const char *
2138 evrid2vrstr(Pool *pool, Id evrid)
2140 const char *p, *evr = id2str(pool, evrid);
2143 for (p = evr; *p >= '0' && *p <= '9'; p++)
2145 return p != evr && *p == ':' ? p + 1 : evr;
2149 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2151 Pool *pool = data->repo->pool;
2153 const char *str, *fp;
2157 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2160 if ((dir = strrchr(file, '/')) != 0)
2171 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2176 if (l == 1 && dir[0] == '.')
2178 s = pool->solvables + solvid;
2181 str = id2str(pool, s->arch);
2182 if (!strncmp(dir, str, l) && !str[l])
2183 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2185 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2188 char *dir2 = strdup(dir);
2190 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2195 str = id2str(pool, s->name);
2197 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2200 str = evrid2vrstr(pool, s->evr);
2202 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2205 str = id2str(pool, s->arch);
2207 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2209 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2214 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2218 repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
2224 key.type = REPOKEY_TYPE_IDARRAY;
2226 key.storage = KEY_STORAGE_INCORE;
2227 repodata_set(data, solvid, &key, data->attriddatalen);
2228 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, q->count + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2229 for (i = 0; i < q->count; i++)
2230 data->attriddata[data->attriddatalen++] = q->elements[i];
2231 data->attriddata[data->attriddatalen++] = 0;
2235 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2239 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2241 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2242 data->attriddata[data->attriddatalen++] = dir;
2243 data->attriddata[data->attriddatalen++] = num;
2244 data->attriddata[data->attriddatalen++] = num2;
2245 data->attriddata[data->attriddatalen++] = 0;
2249 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2255 l = strlen(str) + 1;
2256 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2257 memcpy(data->attrdata + data->attrdatalen, str, l);
2258 stroff = data->attrdatalen;
2259 data->attrdatalen += l;
2262 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2264 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2265 data->attriddata[data->attriddatalen++] = dir;
2266 data->attriddata[data->attriddatalen++] = stroff;
2267 data->attriddata[data->attriddatalen++] = 0;
2271 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2274 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2276 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2277 data->attriddata[data->attriddatalen++] = id;
2278 data->attriddata[data->attriddatalen++] = 0;
2282 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2286 if (data->localpool)
2287 id = stringpool_str2id(&data->spool, str, 1);
2289 id = str2id(data->repo->pool, str, 1);
2290 repodata_add_idarray(data, solvid, keyname, id);
2294 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2296 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2297 data->attriddata[data->attriddatalen++] = ghandle;
2298 data->attriddata[data->attriddatalen++] = 0;
2302 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2304 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2305 data->attriddata[data->attriddatalen++] = ghandle;
2306 data->attriddata[data->attriddatalen++] = 0;
2310 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2313 app = repodata_get_attrp(data, solvid);
2317 for (; *ap; ap += 2)
2318 if (data->keys[*ap].name == keyname)
2324 for (; *ap; ap += 2)
2326 if (data->keys[*ap].name == keyname)
2334 /* XXX: does not work correctly, needs fix in iterators! */
2336 repodata_delete(Repodata *data, Id solvid, Id keyname)
2340 key.type = REPOKEY_TYPE_DELETED;
2342 key.storage = KEY_STORAGE_INCORE;
2343 repodata_set(data, solvid, &key, 0);
2346 /* add all (uninternalized) attrs from src to dest */
2348 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2351 if (dest == src || !(keyp = data->attrs[src - data->start]))
2353 for (; *keyp; keyp += 2)
2354 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2357 /* add some (uninternalized) attrs from src to dest */
2359 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2362 if (dest == src || !(keyp = data->attrs[src - data->start]))
2364 for (; *keyp; keyp += 2)
2365 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2366 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2371 /**********************************************************************/
2373 /* TODO: unify with repo_write and repo_solv! */
2375 #define EXTDATA_BLOCK 1023
2383 data_addid(struct extdata *xd, Id x)
2387 xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2388 dp = xd->buf + xd->len;
2393 *dp++ = (x >> 28) | 128;
2395 *dp++ = (x >> 21) | 128;
2396 *dp++ = (x >> 14) | 128;
2399 *dp++ = (x >> 7) | 128;
2401 xd->len = dp - xd->buf;
2405 data_addideof(struct extdata *xd, Id x, int eof)
2408 x = (x & 63) | ((x & ~63) << 1);
2409 data_addid(xd, (eof ? x : x | 64));
2413 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2415 xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2416 memcpy(xd->buf + xd->len, blob, len);
2420 /*********************************/
2422 /* internalalize some key into incore/vincore data */
2425 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2426 struct extdata *newvincore,
2428 Repokey *key, Id val)
2432 unsigned int oldvincorelen = 0;
2436 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2439 oldvincorelen = xd->len;
2443 case REPOKEY_TYPE_VOID:
2444 case REPOKEY_TYPE_CONSTANT:
2445 case REPOKEY_TYPE_CONSTANTID:
2447 case REPOKEY_TYPE_STR:
2448 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2450 case REPOKEY_TYPE_MD5:
2451 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2453 case REPOKEY_TYPE_SHA1:
2454 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2456 case REPOKEY_TYPE_SHA256:
2457 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2459 case REPOKEY_TYPE_ID:
2460 case REPOKEY_TYPE_NUM:
2461 case REPOKEY_TYPE_DIR:
2462 data_addid(xd, val);
2464 case REPOKEY_TYPE_BINARY:
2467 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2469 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2472 case REPOKEY_TYPE_IDARRAY:
2473 for (ida = data->attriddata + val; *ida; ida++)
2474 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2476 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2477 for (ida = data->attriddata + val; *ida; ida += 3)
2479 data_addid(xd, ida[0]);
2480 data_addid(xd, ida[1]);
2481 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2484 case REPOKEY_TYPE_DIRSTRARRAY:
2485 for (ida = data->attriddata + val; *ida; ida += 2)
2487 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2488 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2491 case REPOKEY_TYPE_FIXARRAY:
2495 for (ida = data->attriddata + val; *ida; ida++)
2498 Id *kp = data->xattrs[-*ida];
2506 schemaid = repodata_schema2id(data, schema, 1);
2507 else if (schemaid != repodata_schema2id(data, schema, 0))
2509 pool_debug(data->repo->pool, SAT_FATAL, "fixarray substructs with different schemas\n");
2515 data_addid(xd, num);
2516 data_addid(xd, schemaid);
2517 for (ida = data->attriddata + val; *ida; ida++)
2519 Id *kp = data->xattrs[-*ida];
2523 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2527 case REPOKEY_TYPE_FLEXARRAY:
2530 for (ida = data->attriddata + val; *ida; ida++)
2532 data_addid(xd, num);
2533 for (ida = data->attriddata + val; *ida; ida++)
2535 Id *kp = data->xattrs[-*ida];
2538 data_addid(xd, 0); /* XXX */
2545 schemaid = repodata_schema2id(data, schema, 1);
2546 data_addid(xd, schemaid);
2547 kp = data->xattrs[-*ida];
2549 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2554 pool_debug(data->repo->pool, SAT_FATAL, "don't know how to handle type %d\n", key->type);
2557 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2559 /* put offset/len in incore */
2560 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2561 oldvincorelen = xd->len - oldvincorelen;
2562 data_addid(newincore, oldvincorelen);
2567 repodata_internalize(Repodata *data)
2569 Repokey *key, solvkey;
2571 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2572 unsigned char *dp, *ndp;
2573 int newschema, oldcount;
2574 struct extdata newincore;
2575 struct extdata newvincore;
2578 if (!data->attrs && !data->xattrs)
2581 newvincore.buf = data->vincore;
2582 newvincore.len = data->vincorelen;
2584 /* find the solvables key, create if needed */
2585 memset(&solvkey, 0, sizeof(solvkey));
2586 solvkey.name = REPOSITORY_SOLVABLES;
2587 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2589 solvkey.storage = KEY_STORAGE_INCORE;
2590 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2592 schema = sat_malloc2(data->nkeys, sizeof(Id));
2593 seen = sat_malloc2(data->nkeys, sizeof(Id));
2595 /* Merge the data already existing (in data->schemata, ->incoredata and
2596 friends) with the new attributes in data->attrs[]. */
2597 nentry = data->end - data->start;
2598 memset(&newincore, 0, sizeof(newincore));
2599 data_addid(&newincore, 0); /* start data at offset 1 */
2601 data->mainschema = 0;
2602 data->mainschemaoffsets = sat_free(data->mainschemaoffsets);
2604 /* join entry data */
2605 /* we start with the meta data, entry -1 */
2606 for (entry = -1; entry < nentry; entry++)
2608 memset(seen, 0, data->nkeys * sizeof(Id));
2610 dp = data->incoredata;
2613 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2614 dp = data_read_id(dp, &oldschema);
2617 fprintf(stderr, "oldschema %d\n", oldschema);
2618 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2619 fprintf(stderr, "schemadata %p\n", data->schemadata);
2621 /* seen: -1: old data 0: skipped >0: id + 1 */
2625 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2629 pool_debug(data->repo->pool, SAT_FATAL, "Inconsistent old data (key occured twice).\n");
2637 keyp = data->attrs ? data->attrs[entry] : 0;
2640 /* strip solvables key */
2642 for (sp = keyp = schema; *sp; sp++)
2643 if (*sp != solvkeyid)
2648 seen[solvkeyid] = 0;
2649 keyp = data->xattrs ? data->xattrs[1] : 0;
2652 for (; *keyp; keyp += 2)
2659 seen[*keyp] = keyp[1] + 1;
2661 if (entry < 0 && data->end != data->start)
2668 /* Ideally we'd like to sort the new schema here, to ensure
2669 schema equality independend of the ordering. We can't do that
2670 yet. For once see below (old ids need to come before new ids).
2671 An additional difficulty is that we also need to move
2672 the values with the keys. */
2673 schemaid = repodata_schema2id(data, schema, 1);
2675 schemaid = oldschema;
2678 /* Now create data blob. We walk through the (possibly new) schema
2679 and either copy over old data, or insert the new. */
2680 /* XXX Here we rely on the fact that the (new) schema has the form
2681 o1 o2 o3 o4 ... | n1 n2 n3 ...
2682 (oX being the old keyids (possibly overwritten), and nX being
2683 the new keyids). This rules out sorting the keyids in order
2684 to ensure a small schema count. */
2686 data->incoreoffset[entry] = newincore.len;
2687 data_addid(&newincore, schemaid);
2690 data->mainschema = schemaid;
2691 data->mainschemaoffsets = sat_calloc(sp - schema, sizeof(Id));
2693 keypstart = data->schemadata + data->schemata[schemaid];
2694 for (keyp = keypstart; *keyp; keyp++)
2697 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2698 if (*keyp == solvkeyid)
2700 /* add flexarray entry count */
2701 data_addid(&newincore, data->end - data->start);
2704 key = data->keys + *keyp;
2706 fprintf(stderr, "internalize %d(%d):%s:%s\n", entry, entry + data->start, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
2711 /* Skip the data associated with this old key. */
2712 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2714 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2715 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2717 else if (key->storage == KEY_STORAGE_INCORE)
2718 ndp = data_skip_key(data, dp, key);
2721 if (seen[*keyp] == -1)
2723 /* If this key was an old one _and_ was not overwritten with
2724 a different value copy over the old value (we skipped it
2727 data_addblob(&newincore, dp, ndp - dp);
2730 else if (seen[*keyp])
2732 /* Otherwise we have a new value. Parse it into the internal
2734 repodata_serialize_key(data, &newincore, &newvincore,
2735 schema, key, seen[*keyp] - 1);
2739 if (entry >= 0 && data->attrs && data->attrs[entry])
2740 data->attrs[entry] = sat_free(data->attrs[entry]);
2742 /* free all xattrs */
2743 for (entry = 0; entry < data->nxattrs; entry++)
2744 if (data->xattrs[entry])
2745 sat_free(data->xattrs[entry]);
2746 data->xattrs = sat_free(data->xattrs);
2749 data->lasthandle = 0;
2751 data->lastdatalen = 0;
2754 repodata_free_schemahash(data);
2756 sat_free(data->incoredata);
2757 data->incoredata = newincore.buf;
2758 data->incoredatalen = newincore.len;
2759 data->incoredatafree = 0;
2761 sat_free(data->vincore);
2762 data->vincore = newvincore.buf;
2763 data->vincorelen = newvincore.len;
2765 data->attrs = sat_free(data->attrs);
2766 data->attrdata = sat_free(data->attrdata);
2767 data->attriddata = sat_free(data->attriddata);
2768 data->attrdatalen = 0;
2769 data->attriddatalen = 0;
2773 repodata_disable_paging(Repodata *data)
2775 if (maybe_load_repodata(data, 0))
2776 repopagestore_disable_paging(&data->store);
2780 repodata_load_stub(Repodata *data)
2782 Repo *repo = data->repo;
2783 Pool *pool = repo->pool;
2786 if (!pool->loadcallback)
2788 data->state = REPODATA_ERROR;
2791 data->state = REPODATA_LOADING;
2792 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2793 data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
2797 repodata_create_stubs(Repodata *data)
2799 Repo *repo = data->repo;
2800 Pool *pool = repo->pool;
2807 int datastart, dataend;
2809 repodataid = data - repo->repodata;
2810 datastart = data->start;
2811 dataend = data->end;
2812 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2813 while (dataiterator_step(&di))
2815 if (di.data - repo->repodata != repodataid)
2819 dataiterator_free(&di);
2822 stubdataids = sat_calloc(cnt, sizeof(*stubdataids));
2823 for (i = 0; i < cnt; i++)
2825 sdata = repo_add_repodata(repo, 0);
2826 if (dataend > datastart)
2827 repodata_extend_block(sdata, datastart, dataend - datastart);
2828 stubdataids[i] = sdata - repo->repodata;
2829 sdata->state = REPODATA_STUB;
2830 sdata->loadcallback = repodata_load_stub;
2833 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2835 while (dataiterator_step(&di))
2837 if (di.data - repo->repodata != repodataid)
2839 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
2841 dataiterator_entersub(&di);
2842 sdata = repo->repodata + stubdataids[i++];
2846 switch (di.key->type)
2848 case REPOKEY_TYPE_ID:
2849 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
2851 case REPOKEY_TYPE_CONSTANTID:
2852 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
2854 case REPOKEY_TYPE_STR:
2855 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
2857 case REPOKEY_TYPE_VOID:
2858 repodata_set_void(sdata, SOLVID_META, di.key->name);
2860 case REPOKEY_TYPE_NUM:
2861 repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num);
2863 case REPOKEY_TYPE_MD5:
2864 case REPOKEY_TYPE_SHA1:
2865 case REPOKEY_TYPE_SHA256:
2866 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
2868 case REPOKEY_TYPE_IDARRAY:
2869 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
2870 if (di.key->name == REPOSITORY_KEYS)
2877 xkeyname = di.kv.id;
2880 xkey.name = xkeyname;
2881 xkey.type = di.kv.id;
2882 xkey.storage = KEY_STORAGE_INCORE;
2884 repodata_key2id(sdata, &xkey, 1);
2891 dataiterator_free(&di);
2892 for (i = 0; i < cnt; i++)
2893 repodata_internalize(repo->repodata + stubdataids[i]);
2894 sat_free(stubdataids);
2898 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: