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;
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);
677 if (key->type != REPOKEY_TYPE_IDARRAY && key->type != REPOKEY_TYPE_REL_IDARRAY)
681 dp = data_read_ideof(dp, &id, &eof);
690 repodata_globalize_id(Repodata *data, Id id, int create)
692 if (!id || !data || !data->localpool)
694 return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
698 /************************************************************************
704 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
708 case REPOKEY_TYPE_ID:
709 case REPOKEY_TYPE_CONSTANTID:
710 case REPOKEY_TYPE_IDARRAY:
711 if (data && data->localpool)
712 kv->str = stringpool_id2str(&data->spool, kv->id);
714 kv->str = id2str(pool, kv->id);
715 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
718 for (s = kv->str; *s >= 'a' && *s <= 'z'; s++)
720 if (*s == ':' && s > kv->str)
724 case REPOKEY_TYPE_STR:
726 case REPOKEY_TYPE_DIRSTRARRAY:
727 if (!(flags & SEARCH_FILES))
728 return 1; /* match just the basename */
729 /* Put the full filename into kv->str. */
730 kv->str = repodata_dir2str(data, kv->id, kv->str);
731 /* And to compensate for that put the "empty" directory into
732 kv->id, so that later calls to repodata_dir2str on this data
733 come up with the same filename again. */
736 case REPOKEY_TYPE_MD5:
737 case REPOKEY_TYPE_SHA1:
738 case REPOKEY_TYPE_SHA256:
739 if (!(flags & SEARCH_CHECKSUMS))
740 return 0; /* skip em */
741 kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str);
749 struct subschema_data {
755 /* search a specific repodata */
757 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
761 Id keyid, *kp, *keyp;
762 unsigned char *dp, *ddp;
768 if (!maybe_load_repodata(data, keyname))
770 if (solvid == SOLVID_SUBSCHEMA)
772 struct subschema_data *subd = cbdata;
773 cbdata = subd->cbdata;
775 schema = subd->parent->id;
776 dp = (unsigned char *)subd->parent->str;
777 kv.parent = subd->parent;
782 dp = solvid2data(data, solvid, &schema);
785 s = data->repo->pool->solvables + solvid;
788 keyp = data->schemadata + data->schemata[schema];
791 /* search for a specific key */
792 for (kp = keyp; *kp; kp++)
793 if (data->keys[*kp].name == keyname)
797 dp = forward_to_key(data, *kp, keyp, dp);
803 while ((keyid = *keyp++) != 0)
806 key = data->keys + keyid;
807 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
809 if (key->type == REPOKEY_TYPE_DELETED)
811 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
813 struct subschema_data subd;
817 subd.cbdata = cbdata;
820 ddp = data_read_id(ddp, &nentries);
824 while (ddp && nentries > 0)
828 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
829 ddp = data_read_id(ddp, &schema);
831 kv.str = (char *)ddp;
832 stop = callback(cbdata, s, data, key, &kv);
833 if (stop > SEARCH_NEXT_KEY)
835 if (stop && stop != SEARCH_ENTERSUB)
837 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
838 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
839 ddp = data_skip_schema(data, ddp, schema);
842 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
846 kv.str = (char *)ddp;
847 stop = callback(cbdata, s, data, key, &kv);
848 if (stop > SEARCH_NEXT_KEY)
858 ddp = data_fetch(ddp, &kv, key);
861 stop = callback(cbdata, s, data, key, &kv);
864 while (!kv.eof && !stop);
865 if (onekey || stop > SEARCH_NEXT_KEY)
871 repodata_setpos_kv(Repodata *data, KeyValue *kv)
873 Pool *pool = data->repo->pool;
875 pool_clear_pos(pool);
878 pool->pos.repo = data->repo;
879 pool->pos.repodataid = data - data->repo->repodata;
880 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
881 pool->pos.schema = kv->id;
885 /************************************************************************
886 * data iterator functions
889 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
890 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
891 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
892 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
893 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
894 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
895 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
896 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
897 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
898 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
899 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
900 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
901 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
902 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
906 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
920 case SOLVABLE_VENDOR:
923 case SOLVABLE_PROVIDES:
925 return s->provides ? s->repo->idarraydata + s->provides : 0;
926 case SOLVABLE_OBSOLETES:
928 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
929 case SOLVABLE_CONFLICTS:
931 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
932 case SOLVABLE_REQUIRES:
934 return s->requires ? s->repo->idarraydata + s->requires : 0;
935 case SOLVABLE_RECOMMENDS:
937 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
938 case SOLVABLE_SUPPLEMENTS:
940 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
941 case SOLVABLE_SUGGESTS:
943 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
944 case SOLVABLE_ENHANCES:
946 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
949 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
956 datamatcher_init(Datamatcher *ma, const char *match, int flags)
962 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
964 ma->matchdata = sat_calloc(1, sizeof(regex_t));
965 ma->error = regcomp((regex_t *)ma->matchdata, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
968 sat_free(ma->matchdata);
969 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
976 datamatcher_free(Datamatcher *ma)
978 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
980 regfree(ma->matchdata);
981 ma->matchdata = sat_free(ma->matchdata);
986 datamatcher_match(Datamatcher *ma, const char *str)
989 switch ((ma->flags & SEARCH_STRINGMASK))
991 case SEARCH_SUBSTRING:
992 if (ma->flags & SEARCH_NOCASE)
994 if (!strcasestr(str, ma->match))
999 if (!strstr(str, ma->match))
1004 if (ma->flags & SEARCH_NOCASE)
1006 if (strcasecmp(ma->match, str))
1011 if (strcmp(ma->match, str))
1015 case SEARCH_STRINGSTART:
1016 if (ma->flags & SEARCH_NOCASE)
1018 if (strncasecmp(ma->match, str, strlen(ma->match)))
1023 if (strncmp(ma->match, str, strlen(ma->match)))
1027 case SEARCH_STRINGEND:
1028 l = strlen(str) - strlen(ma->match);
1031 if (ma->flags & SEARCH_NOCASE)
1033 if (strcasecmp(ma->match, str + l))
1038 if (strcmp(ma->match, str + l))
1043 if (fnmatch(ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
1047 if (regexec((const regex_t *)ma->matchdata, str, 0, NULL, 0))
1057 repodata_filelistfilter_matches(Repodata *data, const char *str)
1059 /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */
1060 /* for now hardcoded */
1061 if (strstr(str, "bin/"))
1063 if (!strncmp(str, "/etc/", 5))
1065 if (!strcmp(str, "/usr/lib/sendmail"))
1087 di_nextarrayelement,
1092 di_nextsolvableattr,
1097 /* see repo.h for documentation */
1099 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
1101 memset(di, 0, sizeof(*di));
1103 di->flags = flags & ~SEARCH_THISSOLVID;
1104 if (!pool || (repo && repo->pool != pool))
1112 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1118 di->keyname = keyname;
1119 di->keynames[0] = keyname;
1120 dataiterator_set_search(di, repo, p);
1125 dataiterator_init_clone(Dataiterator *di, Dataiterator *from)
1128 memset(&di->matcher, 0, sizeof(di->matcher));
1129 if (from->matcher.match)
1130 datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags);
1135 for (i = 1; i < di->nparents; i++)
1136 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1137 di->kv.parent = &di->parents[di->nparents - 1].kv;
1142 dataiterator_set_match(Dataiterator *di, const char *match, int flags)
1144 di->flags = (flags & ~SEARCH_THISSOLVID) | (di->flags & SEARCH_THISSOLVID);
1145 datamatcher_free(&di->matcher);
1146 memset(&di->matcher, 0, sizeof(di->matcher));
1150 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1160 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
1164 di->flags &= ~SEARCH_THISSOLVID;
1168 if (!di->pool->nrepos)
1176 di->repo = di->pool->repos[0];
1178 di->state = di_enterrepo;
1180 dataiterator_jump_to_solvid(di, p);
1184 dataiterator_set_keyname(Dataiterator *di, Id keyname)
1187 di->keyname = keyname;
1188 di->keynames[0] = keyname;
1192 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1196 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1198 di->state = di_bye; /* sorry */
1201 for (i = di->nkeynames + 1; i > 0; i--)
1202 di->keynames[i] = di->keynames[i - 1];
1203 di->keynames[0] = di->keyname = keyname;
1208 dataiterator_free(Dataiterator *di)
1210 if (di->matcher.match)
1211 datamatcher_free(&di->matcher);
1214 static inline unsigned char *
1215 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1217 Id *keyp = di->keyp;
1218 Repokey *keys = di->data->keys;
1221 for (keyp = di->keyp; *keyp; keyp++)
1222 if (keys[*keyp].name == keyname)
1226 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1234 dataiterator_filelistcheck(Dataiterator *di)
1237 int needcomplete = 0;
1238 Repodata *data = di->data;
1240 if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
1241 if (!di->matcher.match
1242 || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
1243 && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)
1244 || !repodata_filelistfilter_matches(di->data, di->matcher.match))
1246 if (data->state != REPODATA_AVAILABLE)
1247 return needcomplete ? 1 : 0;
1248 for (j = 1; j < data->nkeys; j++)
1249 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
1251 return j == data->nkeys && !needcomplete ? 0 : 1;
1255 dataiterator_step(Dataiterator *di)
1263 case di_enterrepo: di_enterrepo:
1266 if (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS))
1268 if (!(di->flags & SEARCH_THISSOLVID))
1270 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1271 goto di_nextsolvable;
1275 case di_entersolvable: di_entersolvable:
1276 if (di->repodataid >= 0)
1278 di->repodataid = 0; /* reset repodata iterator */
1279 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)
1281 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1283 goto di_entersolvablekey;
1288 case di_enterrepodata: di_enterrepodata:
1289 if (di->repodataid >= 0)
1291 if (di->repodataid >= di->repo->nrepodata)
1292 goto di_nextsolvable;
1293 di->data = di->repo->repodata + di->repodataid;
1295 if (di->repodataid >= 0 && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
1296 goto di_nextrepodata;
1297 if (!maybe_load_repodata(di->data, di->keyname))
1298 goto di_nextrepodata;
1299 di->dp = solvid2data(di->data, di->solvid, &schema);
1301 goto di_nextrepodata;
1302 if (di->solvid == SOLVID_POS)
1303 di->solvid = di->pool->pos.solvid;
1304 /* reset key iterator */
1305 di->keyp = di->data->schemadata + di->data->schemata[schema];
1308 case di_enterschema: di_enterschema:
1310 di->dp = dataiterator_find_keyname(di, di->keyname);
1311 if (!di->dp || !*di->keyp)
1315 goto di_nextrepodata;
1319 case di_enterkey: di_enterkey:
1321 di->key = di->data->keys + *di->keyp;
1322 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1325 if (di->key->type == REPOKEY_TYPE_DELETED)
1327 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1329 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1335 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1337 di->state = di_nextkey;
1339 di->state = di_nextattr;
1342 case di_nextkey: di_nextkey:
1343 if (!di->keyname && *++di->keyp)
1349 case di_nextrepodata: di_nextrepodata:
1350 if (di->repodataid >= 0 && ++di->repodataid < di->repo->nrepodata)
1351 goto di_enterrepodata;
1354 case di_nextsolvable: di_nextsolvable:
1355 if (!(di->flags & SEARCH_THISSOLVID))
1358 di->solvid = di->repo->start;
1361 for (; di->solvid < di->repo->end; di->solvid++)
1363 if (di->pool->solvables[di->solvid].repo == di->repo)
1364 goto di_entersolvable;
1369 case di_nextrepo: di_nextrepo:
1370 if (di->repoid >= 0)
1374 if (di->repoid < di->pool->nrepos)
1376 di->repo = di->pool->repos[di->repoid];
1382 case di_bye: di_bye:
1386 case di_enterarray: di_enterarray:
1387 if (di->key->name == REPOSITORY_SOLVABLES)
1389 di->ddp = data_read_id(di->ddp, &di->kv.num);
1394 case di_nextarrayelement: di_nextarrayelement:
1397 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1398 if (di->kv.entry == di->kv.num)
1400 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1402 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1404 di->kv.str = (char *)di->ddp;
1406 di->state = di_nextkey;
1409 if (di->kv.entry == di->kv.num - 1)
1411 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1412 di->ddp = data_read_id(di->ddp, &di->kv.id);
1413 di->kv.str = (char *)di->ddp;
1414 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1416 if ((di->flags & SEARCH_SUB) != 0)
1417 di->state = di_entersub;
1419 di->state = di_nextarrayelement;
1422 case di_entersub: di_entersub:
1423 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1424 goto di_nextarrayelement; /* sorry, full */
1425 di->parents[di->nparents].kv = di->kv;
1426 di->parents[di->nparents].dp = di->dp;
1427 di->parents[di->nparents].keyp = di->keyp;
1428 di->dp = (unsigned char *)di->kv.str;
1429 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1430 memset(&di->kv, 0, sizeof(di->kv));
1431 di->kv.parent = &di->parents[di->nparents].kv;
1433 di->keyname = di->keynames[di->nparents - di->rootlevel];
1434 goto di_enterschema;
1436 case di_leavesub: di_leavesub:
1437 if (di->nparents - 1 < di->rootlevel)
1440 di->dp = di->parents[di->nparents].dp;
1441 di->kv = di->parents[di->nparents].kv;
1442 di->keyp = di->parents[di->nparents].keyp;
1443 di->key = di->data->keys + *di->keyp;
1444 di->ddp = (unsigned char *)di->kv.str;
1445 di->keyname = di->keynames[di->nparents - di->rootlevel];
1446 goto di_nextarrayelement;
1448 /* special solvable attr handling follows */
1450 case di_nextsolvableattr:
1451 di->kv.id = *di->idp++;
1456 di->state = di_nextsolvablekey;
1460 case di_nextsolvablekey: di_nextsolvablekey:
1461 if (di->keyname || di->key->name == RPM_RPMDBID)
1462 goto di_enterrepodata;
1466 case di_entersolvablekey: di_entersolvablekey:
1467 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1468 if (!di->idp || !di->idp[0])
1469 goto di_nextsolvablekey;
1470 di->kv.id = di->idp[0];
1471 di->kv.num = di->idp[0];
1473 if (!di->kv.eof && !di->idp[0])
1477 di->state = di_nextsolvablekey;
1479 di->state = di_nextsolvableattr;
1483 if (di->matcher.match)
1485 /* simple pre-check so that we don't need to stringify */
1486 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))
1488 int l = strlen(di->matcher.match) - strlen(di->kv.str);
1489 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
1492 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1494 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1498 if (!datamatcher_match(&di->matcher, di->kv.str))
1501 /* found something! */
1507 dataiterator_entersub(Dataiterator *di)
1509 if (di->state == di_nextarrayelement)
1510 di->state = di_entersub;
1514 dataiterator_setpos(Dataiterator *di)
1516 if (di->kv.eof == 2)
1518 pool_clear_pos(di->pool);
1521 di->pool->pos.solvid = di->solvid;
1522 di->pool->pos.repo = di->repo;
1523 di->pool->pos.repodataid = di->data - di->repo->repodata;
1524 di->pool->pos.schema = di->kv.id;
1525 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1529 dataiterator_setpos_parent(Dataiterator *di)
1531 if (!di->kv.parent || di->kv.parent->eof == 2)
1533 pool_clear_pos(di->pool);
1536 di->pool->pos.solvid = di->solvid;
1537 di->pool->pos.repo = di->repo;
1538 di->pool->pos.repodataid = di->data - di->repo->repodata;
1539 di->pool->pos.schema = di->kv.parent->id;
1540 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1543 /* clones just the position, not the search keys/matcher */
1545 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
1547 di->state = from->state;
1548 di->flags &= ~SEARCH_THISSOLVID;
1549 di->flags |= (from->flags & SEARCH_THISSOLVID);
1550 di->repo = from->repo;
1551 di->data = from->data;
1553 di->ddp = from->ddp;
1554 di->idp = from->idp;
1555 di->keyp = from->keyp;
1556 di->key = from->key;
1558 di->repodataid = from->repodataid;
1559 di->solvid = from->solvid;
1560 di->repoid = from->repoid;
1561 di->rootlevel = from->rootlevel;
1562 memcpy(di->parents, from->parents, sizeof(from->parents));
1563 di->nparents = from->nparents;
1567 for (i = 1; i < di->nparents; i++)
1568 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1569 di->kv.parent = &di->parents[di->nparents - 1].kv;
1574 dataiterator_seek(Dataiterator *di, int whence)
1576 if ((whence & DI_SEEK_STAY) != 0)
1577 di->rootlevel = di->nparents;
1578 switch (whence & ~DI_SEEK_STAY)
1581 if (di->state != di_nextarrayelement)
1583 if ((whence & DI_SEEK_STAY) != 0)
1584 di->rootlevel = di->nparents + 1; /* XXX: dangerous! */
1585 di->state = di_entersub;
1587 case DI_SEEK_PARENT:
1594 if (di->rootlevel > di->nparents)
1595 di->rootlevel = di->nparents;
1596 di->dp = di->parents[di->nparents].dp;
1597 di->kv = di->parents[di->nparents].kv;
1598 di->keyp = di->parents[di->nparents].keyp;
1599 di->key = di->data->keys + *di->keyp;
1600 di->ddp = (unsigned char *)di->kv.str;
1601 di->keyname = di->keynames[di->nparents - di->rootlevel];
1602 di->state = di_nextarrayelement;
1604 case DI_SEEK_REWIND:
1610 di->dp = (unsigned char *)di->kv.parent->str;
1611 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
1612 di->state = di_enterschema;
1620 dataiterator_skip_attribute(Dataiterator *di)
1622 if (di->state == di_nextsolvableattr)
1623 di->state = di_nextsolvablekey;
1625 di->state = di_nextkey;
1629 dataiterator_skip_solvable(Dataiterator *di)
1634 di->keyname = di->keynames[0];
1635 di->state = di_nextsolvable;
1639 dataiterator_skip_repo(Dataiterator *di)
1644 di->keyname = di->keynames[0];
1645 di->state = di_nextrepo;
1649 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1654 di->keyname = di->keynames[0];
1655 if (solvid == SOLVID_POS)
1657 di->repo = di->pool->pos.repo;
1664 di->data = di->repo->repodata + di->pool->pos.repodataid;
1665 di->repodataid = -1;
1666 di->solvid = solvid;
1667 di->state = di_enterrepo;
1668 di->flags |= SEARCH_THISSOLVID;
1673 di->repo = di->pool->solvables[solvid].repo;
1676 else if (di->repoid >= 0)
1678 if (!di->pool->nrepos)
1683 di->repo = di->pool->repos[0];
1687 di->solvid = solvid;
1689 di->flags |= SEARCH_THISSOLVID;
1690 di->state = di_enterrepo;
1694 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1703 di->flags &= ~SEARCH_THISSOLVID;
1704 di->state = di_enterrepo;
1708 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1710 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1714 return datamatcher_match(ma, di->kv.str);
1717 /************************************************************************
1718 * data modify functions
1721 /* extend repodata so that it includes solvables p */
1723 repodata_extend(Repodata *data, Id p)
1725 if (data->start == data->end)
1726 data->start = data->end = p;
1729 int old = data->end - data->start;
1730 int new = p - data->end + 1;
1733 data->attrs = sat_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1734 memset(data->attrs + old, 0, new * sizeof(Id *));
1736 data->incoreoffset = sat_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1737 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1740 if (p < data->start)
1742 int old = data->end - data->start;
1743 int new = data->start - p;
1746 data->attrs = sat_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1747 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1748 memset(data->attrs, 0, new * sizeof(Id *));
1750 data->incoreoffset = sat_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1751 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1752 memset(data->incoreoffset, 0, new * sizeof(Id));
1757 /* shrink end of repodata */
1759 repodata_shrink(Repodata *data, int end)
1763 if (data->end <= end)
1765 if (data->start >= end)
1769 for (i = 0; i < data->end - data->start; i++)
1770 sat_free(data->attrs[i]);
1771 data->attrs = sat_free(data->attrs);
1773 data->incoreoffset = sat_free(data->incoreoffset);
1774 data->start = data->end = 0;
1779 for (i = end; i < data->end; i++)
1780 sat_free(data->attrs[i - data->start]);
1781 data->attrs = sat_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
1783 if (data->incoreoffset)
1784 data->incoreoffset = sat_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
1788 /* extend repodata so that it includes solvables from start to start + num - 1 */
1790 repodata_extend_block(Repodata *data, Id start, Id num)
1794 if (!data->incoreoffset)
1796 data->incoreoffset = sat_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1797 data->start = start;
1798 data->end = start + num;
1801 repodata_extend(data, start);
1803 repodata_extend(data, start + num - 1);
1806 /**********************************************************************/
1809 #define REPODATA_ATTRS_BLOCK 31
1810 #define REPODATA_ATTRDATA_BLOCK 1023
1811 #define REPODATA_ATTRIDDATA_BLOCK 63
1815 repodata_new_handle(Repodata *data)
1819 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1822 data->xattrs = sat_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1823 data->xattrs[data->nxattrs] = 0;
1824 return -(data->nxattrs++);
1828 repodata_get_attrp(Repodata *data, Id handle)
1830 if (handle == SOLVID_META)
1834 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1839 return data->xattrs - handle;
1840 if (handle < data->start || handle >= data->end)
1841 repodata_extend(data, handle);
1843 data->attrs = sat_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1844 return data->attrs + (handle - data->start);
1848 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1854 app = repodata_get_attrp(data, handle);
1859 /* Determine equality based on the name only, allows us to change
1860 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1861 for (pp = ap; *pp; pp += 2)
1862 if (data->keys[*pp].name == data->keys[keyid].name)
1866 if (overwrite || data->keys[*pp].type == REPOKEY_TYPE_DELETED)
1875 ap = sat_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1885 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1889 keyid = repodata_key2id(data, key, 1);
1890 repodata_insert_keyid(data, solvid, keyid, val, 1);
1894 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1898 key.type = REPOKEY_TYPE_ID;
1900 key.storage = KEY_STORAGE_INCORE;
1901 repodata_set(data, solvid, &key, id);
1905 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1909 key.type = REPOKEY_TYPE_NUM;
1911 key.storage = KEY_STORAGE_INCORE;
1912 repodata_set(data, solvid, &key, (Id)num);
1916 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
1920 if (data->localpool)
1921 id = stringpool_str2id(&data->spool, str, 1);
1923 id = str2id(data->repo->pool, str, 1);
1925 key.type = REPOKEY_TYPE_ID;
1927 key.storage = KEY_STORAGE_INCORE;
1928 repodata_set(data, solvid, &key, id);
1932 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
1936 key.type = REPOKEY_TYPE_CONSTANT;
1937 key.size = constant;
1938 key.storage = KEY_STORAGE_INCORE;
1939 repodata_set(data, solvid, &key, 0);
1943 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
1947 key.type = REPOKEY_TYPE_CONSTANTID;
1949 key.storage = KEY_STORAGE_INCORE;
1950 repodata_set(data, solvid, &key, 0);
1954 repodata_set_void(Repodata *data, Id solvid, Id keyname)
1958 key.type = REPOKEY_TYPE_VOID;
1960 key.storage = KEY_STORAGE_INCORE;
1961 repodata_set(data, solvid, &key, 0);
1965 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
1970 l = strlen(str) + 1;
1972 key.type = REPOKEY_TYPE_STR;
1974 key.storage = KEY_STORAGE_INCORE;
1975 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1976 memcpy(data->attrdata + data->attrdatalen, str, l);
1977 repodata_set(data, solvid, &key, data->attrdatalen);
1978 data->attrdatalen += l;
1982 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
1988 key.type = REPOKEY_TYPE_BINARY;
1990 key.storage = KEY_STORAGE_INCORE;
1991 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
1992 dp = data->attrdata + data->attrdatalen;
1993 if (len >= (1 << 14))
1995 if (len >= (1 << 28))
1996 *dp++ = (len >> 28) | 128;
1997 if (len >= (1 << 21))
1998 *dp++ = (len >> 21) | 128;
1999 *dp++ = (len >> 14) | 128;
2001 if (len >= (1 << 7))
2002 *dp++ = (len >> 7) | 128;
2005 memcpy(dp, buf, len);
2006 repodata_set(data, solvid, &key, data->attrdatalen);
2007 data->attrdatalen = dp + len - data->attrdata;
2010 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
2011 * so that the caller can append entrysize new elements plus the termination zero there */
2013 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
2016 Id *ida, *pp, **ppp;
2018 /* check if it is the same as last time, this speeds things up a lot */
2019 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
2021 /* great! just append the new data */
2022 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2023 data->attriddatalen--; /* overwrite terminating 0 */
2024 data->lastdatalen += entrysize;
2028 ppp = repodata_get_attrp(data, handle);
2032 for (; *pp; pp += 2)
2033 if (data->keys[*pp].name == keyname)
2036 if (!pp || !*pp || data->keys[*pp].type != keytype)
2038 /* not found. allocate new key */
2044 key.storage = KEY_STORAGE_INCORE;
2045 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2046 keyid = repodata_key2id(data, &key, 1);
2047 repodata_insert_keyid(data, handle, keyid, data->attriddatalen, 1);
2048 data->lasthandle = handle;
2049 data->lastkey = keyid;
2050 data->lastdatalen = data->attriddatalen + entrysize + 1;
2054 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
2055 oldsize += entrysize;
2056 if (ida + 1 == data->attriddata + data->attriddatalen)
2058 /* this was the last entry, just append it */
2059 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2060 data->attriddatalen--; /* overwrite terminating 0 */
2064 /* too bad. move to back. */
2065 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2066 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
2067 pp[1] = data->attriddatalen;
2068 data->attriddatalen += oldsize;
2070 data->lasthandle = handle;
2071 data->lastkey = *pp;
2072 data->lastdatalen = data->attriddatalen + entrysize + 1;
2076 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2077 const unsigned char *str)
2082 if (!(l = sat_chksum_len(type)))
2087 key.storage = KEY_STORAGE_INCORE;
2088 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2089 memcpy(data->attrdata + data->attrdatalen, str, l);
2090 repodata_set(data, solvid, &key, data->attrdatalen);
2091 data->attrdatalen += l;
2095 hexstr2bytes(unsigned char *buf, const char *str, int buflen)
2098 for (i = 0; i < buflen; i++)
2100 #define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
2101 : ((c)>='a' && (c)<='f') ? ((c)-('a'-10)) \
2102 : ((c)>='A' && (c)<='F') ? ((c)-('A'-10)) \
2113 buf[i] = (buf[i] << 4) | v;
2120 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2123 unsigned char buf[64];
2126 if (!(l = sat_chksum_len(type)))
2128 if (hexstr2bytes(buf, str, l) != l)
2130 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2134 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2139 if (!(l = sat_chksum_len(type)))
2141 s = str = pool_alloctmpspace(data->repo->pool, 2 * l + 1);
2142 for (i = 0; i < l; i++)
2144 unsigned char v = buf[i];
2145 unsigned char w = v >> 4;
2146 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
2148 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
2154 /* rpm filenames don't contain the epoch, so strip it */
2155 static inline const char *
2156 evrid2vrstr(Pool *pool, Id evrid)
2158 const char *p, *evr = id2str(pool, evrid);
2161 for (p = evr; *p >= '0' && *p <= '9'; p++)
2163 return p != evr && *p == ':' ? p + 1 : evr;
2167 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2169 Pool *pool = data->repo->pool;
2171 const char *str, *fp;
2175 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2178 if ((dir = strrchr(file, '/')) != 0)
2189 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2194 if (l == 1 && dir[0] == '.')
2196 s = pool->solvables + solvid;
2199 str = id2str(pool, s->arch);
2200 if (!strncmp(dir, str, l) && !str[l])
2201 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2203 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2206 char *dir2 = strdup(dir);
2208 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2213 str = id2str(pool, s->name);
2215 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2218 str = evrid2vrstr(pool, s->evr);
2220 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2223 str = id2str(pool, s->arch);
2225 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2227 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2232 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2236 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2240 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2242 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2243 data->attriddata[data->attriddatalen++] = dir;
2244 data->attriddata[data->attriddatalen++] = num;
2245 data->attriddata[data->attriddatalen++] = num2;
2246 data->attriddata[data->attriddatalen++] = 0;
2250 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2256 l = strlen(str) + 1;
2257 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2258 memcpy(data->attrdata + data->attrdatalen, str, l);
2259 stroff = data->attrdatalen;
2260 data->attrdatalen += l;
2263 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2265 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2266 data->attriddata[data->attriddatalen++] = dir;
2267 data->attriddata[data->attriddatalen++] = stroff;
2268 data->attriddata[data->attriddatalen++] = 0;
2272 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2275 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2277 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2278 data->attriddata[data->attriddatalen++] = id;
2279 data->attriddata[data->attriddatalen++] = 0;
2283 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2287 if (data->localpool)
2288 id = stringpool_str2id(&data->spool, str, 1);
2290 id = str2id(data->repo->pool, str, 1);
2291 repodata_add_idarray(data, solvid, keyname, id);
2295 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2297 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2298 data->attriddata[data->attriddatalen++] = ghandle;
2299 data->attriddata[data->attriddatalen++] = 0;
2303 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2305 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2306 data->attriddata[data->attriddatalen++] = ghandle;
2307 data->attriddata[data->attriddatalen++] = 0;
2311 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2314 app = repodata_get_attrp(data, solvid);
2318 for (; *ap; ap += 2)
2319 if (data->keys[*ap].name == keyname)
2325 for (; *ap; ap += 2)
2327 if (data->keys[*ap].name == keyname)
2335 /* XXX: does not work correctly, needs fix in iterators! */
2337 repodata_delete(Repodata *data, Id solvid, Id keyname)
2341 key.type = REPOKEY_TYPE_DELETED;
2343 key.storage = KEY_STORAGE_INCORE;
2344 repodata_set(data, solvid, &key, 0);
2347 /* add all (uninternalized) attrs from src to dest */
2349 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2352 if (dest == src || !(keyp = data->attrs[src - data->start]))
2354 for (; *keyp; keyp += 2)
2355 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2358 /* add some (uninternalized) attrs from src to dest */
2360 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2363 if (dest == src || !(keyp = data->attrs[src - data->start]))
2365 for (; *keyp; keyp += 2)
2366 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2367 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2372 /**********************************************************************/
2374 /* TODO: unify with repo_write and repo_solv! */
2376 #define EXTDATA_BLOCK 1023
2384 data_addid(struct extdata *xd, Id x)
2388 xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2389 dp = xd->buf + xd->len;
2394 *dp++ = (x >> 28) | 128;
2396 *dp++ = (x >> 21) | 128;
2397 *dp++ = (x >> 14) | 128;
2400 *dp++ = (x >> 7) | 128;
2402 xd->len = dp - xd->buf;
2406 data_addideof(struct extdata *xd, Id x, int eof)
2409 x = (x & 63) | ((x & ~63) << 1);
2410 data_addid(xd, (eof ? x : x | 64));
2414 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2416 xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2417 memcpy(xd->buf + xd->len, blob, len);
2421 /*********************************/
2424 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2425 struct extdata *newvincore,
2427 Repokey *key, Id val)
2429 /* Otherwise we have a new value. Parse it into the internal
2433 unsigned int oldvincorelen = 0;
2437 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2440 oldvincorelen = xd->len;
2444 case REPOKEY_TYPE_VOID:
2445 case REPOKEY_TYPE_CONSTANT:
2446 case REPOKEY_TYPE_CONSTANTID:
2448 case REPOKEY_TYPE_STR:
2449 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2451 case REPOKEY_TYPE_MD5:
2452 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2454 case REPOKEY_TYPE_SHA1:
2455 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2457 case REPOKEY_TYPE_SHA256:
2458 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2460 case REPOKEY_TYPE_ID:
2461 case REPOKEY_TYPE_NUM:
2462 case REPOKEY_TYPE_DIR:
2463 data_addid(xd, val);
2465 case REPOKEY_TYPE_BINARY:
2468 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2470 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2473 case REPOKEY_TYPE_IDARRAY:
2474 for (ida = data->attriddata + val; *ida; ida++)
2475 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2477 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2478 for (ida = data->attriddata + val; *ida; ida += 3)
2480 data_addid(xd, ida[0]);
2481 data_addid(xd, ida[1]);
2482 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2485 case REPOKEY_TYPE_DIRSTRARRAY:
2486 for (ida = data->attriddata + val; *ida; ida += 2)
2488 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2489 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2492 case REPOKEY_TYPE_FIXARRAY:
2496 for (ida = data->attriddata + val; *ida; ida++)
2499 fprintf(stderr, "serialize struct %d\n", *ida);
2502 Id *kp = data->xattrs[-*ida];
2509 fprintf(stderr, " %s:%d\n", id2str(data->repo->pool, data->keys[*kp].name), kp[1]);
2515 schemaid = repodata_schema2id(data, schema, 1);
2516 else if (schemaid != repodata_schema2id(data, schema, 0))
2518 pool_debug(data->repo->pool, SAT_FATAL, "fixarray substructs with different schemas\n");
2522 fprintf(stderr, " schema %d\n", schemaid);
2527 data_addid(xd, num);
2528 data_addid(xd, schemaid);
2529 for (ida = data->attriddata + val; *ida; ida++)
2531 Id *kp = data->xattrs[-*ida];
2536 repodata_serialize_key(data, newincore, newvincore,
2537 schema, data->keys + *kp, kp[1]);
2542 case REPOKEY_TYPE_FLEXARRAY:
2545 for (ida = data->attriddata + val; *ida; ida++)
2547 data_addid(xd, num);
2548 for (ida = data->attriddata + val; *ida; ida++)
2550 Id *kp = data->xattrs[-*ida];
2553 data_addid(xd, 0); /* XXX */
2560 schemaid = repodata_schema2id(data, schema, 1);
2561 data_addid(xd, schemaid);
2562 kp = data->xattrs[-*ida];
2565 repodata_serialize_key(data, newincore, newvincore,
2566 schema, data->keys + *kp, kp[1]);
2572 pool_debug(data->repo->pool, SAT_FATAL, "don't know how to handle type %d\n", key->type);
2575 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2577 /* put offset/len in incore */
2578 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2579 oldvincorelen = xd->len - oldvincorelen;
2580 data_addid(newincore, oldvincorelen);
2585 repodata_internalize(Repodata *data)
2587 Repokey *key, solvkey;
2589 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2590 unsigned char *dp, *ndp;
2591 int newschema, oldcount;
2592 struct extdata newincore;
2593 struct extdata newvincore;
2596 if (!data->attrs && !data->xattrs)
2599 newvincore.buf = data->vincore;
2600 newvincore.len = data->vincorelen;
2602 /* find the solvables key, create if needed */
2603 memset(&solvkey, 0, sizeof(solvkey));
2604 solvkey.name = REPOSITORY_SOLVABLES;
2605 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2607 solvkey.storage = KEY_STORAGE_INCORE;
2608 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2610 schema = sat_malloc2(data->nkeys, sizeof(Id));
2611 seen = sat_malloc2(data->nkeys, sizeof(Id));
2613 /* Merge the data already existing (in data->schemata, ->incoredata and
2614 friends) with the new attributes in data->attrs[]. */
2615 nentry = data->end - data->start;
2616 memset(&newincore, 0, sizeof(newincore));
2617 data_addid(&newincore, 0); /* start data at offset 1 */
2619 data->mainschema = 0;
2620 data->mainschemaoffsets = sat_free(data->mainschemaoffsets);
2622 /* join entry data */
2623 /* we start with the meta data, entry -1 */
2624 for (entry = -1; entry < nentry; entry++)
2626 memset(seen, 0, data->nkeys * sizeof(Id));
2628 dp = data->incoredata;
2631 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2632 dp = data_read_id(dp, &oldschema);
2635 fprintf(stderr, "oldschema %d\n", oldschema);
2636 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2637 fprintf(stderr, "schemadata %p\n", data->schemadata);
2639 /* seen: -1: old data 0: skipped >0: id + 1 */
2643 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2647 pool_debug(data->repo->pool, SAT_FATAL, "Inconsistent old data (key occured twice).\n");
2655 keyp = data->attrs ? data->attrs[entry] : 0;
2658 /* strip solvables key */
2660 for (sp = keyp = schema; *sp; sp++)
2661 if (*sp != solvkeyid)
2666 seen[solvkeyid] = 0;
2667 keyp = data->xattrs ? data->xattrs[1] : 0;
2670 for (; *keyp; keyp += 2)
2677 seen[*keyp] = keyp[1] + 1;
2679 if (entry < 0 && data->end != data->start)
2686 /* Ideally we'd like to sort the new schema here, to ensure
2687 schema equality independend of the ordering. We can't do that
2688 yet. For once see below (old ids need to come before new ids).
2689 An additional difficulty is that we also need to move
2690 the values with the keys. */
2691 schemaid = repodata_schema2id(data, schema, 1);
2693 schemaid = oldschema;
2696 /* Now create data blob. We walk through the (possibly new) schema
2697 and either copy over old data, or insert the new. */
2698 /* XXX Here we rely on the fact that the (new) schema has the form
2699 o1 o2 o3 o4 ... | n1 n2 n3 ...
2700 (oX being the old keyids (possibly overwritten), and nX being
2701 the new keyids). This rules out sorting the keyids in order
2702 to ensure a small schema count. */
2704 data->incoreoffset[entry] = newincore.len;
2705 data_addid(&newincore, schemaid);
2708 data->mainschema = schemaid;
2709 data->mainschemaoffsets = sat_calloc(sp - schema, sizeof(Id));
2711 keypstart = data->schemadata + data->schemata[schemaid];
2712 for (keyp = keypstart; *keyp; keyp++)
2715 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2716 if (*keyp == solvkeyid)
2718 /* add flexarray entry count */
2719 data_addid(&newincore, data->end - data->start);
2722 key = data->keys + *keyp;
2724 fprintf(stderr, "internalize %d(%d):%s:%s\n", entry, entry + data->start, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
2729 /* Skip the data associated with this old key. */
2730 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2732 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2733 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2735 else if (key->storage == KEY_STORAGE_INCORE)
2736 ndp = data_skip_key(data, dp, key);
2739 if (seen[*keyp] == -1)
2741 /* If this key was an old one _and_ was not overwritten with
2742 a different value copy over the old value (we skipped it
2745 data_addblob(&newincore, dp, ndp - dp);
2748 else if (seen[*keyp])
2750 /* Otherwise we have a new value. Parse it into the internal
2752 repodata_serialize_key(data, &newincore, &newvincore,
2753 schema, key, seen[*keyp] - 1);
2757 if (entry >= 0 && data->attrs && data->attrs[entry])
2758 data->attrs[entry] = sat_free(data->attrs[entry]);
2760 /* free all xattrs */
2761 for (entry = 0; entry < data->nxattrs; entry++)
2762 if (data->xattrs[entry])
2763 sat_free(data->xattrs[entry]);
2764 data->xattrs = sat_free(data->xattrs);
2767 data->lasthandle = 0;
2769 data->lastdatalen = 0;
2772 repodata_free_schemahash(data);
2774 sat_free(data->incoredata);
2775 data->incoredata = newincore.buf;
2776 data->incoredatalen = newincore.len;
2777 data->incoredatafree = 0;
2779 sat_free(data->vincore);
2780 data->vincore = newvincore.buf;
2781 data->vincorelen = newvincore.len;
2783 data->attrs = sat_free(data->attrs);
2784 data->attrdata = sat_free(data->attrdata);
2785 data->attriddata = sat_free(data->attriddata);
2786 data->attrdatalen = 0;
2787 data->attriddatalen = 0;
2791 repodata_disable_paging(Repodata *data)
2793 if (maybe_load_repodata(data, 0))
2794 repopagestore_disable_paging(&data->store);
2798 repodata_load_stub(Repodata *data)
2800 Repo *repo = data->repo;
2801 Pool *pool = repo->pool;
2804 if (!pool->loadcallback)
2806 data->state = REPODATA_ERROR;
2809 data->state = REPODATA_LOADING;
2810 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2811 data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
2815 repodata_create_stubs(Repodata *data)
2817 Repo *repo = data->repo;
2818 Pool *pool = repo->pool;
2825 int datastart, dataend;
2827 repodataid = data - repo->repodata;
2828 datastart = data->start;
2829 dataend = data->end;
2830 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2831 while (dataiterator_step(&di))
2833 if (di.data - repo->repodata != repodataid)
2837 dataiterator_free(&di);
2840 stubdataids = sat_calloc(cnt, sizeof(*stubdataids));
2841 for (i = 0; i < cnt; i++)
2843 sdata = repo_add_repodata(repo, 0);
2844 if (dataend > datastart)
2845 repodata_extend_block(sdata, datastart, dataend - datastart);
2846 stubdataids[i] = sdata - repo->repodata;
2847 sdata->state = REPODATA_STUB;
2848 sdata->loadcallback = repodata_load_stub;
2851 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2853 while (dataiterator_step(&di))
2855 if (di.data - repo->repodata != repodataid)
2857 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
2859 dataiterator_entersub(&di);
2860 sdata = repo->repodata + stubdataids[i++];
2864 switch (di.key->type)
2866 case REPOKEY_TYPE_ID:
2867 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
2869 case REPOKEY_TYPE_CONSTANTID:
2870 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
2872 case REPOKEY_TYPE_STR:
2873 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
2875 case REPOKEY_TYPE_VOID:
2876 repodata_set_void(sdata, SOLVID_META, di.key->name);
2878 case REPOKEY_TYPE_NUM:
2879 repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num);
2881 case REPOKEY_TYPE_MD5:
2882 case REPOKEY_TYPE_SHA1:
2883 case REPOKEY_TYPE_SHA256:
2884 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
2886 case REPOKEY_TYPE_IDARRAY:
2887 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
2888 if (di.key->name == REPOSITORY_KEYS)
2895 xkeyname = di.kv.id;
2898 xkey.name = xkeyname;
2899 xkey.type = di.kv.id;
2900 xkey.storage = KEY_STORAGE_INCORE;
2902 repodata_key2id(sdata, &xkey, 1);
2909 dataiterator_free(&di);
2910 for (i = 0; i < cnt; i++)
2911 repodata_internalize(repo->repodata + stubdataids[i]);
2912 sat_free(stubdataids);
2916 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: