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 /***************************************************************
125 * key pool management
128 /* this is not so time critical that we need a hash, so we do a simple
131 repodata_key2id(Repodata *data, Repokey *key, int create)
135 for (keyid = 1; keyid < data->nkeys; keyid++)
136 if (data->keys[keyid].name == key->name && data->keys[keyid].type == key->type)
138 if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != data->keys[keyid].size)
142 if (keyid == data->nkeys)
146 /* allocate new key */
147 data->keys = sat_realloc2(data->keys, data->nkeys + 1, sizeof(Repokey));
148 data->keys[data->nkeys++] = *key;
149 if (data->verticaloffset)
151 data->verticaloffset = sat_realloc2(data->verticaloffset, data->nkeys, sizeof(Id));
152 data->verticaloffset[data->nkeys - 1] = 0;
154 data->keybits[(key->name >> 3) & (sizeof(data->keybits) - 1)] |= 1 << (key->name & 7);
160 /***************************************************************
161 * schema pool management
164 #define SCHEMATA_BLOCK 31
165 #define SCHEMATADATA_BLOCK 255
168 repodata_schema2id(Repodata *data, Id *schema, int create)
174 if ((schematahash = data->schematahash) == 0)
176 data->schematahash = schematahash = sat_calloc(256, sizeof(Id));
177 for (i = 0; i < data->nschemata; i++)
179 for (sp = data->schemadata + data->schemata[i], h = 0; *sp; len++)
182 schematahash[h] = i + 1;
184 data->schemadata = sat_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
185 data->schemata = sat_extend_resize(data->schemata, data->nschemata, sizeof(Id), SCHEMATA_BLOCK);
188 for (sp = schema, len = 0, h = 0; *sp; len++)
193 cid = schematahash[h];
197 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
200 for (cid = 0; cid < data->nschemata; cid++)
201 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
207 data->schemadata = sat_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
208 data->schemata = sat_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
210 memcpy(data->schemadata + data->schemadatalen, schema, len * sizeof(Id));
211 data->schemata[data->nschemata] = data->schemadatalen;
212 data->schemadatalen += len;
213 schematahash[h] = data->nschemata + 1;
215 fprintf(stderr, "schema2id: new schema\n");
217 return data->nschemata++;
221 repodata_free_schemahash(Repodata *data)
223 data->schematahash = sat_free(data->schematahash);
225 data->schemata = sat_realloc2(data->schemata, data->nschemata, sizeof(Id));
226 data->schemadata = sat_realloc2(data->schemadata, data->schemadatalen, sizeof(Id));
230 /***************************************************************
231 * dir pool management
234 #ifndef HAVE_STRCHRNUL
235 static inline const char *strchrnul(const char *str, char x)
237 const char *p = strchr(str, x);
238 return p ? p : str + strlen(str);
243 repodata_str2dir(Repodata *data, const char *dir, int create)
249 while (*dir == '/' && dir[1] == '/')
251 if (*dir == '/' && !dir[1])
253 if (data->dirpool.ndirs)
255 return dirpool_add_dir(&data->dirpool, 0, 1, create);
259 dire = strchrnul(dir, '/');
261 id = stringpool_strn2id(&data->spool, dir, dire - dir, create);
263 id = strn2id(data->repo->pool, dir, dire - dir, create);
266 parent = dirpool_add_dir(&data->dirpool, parent, id, create);
279 repodata_dir2str(Repodata *data, Id did, const char *suf)
281 Pool *pool = data->repo->pool;
288 return suf ? suf : "";
292 comp = dirpool_compid(&data->dirpool, parent);
293 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
295 parent = dirpool_parent(&data->dirpool, parent);
300 l += strlen(suf) + 1;
301 p = pool_alloctmpspace(pool, l + 1) + l;
312 comp = dirpool_compid(&data->dirpool, parent);
313 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
316 strncpy(p, comps, l);
317 parent = dirpool_parent(&data->dirpool, parent);
325 /***************************************************************
329 static inline unsigned char *
330 data_skip_schema(Repodata *data, unsigned char *dp, Id schema)
332 Id *keyp = data->schemadata + data->schemata[schema];
333 for (; *keyp; keyp++)
334 dp = data_skip_key(data, dp, data->keys + *keyp);
339 data_skip_key(Repodata *data, unsigned char *dp, Repokey *key)
341 int nentries, schema;
344 case REPOKEY_TYPE_FIXARRAY:
345 dp = data_read_id(dp, &nentries);
348 dp = data_read_id(dp, &schema);
350 dp = data_skip_schema(data, dp, schema);
352 case REPOKEY_TYPE_FLEXARRAY:
353 dp = data_read_id(dp, &nentries);
356 dp = data_read_id(dp, &schema);
357 dp = data_skip_schema(data, dp, schema);
361 if (key->storage == KEY_STORAGE_INCORE)
362 dp = data_skip(dp, key->type);
363 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
365 dp = data_skip(dp, REPOKEY_TYPE_ID);
366 dp = data_skip(dp, REPOKEY_TYPE_ID);
372 static unsigned char *
373 forward_to_key(Repodata *data, Id keyid, Id *keyp, unsigned char *dp)
379 if (data->mainschemaoffsets && dp == data->incoredata + data->mainschemaoffsets[0] && keyp == data->schemadata + data->schemata[data->mainschema])
382 for (i = 0; (k = *keyp++) != 0; i++)
384 return data->incoredata + data->mainschemaoffsets[i];
387 while ((k = *keyp++) != 0)
391 if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
393 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip offset */
394 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip length */
397 if (data->keys[k].storage != KEY_STORAGE_INCORE)
399 dp = data_skip_key(data, dp, data->keys + k);
404 static unsigned char *
405 get_vertical_data(Repodata *data, Repokey *key, Id off, Id len)
410 if (off >= data->lastverticaloffset)
412 off -= data->lastverticaloffset;
413 if (off + len > data->vincorelen)
415 return data->vincore + off;
417 if (off + len > key->size)
419 /* we now have the offset, go into vertical */
420 off += data->verticaloffset[key - data->keys];
421 /* fprintf(stderr, "key %d page %d\n", key->name, off / BLOB_PAGESIZE); */
422 dp = repopagestore_load_page_range(&data->store, off / BLOB_PAGESIZE, (off + len - 1) / BLOB_PAGESIZE);
424 dp += off % BLOB_PAGESIZE;
428 static inline unsigned char *
429 get_data(Repodata *data, Repokey *key, unsigned char **dpp, int advance)
431 unsigned char *dp = *dpp;
435 if (key->storage == KEY_STORAGE_INCORE)
438 *dpp = data_skip_key(data, dp, key);
441 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
444 dp = data_read_id(dp, &off);
445 dp = data_read_id(dp, &len);
448 return get_vertical_data(data, key, off, len);
454 load_repodata(Repodata *data)
456 if (data->loadcallback)
458 data->loadcallback(data);
459 if (data->state == REPODATA_AVAILABLE)
462 data->state = REPODATA_ERROR;
467 maybe_load_repodata(Repodata *data, Id keyname)
469 if (keyname && !repodata_precheck_keyname(data, keyname))
470 return 0; /* do not bother... */
477 for (i = 0; i < data->nkeys; i++)
478 if (keyname == data->keys[i].name)
480 if (i == data->nkeys)
483 return load_repodata(data);
486 case REPODATA_AVAILABLE:
487 case REPODATA_LOADING:
490 data->state = REPODATA_ERROR;
495 static inline unsigned char *
496 solvid2data(Repodata *data, Id solvid, Id *schemap)
498 unsigned char *dp = data->incoredata;
501 if (solvid == SOLVID_META) /* META */
503 else if (solvid == SOLVID_POS) /* META */
505 Pool *pool = data->repo->pool;
506 if (data->repo != pool->pos.repo)
508 if (data != data->repo->repodata + pool->pos.repodataid)
510 *schemap = pool->pos.schema;
511 return data->incoredata + pool->pos.dp;
515 if (solvid < data->start || solvid >= data->end)
517 dp += data->incoreoffset[solvid - data->start];
519 return data_read_id(dp, schemap);
522 /************************************************************************
526 static inline unsigned char *
527 find_key_data(Repodata *data, Id solvid, Id keyname, Repokey **keypp)
530 Id schema, *keyp, *kp;
533 if (!maybe_load_repodata(data, keyname))
535 dp = solvid2data(data, solvid, &schema);
538 keyp = data->schemadata + data->schemata[schema];
539 for (kp = keyp; *kp; kp++)
540 if (data->keys[*kp].name == keyname)
544 *keypp = key = data->keys + *kp;
545 if (key->type == REPOKEY_TYPE_DELETED)
547 if (key->type == REPOKEY_TYPE_VOID || key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID)
548 return dp; /* no need to forward... */
549 dp = forward_to_key(data, *kp, keyp, dp);
552 return get_data(data, key, &dp, 0);
556 repodata_lookup_type(Repodata *data, Id solvid, Id keyname)
558 Id schema, *keyp, *kp;
559 if (!maybe_load_repodata(data, keyname))
561 if (!solvid2data(data, solvid, &schema))
563 keyp = data->schemadata + data->schemata[schema];
564 for (kp = keyp; *kp; kp++)
565 if (data->keys[*kp].name == keyname)
566 return data->keys[*kp].type == REPOKEY_TYPE_DELETED ? 0 : data->keys[*kp].type;
571 repodata_lookup_id(Repodata *data, Id solvid, Id keyname)
577 dp = find_key_data(data, solvid, keyname, &key);
580 if (key->type == REPOKEY_TYPE_CONSTANTID)
582 if (key->type != REPOKEY_TYPE_ID)
584 dp = data_read_id(dp, &id);
589 repodata_lookup_str(Repodata *data, Id solvid, Id keyname)
595 dp = find_key_data(data, solvid, keyname, &key);
598 if (key->type == REPOKEY_TYPE_STR)
599 return (const char *)dp;
600 if (key->type == REPOKEY_TYPE_CONSTANTID)
601 return id2str(data->repo->pool, key->size);
602 if (key->type == REPOKEY_TYPE_ID)
603 dp = data_read_id(dp, &id);
607 return data->spool.stringspace + data->spool.strings[id];
608 return id2str(data->repo->pool, id);
612 repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned int *value)
619 dp = find_key_data(data, solvid, keyname, &key);
622 if (key->type == REPOKEY_TYPE_NUM
623 || key->type == REPOKEY_TYPE_U32
624 || key->type == REPOKEY_TYPE_CONSTANT)
626 dp = data_fetch(dp, &kv, key);
634 repodata_lookup_void(Repodata *data, Id solvid, Id keyname)
640 if (!maybe_load_repodata(data, keyname))
642 dp = solvid2data(data, solvid, &schema);
645 /* can't use find_key_data as we need to test the type */
646 for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++)
647 if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID)
652 const unsigned char *
653 repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep)
658 dp = find_key_data(data, solvid, keyname, &key);
666 repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
674 dp = find_key_data(data, solvid, keyname, &key);
679 dp = data_read_ideof(dp, &id, &eof);
688 repodata_globalize_id(Repodata *data, Id id, int create)
690 if (!id || !data || !data->localpool)
692 return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
696 /************************************************************************
702 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
706 case REPOKEY_TYPE_ID:
707 case REPOKEY_TYPE_CONSTANTID:
708 case REPOKEY_TYPE_IDARRAY:
709 if (data && data->localpool)
710 kv->str = stringpool_id2str(&data->spool, kv->id);
712 kv->str = id2str(pool, kv->id);
713 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
716 for (s = kv->str; *s >= 'a' && *s <= 'z'; s++)
718 if (*s == ':' && s > kv->str)
722 case REPOKEY_TYPE_STR:
724 case REPOKEY_TYPE_DIRSTRARRAY:
725 if (!(flags & SEARCH_FILES))
726 return 1; /* match just the basename */
727 /* Put the full filename into kv->str. */
728 kv->str = repodata_dir2str(data, kv->id, kv->str);
729 /* And to compensate for that put the "empty" directory into
730 kv->id, so that later calls to repodata_dir2str on this data
731 come up with the same filename again. */
734 case REPOKEY_TYPE_MD5:
735 case REPOKEY_TYPE_SHA1:
736 case REPOKEY_TYPE_SHA256:
737 if (!(flags & SEARCH_CHECKSUMS))
738 return 0; /* skip em */
739 kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str);
747 struct subschema_data {
753 /* search a specific repodata */
755 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
759 Id keyid, *kp, *keyp;
760 unsigned char *dp, *ddp;
766 if (!maybe_load_repodata(data, keyname))
768 if (solvid == SOLVID_SUBSCHEMA)
770 struct subschema_data *subd = cbdata;
771 cbdata = subd->cbdata;
773 schema = subd->parent->id;
774 dp = (unsigned char *)subd->parent->str;
775 kv.parent = subd->parent;
780 dp = solvid2data(data, solvid, &schema);
783 s = data->repo->pool->solvables + solvid;
786 keyp = data->schemadata + data->schemata[schema];
789 /* search for a specific key */
790 for (kp = keyp; *kp; kp++)
791 if (data->keys[*kp].name == keyname)
795 dp = forward_to_key(data, *kp, keyp, dp);
801 while ((keyid = *keyp++) != 0)
804 key = data->keys + keyid;
805 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
807 if (key->type == REPOKEY_TYPE_DELETED)
809 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
811 struct subschema_data subd;
815 subd.cbdata = cbdata;
818 ddp = data_read_id(ddp, &nentries);
822 while (ddp && nentries > 0)
826 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
827 ddp = data_read_id(ddp, &schema);
829 kv.str = (char *)ddp;
830 stop = callback(cbdata, s, data, key, &kv);
831 if (stop > SEARCH_NEXT_KEY)
833 if (stop && stop != SEARCH_ENTERSUB)
835 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
836 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
837 ddp = data_skip_schema(data, ddp, schema);
840 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
844 kv.str = (char *)ddp;
845 stop = callback(cbdata, s, data, key, &kv);
846 if (stop > SEARCH_NEXT_KEY)
856 ddp = data_fetch(ddp, &kv, key);
859 stop = callback(cbdata, s, data, key, &kv);
862 while (!kv.eof && !stop);
863 if (onekey || stop > SEARCH_NEXT_KEY)
869 repodata_setpos_kv(Repodata *data, KeyValue *kv)
871 Pool *pool = data->repo->pool;
873 pool_clear_pos(pool);
876 pool->pos.repo = data->repo;
877 pool->pos.repodataid = data - data->repo->repodata;
878 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
879 pool->pos.schema = kv->id;
883 /************************************************************************
884 * data iterator functions
887 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
888 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
889 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
890 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
891 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
892 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
893 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
894 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
895 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
896 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
897 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
898 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
899 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
900 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
904 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
918 case SOLVABLE_VENDOR:
921 case SOLVABLE_PROVIDES:
923 return s->provides ? s->repo->idarraydata + s->provides : 0;
924 case SOLVABLE_OBSOLETES:
926 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
927 case SOLVABLE_CONFLICTS:
929 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
930 case SOLVABLE_REQUIRES:
932 return s->requires ? s->repo->idarraydata + s->requires : 0;
933 case SOLVABLE_RECOMMENDS:
935 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
936 case SOLVABLE_SUPPLEMENTS:
938 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
939 case SOLVABLE_SUGGESTS:
941 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
942 case SOLVABLE_ENHANCES:
944 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
947 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
954 datamatcher_init(Datamatcher *ma, const char *match, int flags)
960 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
962 ma->matchdata = sat_calloc(1, sizeof(regex_t));
963 ma->error = regcomp((regex_t *)ma->matchdata, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
966 sat_free(ma->matchdata);
967 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
974 datamatcher_free(Datamatcher *ma)
976 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
978 regfree(ma->matchdata);
979 ma->matchdata = sat_free(ma->matchdata);
984 datamatcher_match(Datamatcher *ma, const char *str)
987 switch ((ma->flags & SEARCH_STRINGMASK))
989 case SEARCH_SUBSTRING:
990 if (ma->flags & SEARCH_NOCASE)
992 if (!strcasestr(str, ma->match))
997 if (!strstr(str, ma->match))
1002 if (ma->flags & SEARCH_NOCASE)
1004 if (strcasecmp(ma->match, str))
1009 if (strcmp(ma->match, str))
1013 case SEARCH_STRINGSTART:
1014 if (ma->flags & SEARCH_NOCASE)
1016 if (strncasecmp(ma->match, str, strlen(ma->match)))
1021 if (strncmp(ma->match, str, strlen(ma->match)))
1025 case SEARCH_STRINGEND:
1026 l = strlen(str) - strlen(ma->match);
1029 if (ma->flags & SEARCH_NOCASE)
1031 if (strcasecmp(ma->match, str + l))
1036 if (strcmp(ma->match, str + l))
1041 if (fnmatch(ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
1045 if (regexec((const regex_t *)ma->matchdata, str, 0, NULL, 0))
1055 repodata_filelistfilter_matches(Repodata *data, const char *str)
1057 /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */
1058 /* for now hardcoded */
1059 if (strstr(str, "bin/"))
1061 if (!strncmp(str, "/etc/", 5))
1063 if (!strcmp(str, "/usr/lib/sendmail"))
1085 di_nextarrayelement,
1090 di_nextsolvableattr,
1095 /* see repo.h for documentation */
1097 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
1099 memset(di, 0, sizeof(*di));
1101 di->flags = flags & ~SEARCH_THISSOLVID;
1102 if (!pool || (repo && repo->pool != pool))
1110 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1116 di->keyname = keyname;
1117 di->keynames[0] = keyname;
1118 dataiterator_set_search(di, repo, p);
1123 dataiterator_init_clone(Dataiterator *di, Dataiterator *from)
1126 memset(&di->matcher, 0, sizeof(di->matcher));
1127 if (from->matcher.match)
1128 datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags);
1133 for (i = 1; i < di->nparents; i++)
1134 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1135 di->kv.parent = &di->parents[di->nparents - 1].kv;
1140 dataiterator_set_match(Dataiterator *di, const char *match, int flags)
1142 di->flags = (flags & ~SEARCH_THISSOLVID) | (di->flags & SEARCH_THISSOLVID);
1143 datamatcher_free(&di->matcher);
1144 memset(&di->matcher, 0, sizeof(di->matcher));
1148 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1158 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
1162 di->flags &= ~SEARCH_THISSOLVID;
1166 if (!di->pool->nrepos)
1174 di->repo = di->pool->repos[0];
1176 di->state = di_enterrepo;
1178 dataiterator_jump_to_solvid(di, p);
1182 dataiterator_set_keyname(Dataiterator *di, Id keyname)
1185 di->keyname = keyname;
1186 di->keynames[0] = keyname;
1190 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1194 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1196 di->state = di_bye; /* sorry */
1199 for (i = di->nkeynames + 1; i > 0; i--)
1200 di->keynames[i] = di->keynames[i - 1];
1201 di->keynames[0] = di->keyname = keyname;
1206 dataiterator_free(Dataiterator *di)
1208 if (di->matcher.match)
1209 datamatcher_free(&di->matcher);
1212 static inline unsigned char *
1213 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1215 Id *keyp = di->keyp;
1216 Repokey *keys = di->data->keys;
1219 for (keyp = di->keyp; *keyp; keyp++)
1220 if (keys[*keyp].name == keyname)
1224 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1232 dataiterator_filelistcheck(Dataiterator *di)
1235 int needcomplete = 0;
1236 Repodata *data = di->data;
1238 if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
1239 if (!di->matcher.match
1240 || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
1241 && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)
1242 || !repodata_filelistfilter_matches(di->data, di->matcher.match))
1244 if (data->state != REPODATA_AVAILABLE)
1245 return needcomplete ? 1 : 0;
1246 for (j = 1; j < data->nkeys; j++)
1247 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
1249 return j == data->nkeys && !needcomplete ? 0 : 1;
1253 dataiterator_step(Dataiterator *di)
1261 case di_enterrepo: di_enterrepo:
1264 if (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS))
1266 if (!(di->flags & SEARCH_THISSOLVID))
1268 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1269 goto di_nextsolvable;
1273 case di_entersolvable: di_entersolvable:
1274 if (di->repodataid >= 0)
1276 di->repodataid = 0; /* reset repodata iterator */
1277 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)
1279 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1281 goto di_entersolvablekey;
1286 case di_enterrepodata: di_enterrepodata:
1287 if (di->repodataid >= 0)
1289 if (di->repodataid >= di->repo->nrepodata)
1290 goto di_nextsolvable;
1291 di->data = di->repo->repodata + di->repodataid;
1293 if (di->repodataid >= 0 && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
1294 goto di_nextrepodata;
1295 if (!maybe_load_repodata(di->data, di->keyname))
1296 goto di_nextrepodata;
1297 di->dp = solvid2data(di->data, di->solvid, &schema);
1299 goto di_nextrepodata;
1300 if (di->solvid == SOLVID_POS)
1301 di->solvid = di->pool->pos.solvid;
1302 /* reset key iterator */
1303 di->keyp = di->data->schemadata + di->data->schemata[schema];
1306 case di_enterschema: di_enterschema:
1308 di->dp = dataiterator_find_keyname(di, di->keyname);
1309 if (!di->dp || !*di->keyp)
1313 goto di_nextrepodata;
1317 case di_enterkey: di_enterkey:
1319 di->key = di->data->keys + *di->keyp;
1320 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1323 if (di->key->type == REPOKEY_TYPE_DELETED)
1325 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1327 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1333 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1335 di->state = di_nextkey;
1337 di->state = di_nextattr;
1340 case di_nextkey: di_nextkey:
1341 if (!di->keyname && *++di->keyp)
1347 case di_nextrepodata: di_nextrepodata:
1348 if (di->repodataid >= 0 && ++di->repodataid < di->repo->nrepodata)
1349 goto di_enterrepodata;
1352 case di_nextsolvable: di_nextsolvable:
1353 if (!(di->flags & SEARCH_THISSOLVID))
1356 di->solvid = di->repo->start;
1359 for (; di->solvid < di->repo->end; di->solvid++)
1361 if (di->pool->solvables[di->solvid].repo == di->repo)
1362 goto di_entersolvable;
1367 case di_nextrepo: di_nextrepo:
1368 if (di->repoid >= 0)
1372 if (di->repoid < di->pool->nrepos)
1374 di->repo = di->pool->repos[di->repoid];
1380 case di_bye: di_bye:
1384 case di_enterarray: di_enterarray:
1385 if (di->key->name == REPOSITORY_SOLVABLES)
1387 di->ddp = data_read_id(di->ddp, &di->kv.num);
1392 case di_nextarrayelement: di_nextarrayelement:
1395 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1396 if (di->kv.entry == di->kv.num)
1398 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1400 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1402 di->kv.str = (char *)di->ddp;
1404 di->state = di_nextkey;
1407 if (di->kv.entry == di->kv.num - 1)
1409 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1410 di->ddp = data_read_id(di->ddp, &di->kv.id);
1411 di->kv.str = (char *)di->ddp;
1412 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1414 if ((di->flags & SEARCH_SUB) != 0)
1415 di->state = di_entersub;
1417 di->state = di_nextarrayelement;
1420 case di_entersub: di_entersub:
1421 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1422 goto di_nextarrayelement; /* sorry, full */
1423 di->parents[di->nparents].kv = di->kv;
1424 di->parents[di->nparents].dp = di->dp;
1425 di->parents[di->nparents].keyp = di->keyp;
1426 di->dp = (unsigned char *)di->kv.str;
1427 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1428 memset(&di->kv, 0, sizeof(di->kv));
1429 di->kv.parent = &di->parents[di->nparents].kv;
1431 di->keyname = di->keynames[di->nparents - di->rootlevel];
1432 goto di_enterschema;
1434 case di_leavesub: di_leavesub:
1435 if (di->nparents - 1 < di->rootlevel)
1438 di->dp = di->parents[di->nparents].dp;
1439 di->kv = di->parents[di->nparents].kv;
1440 di->keyp = di->parents[di->nparents].keyp;
1441 di->key = di->data->keys + *di->keyp;
1442 di->ddp = (unsigned char *)di->kv.str;
1443 di->keyname = di->keynames[di->nparents - di->rootlevel];
1444 goto di_nextarrayelement;
1446 /* special solvable attr handling follows */
1448 case di_nextsolvableattr:
1449 di->kv.id = *di->idp++;
1454 di->state = di_nextsolvablekey;
1458 case di_nextsolvablekey: di_nextsolvablekey:
1459 if (di->keyname || di->key->name == RPM_RPMDBID)
1460 goto di_enterrepodata;
1464 case di_entersolvablekey: di_entersolvablekey:
1465 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1466 if (!di->idp || !di->idp[0])
1467 goto di_nextsolvablekey;
1468 di->kv.id = di->idp[0];
1469 di->kv.num = di->idp[0];
1471 if (!di->kv.eof && !di->idp[0])
1475 di->state = di_nextsolvablekey;
1477 di->state = di_nextsolvableattr;
1481 if (di->matcher.match)
1483 /* simple pre-check so that we don't need to stringify */
1484 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))
1486 int l = strlen(di->matcher.match) - strlen(di->kv.str);
1487 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
1490 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1492 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1496 if (!datamatcher_match(&di->matcher, di->kv.str))
1499 /* found something! */
1505 dataiterator_entersub(Dataiterator *di)
1507 if (di->state == di_nextarrayelement)
1508 di->state = di_entersub;
1512 dataiterator_setpos(Dataiterator *di)
1514 if (di->kv.eof == 2)
1516 pool_clear_pos(di->pool);
1519 di->pool->pos.solvid = di->solvid;
1520 di->pool->pos.repo = di->repo;
1521 di->pool->pos.repodataid = di->data - di->repo->repodata;
1522 di->pool->pos.schema = di->kv.id;
1523 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1527 dataiterator_setpos_parent(Dataiterator *di)
1529 if (!di->kv.parent || di->kv.parent->eof == 2)
1531 pool_clear_pos(di->pool);
1534 di->pool->pos.solvid = di->solvid;
1535 di->pool->pos.repo = di->repo;
1536 di->pool->pos.repodataid = di->data - di->repo->repodata;
1537 di->pool->pos.schema = di->kv.parent->id;
1538 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1541 /* clones just the position, not the search keys/matcher */
1543 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
1545 di->state = from->state;
1546 di->flags &= ~SEARCH_THISSOLVID;
1547 di->flags |= (from->flags & SEARCH_THISSOLVID);
1548 di->repo = from->repo;
1549 di->data = from->data;
1551 di->ddp = from->ddp;
1552 di->idp = from->idp;
1553 di->keyp = from->keyp;
1554 di->key = from->key;
1556 di->repodataid = from->repodataid;
1557 di->solvid = from->solvid;
1558 di->repoid = from->repoid;
1559 di->rootlevel = from->rootlevel;
1560 memcpy(di->parents, from->parents, sizeof(from->parents));
1561 di->nparents = from->nparents;
1565 for (i = 1; i < di->nparents; i++)
1566 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1567 di->kv.parent = &di->parents[di->nparents - 1].kv;
1572 dataiterator_seek(Dataiterator *di, int whence)
1574 if ((whence & DI_SEEK_STAY) != 0)
1575 di->rootlevel = di->nparents;
1576 switch (whence & ~DI_SEEK_STAY)
1579 if (di->state != di_nextarrayelement)
1581 if ((whence & DI_SEEK_STAY) != 0)
1582 di->rootlevel = di->nparents + 1; /* XXX: dangerous! */
1583 di->state = di_entersub;
1585 case DI_SEEK_PARENT:
1592 if (di->rootlevel > di->nparents)
1593 di->rootlevel = di->nparents;
1594 di->dp = di->parents[di->nparents].dp;
1595 di->kv = di->parents[di->nparents].kv;
1596 di->keyp = di->parents[di->nparents].keyp;
1597 di->key = di->data->keys + *di->keyp;
1598 di->ddp = (unsigned char *)di->kv.str;
1599 di->keyname = di->keynames[di->nparents - di->rootlevel];
1600 di->state = di_nextarrayelement;
1602 case DI_SEEK_REWIND:
1608 di->dp = (unsigned char *)di->kv.parent->str;
1609 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
1610 di->state = di_enterschema;
1618 dataiterator_skip_attribute(Dataiterator *di)
1620 if (di->state == di_nextsolvableattr)
1621 di->state = di_nextsolvablekey;
1623 di->state = di_nextkey;
1627 dataiterator_skip_solvable(Dataiterator *di)
1632 di->keyname = di->keynames[0];
1633 di->state = di_nextsolvable;
1637 dataiterator_skip_repo(Dataiterator *di)
1642 di->keyname = di->keynames[0];
1643 di->state = di_nextrepo;
1647 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1652 di->keyname = di->keynames[0];
1653 if (solvid == SOLVID_POS)
1655 di->repo = di->pool->pos.repo;
1662 di->data = di->repo->repodata + di->pool->pos.repodataid;
1663 di->repodataid = -1;
1664 di->solvid = solvid;
1665 di->state = di_enterrepo;
1666 di->flags |= SEARCH_THISSOLVID;
1671 di->repo = di->pool->solvables[solvid].repo;
1674 else if (di->repoid >= 0)
1676 if (!di->pool->nrepos)
1681 di->repo = di->pool->repos[0];
1685 di->solvid = solvid;
1687 di->flags |= SEARCH_THISSOLVID;
1688 di->state = di_enterrepo;
1692 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1701 di->flags &= ~SEARCH_THISSOLVID;
1702 di->state = di_enterrepo;
1706 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1708 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1712 return datamatcher_match(ma, di->kv.str);
1715 /************************************************************************
1716 * data modify functions
1719 /* extend repodata so that it includes solvables p */
1721 repodata_extend(Repodata *data, Id p)
1723 if (data->start == data->end)
1724 data->start = data->end = p;
1727 int old = data->end - data->start;
1728 int new = p - data->end + 1;
1731 data->attrs = sat_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1732 memset(data->attrs + old, 0, new * sizeof(Id *));
1734 data->incoreoffset = sat_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1735 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1738 if (p < data->start)
1740 int old = data->end - data->start;
1741 int new = data->start - p;
1744 data->attrs = sat_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1745 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1746 memset(data->attrs, 0, new * sizeof(Id *));
1748 data->incoreoffset = sat_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1749 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1750 memset(data->incoreoffset, 0, new * sizeof(Id));
1755 /* shrink end of repodata */
1757 repodata_shrink(Repodata *data, int end)
1761 if (data->end <= end)
1763 if (data->start >= end)
1767 for (i = 0; i < data->end - data->start; i++)
1768 sat_free(data->attrs[i]);
1769 data->attrs = sat_free(data->attrs);
1771 data->incoreoffset = sat_free(data->incoreoffset);
1772 data->start = data->end = 0;
1777 for (i = end; i < data->end; i++)
1778 sat_free(data->attrs[i - data->start]);
1779 data->attrs = sat_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
1781 if (data->incoreoffset)
1782 data->incoreoffset = sat_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
1786 /* extend repodata so that it includes solvables from start to start + num - 1 */
1788 repodata_extend_block(Repodata *data, Id start, Id num)
1792 if (!data->incoreoffset)
1794 data->incoreoffset = sat_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1795 data->start = start;
1796 data->end = start + num;
1799 repodata_extend(data, start);
1801 repodata_extend(data, start + num - 1);
1804 /**********************************************************************/
1807 #define REPODATA_ATTRS_BLOCK 31
1808 #define REPODATA_ATTRDATA_BLOCK 1023
1809 #define REPODATA_ATTRIDDATA_BLOCK 63
1813 repodata_new_handle(Repodata *data)
1817 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1820 data->xattrs = sat_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1821 data->xattrs[data->nxattrs] = 0;
1822 return -(data->nxattrs++);
1826 repodata_get_attrp(Repodata *data, Id handle)
1828 if (handle == SOLVID_META)
1832 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1837 return data->xattrs - handle;
1838 if (handle < data->start || handle >= data->end)
1839 repodata_extend(data, handle);
1841 data->attrs = sat_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1842 return data->attrs + (handle - data->start);
1846 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1852 app = repodata_get_attrp(data, handle);
1857 /* Determine equality based on the name only, allows us to change
1858 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1859 for (pp = ap; *pp; pp += 2)
1860 if (data->keys[*pp].name == data->keys[keyid].name)
1873 ap = sat_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1883 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1887 keyid = repodata_key2id(data, key, 1);
1888 repodata_insert_keyid(data, solvid, keyid, val, 1);
1892 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1896 key.type = REPOKEY_TYPE_ID;
1898 key.storage = KEY_STORAGE_INCORE;
1899 repodata_set(data, solvid, &key, id);
1903 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1907 key.type = REPOKEY_TYPE_NUM;
1909 key.storage = KEY_STORAGE_INCORE;
1910 repodata_set(data, solvid, &key, (Id)num);
1914 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
1918 if (data->localpool)
1919 id = stringpool_str2id(&data->spool, str, 1);
1921 id = str2id(data->repo->pool, str, 1);
1923 key.type = REPOKEY_TYPE_ID;
1925 key.storage = KEY_STORAGE_INCORE;
1926 repodata_set(data, solvid, &key, id);
1930 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
1934 key.type = REPOKEY_TYPE_CONSTANT;
1935 key.size = constant;
1936 key.storage = KEY_STORAGE_INCORE;
1937 repodata_set(data, solvid, &key, 0);
1941 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
1945 key.type = REPOKEY_TYPE_CONSTANTID;
1947 key.storage = KEY_STORAGE_INCORE;
1948 repodata_set(data, solvid, &key, 0);
1952 repodata_set_void(Repodata *data, Id solvid, Id keyname)
1956 key.type = REPOKEY_TYPE_VOID;
1958 key.storage = KEY_STORAGE_INCORE;
1959 repodata_set(data, solvid, &key, 0);
1963 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
1968 l = strlen(str) + 1;
1970 key.type = REPOKEY_TYPE_STR;
1972 key.storage = KEY_STORAGE_INCORE;
1973 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1974 memcpy(data->attrdata + data->attrdatalen, str, l);
1975 repodata_set(data, solvid, &key, data->attrdatalen);
1976 data->attrdatalen += l;
1980 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
1986 key.type = REPOKEY_TYPE_BINARY;
1988 key.storage = KEY_STORAGE_INCORE;
1989 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
1990 dp = data->attrdata + data->attrdatalen;
1991 if (len >= (1 << 14))
1993 if (len >= (1 << 28))
1994 *dp++ = (len >> 28) | 128;
1995 if (len >= (1 << 21))
1996 *dp++ = (len >> 21) | 128;
1997 *dp++ = (len >> 14) | 128;
1999 if (len >= (1 << 7))
2000 *dp++ = (len >> 7) | 128;
2003 memcpy(dp, buf, len);
2004 repodata_set(data, solvid, &key, data->attrdatalen);
2005 data->attrdatalen = dp + len - data->attrdata;
2008 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
2009 * so that the caller can append the new element there */
2011 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
2014 Id *ida, *pp, **ppp;
2016 /* check if it is the same as last time, this speeds things up a lot */
2017 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
2019 /* great! just append the new data */
2020 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2021 data->attriddatalen--; /* overwrite terminating 0 */
2022 data->lastdatalen += entrysize;
2026 ppp = repodata_get_attrp(data, handle);
2029 for (; *pp; pp += 2)
2030 if (data->keys[*pp].name == keyname && data->keys[*pp].type == keytype)
2034 /* not found. allocate new key */
2039 key.storage = KEY_STORAGE_INCORE;
2040 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2041 repodata_set(data, handle, &key, data->attriddatalen);
2042 data->lasthandle = 0; /* next time... */
2046 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
2047 oldsize += entrysize;
2048 if (ida + 1 == data->attriddata + data->attriddatalen)
2050 /* this was the last entry, just append it */
2051 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2052 data->attriddatalen--; /* overwrite terminating 0 */
2056 /* too bad. move to back. */
2057 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2058 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
2059 pp[1] = data->attriddatalen;
2060 data->attriddatalen += oldsize;
2062 data->lasthandle = handle;
2063 data->lastkey = *pp;
2064 data->lastdatalen = data->attriddatalen + entrysize + 1;
2068 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2069 const unsigned char *str)
2074 if (!(l = sat_chksum_len(type)))
2079 key.storage = KEY_STORAGE_INCORE;
2080 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2081 memcpy(data->attrdata + data->attrdatalen, str, l);
2082 repodata_set(data, solvid, &key, data->attrdatalen);
2083 data->attrdatalen += l;
2087 hexstr2bytes(unsigned char *buf, const char *str, int buflen)
2090 for (i = 0; i < buflen; i++)
2092 #define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
2093 : ((c)>='a' && (c)<='f') ? ((c)-('a'-10)) \
2094 : ((c)>='A' && (c)<='F') ? ((c)-('A'-10)) \
2105 buf[i] = (buf[i] << 4) | v;
2112 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2115 unsigned char buf[64];
2118 if (!(l = sat_chksum_len(type)))
2120 if (hexstr2bytes(buf, str, l) != l)
2122 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2126 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2131 if (!(l = sat_chksum_len(type)))
2133 s = str = pool_alloctmpspace(data->repo->pool, 2 * l + 1);
2134 for (i = 0; i < l; i++)
2136 unsigned char v = buf[i];
2137 unsigned char w = v >> 4;
2138 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
2140 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
2146 /* rpm filenames don't contain the epoch, so strip it */
2147 static inline const char *
2148 evrid2vrstr(Pool *pool, Id evrid)
2150 const char *p, *evr = id2str(pool, evrid);
2153 for (p = evr; *p >= '0' && *p <= '9'; p++)
2155 return p != evr && *p == ':' ? p + 1 : evr;
2159 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2161 Pool *pool = data->repo->pool;
2163 const char *str, *fp;
2167 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2170 if ((dir = strrchr(file, '/')) != 0)
2181 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2186 if (l == 1 && dir[0] == '.')
2188 s = pool->solvables + solvid;
2191 str = id2str(pool, s->arch);
2192 if (!strncmp(dir, str, l) && !str[l])
2193 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2195 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2198 char *dir2 = strdup(dir);
2200 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2205 str = id2str(pool, s->name);
2207 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2210 str = evrid2vrstr(pool, s->evr);
2212 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2215 str = id2str(pool, s->arch);
2217 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2219 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2224 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2228 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2232 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2234 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2235 data->attriddata[data->attriddatalen++] = dir;
2236 data->attriddata[data->attriddatalen++] = num;
2237 data->attriddata[data->attriddatalen++] = num2;
2238 data->attriddata[data->attriddatalen++] = 0;
2242 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2248 l = strlen(str) + 1;
2249 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2250 memcpy(data->attrdata + data->attrdatalen, str, l);
2251 stroff = data->attrdatalen;
2252 data->attrdatalen += l;
2255 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2257 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2258 data->attriddata[data->attriddatalen++] = dir;
2259 data->attriddata[data->attriddatalen++] = stroff;
2260 data->attriddata[data->attriddatalen++] = 0;
2264 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2267 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2269 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2270 data->attriddata[data->attriddatalen++] = id;
2271 data->attriddata[data->attriddatalen++] = 0;
2275 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2279 if (data->localpool)
2280 id = stringpool_str2id(&data->spool, str, 1);
2282 id = str2id(data->repo->pool, str, 1);
2283 repodata_add_idarray(data, solvid, keyname, id);
2287 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2289 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2290 data->attriddata[data->attriddatalen++] = ghandle;
2291 data->attriddata[data->attriddatalen++] = 0;
2295 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2297 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2298 data->attriddata[data->attriddatalen++] = ghandle;
2299 data->attriddata[data->attriddatalen++] = 0;
2303 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2306 app = repodata_get_attrp(data, solvid);
2310 for (; *ap; ap += 2)
2311 if (data->keys[*ap].name == keyname)
2317 for (; *ap; ap += 2)
2319 if (data->keys[*ap].name == keyname)
2327 /* XXX: does not work correctly, needs fix in iterators! */
2329 repodata_delete(Repodata *data, Id solvid, Id keyname)
2333 key.type = REPOKEY_TYPE_DELETED;
2335 key.storage = KEY_STORAGE_INCORE;
2336 repodata_set(data, solvid, &key, 0);
2339 /* add all (uninternalized) attrs from src to dest */
2341 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2344 if (dest == src || !(keyp = data->attrs[src - data->start]))
2346 for (; *keyp; keyp += 2)
2347 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2350 /* add some (uninternalized) attrs from src to dest */
2352 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2355 if (dest == src || !(keyp = data->attrs[src - data->start]))
2357 for (; *keyp; keyp += 2)
2358 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2359 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2364 /**********************************************************************/
2366 /* TODO: unify with repo_write and repo_solv! */
2368 #define EXTDATA_BLOCK 1023
2376 data_addid(struct extdata *xd, Id x)
2380 xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2381 dp = xd->buf + xd->len;
2386 *dp++ = (x >> 28) | 128;
2388 *dp++ = (x >> 21) | 128;
2389 *dp++ = (x >> 14) | 128;
2392 *dp++ = (x >> 7) | 128;
2394 xd->len = dp - xd->buf;
2398 data_addideof(struct extdata *xd, Id x, int eof)
2401 x = (x & 63) | ((x & ~63) << 1);
2402 data_addid(xd, (eof ? x : x | 64));
2406 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2408 xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2409 memcpy(xd->buf + xd->len, blob, len);
2413 /*********************************/
2416 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2417 struct extdata *newvincore,
2419 Repokey *key, Id val)
2421 /* Otherwise we have a new value. Parse it into the internal
2425 unsigned int oldvincorelen = 0;
2429 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2432 oldvincorelen = xd->len;
2436 case REPOKEY_TYPE_VOID:
2437 case REPOKEY_TYPE_CONSTANT:
2438 case REPOKEY_TYPE_CONSTANTID:
2440 case REPOKEY_TYPE_STR:
2441 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2443 case REPOKEY_TYPE_MD5:
2444 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2446 case REPOKEY_TYPE_SHA1:
2447 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2449 case REPOKEY_TYPE_SHA256:
2450 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2452 case REPOKEY_TYPE_ID:
2453 case REPOKEY_TYPE_NUM:
2454 case REPOKEY_TYPE_DIR:
2455 data_addid(xd, val);
2457 case REPOKEY_TYPE_BINARY:
2460 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2462 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2465 case REPOKEY_TYPE_IDARRAY:
2466 for (ida = data->attriddata + val; *ida; ida++)
2467 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2469 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2470 for (ida = data->attriddata + val; *ida; ida += 3)
2472 data_addid(xd, ida[0]);
2473 data_addid(xd, ida[1]);
2474 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2477 case REPOKEY_TYPE_DIRSTRARRAY:
2478 for (ida = data->attriddata + val; *ida; ida += 2)
2480 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2481 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2484 case REPOKEY_TYPE_FIXARRAY:
2488 for (ida = data->attriddata + val; *ida; ida++)
2491 fprintf(stderr, "serialize struct %d\n", *ida);
2494 Id *kp = data->xattrs[-*ida];
2501 fprintf(stderr, " %s:%d\n", id2str(data->repo->pool, data->keys[*kp].name), kp[1]);
2507 schemaid = repodata_schema2id(data, schema, 1);
2508 else if (schemaid != repodata_schema2id(data, schema, 0))
2510 pool_debug(data->repo->pool, SAT_FATAL, "fixarray substructs with different schemas\n");
2514 fprintf(stderr, " schema %d\n", schemaid);
2519 data_addid(xd, num);
2520 data_addid(xd, schemaid);
2521 for (ida = data->attriddata + val; *ida; ida++)
2523 Id *kp = data->xattrs[-*ida];
2528 repodata_serialize_key(data, newincore, newvincore,
2529 schema, data->keys + *kp, kp[1]);
2534 case REPOKEY_TYPE_FLEXARRAY:
2537 for (ida = data->attriddata + val; *ida; ida++)
2539 data_addid(xd, num);
2540 for (ida = data->attriddata + val; *ida; ida++)
2542 Id *kp = data->xattrs[-*ida];
2545 data_addid(xd, 0); /* XXX */
2552 schemaid = repodata_schema2id(data, schema, 1);
2553 data_addid(xd, schemaid);
2554 kp = data->xattrs[-*ida];
2557 repodata_serialize_key(data, newincore, newvincore,
2558 schema, data->keys + *kp, kp[1]);
2564 pool_debug(data->repo->pool, SAT_FATAL, "don't know how to handle type %d\n", key->type);
2567 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2569 /* put offset/len in incore */
2570 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2571 oldvincorelen = xd->len - oldvincorelen;
2572 data_addid(newincore, oldvincorelen);
2577 repodata_internalize(Repodata *data)
2579 Repokey *key, solvkey;
2581 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2582 unsigned char *dp, *ndp;
2583 int newschema, oldcount;
2584 struct extdata newincore;
2585 struct extdata newvincore;
2588 if (!data->attrs && !data->xattrs)
2591 newvincore.buf = data->vincore;
2592 newvincore.len = data->vincorelen;
2594 /* find the solvables key, create if needed */
2595 memset(&solvkey, 0, sizeof(solvkey));
2596 solvkey.name = REPOSITORY_SOLVABLES;
2597 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2599 solvkey.storage = KEY_STORAGE_INCORE;
2600 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2602 schema = sat_malloc2(data->nkeys, sizeof(Id));
2603 seen = sat_malloc2(data->nkeys, sizeof(Id));
2605 /* Merge the data already existing (in data->schemata, ->incoredata and
2606 friends) with the new attributes in data->attrs[]. */
2607 nentry = data->end - data->start;
2608 memset(&newincore, 0, sizeof(newincore));
2609 data_addid(&newincore, 0); /* start data at offset 1 */
2611 data->mainschema = 0;
2612 data->mainschemaoffsets = sat_free(data->mainschemaoffsets);
2614 /* join entry data */
2615 /* we start with the meta data, entry -1 */
2616 for (entry = -1; entry < nentry; entry++)
2618 memset(seen, 0, data->nkeys * sizeof(Id));
2620 dp = data->incoredata;
2623 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2624 dp = data_read_id(dp, &oldschema);
2627 fprintf(stderr, "oldschema %d\n", oldschema);
2628 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2629 fprintf(stderr, "schemadata %p\n", data->schemadata);
2631 /* seen: -1: old data 0: skipped >0: id + 1 */
2635 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2639 pool_debug(data->repo->pool, SAT_FATAL, "Inconsistent old data (key occured twice).\n");
2647 keyp = data->attrs ? data->attrs[entry] : 0;
2650 /* strip solvables key */
2652 for (sp = keyp = schema; *sp; sp++)
2653 if (*sp != solvkeyid)
2658 seen[solvkeyid] = 0;
2659 keyp = data->xattrs ? data->xattrs[1] : 0;
2662 for (; *keyp; keyp += 2)
2669 seen[*keyp] = keyp[1] + 1;
2671 if (entry < 0 && data->end != data->start)
2678 /* Ideally we'd like to sort the new schema here, to ensure
2679 schema equality independend of the ordering. We can't do that
2680 yet. For once see below (old ids need to come before new ids).
2681 An additional difficulty is that we also need to move
2682 the values with the keys. */
2683 schemaid = repodata_schema2id(data, schema, 1);
2685 schemaid = oldschema;
2688 /* Now create data blob. We walk through the (possibly new) schema
2689 and either copy over old data, or insert the new. */
2690 /* XXX Here we rely on the fact that the (new) schema has the form
2691 o1 o2 o3 o4 ... | n1 n2 n3 ...
2692 (oX being the old keyids (possibly overwritten), and nX being
2693 the new keyids). This rules out sorting the keyids in order
2694 to ensure a small schema count. */
2696 data->incoreoffset[entry] = newincore.len;
2697 data_addid(&newincore, schemaid);
2700 data->mainschema = schemaid;
2701 data->mainschemaoffsets = sat_calloc(sp - schema, sizeof(Id));
2703 keypstart = data->schemadata + data->schemata[schemaid];
2704 for (keyp = keypstart; *keyp; keyp++)
2707 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2708 if (*keyp == solvkeyid)
2710 /* add flexarray entry count */
2711 data_addid(&newincore, data->end - data->start);
2714 key = data->keys + *keyp;
2716 fprintf(stderr, "internalize %d(%d):%s:%s\n", entry, entry + data->start, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
2721 /* Skip the data associated with this old key. */
2722 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2724 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2725 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2727 else if (key->storage == KEY_STORAGE_INCORE)
2728 ndp = data_skip_key(data, dp, key);
2731 if (seen[*keyp] == -1)
2733 /* If this key was an old one _and_ was not overwritten with
2734 a different value copy over the old value (we skipped it
2737 data_addblob(&newincore, dp, ndp - dp);
2740 else if (seen[*keyp])
2742 /* Otherwise we have a new value. Parse it into the internal
2744 repodata_serialize_key(data, &newincore, &newvincore,
2745 schema, key, seen[*keyp] - 1);
2749 if (entry >= 0 && data->attrs && data->attrs[entry])
2750 data->attrs[entry] = sat_free(data->attrs[entry]);
2752 /* free all xattrs */
2753 for (entry = 0; entry < data->nxattrs; entry++)
2754 if (data->xattrs[entry])
2755 sat_free(data->xattrs[entry]);
2756 data->xattrs = sat_free(data->xattrs);
2759 data->lasthandle = 0;
2761 data->lastdatalen = 0;
2764 repodata_free_schemahash(data);
2766 sat_free(data->incoredata);
2767 data->incoredata = newincore.buf;
2768 data->incoredatalen = newincore.len;
2769 data->incoredatafree = 0;
2771 sat_free(data->vincore);
2772 data->vincore = newvincore.buf;
2773 data->vincorelen = newvincore.len;
2775 data->attrs = sat_free(data->attrs);
2776 data->attrdata = sat_free(data->attrdata);
2777 data->attriddata = sat_free(data->attriddata);
2778 data->attrdatalen = 0;
2779 data->attriddatalen = 0;
2783 repodata_disable_paging(Repodata *data)
2785 if (maybe_load_repodata(data, 0))
2786 repopagestore_disable_paging(&data->store);
2790 repodata_load_stub(Repodata *data)
2792 Repo *repo = data->repo;
2793 Pool *pool = repo->pool;
2796 if (!pool->loadcallback)
2798 data->state = REPODATA_ERROR;
2801 data->state = REPODATA_LOADING;
2802 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2804 data->state = REPODATA_ERROR;
2808 repodata_create_stubs(Repodata *data)
2810 Repo *repo = data->repo;
2811 Pool *pool = repo->pool;
2818 int datastart, dataend;
2820 repodataid = data - repo->repodata;
2821 datastart = data->start;
2822 dataend = data->end;
2823 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2824 while (dataiterator_step(&di))
2826 if (di.data - repo->repodata != repodataid)
2830 dataiterator_free(&di);
2833 stubdataids = sat_calloc(cnt, sizeof(*stubdataids));
2834 for (i = 0; i < cnt; i++)
2836 sdata = repo_add_repodata(repo, 0);
2837 if (dataend > datastart)
2838 repodata_extend_block(sdata, datastart, dataend - datastart);
2839 stubdataids[i] = sdata - repo->repodata;
2840 sdata->state = REPODATA_STUB;
2841 sdata->loadcallback = repodata_load_stub;
2844 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2846 while (dataiterator_step(&di))
2848 if (di.data - repo->repodata != repodataid)
2850 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
2852 dataiterator_entersub(&di);
2853 sdata = repo->repodata + stubdataids[i++];
2857 switch (di.key->type)
2859 case REPOKEY_TYPE_ID:
2860 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
2862 case REPOKEY_TYPE_CONSTANTID:
2863 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
2865 case REPOKEY_TYPE_STR:
2866 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
2868 case REPOKEY_TYPE_VOID:
2869 repodata_set_void(sdata, SOLVID_META, di.key->name);
2871 case REPOKEY_TYPE_NUM:
2872 repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num);
2874 case REPOKEY_TYPE_MD5:
2875 case REPOKEY_TYPE_SHA1:
2876 case REPOKEY_TYPE_SHA256:
2877 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
2879 case REPOKEY_TYPE_IDARRAY:
2880 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
2881 if (di.key->name == REPOSITORY_KEYS)
2888 xkeyname = di.kv.id;
2891 xkey.name = xkeyname;
2892 xkey.type = di.kv.id;
2893 xkey.storage = KEY_STORAGE_INCORE;
2895 repodata_key2id(sdata, &xkey, 1);
2902 dataiterator_free(&di);
2903 for (i = 0; i < cnt; i++)
2904 repodata_internalize(repo->repodata + stubdataids[i]);
2905 sat_free(stubdataids);
2909 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: