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 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2109 unsigned char buf[64];
2112 if (!(l = sat_chksum_len(type)))
2114 if (l > sizeof(buf) || sat_hex2bin(&str, buf, l) != l)
2116 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2120 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2124 if (!(l = sat_chksum_len(type)))
2126 return pool_bin2hex(data->repo->pool, buf, l);
2129 /* rpm filenames don't contain the epoch, so strip it */
2130 static inline const char *
2131 evrid2vrstr(Pool *pool, Id evrid)
2133 const char *p, *evr = id2str(pool, evrid);
2136 for (p = evr; *p >= '0' && *p <= '9'; p++)
2138 return p != evr && *p == ':' ? p + 1 : evr;
2142 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2144 Pool *pool = data->repo->pool;
2146 const char *str, *fp;
2150 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2153 if ((dir = strrchr(file, '/')) != 0)
2164 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2169 if (l == 1 && dir[0] == '.')
2171 s = pool->solvables + solvid;
2174 str = id2str(pool, s->arch);
2175 if (!strncmp(dir, str, l) && !str[l])
2176 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2178 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2181 char *dir2 = strdup(dir);
2183 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2188 str = id2str(pool, s->name);
2190 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2193 str = evrid2vrstr(pool, s->evr);
2195 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2198 str = id2str(pool, s->arch);
2200 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2202 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2207 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2211 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2215 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2217 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2218 data->attriddata[data->attriddatalen++] = dir;
2219 data->attriddata[data->attriddatalen++] = num;
2220 data->attriddata[data->attriddatalen++] = num2;
2221 data->attriddata[data->attriddatalen++] = 0;
2225 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2231 l = strlen(str) + 1;
2232 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2233 memcpy(data->attrdata + data->attrdatalen, str, l);
2234 stroff = data->attrdatalen;
2235 data->attrdatalen += l;
2238 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2240 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2241 data->attriddata[data->attriddatalen++] = dir;
2242 data->attriddata[data->attriddatalen++] = stroff;
2243 data->attriddata[data->attriddatalen++] = 0;
2247 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2250 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2252 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2253 data->attriddata[data->attriddatalen++] = id;
2254 data->attriddata[data->attriddatalen++] = 0;
2258 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2262 if (data->localpool)
2263 id = stringpool_str2id(&data->spool, str, 1);
2265 id = str2id(data->repo->pool, str, 1);
2266 repodata_add_idarray(data, solvid, keyname, id);
2270 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2272 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2273 data->attriddata[data->attriddatalen++] = ghandle;
2274 data->attriddata[data->attriddatalen++] = 0;
2278 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2280 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2281 data->attriddata[data->attriddatalen++] = ghandle;
2282 data->attriddata[data->attriddatalen++] = 0;
2286 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2289 app = repodata_get_attrp(data, solvid);
2293 for (; *ap; ap += 2)
2294 if (data->keys[*ap].name == keyname)
2300 for (; *ap; ap += 2)
2302 if (data->keys[*ap].name == keyname)
2310 /* XXX: does not work correctly, needs fix in iterators! */
2312 repodata_delete(Repodata *data, Id solvid, Id keyname)
2316 key.type = REPOKEY_TYPE_DELETED;
2318 key.storage = KEY_STORAGE_INCORE;
2319 repodata_set(data, solvid, &key, 0);
2322 /* add all (uninternalized) attrs from src to dest */
2324 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2327 if (dest == src || !(keyp = data->attrs[src - data->start]))
2329 for (; *keyp; keyp += 2)
2330 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2333 /* add some (uninternalized) attrs from src to dest */
2335 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2338 if (dest == src || !(keyp = data->attrs[src - data->start]))
2340 for (; *keyp; keyp += 2)
2341 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2342 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2347 /**********************************************************************/
2349 /* TODO: unify with repo_write and repo_solv! */
2351 #define EXTDATA_BLOCK 1023
2359 data_addid(struct extdata *xd, Id x)
2363 xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2364 dp = xd->buf + xd->len;
2369 *dp++ = (x >> 28) | 128;
2371 *dp++ = (x >> 21) | 128;
2372 *dp++ = (x >> 14) | 128;
2375 *dp++ = (x >> 7) | 128;
2377 xd->len = dp - xd->buf;
2381 data_addideof(struct extdata *xd, Id x, int eof)
2384 x = (x & 63) | ((x & ~63) << 1);
2385 data_addid(xd, (eof ? x : x | 64));
2389 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2391 xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2392 memcpy(xd->buf + xd->len, blob, len);
2396 /*********************************/
2399 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2400 struct extdata *newvincore,
2402 Repokey *key, Id val)
2404 /* Otherwise we have a new value. Parse it into the internal
2408 unsigned int oldvincorelen = 0;
2412 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2415 oldvincorelen = xd->len;
2419 case REPOKEY_TYPE_VOID:
2420 case REPOKEY_TYPE_CONSTANT:
2421 case REPOKEY_TYPE_CONSTANTID:
2423 case REPOKEY_TYPE_STR:
2424 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2426 case REPOKEY_TYPE_MD5:
2427 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2429 case REPOKEY_TYPE_SHA1:
2430 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2432 case REPOKEY_TYPE_SHA256:
2433 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2435 case REPOKEY_TYPE_ID:
2436 case REPOKEY_TYPE_NUM:
2437 case REPOKEY_TYPE_DIR:
2438 data_addid(xd, val);
2440 case REPOKEY_TYPE_BINARY:
2443 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2445 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2448 case REPOKEY_TYPE_IDARRAY:
2449 for (ida = data->attriddata + val; *ida; ida++)
2450 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2452 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2453 for (ida = data->attriddata + val; *ida; ida += 3)
2455 data_addid(xd, ida[0]);
2456 data_addid(xd, ida[1]);
2457 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2460 case REPOKEY_TYPE_DIRSTRARRAY:
2461 for (ida = data->attriddata + val; *ida; ida += 2)
2463 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2464 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2467 case REPOKEY_TYPE_FIXARRAY:
2471 for (ida = data->attriddata + val; *ida; ida++)
2474 fprintf(stderr, "serialize struct %d\n", *ida);
2477 Id *kp = data->xattrs[-*ida];
2484 fprintf(stderr, " %s:%d\n", id2str(data->repo->pool, data->keys[*kp].name), kp[1]);
2490 schemaid = repodata_schema2id(data, schema, 1);
2491 else if (schemaid != repodata_schema2id(data, schema, 0))
2493 pool_debug(data->repo->pool, SAT_FATAL, "fixarray substructs with different schemas\n");
2497 fprintf(stderr, " schema %d\n", schemaid);
2502 data_addid(xd, num);
2503 data_addid(xd, schemaid);
2504 for (ida = data->attriddata + val; *ida; ida++)
2506 Id *kp = data->xattrs[-*ida];
2511 repodata_serialize_key(data, newincore, newvincore,
2512 schema, data->keys + *kp, kp[1]);
2517 case REPOKEY_TYPE_FLEXARRAY:
2520 for (ida = data->attriddata + val; *ida; ida++)
2522 data_addid(xd, num);
2523 for (ida = data->attriddata + val; *ida; ida++)
2525 Id *kp = data->xattrs[-*ida];
2528 data_addid(xd, 0); /* XXX */
2535 schemaid = repodata_schema2id(data, schema, 1);
2536 data_addid(xd, schemaid);
2537 kp = data->xattrs[-*ida];
2540 repodata_serialize_key(data, newincore, newvincore,
2541 schema, data->keys + *kp, kp[1]);
2547 pool_debug(data->repo->pool, SAT_FATAL, "don't know how to handle type %d\n", key->type);
2550 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2552 /* put offset/len in incore */
2553 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2554 oldvincorelen = xd->len - oldvincorelen;
2555 data_addid(newincore, oldvincorelen);
2560 repodata_internalize(Repodata *data)
2562 Repokey *key, solvkey;
2564 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2565 unsigned char *dp, *ndp;
2566 int newschema, oldcount;
2567 struct extdata newincore;
2568 struct extdata newvincore;
2571 if (!data->attrs && !data->xattrs)
2574 newvincore.buf = data->vincore;
2575 newvincore.len = data->vincorelen;
2577 /* find the solvables key, create if needed */
2578 memset(&solvkey, 0, sizeof(solvkey));
2579 solvkey.name = REPOSITORY_SOLVABLES;
2580 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2582 solvkey.storage = KEY_STORAGE_INCORE;
2583 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2585 schema = sat_malloc2(data->nkeys, sizeof(Id));
2586 seen = sat_malloc2(data->nkeys, sizeof(Id));
2588 /* Merge the data already existing (in data->schemata, ->incoredata and
2589 friends) with the new attributes in data->attrs[]. */
2590 nentry = data->end - data->start;
2591 memset(&newincore, 0, sizeof(newincore));
2592 data_addid(&newincore, 0); /* start data at offset 1 */
2594 data->mainschema = 0;
2595 data->mainschemaoffsets = sat_free(data->mainschemaoffsets);
2597 /* join entry data */
2598 /* we start with the meta data, entry -1 */
2599 for (entry = -1; entry < nentry; entry++)
2601 memset(seen, 0, data->nkeys * sizeof(Id));
2603 dp = data->incoredata;
2606 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2607 dp = data_read_id(dp, &oldschema);
2610 fprintf(stderr, "oldschema %d\n", oldschema);
2611 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2612 fprintf(stderr, "schemadata %p\n", data->schemadata);
2614 /* seen: -1: old data 0: skipped >0: id + 1 */
2618 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2622 pool_debug(data->repo->pool, SAT_FATAL, "Inconsistent old data (key occured twice).\n");
2630 keyp = data->attrs ? data->attrs[entry] : 0;
2633 /* strip solvables key */
2635 for (sp = keyp = schema; *sp; sp++)
2636 if (*sp != solvkeyid)
2641 seen[solvkeyid] = 0;
2642 keyp = data->xattrs ? data->xattrs[1] : 0;
2645 for (; *keyp; keyp += 2)
2652 seen[*keyp] = keyp[1] + 1;
2654 if (entry < 0 && data->end != data->start)
2661 /* Ideally we'd like to sort the new schema here, to ensure
2662 schema equality independend of the ordering. We can't do that
2663 yet. For once see below (old ids need to come before new ids).
2664 An additional difficulty is that we also need to move
2665 the values with the keys. */
2666 schemaid = repodata_schema2id(data, schema, 1);
2668 schemaid = oldschema;
2671 /* Now create data blob. We walk through the (possibly new) schema
2672 and either copy over old data, or insert the new. */
2673 /* XXX Here we rely on the fact that the (new) schema has the form
2674 o1 o2 o3 o4 ... | n1 n2 n3 ...
2675 (oX being the old keyids (possibly overwritten), and nX being
2676 the new keyids). This rules out sorting the keyids in order
2677 to ensure a small schema count. */
2679 data->incoreoffset[entry] = newincore.len;
2680 data_addid(&newincore, schemaid);
2683 data->mainschema = schemaid;
2684 data->mainschemaoffsets = sat_calloc(sp - schema, sizeof(Id));
2686 keypstart = data->schemadata + data->schemata[schemaid];
2687 for (keyp = keypstart; *keyp; keyp++)
2690 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2691 if (*keyp == solvkeyid)
2693 /* add flexarray entry count */
2694 data_addid(&newincore, data->end - data->start);
2697 key = data->keys + *keyp;
2699 fprintf(stderr, "internalize %d(%d):%s:%s\n", entry, entry + data->start, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
2704 /* Skip the data associated with this old key. */
2705 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2707 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2708 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2710 else if (key->storage == KEY_STORAGE_INCORE)
2711 ndp = data_skip_key(data, dp, key);
2714 if (seen[*keyp] == -1)
2716 /* If this key was an old one _and_ was not overwritten with
2717 a different value copy over the old value (we skipped it
2720 data_addblob(&newincore, dp, ndp - dp);
2723 else if (seen[*keyp])
2725 /* Otherwise we have a new value. Parse it into the internal
2727 repodata_serialize_key(data, &newincore, &newvincore,
2728 schema, key, seen[*keyp] - 1);
2732 if (entry >= 0 && data->attrs && data->attrs[entry])
2733 data->attrs[entry] = sat_free(data->attrs[entry]);
2735 /* free all xattrs */
2736 for (entry = 0; entry < data->nxattrs; entry++)
2737 if (data->xattrs[entry])
2738 sat_free(data->xattrs[entry]);
2739 data->xattrs = sat_free(data->xattrs);
2742 data->lasthandle = 0;
2744 data->lastdatalen = 0;
2747 repodata_free_schemahash(data);
2749 sat_free(data->incoredata);
2750 data->incoredata = newincore.buf;
2751 data->incoredatalen = newincore.len;
2752 data->incoredatafree = 0;
2754 sat_free(data->vincore);
2755 data->vincore = newvincore.buf;
2756 data->vincorelen = newvincore.len;
2758 data->attrs = sat_free(data->attrs);
2759 data->attrdata = sat_free(data->attrdata);
2760 data->attriddata = sat_free(data->attriddata);
2761 data->attrdatalen = 0;
2762 data->attriddatalen = 0;
2766 repodata_disable_paging(Repodata *data)
2768 if (maybe_load_repodata(data, 0))
2769 repopagestore_disable_paging(&data->store);
2773 repodata_load_stub(Repodata *data)
2775 Repo *repo = data->repo;
2776 Pool *pool = repo->pool;
2779 if (!pool->loadcallback)
2781 data->state = REPODATA_ERROR;
2784 data->state = REPODATA_LOADING;
2785 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2786 data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
2790 repodata_create_stubs(Repodata *data)
2792 Repo *repo = data->repo;
2793 Pool *pool = repo->pool;
2800 int datastart, dataend;
2802 repodataid = data - repo->repodata;
2803 datastart = data->start;
2804 dataend = data->end;
2805 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2806 while (dataiterator_step(&di))
2808 if (di.data - repo->repodata != repodataid)
2812 dataiterator_free(&di);
2815 stubdataids = sat_calloc(cnt, sizeof(*stubdataids));
2816 for (i = 0; i < cnt; i++)
2818 sdata = repo_add_repodata(repo, 0);
2819 if (dataend > datastart)
2820 repodata_extend_block(sdata, datastart, dataend - datastart);
2821 stubdataids[i] = sdata - repo->repodata;
2822 sdata->state = REPODATA_STUB;
2823 sdata->loadcallback = repodata_load_stub;
2826 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2828 while (dataiterator_step(&di))
2830 if (di.data - repo->repodata != repodataid)
2832 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
2834 dataiterator_entersub(&di);
2835 sdata = repo->repodata + stubdataids[i++];
2839 switch (di.key->type)
2841 case REPOKEY_TYPE_ID:
2842 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
2844 case REPOKEY_TYPE_CONSTANTID:
2845 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
2847 case REPOKEY_TYPE_STR:
2848 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
2850 case REPOKEY_TYPE_VOID:
2851 repodata_set_void(sdata, SOLVID_META, di.key->name);
2853 case REPOKEY_TYPE_NUM:
2854 repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num);
2856 case REPOKEY_TYPE_MD5:
2857 case REPOKEY_TYPE_SHA1:
2858 case REPOKEY_TYPE_SHA256:
2859 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
2861 case REPOKEY_TYPE_IDARRAY:
2862 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
2863 if (di.key->name == REPOSITORY_KEYS)
2870 xkeyname = di.kv.id;
2873 xkey.name = xkeyname;
2874 xkey.type = di.kv.id;
2875 xkey.storage = KEY_STORAGE_INCORE;
2877 repodata_key2id(sdata, &xkey, 1);
2884 dataiterator_free(&di);
2885 for (i = 0; i < cnt; i++)
2886 repodata_internalize(repo->repodata + stubdataids[i]);
2887 sat_free(stubdataids);
2891 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: